Mercurial > hg > graal-jvmci-8
changeset 14850:fbae9be45c95
Merge.
line wrap: on
line diff
--- a/graal/com.oracle.graal.alloc/src/com/oracle/graal/alloc/ComputeBlockOrder.java Wed Mar 26 14:43:50 2014 +0100 +++ b/graal/com.oracle.graal.alloc/src/com/oracle/graal/alloc/ComputeBlockOrder.java Wed Mar 26 20:44:11 2014 +0100 @@ -26,7 +26,6 @@ import java.util.*; import com.oracle.graal.nodes.cfg.*; -import com.oracle.graal.nodes.util.*; /** * Computes an ordering of the block that can be used by the linear scan register allocator and the @@ -67,11 +66,11 @@ * * @return sorted list of blocks */ - public static <T extends AbstractBlock<T>> List<T> computeLinearScanOrder(int blockCount, T startBlock, NodesToDoubles nodeProbabilities) { + public static <T extends AbstractBlock<T>> List<T> computeLinearScanOrder(int blockCount, T startBlock, BlocksToDoubles blockProbabilities) { List<T> order = new ArrayList<>(); BitSet visitedBlocks = new BitSet(blockCount); - PriorityQueue<T> worklist = initializeWorklist(startBlock, visitedBlocks, nodeProbabilities); - computeLinearScanOrder(order, worklist, visitedBlocks, nodeProbabilities); + PriorityQueue<T> worklist = initializeWorklist(startBlock, visitedBlocks, blockProbabilities); + computeLinearScanOrder(order, worklist, visitedBlocks, blockProbabilities); assert checkOrder(order, blockCount); return order; } @@ -81,11 +80,11 @@ * * @return sorted list of blocks */ - public static <T extends AbstractBlock<T>> List<T> computeCodeEmittingOrder(int blockCount, T startBlock, NodesToDoubles nodeProbabilities) { + public static <T extends AbstractBlock<T>> List<T> computeCodeEmittingOrder(int blockCount, T startBlock, BlocksToDoubles blockProbabilities) { List<T> order = new ArrayList<>(); BitSet visitedBlocks = new BitSet(blockCount); - PriorityQueue<T> worklist = initializeWorklist(startBlock, visitedBlocks, nodeProbabilities); - computeCodeEmittingOrder(order, worklist, visitedBlocks, nodeProbabilities); + PriorityQueue<T> worklist = initializeWorklist(startBlock, visitedBlocks, blockProbabilities); + computeCodeEmittingOrder(order, worklist, visitedBlocks, blockProbabilities); assert checkOrder(order, blockCount); return order; } @@ -93,28 +92,28 @@ /** * Iteratively adds paths to the code emission block order. */ - private static <T extends AbstractBlock<T>> void computeCodeEmittingOrder(List<T> order, PriorityQueue<T> worklist, BitSet visitedBlocks, NodesToDoubles nodeProbabilities) { + private static <T extends AbstractBlock<T>> void computeCodeEmittingOrder(List<T> order, PriorityQueue<T> worklist, BitSet visitedBlocks, BlocksToDoubles blockProbabilities) { while (!worklist.isEmpty()) { T nextImportantPath = worklist.poll(); - addPathToCodeEmittingOrder(nextImportantPath, order, worklist, visitedBlocks, nodeProbabilities); + addPathToCodeEmittingOrder(nextImportantPath, order, worklist, visitedBlocks, blockProbabilities); } } /** * Iteratively adds paths to the linear scan block order. */ - private static <T extends AbstractBlock<T>> void computeLinearScanOrder(List<T> order, PriorityQueue<T> worklist, BitSet visitedBlocks, NodesToDoubles nodeProbabilities) { + private static <T extends AbstractBlock<T>> void computeLinearScanOrder(List<T> order, PriorityQueue<T> worklist, BitSet visitedBlocks, BlocksToDoubles blockProbabilities) { while (!worklist.isEmpty()) { T nextImportantPath = worklist.poll(); - addPathToLinearScanOrder(nextImportantPath, order, worklist, visitedBlocks, nodeProbabilities); + addPathToLinearScanOrder(nextImportantPath, order, worklist, visitedBlocks, blockProbabilities); } } /** * Initializes the priority queue used for the work list of blocks and adds the start block. */ - private static <T extends AbstractBlock<T>> PriorityQueue<T> initializeWorklist(T startBlock, BitSet visitedBlocks, NodesToDoubles nodeProbabilities) { - PriorityQueue<T> result = new PriorityQueue<>(INITIAL_WORKLIST_CAPACITY, new BlockOrderComparator<T>(nodeProbabilities)); + private static <T extends AbstractBlock<T>> PriorityQueue<T> initializeWorklist(T startBlock, BitSet visitedBlocks, BlocksToDoubles blockProbabilities) { + PriorityQueue<T> result = new PriorityQueue<>(INITIAL_WORKLIST_CAPACITY, new BlockOrderComparator<T>(blockProbabilities)); result.add(startBlock); visitedBlocks.set(startBlock.getId()); return result; @@ -123,10 +122,10 @@ /** * Add a linear path to the linear scan order greedily following the most likely successor. */ - private static <T extends AbstractBlock<T>> void addPathToLinearScanOrder(T block, List<T> order, PriorityQueue<T> worklist, BitSet visitedBlocks, NodesToDoubles nodeProbabilities) { + private static <T extends AbstractBlock<T>> void addPathToLinearScanOrder(T block, List<T> order, PriorityQueue<T> worklist, BitSet visitedBlocks, BlocksToDoubles blockProbabilities) { block.setLinearScanNumber(order.size()); order.add(block); - T mostLikelySuccessor = findAndMarkMostLikelySuccessor(block, visitedBlocks, nodeProbabilities); + T mostLikelySuccessor = findAndMarkMostLikelySuccessor(block, visitedBlocks, blockProbabilities); enqueueSuccessors(block, worklist, visitedBlocks); if (mostLikelySuccessor != null) { if (!mostLikelySuccessor.isLoopHeader() && mostLikelySuccessor.getPredecessorCount() > 1) { @@ -135,17 +134,17 @@ double unscheduledSum = 0.0; for (T pred : mostLikelySuccessor.getPredecessors()) { if (pred.getLinearScanNumber() == -1) { - unscheduledSum += nodeProbabilities.get(pred.getBeginNode()); + unscheduledSum += blockProbabilities.get(pred); } } - if (unscheduledSum > nodeProbabilities.get(block.getBeginNode()) / PENALTY_VERSUS_UNSCHEDULED) { + if (unscheduledSum > blockProbabilities.get(block) / PENALTY_VERSUS_UNSCHEDULED) { // Add this merge only after at least one additional predecessor gets scheduled. visitedBlocks.clear(mostLikelySuccessor.getId()); return; } } - addPathToLinearScanOrder(mostLikelySuccessor, order, worklist, visitedBlocks, nodeProbabilities); + addPathToLinearScanOrder(mostLikelySuccessor, order, worklist, visitedBlocks, blockProbabilities); } } @@ -153,7 +152,7 @@ * Add a linear path to the code emission order greedily following the most likely successor. */ @SuppressWarnings("unchecked") - private static <T extends AbstractBlock<T>> void addPathToCodeEmittingOrder(T initialBlock, List<T> order, PriorityQueue<T> worklist, BitSet visitedBlocks, NodesToDoubles nodeProbabilities) { + private static <T extends AbstractBlock<T>> void addPathToCodeEmittingOrder(T initialBlock, List<T> order, PriorityQueue<T> worklist, BitSet visitedBlocks, BlocksToDoubles blockProbabilities) { T block = initialBlock; while (block != null) { // Skip loop headers if there is only a single loop end block to @@ -184,7 +183,7 @@ } } - T mostLikelySuccessor = findAndMarkMostLikelySuccessor(block, visitedBlocks, nodeProbabilities); + T mostLikelySuccessor = findAndMarkMostLikelySuccessor(block, visitedBlocks, blockProbabilities); enqueueSuccessors(block, worklist, visitedBlocks); block = mostLikelySuccessor; } @@ -201,12 +200,11 @@ /** * Find the highest likely unvisited successor block of a given block. */ - private static <T extends AbstractBlock<T>> T findAndMarkMostLikelySuccessor(T block, BitSet visitedBlocks, NodesToDoubles nodeProbabilities) { + private static <T extends AbstractBlock<T>> T findAndMarkMostLikelySuccessor(T block, BitSet visitedBlocks, BlocksToDoubles blockProbabilities) { T result = null; for (T successor : block.getSuccessors()) { - assert nodeProbabilities.get(successor.getBeginNode()) >= 0.0 : "Probabilities must be positive"; - if (!visitedBlocks.get(successor.getId()) && successor.getLoopDepth() >= block.getLoopDepth() && - (result == null || nodeProbabilities.get(successor.getBeginNode()) >= nodeProbabilities.get(result.getBeginNode()))) { + assert blockProbabilities.get(successor) >= 0.0 : "Probabilities must be positive"; + if (!visitedBlocks.get(successor.getId()) && successor.getLoopDepth() >= block.getLoopDepth() && (result == null || blockProbabilities.get(successor) >= blockProbabilities.get(result))) { result = successor; } } @@ -249,9 +247,9 @@ */ private static class BlockOrderComparator<T extends AbstractBlock<T>> implements Comparator<T> { - private final NodesToDoubles probabilities; + private final BlocksToDoubles probabilities; - public BlockOrderComparator(NodesToDoubles probabilities) { + public BlockOrderComparator(BlocksToDoubles probabilities) { this.probabilities = probabilities; } @@ -264,7 +262,7 @@ } // Blocks with high probability before blocks with low probability. - if (probabilities.get(a.getBeginNode()) > probabilities.get(b.getBeginNode())) { + if (probabilities.get(a) > probabilities.get(b)) { return -1; } else { return 1;
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.api.meta/src/com/oracle/graal/api/meta/KindInterface.java Wed Mar 26 20:44:11 2014 +0100 @@ -0,0 +1,7 @@ +package com.oracle.graal.api.meta; + +public interface KindInterface { + + public Kind getKind(); + +}
--- a/graal/com.oracle.graal.api.meta/src/com/oracle/graal/api/meta/Value.java Wed Mar 26 14:43:50 2014 +0100 +++ b/graal/com.oracle.graal.api.meta/src/com/oracle/graal/api/meta/Value.java Wed Mar 26 20:44:11 2014 +0100 @@ -28,7 +28,7 @@ * Abstract base class for values manipulated by the compiler. All values have a {@linkplain Kind * kind} and are immutable. */ -public abstract class Value implements Serializable { +public abstract class Value implements Serializable, KindInterface { private static final long serialVersionUID = -6909397188697766469L;
--- a/graal/com.oracle.graal.baseline/src/com/oracle/graal/baseline/BaselineCompiler.java Wed Mar 26 14:43:50 2014 +0100 +++ b/graal/com.oracle.graal.baseline/src/com/oracle/graal/baseline/BaselineCompiler.java Wed Mar 26 20:44:11 2014 +0100 @@ -23,43 +23,41 @@ package com.oracle.graal.baseline; import static com.oracle.graal.api.code.TypeCheckHints.*; -import static com.oracle.graal.api.meta.DeoptimizationAction.*; -import static com.oracle.graal.api.meta.DeoptimizationReason.*; import static com.oracle.graal.bytecode.Bytecodes.*; import static com.oracle.graal.phases.GraalOptions.*; import static java.lang.reflect.Modifier.*; -import java.lang.reflect.*; import java.util.*; +import com.oracle.graal.alloc.*; import com.oracle.graal.api.code.*; import com.oracle.graal.api.meta.*; -import com.oracle.graal.api.meta.ProfilingInfo.TriState; import com.oracle.graal.api.meta.ResolvedJavaType.Representation; import com.oracle.graal.bytecode.*; +import com.oracle.graal.compiler.*; +import com.oracle.graal.compiler.alloc.*; +import com.oracle.graal.compiler.gen.*; +import com.oracle.graal.compiler.target.*; import com.oracle.graal.debug.*; +import com.oracle.graal.debug.Debug.Scope; import com.oracle.graal.graph.*; import com.oracle.graal.java.*; -import com.oracle.graal.java.BciBlockMapping.Block; +import com.oracle.graal.java.BciBlockMapping.BciBlock; import com.oracle.graal.java.BciBlockMapping.ExceptionDispatchBlock; -import com.oracle.graal.java.GraphBuilderPhase.*; import com.oracle.graal.lir.*; +import com.oracle.graal.lir.asm.*; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.calc.*; import com.oracle.graal.nodes.calc.FloatConvertNode.FloatConvert; -import com.oracle.graal.nodes.extended.*; -import com.oracle.graal.nodes.java.*; +import com.oracle.graal.nodes.cfg.*; import com.oracle.graal.nodes.java.MethodCallTargetNode.InvokeKind; -import com.oracle.graal.nodes.type.*; -import com.oracle.graal.nodes.util.*; -import com.oracle.graal.phases.*; -import com.oracle.graal.phases.tiers.*; +import com.oracle.graal.nodes.java.*; /** * The {@code GraphBuilder} class parses the bytecode of a method and builds the IR graph. */ @SuppressWarnings("all") -public class BaselineCompiler { +public class BaselineCompiler implements BytecodeParser<BciBlock> { public BaselineCompiler(GraphBuilderConfiguration graphBuilderConfig, MetaAccessProvider metaAccess) { this.graphBuilderConfig = graphBuilderConfig; @@ -73,13 +71,19 @@ private ProfilingInfo profilingInfo; private BytecodeStream stream; // the bytecode stream - private Block currentBlock; + private Backend backend; + private LIRGenerator lirGen; + private LIRFrameStateBuilder frameState; + private LIRGenerationResult lirGenRes; + + private BciBlock currentBlock; private ValueNode methodSynchronizedObject; private ExceptionDispatchBlock unwindBlock; private final GraphBuilderConfiguration graphBuilderConfig; - private Block[] loopHeaders; + private BciBlock[] loopHeaders; + private BytecodeParseHelper<Value> parserHelper; /** * Meters the number of actual bytecodes parsed. @@ -90,9 +94,11 @@ return method; } - public LIR generate(ResolvedJavaMethod method, int entryBCI) { + public CompilationResult generate(ResolvedJavaMethod method, int entryBCI, Backend backend, CompilationResult compilationResult, ResolvedJavaMethod installedCodeOwner, + CompilationResultBuilderFactory factory) { this.method = method; this.entryBCI = entryBCI; + this.backend = backend; profilingInfo = method.getProfilingInfo(); assert method.getCode() != null : "method must contain bytecodes: " + method; this.stream = new BytecodeStream(method.getCode()); @@ -100,12 +106,22 @@ unwindBlock = null; methodSynchronizedObject = null; TTY.Filter filter = new TTY.Filter(PrintFilter.getValue(), method); + + frameState = new LIRFrameStateBuilder(method); + parserHelper = new BytecodeParseHelper<>(frameState); + + // build blocks and LIR instructions try { build(); } finally { filter.remove(); } - return null; + + // emitCode + Assumptions assumptions = new Assumptions(OptAssumptions.getValue()); + GraalCompiler.emitCode(backend, assumptions, lirGenRes, compilationResult, installedCodeOwner, factory); + + return compilationResult; } protected void build() { @@ -114,12 +130,19 @@ TTY.println(MetaUtil.indent(MetaUtil.profileToString(profilingInfo, method, CodeUtil.NEW_LINE), " ")); } - Indent indent = Debug.logAndIndent("build graph for %s", method); + // Indent indent = Debug.logAndIndent("build graph for %s", method); // compute the block map, setup exception handlers and get the entrypoint(s) BciBlockMapping blockMap = BciBlockMapping.create(method); loopHeaders = blockMap.loopHeaders; + // add predecessors + for (BciBlock block : blockMap.blocks) { + for (BciBlock successor : block.getSuccessors()) { + successor.getPredecessors().add(block); + } + } + if (isSynchronized(method.getModifiers())) { throw GraalInternalError.unimplemented("Handle synchronized methods"); } @@ -131,11 +154,56 @@ throw GraalInternalError.unimplemented("Handle start block as loop header"); } - for (Block block : blockMap.blocks) { - processBlock(block); + // add loops ? how do we add looks when we haven't parsed the bytecode? + + // create the control flow graph + LIRControlFlowGraph cfg = new LIRControlFlowGraph(blockMap.blocks.toArray(new BciBlock[0]), new Loop[0]); + + BlocksToDoubles blockProbabilities = new BlocksToDoubles(blockMap.blocks.size()); + for (BciBlock b : blockMap.blocks) { + blockProbabilities.put(b, 1); } - indent.outdent(); + // create the LIR + List<? extends AbstractBlock<?>> linearScanOrder = ComputeBlockOrder.computeLinearScanOrder(blockMap.blocks.size(), blockMap.startBlock, blockProbabilities); + List<? extends AbstractBlock<?>> codeEmittingOrder = ComputeBlockOrder.computeCodeEmittingOrder(blockMap.blocks.size(), blockMap.startBlock, blockProbabilities); + LIR lir = new LIR(cfg, linearScanOrder, codeEmittingOrder); + + FrameMap frameMap = backend.newFrameMap(); + TargetDescription target = backend.getTarget(); + CallingConvention cc = CodeUtil.getCallingConvention(backend.getProviders().getCodeCache(), CallingConvention.Type.JavaCallee, method, false); + this.lirGenRes = backend.newLIRGenerationResult(lir, frameMap, null); + this.lirGen = backend.newLIRGenerator(cc, lirGenRes); + + try (Scope ds = Debug.scope("BackEnd", lir)) { + try (Scope s = Debug.scope("LIRGen", lirGen)) { + + // possibly add all the arguments to slots in the local variable array + + for (BciBlock block : blockMap.blocks) { + + // lirGen.doBlock(block, method, this); + } + // indent.outdent(); + + lirGen.beforeRegisterAllocation(); + Debug.dump(lir, "After LIR generation"); + } catch (Throwable e) { + throw Debug.handle(e); + } + + // try (Scope s = Debug.scope("Allocator", nodeLirGen)) { + try (Scope s = Debug.scope("Allocator")) { + + if (backend.shouldAllocateRegisters()) { + new LinearScan(target, lir, frameMap).allocate(); + } + } catch (Throwable e) { + throw Debug.handle(e); + } + } catch (Throwable e) { + throw Debug.handle(e); + } } public BytecodeStream stream() { @@ -147,11 +215,11 @@ } private void loadLocal(int index, Kind kind) { - throw GraalInternalError.unimplemented(); + parserHelper.loadLocal(index, kind); } private void storeLocal(Kind kind, int index) { - throw GraalInternalError.unimplemented(); + parserHelper.storeLocal(kind, index); } /** @@ -250,7 +318,10 @@ } private void genArithmeticOp(Kind result, int opcode) { - throw GraalInternalError.unimplemented(); + Value a = frameState.ipop(); + Value b = frameState.ipop(); + Value r = lirGen.emitAdd(a, b); + frameState.ipush(r); } private void genIntegerDivOp(Kind result, int opcode) { @@ -434,7 +505,7 @@ throw GraalInternalError.unimplemented(); } - private void processBlock(Block block) { + public void processBlock(BciBlock block) { Indent indent = Debug.logAndIndent("Parsing block %s firstInstruction: %s loopHeader: %b", block, block.firstInstruction, block.isLoopHeader); currentBlock = block; iterateBytecodesForBlock(block); @@ -445,7 +516,7 @@ throw GraalInternalError.unimplemented(); } - private void iterateBytecodesForBlock(Block block) { + private void iterateBytecodesForBlock(BciBlock block) { int endBCI = stream.endBCI(); @@ -646,12 +717,12 @@ case RET : genRet(stream.readLocalIndex()); break; case TABLESWITCH : genSwitch(new BytecodeTableSwitch(stream(), bci())); break; case LOOKUPSWITCH : genSwitch(new BytecodeLookupSwitch(stream(), bci())); break; -// case IRETURN : genReturn(frameState.ipop()); break; -// case LRETURN : genReturn(frameState.lpop()); break; -// case FRETURN : genReturn(frameState.fpop()); break; -// case DRETURN : genReturn(frameState.dpop()); break; -// case ARETURN : genReturn(frameState.apop()); break; -// case RETURN : genReturn(null); break; + case IRETURN : genReturn(frameState.ipop()); break; + case LRETURN : genReturn(frameState.lpop()); break; + case FRETURN : genReturn(frameState.fpop()); break; + case DRETURN : genReturn(frameState.dpop()); break; + case ARETURN : genReturn(frameState.apop()); break; + case RETURN : genReturn(null); break; case GETSTATIC : cpi = stream.readCPI(); genGetStatic(lookupField(cpi, opcode)); break; case PUTSTATIC : cpi = stream.readCPI(); genPutStatic(lookupField(cpi, opcode)); break; case GETFIELD : cpi = stream.readCPI(); genGetField(lookupField(cpi, opcode)); break; @@ -700,11 +771,31 @@ if (!currentBlock.jsrScope.isEmpty()) { sb.append(' ').append(currentBlock.jsrScope); } - Debug.log(sb.toString()); + Debug.log("%s", sb); } } private void genArrayLength() { throw GraalInternalError.unimplemented(); } + + private void genReturn(Value x) { + // frameState.setRethrowException(false); + frameState.clearStack(); +// if (graphBuilderConfig.eagerInfopointMode()) { +// append(new InfopointNode(InfopointReason.METHOD_END, frameState.create(bci()))); +// } + +// synchronizedEpilogue(FrameState.AFTER_BCI, x); +// if (frameState.lockDepth() != 0) { +// throw new BailoutException("unbalanced monitors"); +// } + + // lirGen.visitReturn(x); + throw GraalInternalError.unimplemented(); + } + + public void setParameter(int i, Variable emitMove) { + frameState.storeLocal(i, emitMove); + } }
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.baseline/src/com/oracle/graal/baseline/LIRBlock.java Wed Mar 26 20:44:11 2014 +0100 @@ -0,0 +1,62 @@ +/* + * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package com.oracle.graal.baseline; + +import java.util.*; + +import com.oracle.graal.nodes.cfg.*; + +public class LIRBlock extends AbstractBlockBase<LIRBlock> { + + public LIRBlock(int id) { + this.id = id; + predecessors = Collections.emptyList(); + successors = Collections.emptyList(); + } + + public Loop getLoop() { + // TODO Auto-generated method stub + return null; + } + + public int getLoopDepth() { + // TODO Auto-generated method stub + return 0; + } + + public boolean isLoopEnd() { + // TODO Auto-generated method stub + return false; + } + + public boolean isLoopHeader() { + // TODO Auto-generated method stub + return false; + } + + public boolean isExceptionEntry() { + // TODO Auto-generated method stub + return false; + } + +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.baseline/src/com/oracle/graal/baseline/LIRControlFlowGraph.java Wed Mar 26 20:44:11 2014 +0100 @@ -0,0 +1,52 @@ +/* + * Copyright (c) 2014, 2014, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package com.oracle.graal.baseline; + +import com.oracle.graal.java.BciBlockMapping.BciBlock; +import com.oracle.graal.nodes.cfg.*; + +public class LIRControlFlowGraph implements AbstractControlFlowGraph<BciBlock> { + + private BciBlock[] blocks; + private Loop[] loops; + + public LIRControlFlowGraph(BciBlock[] blocks, Loop[] loops) { + this.blocks = blocks; + this.loops = loops; + } + + public BciBlock[] getBlocks() { + return blocks; + } + + public Loop[] getLoops() { + return loops; + } + + public BciBlock getStartBlock() { + if (blocks.length > 0) + return blocks[0]; + return null; + } + +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.baseline/src/com/oracle/graal/baseline/LIRFrameStateBuilder.java Wed Mar 26 20:44:11 2014 +0100 @@ -0,0 +1,226 @@ +package com.oracle.graal.baseline; + +import com.oracle.graal.api.meta.*; +import com.oracle.graal.java.*; + +public class LIRFrameStateBuilder extends AbstractFrameStateBuilder<Value> { + + private final Value[] locals; + private final Value[] stack; + private Value[] lockedObjects; + + public LIRFrameStateBuilder(ResolvedJavaMethod method) { + super(method); + + this.locals = new Value[method.getMaxLocals()]; + // we always need at least one stack slot (for exceptions) + this.stack = new Value[Math.max(1, method.getMaxStackSize())]; + } + + protected LIRFrameStateBuilder(LIRFrameStateBuilder other) { + super(other); + // TODO Auto-generated constructor stub + locals = other.locals; + stack = other.stack; + lockedObjects = other.lockedObjects; + } + + @Override + public int localsSize() { + return locals.length; + } + + @Override + public Value localAt(int i) { + return locals[i]; + } + + @Override + public Value stackAt(int i) { + return stack[i]; + } + + @Override + public Value loadLocal(int i) { + Value x = locals[i]; + assert !isTwoSlot(x.getKind()) || locals[i + 1] == null; + assert i == 0 || locals[i - 1] == null || !isTwoSlot(locals[i - 1].getKind()); + return x; + } + + @Override + public void storeLocal(int i, Value x) { + assert x == null || x.getKind() != Kind.Void && x.getKind() != Kind.Illegal : "unexpected value: " + x; + locals[i] = x; + if (x != null && isTwoSlot(x.getKind())) { + // if this is a double word, then kill i+1 + locals[i + 1] = null; + } + if (x != null && i > 0) { + Value p = locals[i - 1]; + if (p != null && isTwoSlot(p.getKind())) { + // if there was a double word at i - 1, then kill it + locals[i - 1] = null; + } + } + } + + @Override + public void storeStack(int i, Value x) { + assert x == null || (stack[i] == null || x.getKind() == stack[i].getKind()) : "Method does not handle changes from one-slot to two-slot values or non-alive values"; + stack[i] = x; + } + + @Override + public void push(Kind kind, Value x) { + assert x.getKind() != Kind.Void && x.getKind() != Kind.Illegal; + xpush(assertKind(kind, x)); + if (isTwoSlot(kind)) { + xpush(null); + } + } + + @Override + public void xpush(Value x) { + assert x == null || (x.getKind() != Kind.Void && x.getKind() != Kind.Illegal); + stack[stackSize++] = x; + } + + @Override + public void ipush(Value x) { + xpush(assertInt(x)); + } + + @Override + public void fpush(Value x) { + xpush(assertFloat(x)); + } + + @Override + public void apush(Value x) { + xpush(assertObject(x)); + } + + @Override + public void lpush(Value x) { + xpush(assertLong(x)); + } + + @Override + public void dpush(Value x) { + xpush(assertDouble(x)); + + } + + @Override + public void pushReturn(Kind kind, Value x) { + if (kind != Kind.Void) { + push(kind.getStackKind(), x); + } + } + + @Override + public Value pop(Kind kind) { + assert kind != Kind.Void; + if (isTwoSlot(kind)) { + xpop(); + } + return assertKind(kind, xpop()); + } + + @Override + public Value xpop() { + Value result = stack[--stackSize]; + return result; + } + + @Override + public Value ipop() { + return assertInt(xpop()); + } + + @Override + public Value fpop() { + return assertFloat(xpop()); + } + + @Override + public Value apop() { + return assertObject(xpop()); + } + + @Override + public Value lpop() { + assertHigh(xpop()); + return assertLong(xpop()); + } + + @Override + public Value dpop() { + assertHigh(xpop()); + return assertDouble(xpop()); + } + + @Override + public Value[] popArguments(int slotSize, int argSize) { + int base = stackSize - slotSize; + Value[] r = new Value[argSize]; + int argIndex = 0; + int stackindex = 0; + while (stackindex < slotSize) { + Value element = stack[base + stackindex]; + assert element != null; + r[argIndex++] = element; + stackindex += stackSlots(element.getKind()); + } + stackSize = base; + return r; + } + + @Override + public Value peek(int argumentNumber) { + int idx = stackSize() - 1; + for (int i = 0; i < argumentNumber; i++) { + if (stackAt(idx) == null) { + idx--; + assert isTwoSlot(stackAt(idx).getKind()); + } + idx--; + } + return stackAt(idx); + } + + private static Value assertKind(Kind kind, Value x) { + assert x != null && x.getKind() == kind : "kind=" + kind + ", value=" + x + ((x == null) ? "" : ", value.kind=" + x.getKind()); + return x; + } + + private static Value assertLong(Value x) { + assert x != null && (x.getKind() == Kind.Long); + return x; + } + + private static Value assertInt(Value x) { + assert x != null && (x.getKind() == Kind.Int); + return x; + } + + private static Value assertFloat(Value x) { + assert x != null && (x.getKind() == Kind.Float); + return x; + } + + private static Value assertObject(Value x) { + assert x != null && (x.getKind() == Kind.Object); + return x; + } + + private static Value assertDouble(Value x) { + assert x != null && (x.getKind() == Kind.Double); + return x; + } + + private static void assertHigh(Value x) { + assert x == null; + } +}
--- a/graal/com.oracle.graal.compiler.amd64/src/com/oracle/graal/compiler/amd64/AMD64LIRGenerator.java Wed Mar 26 14:43:50 2014 +0100 +++ b/graal/com.oracle.graal.compiler.amd64/src/com/oracle/graal/compiler/amd64/AMD64LIRGenerator.java Wed Mar 26 20:44:11 2014 +0100 @@ -60,9 +60,8 @@ import com.oracle.graal.lir.amd64.AMD64ControlFlow.ReturnOp; import com.oracle.graal.lir.amd64.AMD64ControlFlow.StrategySwitchOp; import com.oracle.graal.lir.amd64.AMD64ControlFlow.TableSwitchOp; -import com.oracle.graal.lir.amd64.AMD64Move.LeaDataOp; import com.oracle.graal.lir.amd64.AMD64Move.LeaOp; -import com.oracle.graal.lir.amd64.AMD64Move.ZeroExtendLoadOp; +import com.oracle.graal.lir.amd64.AMD64Move.LoadOp; import com.oracle.graal.lir.amd64.AMD64Move.MembarOp; import com.oracle.graal.lir.amd64.AMD64Move.MoveFromRegOp; import com.oracle.graal.lir.amd64.AMD64Move.MoveToRegOp; @@ -70,7 +69,6 @@ import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.calc.*; import com.oracle.graal.nodes.calc.FloatConvertNode.FloatConvert; -import com.oracle.graal.nodes.spi.*; import com.oracle.graal.nodes.type.*; import com.oracle.graal.phases.util.*; @@ -93,9 +91,9 @@ } } - public AMD64LIRGenerator(StructuredGraph graph, Providers providers, FrameMap frameMap, CallingConvention cc, LIR lir) { - super(graph, providers, frameMap, cc, lir); - lir.setSpillMoveFactory(new AMD64SpillMoveFactory()); + public AMD64LIRGenerator(Providers providers, CallingConvention cc, LIRGenerationResult lirGenRes) { + super(providers, cc, lirGenRes); + lirGenRes.getLIR().setSpillMoveFactory(new AMD64SpillMoveFactory()); } @Override @@ -159,10 +157,6 @@ append(createMove(dst, src)); } - public void emitData(AllocatableValue dst, byte[] data) { - append(new LeaDataOp(dst, data)); - } - @Override public AMD64AddressValue emitAddress(Value base, long displacement, Value index, int scale) { AllocatableValue baseRegister; @@ -225,7 +219,7 @@ return new AMD64AddressValue(target().wordKind, baseRegister, indexRegister, scaleEnum, displacementInt); } - protected AMD64AddressValue asAddressValue(Value address) { + public AMD64AddressValue asAddressValue(Value address) { if (address instanceof AMD64AddressValue) { return (AMD64AddressValue) address; } else { @@ -266,13 +260,6 @@ } @Override - protected void emitIndirectCall(IndirectCallTargetNode callTarget, Value result, Value[] parameters, Value[] temps, LIRFrameState callState) { - AllocatableValue targetAddress = AMD64.rax.asValue(); - emitMove(targetAddress, operand(callTarget.computedAddress())); - append(new AMD64Call.IndirectCallOp(callTarget.target(), result, parameters, temps, targetAddress, callState)); - } - - @Override public void emitOverflowCheckBranch(LabelRef overflow, LabelRef noOverflow, double overflowProbability) { append(new BranchOp(ConditionFlag.Overflow, overflow, noOverflow, overflowProbability)); } @@ -383,7 +370,7 @@ /** * This method emits the compare instruction, and may reorder the operands. It returns true if * it did so. - * + * * @param a the left operand of the comparison * @param b the right operand of the comparison * @return true if the left and right operands were switched, false otherwise @@ -406,12 +393,6 @@ } @Override - public void emitNullCheck(ValueNode v, DeoptimizingNode deopt) { - assert v.getKind() == Kind.Object : v + " - " + v.stamp() + " @ " + deopt; - append(new AMD64Move.NullCheckOp(load(operand(v)), state(deopt))); - } - - @Override public Variable emitNegate(Value inputVal) { AllocatableValue input = asAllocatable(inputVal); Variable result = newVariable(input.getKind()); @@ -551,44 +532,6 @@ } } - @Override - protected boolean peephole(ValueNode valueNode) { - if ((valueNode instanceof IntegerDivNode) || (valueNode instanceof IntegerRemNode)) { - FixedBinaryNode divRem = (FixedBinaryNode) valueNode; - FixedNode node = divRem.next(); - while (node instanceof FixedWithNextNode) { - FixedWithNextNode fixedWithNextNode = (FixedWithNextNode) node; - if (((fixedWithNextNode instanceof IntegerDivNode) || (fixedWithNextNode instanceof IntegerRemNode)) && fixedWithNextNode.getClass() != divRem.getClass()) { - FixedBinaryNode otherDivRem = (FixedBinaryNode) fixedWithNextNode; - if (otherDivRem.x() == divRem.x() && otherDivRem.y() == divRem.y() && !hasOperand(otherDivRem)) { - Value[] results = emitIntegerDivRem(operand(divRem.x()), operand(divRem.y()), (DeoptimizingNode) valueNode); - if (divRem instanceof IntegerDivNode) { - setResult(divRem, results[0]); - setResult(otherDivRem, results[1]); - } else { - setResult(divRem, results[1]); - setResult(otherDivRem, results[0]); - } - return true; - } - } - node = fixedWithNextNode.next(); - } - } - return false; - } - - protected MemoryArithmeticLIRLowerer memoryPeephole; - - @Override - protected MemoryArithmeticLIRLowerer getMemoryLowerer() { - if (memoryPeephole == null) { - // Use the generic one - memoryPeephole = new AMD64MemoryPeephole(this); - } - return memoryPeephole; - } - protected Value emitBinaryMemory(AMD64Arithmetic op, Kind kind, AllocatableValue a, AMD64AddressValue location, LIRFrameState state) { Variable result = newVariable(a.getKind()); append(new BinaryMemory(op, kind, result, a, location, state)); @@ -602,10 +545,11 @@ } protected Value emitZeroExtendMemory(Kind memoryKind, int resultBits, AMD64AddressValue address, LIRFrameState state) { + assert memoryKind.isUnsigned(); // Issue a zero extending load of the proper bit size and set the result to // the proper kind. Variable result = newVariable(resultBits == 32 ? Kind.Int : Kind.Long); - append(new ZeroExtendLoadOp(memoryKind, result, address, state)); + append(new LoadOp(memoryKind, result, address, state)); return result; } @@ -1036,7 +980,7 @@ } @Override - protected void emitReturn(Value input) { + public void emitReturn(Value input) { append(new ReturnOp(input)); } @@ -1052,19 +996,4 @@ append(new TableSwitchOp(lowKey, defaultTarget, targets, key, newVariable(target().wordKind), newVariable(key.getPlatformKind()))); } - @Override - public void visitBreakpointNode(BreakpointNode node) { - JavaType[] sig = new JavaType[node.arguments().size()]; - for (int i = 0; i < sig.length; i++) { - sig[i] = node.arguments().get(i).stamp().javaType(getMetaAccess()); - } - - Value[] parameters = visitInvokeArguments(frameMap.registerConfig.getCallingConvention(CallingConvention.Type.JavaCall, null, sig, target(), false), node.arguments()); - append(new AMD64BreakpointOp(parameters)); - } - - @Override - public void visitInfopointNode(InfopointNode i) { - append(new InfopointOp(stateFor(i.getState()), i.reason)); - } }
--- a/graal/com.oracle.graal.compiler.amd64/src/com/oracle/graal/compiler/amd64/AMD64MemoryPeephole.java Wed Mar 26 14:43:50 2014 +0100 +++ b/graal/com.oracle.graal.compiler.amd64/src/com/oracle/graal/compiler/amd64/AMD64MemoryPeephole.java Wed Mar 26 20:44:11 2014 +0100 @@ -45,10 +45,10 @@ import com.oracle.graal.nodes.type.*; public class AMD64MemoryPeephole implements MemoryArithmeticLIRLowerer { - protected final AMD64LIRGenerator gen; + protected final AMD64NodeLIRGenerator gen; protected List<ValueNode> deferredNodes; - protected AMD64MemoryPeephole(AMD64LIRGenerator gen) { + protected AMD64MemoryPeephole(AMD64NodeLIRGenerator gen) { this.gen = gen; } @@ -90,7 +90,7 @@ } } ensureEvaluated(other); - return gen.emitBinaryMemory(op, access.nullCheckLocation().getValueKind(), gen.asAllocatable(gen.operand(other)), makeAddress(access), getState(access)); + return gen.getLIRGenerator().emitBinaryMemory(op, access.nullCheckLocation().getValueKind(), gen.getLIRGeneratorTool().asAllocatable(gen.operand(other)), makeAddress(access), getState(access)); } /** @@ -124,7 +124,7 @@ AMD64AddressValue address = makeAddress(access); LIRFrameState state = getState(access); evaluateDeferred(); - return gen.emitConvert2MemoryOp(kind, op, address, state); + return gen.getLIRGenerator().emitConvert2MemoryOp(kind, op, address, state); } @Override @@ -248,7 +248,7 @@ @Override public Value emitReinterpretMemory(Stamp stamp, Access access) { - PlatformKind to = gen.getPlatformKind(stamp); + PlatformKind to = gen.getLIRGenerator().getPlatformKind(stamp); Kind from = access.nullCheckLocation().getValueKind(); assert to != from : "should have been eliminated"; @@ -366,7 +366,7 @@ memoryKind = Kind.Char; } evaluateDeferred(); - return gen.emitZeroExtendMemory(memoryKind, resultBits, makeAddress(access), getState(access)); + return gen.getLIRGenerator().emitZeroExtendMemory(memoryKind, resultBits, makeAddress(access), getState(access)); } public boolean emitIfMemory(IfNode x, Access access) { @@ -446,7 +446,7 @@ return false; } ensureEvaluated(other); - gen.emitCompareMemoryConOp(kind, makeAddress(access), constant, getState(access)); + gen.getLIRGenerator().emitCompareMemoryConOp(kind, makeAddress(access), constant, getState(access)); mirrored = right == access; } else { if (kind != kind.getStackKind()) { @@ -460,7 +460,7 @@ } evaluateDeferred(); - gen.emitCompareRegMemoryOp(kind, gen.operand(other), makeAddress(access), getState(access)); + gen.getLIRGenerator().emitCompareRegMemoryOp(kind, gen.operand(other), makeAddress(access), getState(access)); mirrored = left == access; }
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.compiler.amd64/src/com/oracle/graal/compiler/amd64/AMD64NodeLIRGenerator.java Wed Mar 26 20:44:11 2014 +0100 @@ -0,0 +1,113 @@ +/* + * Copyright (c) 2009, 2012, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package com.oracle.graal.compiler.amd64; + +import com.oracle.graal.amd64.*; +import com.oracle.graal.api.code.*; +import com.oracle.graal.api.meta.*; +import com.oracle.graal.compiler.gen.*; +import com.oracle.graal.lir.*; +import com.oracle.graal.lir.amd64.*; +import com.oracle.graal.nodes.*; +import com.oracle.graal.nodes.calc.*; +import com.oracle.graal.nodes.spi.*; + +public abstract class AMD64NodeLIRGenerator extends NodeLIRGenerator { + + public AMD64NodeLIRGenerator(StructuredGraph graph, LIRGenerationResult res, LIRGenerator gen) { + super(graph, res, gen); + } + + protected MemoryArithmeticLIRLowerer memoryPeephole; + + @Override + public MemoryArithmeticLIRLowerer getMemoryLowerer() { + if (memoryPeephole == null) { + // Use the generic one + memoryPeephole = new AMD64MemoryPeephole(this); + } + return memoryPeephole; + } + + @Override + protected void emitIndirectCall(IndirectCallTargetNode callTarget, Value result, Value[] parameters, Value[] temps, LIRFrameState callState) { + AllocatableValue targetAddress = AMD64.rax.asValue(); + gen.emitMove(targetAddress, operand(callTarget.computedAddress())); + append(new AMD64Call.IndirectCallOp(callTarget.target(), result, parameters, temps, targetAddress, callState)); + } + + @Override + public void emitNullCheck(ValueNode v, DeoptimizingNode deopt) { + assert v.getKind() == Kind.Object : v + " - " + v.stamp() + " @ " + deopt; + append(new AMD64Move.NullCheckOp(gen.load(operand(v)), state(deopt))); + } + + @Override + protected boolean peephole(ValueNode valueNode) { + if ((valueNode instanceof IntegerDivNode) || (valueNode instanceof IntegerRemNode)) { + FixedBinaryNode divRem = (FixedBinaryNode) valueNode; + FixedNode node = divRem.next(); + while (node instanceof FixedWithNextNode) { + FixedWithNextNode fixedWithNextNode = (FixedWithNextNode) node; + if (((fixedWithNextNode instanceof IntegerDivNode) || (fixedWithNextNode instanceof IntegerRemNode)) && fixedWithNextNode.getClass() != divRem.getClass()) { + FixedBinaryNode otherDivRem = (FixedBinaryNode) fixedWithNextNode; + if (otherDivRem.x() == divRem.x() && otherDivRem.y() == divRem.y() && operand(otherDivRem) == null) { + Value[] results = ((AMD64LIRGenerator) gen).emitIntegerDivRem(operand(divRem.x()), operand(divRem.y()), (DeoptimizingNode) valueNode); + if (divRem instanceof IntegerDivNode) { + setResult(divRem, results[0]); + setResult(otherDivRem, results[1]); + } else { + setResult(divRem, results[1]); + setResult(otherDivRem, results[0]); + } + return true; + } + } + node = fixedWithNextNode.next(); + } + } + return false; + } + + @Override + public void visitBreakpointNode(BreakpointNode node) { + JavaType[] sig = new JavaType[node.arguments().size()]; + for (int i = 0; i < sig.length; i++) { + sig[i] = node.arguments().get(i).stamp().javaType(gen.getMetaAccess()); + } + + Value[] parameters = visitInvokeArguments(res.getFrameMap().registerConfig.getCallingConvention(CallingConvention.Type.JavaCall, null, sig, gen.target(), false), node.arguments()); + append(new AMD64BreakpointOp(parameters)); + } + + @Override + public void visitInfopointNode(InfopointNode i) { + append(new InfopointOp(stateFor(i.getState()), i.reason)); + } + + @Override + public AMD64LIRGenerator getLIRGenerator() { + return (AMD64LIRGenerator) gen; + } +}
--- a/graal/com.oracle.graal.compiler.hsail/src/com/oracle/graal/compiler/hsail/HSAILLIRGenerator.java Wed Mar 26 14:43:50 2014 +0100 +++ b/graal/com.oracle.graal.compiler.hsail/src/com/oracle/graal/compiler/hsail/HSAILLIRGenerator.java Wed Mar 26 20:44:11 2014 +0100 @@ -32,7 +32,6 @@ import com.oracle.graal.api.meta.*; import com.oracle.graal.asm.*; import com.oracle.graal.compiler.gen.*; -import com.oracle.graal.debug.*; import com.oracle.graal.graph.*; import com.oracle.graal.lir.*; import com.oracle.graal.lir.StandardOp.JumpOp; @@ -54,7 +53,6 @@ import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.calc.*; import com.oracle.graal.nodes.calc.FloatConvertNode.FloatConvert; -import com.oracle.graal.nodes.type.*; import com.oracle.graal.phases.util.*; /** @@ -76,9 +74,9 @@ } } - public HSAILLIRGenerator(StructuredGraph graph, Providers providers, FrameMap frameMap, CallingConvention cc, LIR lir) { - super(graph, providers, frameMap, cc, lir); - lir.setSpillMoveFactory(new HSAILSpillMoveFactory()); + public HSAILLIRGenerator(Providers providers, CallingConvention cc, LIRGenerationResult lirGenRes) { + super(providers, cc, lirGenRes); + lirGenRes.getLIR().setSpillMoveFactory(new HSAILSpillMoveFactory()); } @Override @@ -119,7 +117,7 @@ throw GraalInternalError.unimplemented(); } - protected HSAILAddressValue asAddressValue(Value address) { + public HSAILAddressValue asAddressValue(Value address) { if (address instanceof HSAILAddressValue) { return (HSAILAddressValue) address; } else { @@ -177,7 +175,7 @@ append(new JumpOp(label)); } - protected static HSAILCompare mapKindToCompareOp(Kind kind) { + public static HSAILCompare mapKindToCompareOp(Kind kind) { switch (kind) { case Int: return ICMP; @@ -416,12 +414,6 @@ } @Override - protected boolean peephole(ValueNode valueNode) { - // No peephole optimizations for now. - return false; - } - - @Override public Value emitDiv(Value a, Value b, DeoptimizingNode deopting) { Variable result = newVariable(a.getKind()); switch (a.getKind()) { @@ -701,16 +693,6 @@ } @Override - protected void emitDirectCall(DirectCallTargetNode callTarget, Value result, Value[] parameters, Value[] temps, LIRFrameState callState) { - throw GraalInternalError.unimplemented(); - } - - @Override - protected void emitIndirectCall(IndirectCallTargetNode callTarget, Value result, Value[] parameters, Value[] temps, LIRFrameState callState) { - throw GraalInternalError.unimplemented(); - } - - @Override public void emitBitCount(Variable result, Value value) { if (value.getKind().getStackKind() == Kind.Int) { append(new HSAILBitManipulationOp(IPOPCNT, result, value)); @@ -823,7 +805,7 @@ } @Override - protected void emitReturn(Value input) { + public void emitReturn(Value input) { append(new ReturnOp(input)); } @@ -883,30 +865,8 @@ } @Override - public void visitBreakpointNode(BreakpointNode node) { - throw GraalInternalError.unimplemented(); - } - - @Override - public void visitSafepointNode(SafepointNode i) { - Debug.log("visitSafePointNode unimplemented"); - } - - @Override public void emitUnwind(Value operand) { throw GraalInternalError.unimplemented(); } - @Override - public void emitNullCheck(ValueNode v, DeoptimizingNode deopting) { - assert v.stamp() instanceof ObjectStamp; - Variable obj = newVariable(Kind.Object); - emitMove(obj, operand(v)); - append(new HSAILMove.NullCheckOp(obj, state(deopting))); - } - - @Override - public void visitInfopointNode(InfopointNode i) { - throw GraalInternalError.unimplemented(); - } }
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.compiler.hsail/src/com/oracle/graal/compiler/hsail/HSAILNodeLIRGenerator.java Wed Mar 26 20:44:11 2014 +0100 @@ -0,0 +1,82 @@ +/* + * Copyright (c) 2013, 2014, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package com.oracle.graal.compiler.hsail; + +import com.oracle.graal.api.meta.*; +import com.oracle.graal.compiler.gen.*; +import com.oracle.graal.debug.*; +import com.oracle.graal.graph.*; +import com.oracle.graal.lir.*; +import com.oracle.graal.lir.hsail.*; +import com.oracle.graal.nodes.*; +import com.oracle.graal.nodes.type.*; + +/** + * This class implements the HSAIL specific portion of the LIR generator. + */ +public abstract class HSAILNodeLIRGenerator extends NodeLIRGenerator { + + public HSAILNodeLIRGenerator(StructuredGraph graph, LIRGenerationResult lirGenRes, LIRGenerator lirGen) { + super(graph, lirGenRes, lirGen); + } + + @Override + protected boolean peephole(ValueNode valueNode) { + // No peephole optimizations for now. + return false; + } + + @Override + protected void emitDirectCall(DirectCallTargetNode callTarget, Value result, Value[] parameters, Value[] temps, LIRFrameState callState) { + throw GraalInternalError.unimplemented(); + } + + @Override + protected void emitIndirectCall(IndirectCallTargetNode callTarget, Value result, Value[] parameters, Value[] temps, LIRFrameState callState) { + throw GraalInternalError.unimplemented(); + } + + @Override + public void visitBreakpointNode(BreakpointNode node) { + throw GraalInternalError.unimplemented(); + } + + @Override + public void visitSafepointNode(SafepointNode i) { + Debug.log("visitSafePointNode unimplemented"); + } + + @Override + public void emitNullCheck(ValueNode v, DeoptimizingNode deopting) { + assert v.stamp() instanceof ObjectStamp; + Variable obj = newVariable(Kind.Object); + gen.emitMove(obj, operand(v)); + append(new HSAILMove.NullCheckOp(obj, state(deopting))); + } + + @Override + public void visitInfopointNode(InfopointNode i) { + throw GraalInternalError.unimplemented(); + } +}
--- a/graal/com.oracle.graal.compiler.ptx/src/com/oracle/graal/compiler/ptx/PTXLIRGenerator.java Wed Mar 26 14:43:50 2014 +0100 +++ b/graal/com.oracle.graal.compiler.ptx/src/com/oracle/graal/compiler/ptx/PTXLIRGenerator.java Wed Mar 26 20:44:11 2014 +0100 @@ -29,13 +29,10 @@ import static com.oracle.graal.lir.ptx.PTXBitManipulationOp.IntrinsicOpcode.*; import static com.oracle.graal.lir.ptx.PTXCompare.*; -import java.lang.reflect.*; - import com.oracle.graal.api.code.*; import com.oracle.graal.api.meta.*; import com.oracle.graal.asm.*; import com.oracle.graal.compiler.gen.*; -import com.oracle.graal.debug.*; import com.oracle.graal.graph.*; import com.oracle.graal.lir.*; import com.oracle.graal.lir.StandardOp.JumpOp; @@ -64,7 +61,6 @@ import com.oracle.graal.nodes.calc.*; import com.oracle.graal.nodes.calc.FloatConvertNode.FloatConvert; import com.oracle.graal.nodes.extended.*; -import com.oracle.graal.nodes.java.*; import com.oracle.graal.nodes.type.*; import com.oracle.graal.phases.util.*; @@ -89,11 +85,11 @@ } } - public PTXLIRGenerator(StructuredGraph graph, Providers providers, FrameMap frameMap, CallingConvention cc, LIR lir) { - super(graph, providers, frameMap, cc, lir); - lir.setSpillMoveFactory(new PTXSpillMoveFactory()); + public PTXLIRGenerator(Providers providers, CallingConvention cc, LIRGenerationResult lirGenRes) { + super(providers, cc, lirGenRes); + lirGenRes.getLIR().setSpillMoveFactory(new PTXSpillMoveFactory()); int callVariables = cc.getArgumentCount() + (cc.getReturn().equals(Value.ILLEGAL) ? 0 : 1); - lir.setFirstVariableNumber(callVariables); + lirGenRes.getLIR().setFirstVariableNumber(callVariables); nextPredRegNum = 0; } @@ -134,43 +130,6 @@ return value; } - @Override - public void emitPrologue(StructuredGraph graph) { - // Need to emit .param directives based on incoming arguments and return value - CallingConvention incomingArguments = cc; - Object returnObject = incomingArguments.getReturn(); - AllocatableValue[] params = incomingArguments.getArguments(); - int argCount = incomingArguments.getArgumentCount(); - - if (returnObject.equals(Value.ILLEGAL)) { - params = incomingArguments.getArguments(); - append(new PTXParameterOp(params, false)); - } else { - argCount = incomingArguments.getArgumentCount(); - params = new Variable[argCount + 1]; - for (int i = 0; i < argCount; i++) { - params[i] = incomingArguments.getArgument(i); - } - params[argCount] = (Variable) returnObject; - append(new PTXParameterOp(params, true)); - } - - for (ParameterNode param : graph.getNodes(ParameterNode.class)) { - int localIndex = param.index(); - Value paramValue = params[param.index()]; - int parameterIndex = localIndex; - if (!Modifier.isStatic(graph.method().getModifiers())) { - parameterIndex--; - } - Warp warpAnnotation = parameterIndex >= 0 ? MetaUtil.getParameterAnnotation(Warp.class, parameterIndex, graph.method()) : null; - if (warpAnnotation != null) { - setResult(param, emitWarpParam(paramValue.getKind().getStackKind(), warpAnnotation)); - } else { - setResult(param, emitLoadParam(paramValue.getKind().getStackKind(), paramValue, null)); - } - } - } - public Variable emitWarpParam(Kind kind, Warp annotation) { Variable result = newVariable(kind); Variable tid = newVariable(Kind.Char); @@ -538,12 +497,6 @@ } @Override - protected boolean peephole(ValueNode valueNode) { - // No peephole optimizations for now - return false; - } - - @Override public Value emitDiv(Value a, Value b, DeoptimizingNode deopting) { Variable result = newVariable(a.getKind()); switch (a.getKind()) { @@ -810,16 +763,6 @@ } @Override - protected void emitDirectCall(DirectCallTargetNode callTarget, Value result, Value[] parameters, Value[] temps, LIRFrameState callState) { - throw GraalInternalError.unimplemented("PTXLIRGenerator.emitDirectCall()"); - } - - @Override - protected void emitIndirectCall(IndirectCallTargetNode callTarget, Value result, Value[] parameters, Value[] temps, LIRFrameState callState) { - throw GraalInternalError.unimplemented("PTXLIRGenerator.emitIndirectCall()"); - } - - @Override protected void emitForeignCall(ForeignCallLinkage callTarget, Value result, Value[] arguments, Value[] temps, LIRFrameState info) { throw GraalInternalError.unimplemented("PTXLIRGenerator.emitForeignCall()"); } @@ -885,11 +828,11 @@ } @Override - protected void emitReturn(Value input) { + public void emitReturn(Value input) { append(new ReturnOp(input)); } - private void emitReturnNoVal() { + void emitReturnNoVal() { append(new ReturnNoValOp()); } @@ -908,38 +851,10 @@ } @Override - public void visitCompareAndSwap(LoweredCompareAndSwapNode node, Value address) { - throw GraalInternalError.unimplemented("PTXLIRGenerator.visitCompareAndSwap()"); - } - - @Override - public void visitBreakpointNode(BreakpointNode node) { - throw GraalInternalError.unimplemented("PTXLIRGenerator.visitBreakpointNode()"); - } - - @Override - public void visitSafepointNode(SafepointNode i) { - // LIRFrameState info = state(i); - // append(new PTXSafepointOp(info, runtime().config, this)); - Debug.log("visitSafePointNode unimplemented"); - } - - @Override public void emitUnwind(Value operand) { throw GraalInternalError.unimplemented("PTXLIRGenerator.emitUnwind()"); } - @Override - public void emitNullCheck(ValueNode v, DeoptimizingNode deopting) { - assert v.getKind() == Kind.Object; - append(new PTXMove.NullCheckOp(load(operand(v)), state(deopting))); - } - - @Override - public void visitInfopointNode(InfopointNode i) { - throw GraalInternalError.unimplemented("PTXLIRGenerator.visitInfopointNode()"); - } - public Variable emitLoadParam(Kind kind, Value address, DeoptimizingNode deopting) { PTXAddressValue loadAddress = asAddress(address); @@ -984,16 +899,4 @@ return (new Variable(kind, 0)); } - @Override - public void visitReturn(ReturnNode x) { - AllocatableValue operand = Value.ILLEGAL; - if (x.result() != null) { - operand = resultOperandFor(x.result().getKind()); - // Load the global memory address from return parameter - Variable loadVar = emitLoadReturnAddress(operand.getKind(), operand, null); - // Store result in global memory whose location is loadVar - emitStoreReturnValue(operand.getKind(), loadVar, operand(x.result()), null); - } - emitReturnNoVal(); - } }
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.compiler.ptx/src/com/oracle/graal/compiler/ptx/PTXNodeLIRGenerator.java Wed Mar 26 20:44:11 2014 +0100 @@ -0,0 +1,208 @@ +/* + * Copyright (c) 2013, 2014, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package com.oracle.graal.compiler.ptx; + +import java.lang.reflect.*; + +import com.oracle.graal.api.code.*; +import com.oracle.graal.api.meta.*; +import com.oracle.graal.compiler.gen.*; +import com.oracle.graal.debug.*; +import com.oracle.graal.graph.*; +import com.oracle.graal.lir.*; +import com.oracle.graal.lir.ptx.*; +import com.oracle.graal.nodes.*; +import com.oracle.graal.nodes.cfg.*; +import com.oracle.graal.nodes.java.*; + +/** + * This class implements the PTX specific portion of the LIR generator. + */ +public class PTXNodeLIRGenerator extends NodeLIRGenerator { + + // Number of the predicate register that can be used when needed. + // This value will be recorded and incremented in the LIR instruction + // that sets a predicate register. (e.g., CompareOp) + private int nextPredRegNum; + + public static final ForeignCallDescriptor ARITHMETIC_FREM = new ForeignCallDescriptor("arithmeticFrem", float.class, float.class, float.class); + public static final ForeignCallDescriptor ARITHMETIC_DREM = new ForeignCallDescriptor("arithmeticDrem", double.class, double.class, double.class); + + public static class PTXSpillMoveFactory implements LIR.SpillMoveFactory { + + @Override + public LIRInstruction createMove(AllocatableValue result, Value input) { + throw GraalInternalError.unimplemented("PTXSpillMoveFactory.createMove()"); + } + } + + public PTXNodeLIRGenerator(StructuredGraph graph, LIRGenerationResult lirGenRes, LIRGenerator lirGen) { + super(graph, lirGenRes, lirGen); + } + + public int getNextPredRegNumber() { + return nextPredRegNum; + } + + @Override + public void emitPrologue(StructuredGraph graph) { + // Need to emit .param directives based on incoming arguments and return value + CallingConvention incomingArguments = gen.getCallingConvention(); + Object returnObject = incomingArguments.getReturn(); + AllocatableValue[] params = incomingArguments.getArguments(); + int argCount = incomingArguments.getArgumentCount(); + + if (returnObject.equals(Value.ILLEGAL)) { + params = incomingArguments.getArguments(); + append(new PTXParameterOp(params, false)); + } else { + argCount = incomingArguments.getArgumentCount(); + params = new Variable[argCount + 1]; + for (int i = 0; i < argCount; i++) { + params[i] = incomingArguments.getArgument(i); + } + params[argCount] = (Variable) returnObject; + append(new PTXParameterOp(params, true)); + } + + for (ParameterNode param : graph.getNodes(ParameterNode.class)) { + int localIndex = param.index(); + Value paramValue = params[param.index()]; + int parameterIndex = localIndex; + if (!Modifier.isStatic(graph.method().getModifiers())) { + parameterIndex--; + } + Warp warpAnnotation = parameterIndex >= 0 ? MetaUtil.getParameterAnnotation(Warp.class, parameterIndex, graph.method()) : null; + if (warpAnnotation != null) { + setResult(param, getGen().emitWarpParam(paramValue.getKind().getStackKind(), warpAnnotation)); + } else { + setResult(param, getGen().emitLoadParam(paramValue.getKind().getStackKind(), paramValue, null)); + } + } + } + + private PTXLIRGenerator getGen() { + return (PTXLIRGenerator) gen; + } + + @Override + protected <T extends AbstractBlock<T>> void emitPrologue(ResolvedJavaMethod method, BytecodeParser<T> parser) { + // Need to emit .param directives based on incoming arguments and return value + CallingConvention incomingArguments = gen.getCallingConvention(); + Object returnObject = incomingArguments.getReturn(); + AllocatableValue[] params = incomingArguments.getArguments(); + int argCount = incomingArguments.getArgumentCount(); + + if (returnObject.equals(Value.ILLEGAL)) { + params = incomingArguments.getArguments(); + append(new PTXParameterOp(params, false)); + } else { + argCount = incomingArguments.getArgumentCount(); + params = new Variable[argCount + 1]; + for (int i = 0; i < argCount; i++) { + params[i] = incomingArguments.getArgument(i); + } + params[argCount] = (Variable) returnObject; + append(new PTXParameterOp(params, true)); + } + + Signature sig = method.getSignature(); + boolean isStatic = Modifier.isStatic(method.getModifiers()); + + for (int i = 0; i < sig.getParameterCount(!isStatic); i++) { + Value paramValue = params[i]; + int parameterIndex = i; + if (!isStatic) { + parameterIndex--; + } + Warp warpAnnotation = parameterIndex >= 0 ? MetaUtil.getParameterAnnotation(Warp.class, parameterIndex, method) : null; + if (warpAnnotation != null) { + // setResult(param, emitWarpParam(paramValue.getKind().getStackKind(), + // warpAnnotation)); + parser.setParameter(i, getGen().emitWarpParam(paramValue.getKind().getStackKind(), warpAnnotation)); + } else { + // setResult(param, emitLoadParam(paramValue.getKind().getStackKind(), paramValue, + // null)); + parser.setParameter(i, getGen().emitLoadParam(paramValue.getKind().getStackKind(), paramValue, null)); + } + } + } + + @Override + protected boolean peephole(ValueNode valueNode) { + // No peephole optimizations for now + return false; + } + + @Override + protected void emitDirectCall(DirectCallTargetNode callTarget, Value result, Value[] parameters, Value[] temps, LIRFrameState callState) { + throw GraalInternalError.unimplemented("PTXLIRGenerator.emitDirectCall()"); + } + + @Override + protected void emitIndirectCall(IndirectCallTargetNode callTarget, Value result, Value[] parameters, Value[] temps, LIRFrameState callState) { + throw GraalInternalError.unimplemented("PTXLIRGenerator.emitIndirectCall()"); + } + + @Override + public void visitCompareAndSwap(LoweredCompareAndSwapNode node, Value address) { + throw GraalInternalError.unimplemented("PTXLIRGenerator.visitCompareAndSwap()"); + } + + @Override + public void visitBreakpointNode(BreakpointNode node) { + throw GraalInternalError.unimplemented("PTXLIRGenerator.visitBreakpointNode()"); + } + + @Override + public void visitSafepointNode(SafepointNode i) { + // LIRFrameState info = state(i); + // append(new PTXSafepointOp(info, runtime().config, this)); + Debug.log("visitSafePointNode unimplemented"); + } + + @Override + public void emitNullCheck(ValueNode v, DeoptimizingNode deopting) { + assert v.getKind() == Kind.Object; + append(new PTXMove.NullCheckOp(gen.load(operand(v)), state(deopting))); + } + + @Override + public void visitInfopointNode(InfopointNode i) { + throw GraalInternalError.unimplemented("PTXLIRGenerator.visitInfopointNode()"); + } + + @Override + public void visitReturn(ReturnNode x) { + AllocatableValue operand = Value.ILLEGAL; + if (x.result() != null) { + operand = gen.resultOperandFor(x.result().getKind()); + // Load the global memory address from return parameter + Variable loadVar = getGen().emitLoadReturnAddress(operand.getKind(), operand, null); + // Store result in global memory whose location is loadVar + getGen().emitStoreReturnValue(operand.getKind(), loadVar, operand(x.result()), null); + } + getGen().emitReturnNoVal(); + } +}
--- a/graal/com.oracle.graal.compiler.sparc/src/com/oracle/graal/compiler/sparc/SPARCLIRGenerator.java Wed Mar 26 14:43:50 2014 +0100 +++ b/graal/com.oracle.graal.compiler.sparc/src/com/oracle/graal/compiler/sparc/SPARCLIRGenerator.java Wed Mar 26 20:44:11 2014 +0100 @@ -56,12 +56,10 @@ import com.oracle.graal.lir.sparc.SPARCMove.MembarOp; import com.oracle.graal.lir.sparc.SPARCMove.MoveFromRegOp; import com.oracle.graal.lir.sparc.SPARCMove.MoveToRegOp; -import com.oracle.graal.lir.sparc.SPARCMove.NullCheckOp; import com.oracle.graal.lir.sparc.SPARCMove.StackLoadAddressOp; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.calc.*; import com.oracle.graal.nodes.calc.FloatConvertNode.FloatConvert; -import com.oracle.graal.nodes.java.*; import com.oracle.graal.nodes.type.*; import com.oracle.graal.phases.util.*; @@ -78,9 +76,9 @@ } } - public SPARCLIRGenerator(StructuredGraph graph, Providers providers, FrameMap frameMap, CallingConvention cc, LIR lir) { - super(graph, providers, frameMap, cc, lir); - lir.setSpillMoveFactory(new SPARCSpillMoveFactory()); + public SPARCLIRGenerator(Providers providers, CallingConvention cc, LIRGenerationResult lirGenRes) { + super(providers, cc, lirGenRes); + lirGenRes.getLIR().setSpillMoveFactory(new SPARCSpillMoveFactory()); } @Override @@ -220,13 +218,7 @@ } @Override - protected boolean peephole(ValueNode valueNode) { - // No peephole optimizations for now - return false; - } - - @Override - protected void emitReturn(Value input) { + public void emitReturn(Value input) { append(new ReturnOp(input)); } @@ -923,35 +915,4 @@ append(new ReturnOp(Value.ILLEGAL)); } - @Override - public void visitCompareAndSwap(LoweredCompareAndSwapNode i, Value address) { - throw new InternalError("NYI"); - } - - @Override - public void visitBreakpointNode(BreakpointNode node) { - JavaType[] sig = new JavaType[node.arguments().size()]; - for (int i = 0; i < sig.length; i++) { - sig[i] = node.arguments().get(i).stamp().javaType(getMetaAccess()); - } - - Value[] parameters = visitInvokeArguments(frameMap.registerConfig.getCallingConvention(CallingConvention.Type.JavaCall, null, sig, target(), false), node.arguments()); - append(new SPARCBreakpointOp(parameters)); - } - - @Override - public void emitUnwind(Value operand) { - throw new InternalError("NYI"); - } - - @Override - public void emitNullCheck(ValueNode v, DeoptimizingNode deopting) { - assert v.getKind() == Kind.Object; - append(new NullCheckOp(load(operand(v)), state(deopting))); - } - - @Override - public void visitInfopointNode(InfopointNode i) { - throw new InternalError("NYI"); - } }
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.compiler.sparc/src/com/oracle/graal/compiler/sparc/SPARCNodeLIRGenerator.java Wed Mar 26 20:44:11 2014 +0100 @@ -0,0 +1,75 @@ +/* + * Copyright (c) 2009, 2014, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package com.oracle.graal.compiler.sparc; + +import com.oracle.graal.api.code.*; +import com.oracle.graal.api.meta.*; +import com.oracle.graal.compiler.gen.*; +import com.oracle.graal.lir.sparc.*; +import com.oracle.graal.lir.sparc.SPARCMove.NullCheckOp; +import com.oracle.graal.nodes.*; +import com.oracle.graal.nodes.java.*; + +/** + * This class implements the SPARC specific portion of the LIR generator. + */ +public abstract class SPARCNodeLIRGenerator extends NodeLIRGenerator { + + public SPARCNodeLIRGenerator(StructuredGraph graph, LIRGenerationResult lirGenRes, LIRGenerator lirGen) { + super(graph, lirGenRes, lirGen); + } + + @Override + protected boolean peephole(ValueNode valueNode) { + // No peephole optimizations for now + return false; + } + + @Override + public void visitCompareAndSwap(LoweredCompareAndSwapNode i, Value address) { + throw new InternalError("NYI"); + } + + @Override + public void visitBreakpointNode(BreakpointNode node) { + JavaType[] sig = new JavaType[node.arguments().size()]; + for (int i = 0; i < sig.length; i++) { + sig[i] = node.arguments().get(i).stamp().javaType(gen.getMetaAccess()); + } + + Value[] parameters = visitInvokeArguments(res.getFrameMap().registerConfig.getCallingConvention(CallingConvention.Type.JavaCall, null, sig, gen.target(), false), node.arguments()); + append(new SPARCBreakpointOp(parameters)); + } + + @Override + public void emitNullCheck(ValueNode v, DeoptimizingNode deopting) { + assert v.getKind() == Kind.Object; + append(new NullCheckOp(gen.load(operand(v)), state(deopting))); + } + + @Override + public void visitInfopointNode(InfopointNode i) { + throw new InternalError("NYI"); + } +}
--- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/GraalCompilerTest.java Wed Mar 26 14:43:50 2014 +0100 +++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/GraalCompilerTest.java Wed Mar 26 20:44:11 2014 +0100 @@ -498,10 +498,9 @@ } private CompilationResult compileBaseline(ResolvedJavaMethod javaMethod) { - try (Scope bds = Debug.scope("CompileBaseline")) { + try (Scope bds = Debug.scope("CompileBaseline", javaMethod, providers.getCodeCache())) { BaselineCompiler baselineCompiler = new BaselineCompiler(GraphBuilderConfiguration.getDefault(), providers.getMetaAccess()); - baselineCompiler.generate(javaMethod, -1); - return null; + return baselineCompiler.generate(javaMethod, -1, getBackend(), new CompilationResult(), javaMethod, CompilationResultBuilderFactory.Default); } catch (Throwable e) { throw Debug.handle(e); }
--- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/backend/AllocatorTest.java Wed Mar 26 14:43:50 2014 +0100 +++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/backend/AllocatorTest.java Wed Mar 26 20:44:11 2014 +0100 @@ -73,8 +73,8 @@ public RegisterStats(LIR lir) { this.lir = lir; - for (Block block : lir.codeEmittingOrder()) { - for (LIRInstruction instr : lir.lir(block)) { + for (AbstractBlock<?> block : lir.codeEmittingOrder()) { + for (LIRInstruction instr : lir.getLIRforBlock(block)) { collectStats(instr); } } @@ -120,7 +120,7 @@ } CallingConvention cc = getCallingConvention(getCodeCache(), Type.JavaCallee, graph.method(), false); - LIRGenerator lirGen = GraalCompiler.emitLIR(getBackend(), getBackend().getTarget(), schedule, graph, null, cc); - return new RegisterStats(lirGen.lir); + LIRGenerationResult lirGen = GraalCompiler.emitLIR(getBackend(), getBackend().getTarget(), schedule, graph, null, cc); + return new RegisterStats(lirGen.getLIR()); } }
--- a/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/GraalCompiler.java Wed Mar 26 14:43:50 2014 +0100 +++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/GraalCompiler.java Wed Mar 26 20:44:11 2014 +0100 @@ -145,10 +145,10 @@ throw Debug.handle(e); } try (TimerCloseable a = BackEnd.start()) { - LIRGenerator lirGen = null; - lirGen = emitLIR(backend, target, schedule, graph, stub, cc); - try (Scope s = Debug.scope("CodeGen", lirGen)) { - emitCode(backend, assumptions, lirGen, compilationResult, installedCodeOwner, factory); + LIRGenerationResult lirGenRes = null; + lirGenRes = emitLIR(backend, target, schedule, graph, stub, cc); + try (Scope s = Debug.scope("CodeGen", lirGenRes)) { + emitCode(backend, assumptions, lirGenRes, compilationResult, installedCodeOwner, factory); } catch (Throwable e) { throw Debug.handle(e); } @@ -205,29 +205,32 @@ } - private static void emitBlock(LIRGenerator lirGen, Block b, StructuredGraph graph, BlockMap<List<ScheduledNode>> blockMap) { - if (lirGen.lir.lir(b) == null) { + private static void emitBlock(NodeLIRGenerator nodeLirGen, LIRGenerationResult lirGenRes, Block b, StructuredGraph graph, BlockMap<List<ScheduledNode>> blockMap) { + if (lirGenRes.getLIR().getLIRforBlock(b) == null) { for (Block pred : b.getPredecessors()) { if (!b.isLoopHeader() || !pred.isLoopEnd()) { - emitBlock(lirGen, pred, graph, blockMap); + emitBlock(nodeLirGen, lirGenRes, pred, graph, blockMap); } } - lirGen.doBlock(b, graph, blockMap); + nodeLirGen.doBlock(b, graph, blockMap); } } - public static LIRGenerator emitLIR(Backend backend, TargetDescription target, SchedulePhase schedule, StructuredGraph graph, Object stub, CallingConvention cc) { + public static LIRGenerationResult emitLIR(Backend backend, TargetDescription target, SchedulePhase schedule, StructuredGraph graph, Object stub, CallingConvention cc) { Block[] blocks = schedule.getCFG().getBlocks(); Block startBlock = schedule.getCFG().getStartBlock(); assert startBlock != null; assert startBlock.getPredecessorCount() == 0; LIR lir = null; + List<Block> codeEmittingOrder = null; + List<Block> linearScanOrder = null; try (Scope ds = Debug.scope("MidEnd")) { try (Scope s = Debug.scope("ComputeLinearScanOrder")) { NodesToDoubles nodeProbabilities = new ComputeProbabilityClosure(graph).apply(); - List<Block> codeEmittingOrder = ComputeBlockOrder.computeCodeEmittingOrder(blocks.length, startBlock, nodeProbabilities); - List<Block> linearScanOrder = ComputeBlockOrder.computeLinearScanOrder(blocks.length, startBlock, nodeProbabilities); + BlocksToDoubles blockProbabilities = BlocksToDoubles.createFromNodeProbability(nodeProbabilities, schedule.getCFG()); + codeEmittingOrder = ComputeBlockOrder.computeCodeEmittingOrder(blocks.length, startBlock, blockProbabilities); + linearScanOrder = ComputeBlockOrder.computeLinearScanOrder(blocks.length, startBlock, blockProbabilities); lir = new LIR(schedule.getCFG(), linearScanOrder, codeEmittingOrder); Debug.dump(lir, "After linear scan order"); @@ -239,11 +242,13 @@ } try (Scope ds = Debug.scope("BackEnd", lir)) { FrameMap frameMap = backend.newFrameMap(); - LIRGenerator lirGen = backend.newLIRGenerator(graph, stub, frameMap, cc, lir); + LIRGenerationResult lirGenRes = backend.newLIRGenerationResult(lir, frameMap, stub); + LIRGenerator lirGen = backend.newLIRGenerator(cc, lirGenRes); + NodeLIRGenerator nodeLirGen = backend.newNodeLIRGenerator(graph, lirGenRes, lirGen); try (Scope s = Debug.scope("LIRGen", lirGen)) { - for (Block b : lir.linearScanOrder()) { - emitBlock(lirGen, b, graph, schedule.getBlockToNodesMap()); + for (Block b : linearScanOrder) { + emitBlock(nodeLirGen, lirGenRes, b, graph, schedule.getBlockToNodesMap()); } lirGen.beforeRegisterAllocation(); @@ -252,7 +257,7 @@ throw Debug.handle(e); } - try (Scope s = Debug.scope("Allocator", lirGen)) { + try (Scope s = Debug.scope("Allocator", nodeLirGen)) { if (backend.shouldAllocateRegisters()) { new LinearScan(target, lir, frameMap).allocate(); } @@ -262,7 +267,7 @@ try (Scope s = Debug.scope("ControlFlowOptimizations")) { EdgeMoveOptimizer.optimize(lir); - ControlFlowOptimizer.optimize(lir); + ControlFlowOptimizer.optimize(lir, codeEmittingOrder); if (lirGen.canEliminateRedundantMoves()) { RedundantMoveElimination.optimize(lir, frameMap); } @@ -272,16 +277,16 @@ } catch (Throwable e) { throw Debug.handle(e); } - return lirGen; + return lirGenRes; } catch (Throwable e) { throw Debug.handle(e); } } - public static void emitCode(Backend backend, Assumptions assumptions, LIRGenerator lirGen, CompilationResult compilationResult, ResolvedJavaMethod installedCodeOwner, + public static void emitCode(Backend backend, Assumptions assumptions, LIRGenerationResult lirGenRes, CompilationResult compilationResult, ResolvedJavaMethod installedCodeOwner, CompilationResultBuilderFactory factory) { - CompilationResultBuilder crb = backend.newCompilationResultBuilder(lirGen, compilationResult, factory); - backend.emitCode(crb, lirGen.lir, installedCodeOwner); + CompilationResultBuilder crb = backend.newCompilationResultBuilder(lirGenRes, compilationResult, factory); + backend.emitCode(crb, lirGenRes.getLIR(), installedCodeOwner); crb.finish(); if (!assumptions.isEmpty()) { compilationResult.setAssumptions(assumptions);
--- a/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/alloc/LinearScan.java Wed Mar 26 14:43:50 2014 +0100 +++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/alloc/LinearScan.java Wed Mar 26 20:44:11 2014 +0100 @@ -135,9 +135,9 @@ LIRInstruction[] opIdToInstructionMap; /** - * Map from an instruction {@linkplain LIRInstruction#id id} to the {@linkplain Block block} - * containing the instruction. Entries should be retrieved with {@link #blockForId(int)} as the - * id is not simply an index into this array. + * Map from an instruction {@linkplain LIRInstruction#id id} to the {@linkplain AbstractBlock + * block} containing the instruction. Entries should be retrieved with {@link #blockForId(int)} + * as the id is not simply an index into this array. */ AbstractBlock<?>[] opIdToBlockMap; @@ -172,13 +172,13 @@ } public int getFirstLirInstructionId(AbstractBlock<?> block) { - int result = ir.lir(block).get(0).id(); + int result = ir.getLIRforBlock(block).get(0).id(); assert result >= 0; return result; } public int getLastLirInstructionId(AbstractBlock<?> block) { - List<LIRInstruction> instructions = ir.lir(block); + List<LIRInstruction> instructions = ir.getLIRforBlock(block); int result = instructions.get(instructions.size() - 1).id(); assert result >= 0; return result; @@ -517,7 +517,7 @@ LIRInsertionBuffer insertionBuffer = new LIRInsertionBuffer(); for (AbstractBlock<?> block : sortedBlocks) { - List<LIRInstruction> instructions = ir.lir(block); + List<LIRInstruction> instructions = ir.getLIRforBlock(block); int numInst = instructions.size(); // iterate all instructions of the block. skip the first because it is always a label @@ -624,19 +624,19 @@ // Assign IDs to LIR nodes and build a mapping, lirOps, from ID to LIRInstruction node. int numInstructions = 0; for (AbstractBlock<?> block : sortedBlocks) { - numInstructions += ir.lir(block).size(); + numInstructions += ir.getLIRforBlock(block).size(); } // initialize with correct length opIdToInstructionMap = new LIRInstruction[numInstructions]; - opIdToBlockMap = new Block[numInstructions]; + opIdToBlockMap = new AbstractBlock<?>[numInstructions]; int opId = 0; int index = 0; for (AbstractBlock<?> block : sortedBlocks) { blockData.put(block, new BlockData()); - List<LIRInstruction> instructions = ir.lir(block); + List<LIRInstruction> instructions = ir.getLIRforBlock(block); int numInst = instructions.size(); for (int j = 0; j < numInst; j++) { @@ -681,7 +681,7 @@ final BitSet liveGen = new BitSet(liveSize); final BitSet liveKill = new BitSet(liveSize); - List<LIRInstruction> instructions = ir.lir(block); + List<LIRInstruction> instructions = ir.getLIRforBlock(block); int numInst = instructions.size(); // iterate all instructions of the block @@ -869,7 +869,7 @@ } // check that the liveIn set of the first block is empty - Block startBlock = ir.getControlFlowGraph().getStartBlock(); + AbstractBlock<?> startBlock = ir.getControlFlowGraph().getStartBlock(); if (blockData.get(startBlock).liveIn.cardinality() != 0) { if (DetailedAsserts.getValue()) { reportFailure(numBlocks); @@ -880,9 +880,9 @@ indent.outdent(); } - private static LIRGenerator getLIRGeneratorFromDebugContext() { + private static NodeLIRGenerator getNodeLIRGeneratorFromDebugContext() { if (Debug.isEnabled()) { - LIRGenerator lirGen = Debug.contextLookup(LIRGenerator.class); + NodeLIRGenerator lirGen = Debug.contextLookup(NodeLIRGenerator.class); assert lirGen != null; return lirGen; } @@ -890,7 +890,7 @@ } private static ValueNode getValueForOperandFromDebugContext(Value value) { - LIRGenerator gen = getLIRGeneratorFromDebugContext(); + NodeLIRGenerator gen = getNodeLIRGeneratorFromDebugContext(); if (gen != null) { return gen.valueForOperand(value); } @@ -920,7 +920,7 @@ if (blockData.get(block).liveGen.get(operandNum)) { usedIn.add(block); try (Indent indent3 = Debug.logAndIndent("used in block B%d", block.getId())) { - for (LIRInstruction ins : ir.lir(block)) { + for (LIRInstruction ins : ir.getLIRforBlock(block)) { try (Indent indent4 = Debug.logAndIndent("%d: %s", ins.id(), ins)) { ins.forEachState(new ValueProcedure() { @@ -937,7 +937,7 @@ if (blockData.get(block).liveKill.get(operandNum)) { definedIn.add(block); try (Indent indent3 = Debug.logAndIndent("defined in block B%d", block.getId())) { - for (LIRInstruction ins : ir.lir(block)) { + for (LIRInstruction ins : ir.getLIRforBlock(block)) { Debug.log("%d: %s", ins.id(), ins); } } @@ -1161,7 +1161,7 @@ AbstractBlock<?> block = blockAt(i); Indent indent2 = Debug.logAndIndent("handle block %d", block.getId()); - List<LIRInstruction> instructions = ir.lir(block); + List<LIRInstruction> instructions = ir.getLIRforBlock(block); final int blockFrom = getFirstLirInstructionId(block); int blockTo = getLastLirInstructionId(block); @@ -1510,7 +1510,7 @@ if (fromBlock.getSuccessorCount() <= 1) { Debug.log("inserting moves at end of fromBlock B%d", fromBlock.getId()); - List<LIRInstruction> instructions = ir.lir(fromBlock); + List<LIRInstruction> instructions = ir.getLIRforBlock(fromBlock); LIRInstruction instr = instructions.get(instructions.size() - 1); if (instr instanceof StandardOp.JumpOp) { // insert moves before branch @@ -1523,7 +1523,7 @@ Debug.log("inserting moves at beginning of toBlock B%d", toBlock.getId()); if (DetailedAsserts.getValue()) { - assert ir.lir(fromBlock).get(0) instanceof StandardOp.LabelOp : "block does not start with a label"; + assert ir.getLIRforBlock(fromBlock).get(0) instanceof StandardOp.LabelOp : "block does not start with a label"; // because the number of predecessor edges matches the number of // successor edges, blocks which are reached by switch statements @@ -1534,7 +1534,7 @@ } } - moveResolver.setInsertPosition(ir.lir(toBlock), 1); + moveResolver.setInsertPosition(ir.getLIRforBlock(toBlock), 1); } } @@ -1554,7 +1554,7 @@ // check if block has only one predecessor and only one successor if (block.getPredecessorCount() == 1 && block.getSuccessorCount() == 1) { - List<LIRInstruction> instructions = ir.lir(block); + List<LIRInstruction> instructions = ir.getLIRforBlock(block); assert instructions.get(0) instanceof StandardOp.LabelOp : "block must start with label"; assert instructions.get(instructions.size() - 1) instanceof StandardOp.JumpOp : "block with successor must end with unconditional jump"; @@ -1636,7 +1636,7 @@ // before the branch instruction. So the split child information for this branch // would // be incorrect. - LIRInstruction instr = ir.lir(block).get(ir.lir(block).size() - 1); + LIRInstruction instr = ir.getLIRforBlock(block).get(ir.getLIRforBlock(block).size() - 1); if (instr instanceof StandardOp.JumpOp) { if (blockData.get(block).liveOut.get(operandNumber(operand))) { assert false : "can't get split child for the last branch of a block because the information would be incorrect (moves are inserted before the branch in resolveDataFlow)"; @@ -1752,7 +1752,7 @@ // are not // considered in the live ranges of intervals) // Solution: use the first opId of the branch target block instead. - final LIRInstruction instr = ir.lir(block).get(ir.lir(block).size() - 1); + final LIRInstruction instr = ir.getLIRforBlock(block).get(ir.getLIRforBlock(block).size() - 1); if (instr instanceof StandardOp.JumpOp) { if (blockData.get(block).liveOut.get(operandNumber(operand))) { tempOpId = getFirstLirInstructionId(block.getSuccessors().iterator().next()); @@ -1846,7 +1846,7 @@ try (Indent indent = Debug.logAndIndent("assign locations")) { for (AbstractBlock<?> block : sortedBlocks) { try (Indent indent2 = Debug.logAndIndent("assign locations in block B%d", block.getId())) { - assignLocations(ir.lir(block), iw); + assignLocations(ir.getLIRforBlock(block), iw); } } } @@ -2060,7 +2060,7 @@ IntervalWalker iw = new IntervalWalker(this, fixedIntervals, otherIntervals); for (AbstractBlock<?> block : sortedBlocks) { - List<LIRInstruction> instructions = ir.lir(block); + List<LIRInstruction> instructions = ir.getLIRforBlock(block); for (int j = 0; j < instructions.size(); j++) { LIRInstruction op = instructions.get(j);
--- a/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/alloc/LinearScanWalker.java Wed Mar 26 14:43:50 2014 +0100 +++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/alloc/LinearScanWalker.java Wed Mar 26 20:44:11 2014 +0100 @@ -254,7 +254,7 @@ // numbering of instructions is known. // When the block already contains spill moves, the index must be increased until the // correct index is reached. - List<LIRInstruction> instructions = allocator.ir.lir(opBlock); + List<LIRInstruction> instructions = allocator.ir.getLIRforBlock(opBlock); int index = (opId - instructions.get(0).id()) >> 1; assert instructions.get(index).id() <= opId : "error in calculation";
--- a/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/alloc/RegisterVerifier.java Wed Mar 26 14:43:50 2014 +0100 +++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/alloc/RegisterVerifier.java Wed Mar 26 20:44:11 2014 +0100 @@ -106,7 +106,7 @@ } // process all operations of the block - processOperations(allocator.ir.lir(block), inputState); + processOperations(allocator.ir.getLIRforBlock(block), inputState); // iterate all successors for (AbstractBlock<?> succ : block.getSuccessors()) {
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/gen/BytecodeParser.java Wed Mar 26 20:44:11 2014 +0100 @@ -0,0 +1,32 @@ +/* + * Copyright (c) 2014, 2014, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package com.oracle.graal.compiler.gen; + +import com.oracle.graal.lir.*; +import com.oracle.graal.nodes.cfg.*; + +public interface BytecodeParser<T extends AbstractBlock<T>> { + void processBlock(T block); + + void setParameter(int i, Variable emitMove); +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/gen/LIRGenerationResult.java Wed Mar 26 20:44:11 2014 +0100 @@ -0,0 +1,35 @@ +/* + * Copyright (c) 2014, 2014, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package com.oracle.graal.compiler.gen; + +import com.oracle.graal.lir.*; + +public interface LIRGenerationResult { + FrameMap getFrameMap(); + + LIR getLIR(); + + boolean hasForeignCall(); + + void setForeignCall(boolean b); +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/gen/LIRGenerationResultBase.java Wed Mar 26 20:44:11 2014 +0100 @@ -0,0 +1,59 @@ +/* + * Copyright (c) 2014, 2014, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package com.oracle.graal.compiler.gen; + +import com.oracle.graal.lir.*; + +public class LIRGenerationResultBase implements LIRGenerationResult { + private final LIR lir; + private final FrameMap frameMap; + /** + * Records whether the code being generated makes at least one foreign call. + */ + private boolean hasForeignCall; + + public LIRGenerationResultBase(LIR lir, FrameMap frameMap) { + this.lir = lir; + this.frameMap = frameMap; + } + + public LIR getLIR() { + return lir; + } + + /** + * Determines whether the code being generated makes at least one foreign call. + */ + public boolean hasForeignCall() { + return hasForeignCall; + } + + public final void setForeignCall(boolean hasForeignCall) { + this.hasForeignCall = hasForeignCall; + } + + public final FrameMap getFrameMap() { + return frameMap; + } + +}
--- a/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/gen/LIRGenerator.java Wed Mar 26 14:43:50 2014 +0100 +++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/gen/LIRGenerator.java Wed Mar 26 20:44:11 2014 +0100 @@ -26,39 +26,31 @@ import static com.oracle.graal.api.meta.Value.*; import static com.oracle.graal.lir.LIR.*; import static com.oracle.graal.lir.LIRValueUtil.*; -import static com.oracle.graal.nodes.ConstantNode.*; import static com.oracle.graal.phases.GraalOptions.*; import java.util.*; -import java.util.Map.Entry; import com.oracle.graal.api.code.*; import com.oracle.graal.api.meta.*; import com.oracle.graal.asm.*; -import com.oracle.graal.compiler.target.*; import com.oracle.graal.debug.*; -import com.oracle.graal.debug.Debug.Scope; import com.oracle.graal.graph.*; import com.oracle.graal.lir.*; import com.oracle.graal.lir.StandardOp.BlockEndOp; -import com.oracle.graal.lir.StandardOp.JumpOp; import com.oracle.graal.lir.StandardOp.LabelOp; import com.oracle.graal.lir.StandardOp.NoOp; import com.oracle.graal.nodes.*; -import com.oracle.graal.nodes.PhiNode.PhiType; import com.oracle.graal.nodes.calc.*; import com.oracle.graal.nodes.cfg.*; -import com.oracle.graal.nodes.extended.*; import com.oracle.graal.nodes.spi.*; import com.oracle.graal.nodes.type.*; -import com.oracle.graal.nodes.virtual.*; import com.oracle.graal.options.*; import com.oracle.graal.phases.util.*; /** * This class traverses the HIR instructions and generates LIR instructions from them. */ -public abstract class LIRGenerator implements LIRGeneratorTool, LIRTypeTool { +public abstract class LIRGenerator implements ArithmeticLIRGenerator, LIRGeneratorTool, LIRTypeTool { public static class Options { // @formatter:off @@ -69,16 +61,12 @@ // @formatter:on } - public final FrameMap frameMap; - public final NodeMap<Value> nodeOperands; - public final LIR lir; + private final Providers providers; + private final CallingConvention cc; - private final Providers providers; - protected final CallingConvention cc; + private DebugInfoBuilder debugInfoBuilder; - protected final DebugInfoBuilder debugInfoBuilder; - - protected Block currentBlock; + protected AbstractBlock<?> currentBlock; private final int traceLevel; private final boolean printIRWithLIR; @@ -104,12 +92,12 @@ * The block that does or will contain {@link #op}. This is initially the block where the * first usage of the constant is seen during LIR generation. */ - private Block block; + Block block; /** * The variable into which the constant is loaded. */ - private final Variable variable; + final Variable variable; public LoadConstant(Variable variable, Block block, int index, LIRInstruction op) { this.variable = variable; @@ -144,40 +132,40 @@ if (index >= 0) { // Replace the move with a filler op so that the operation // list does not need to be adjusted. - List<LIRInstruction> instructions = lir.lir(block); + List<LIRInstruction> instructions = lir.getLIRforBlock(block); instructions.set(index, new NoOp(null, -1)); index = -1; } } } - private Map<Constant, LoadConstant> constantLoads; + Map<Constant, LoadConstant> constantLoads; - private ValueNode currentInstruction; - private ValueNode lastInstructionPrinted; // Debugging only + protected LIRGenerationResult res; /** - * Records whether the code being generated makes at least one foreign call. + * set this before using the LIRGenerator + * + * TODO this should be removed */ - private boolean hasForeignCall; + void setDebugInfoBuilder(DebugInfoBuilder builder) { + debugInfoBuilder = builder; + } /** * Checks whether the supplied constant can be used without loading it into a register for store * operations, i.e., on the right hand side of a memory access. - * + * * @param c The constant to check. * @return True if the constant can be used directly, false if the constant needs to be in a * register. */ public abstract boolean canStoreConstant(Constant c, boolean isCompressed); - public LIRGenerator(StructuredGraph graph, Providers providers, FrameMap frameMap, CallingConvention cc, LIR lir) { + public LIRGenerator(Providers providers, CallingConvention cc, LIRGenerationResult res) { + this.res = res; this.providers = providers; - this.frameMap = frameMap; this.cc = cc; - this.nodeOperands = graph.createNodeMap(); - this.lir = lir; - this.debugInfoBuilder = createDebugInfoBuilder(nodeOperands); this.traceLevel = Options.TraceLIRGeneratorLevel.getValue(); this.printIRWithLIR = Options.PrintIRWithLIR.getValue(); } @@ -190,11 +178,6 @@ return true; } - @SuppressWarnings("hiding") - protected DebugInfoBuilder createDebugInfoBuilder(NodeMap<Value> nodeOperands) { - return new DebugInfoBuilder(nodeOperands); - } - @Override public TargetDescription target() { return getCodeCache().getTarget(); @@ -220,112 +203,19 @@ } /** - * Determines whether the code being generated makes at least one foreign call. - */ - public boolean hasForeignCall() { - return hasForeignCall; - } - - /** - * Returns the operand that has been previously initialized by - * {@link #setResult(ValueNode, Value)} with the result of an instruction. It's a code - * generation error to ask for the operand of ValueNode that doesn't have one yet. - * - * @param node A node that produces a result value. - */ - @Override - public Value operand(ValueNode node) { - Value operand = getOperand(node); - assert operand != null : String.format("missing operand for %1s", node); - return operand; - } - - @Override - public boolean hasOperand(ValueNode node) { - return getOperand(node) != null; - } - - private Value getOperand(ValueNode node) { - if (nodeOperands == null) { - return null; - } - Value operand = nodeOperands.get(node); - if (operand == null) { - operand = getConstantOperand(node); - } - return operand; - } - - private Value getConstantOperand(ValueNode node) { - if (!ConstantNodeRecordsUsages) { - Constant value = node.asConstant(); - if (value != null) { - if (canInlineConstant(value)) { - return setResult(node, value); - } else { - Variable loadedValue; - if (constantLoads == null) { - constantLoads = new HashMap<>(); - } - LoadConstant load = constantLoads.get(value); - if (load == null) { - int index = lir.lir(currentBlock).size(); - loadedValue = emitMove(value); - LIRInstruction op = lir.lir(currentBlock).get(index); - constantLoads.put(value, new LoadConstant(loadedValue, currentBlock, index, op)); - } else { - Block dominator = ControlFlowGraph.commonDominator(load.block, currentBlock); - loadedValue = load.variable; - if (dominator != load.block) { - load.unpin(lir); - } else { - assert load.block != currentBlock || load.index < lir.lir(currentBlock).size(); - } - load.block = dominator; - } - return loadedValue; - } - } - } else { - // Constant is loaded by ConstantNode.generate() - } - return null; - } - - public ValueNode valueForOperand(Value value) { - for (Entry<Node, Value> entry : nodeOperands.entries()) { - if (entry.getValue().equals(value)) { - return (ValueNode) entry.getKey(); - } - } - return null; - } - - /** * Creates a new {@linkplain Variable variable}. - * + * * @param platformKind The kind of the new variable. * @return a new variable */ @Override public Variable newVariable(PlatformKind platformKind) { - return new Variable(platformKind, lir.nextVariable()); + return new Variable(platformKind, res.getLIR().nextVariable()); } @Override public RegisterAttributes attributes(Register register) { - return frameMap.registerConfig.getAttributesMap()[register.number]; - } - - @Override - public Value setResult(ValueNode x, Value operand) { - assert (!isRegister(operand) || !attributes(asRegister(operand)).isAllocatable()); - assert nodeOperands == null || nodeOperands.get(x) == null : "operand cannot be set twice"; - assert operand != null && isLegal(operand) : "operand must be legal"; - assert operand.getKind().getStackKind() == x.getKind() || x.getKind() == Kind.Illegal : operand.getKind().getStackKind() + " must match " + x.getKind(); - assert !(x instanceof VirtualObjectNode); - nodeOperands.set(x, operand); - return operand; + return res.getFrameMap().registerConfig.getAttributesMap()[register.number]; } @Override @@ -354,11 +244,13 @@ } public LabelRef getLIRBlock(FixedNode b) { - Block result = lir.getControlFlowGraph().blockFor(b); + assert res.getLIR().getControlFlowGraph() instanceof ControlFlowGraph; + Block result = ((ControlFlowGraph) res.getLIR().getControlFlowGraph()).blockFor(b); int suxIndex = currentBlock.getSuccessors().indexOf(result); assert suxIndex != -1 : "Block not in successor list of current block"; - return LabelRef.forSuccessor(lir, currentBlock, suxIndex); + assert currentBlock instanceof Block; + return LabelRef.forSuccessor(res.getLIR(), (Block) currentBlock, suxIndex); } /** @@ -402,12 +294,12 @@ return new LIRFrameState(null, null, null); } assert state != null; - return debugInfoBuilder.build(state, exceptionEdge); + return getDebugInfoBuilder().build(state, exceptionEdge); } /** * Gets the ABI specific operand used to return a value of a given kind from a method. - * + * * @param kind the kind of value being returned * @return the operand representing the ABI defined location used return a value of kind * {@code kind} @@ -416,24 +308,24 @@ if (kind == Kind.Void) { return ILLEGAL; } - return frameMap.registerConfig.getReturnRegister(kind).asValue(kind); + return res.getFrameMap().registerConfig.getReturnRegister(kind).asValue(kind); } public void append(LIRInstruction op) { if (printIRWithLIR && !TTY.isSuppressed()) { - if (currentInstruction != null && lastInstructionPrinted != currentInstruction) { - lastInstructionPrinted = currentInstruction; - InstructionPrinter ip = new InstructionPrinter(TTY.out()); - ip.printInstructionListing(currentInstruction); - } + // if (currentInstruction != null && lastInstructionPrinted != currentInstruction) { + // lastInstructionPrinted = currentInstruction; + // InstructionPrinter ip = new InstructionPrinter(TTY.out()); + // ip.printInstructionListing(currentInstruction); + // } TTY.println(op.toStringWithIdPrefix()); TTY.println(); } assert LIRVerifier.verify(op); - lir.lir(currentBlock).add(op); + res.getLIR().getLIRforBlock(currentBlock).add(op); } - public void doBlock(Block block, StructuredGraph graph, BlockMap<List<ScheduledNode>> blockMap) { + public final void doBlockStart(AbstractBlock<?> block) { if (printIRWithLIR) { TTY.print(block.toString()); } @@ -441,71 +333,17 @@ currentBlock = block; // set up the list of LIR instructions - assert lir.lir(block) == null : "LIR list already computed for this block"; - lir.setLir(block, new ArrayList<LIRInstruction>()); + assert res.getLIR().getLIRforBlock(block) == null : "LIR list already computed for this block"; + res.getLIR().setLIRforBlock(block, new ArrayList<LIRInstruction>()); append(new LabelOp(new Label(block.getId()), block.isAligned())); if (traceLevel >= 1) { TTY.println("BEGIN Generating LIR for block B" + block.getId()); } - - if (block == lir.getControlFlowGraph().getStartBlock()) { - assert block.getPredecessorCount() == 0; - emitPrologue(graph); - } else { - assert block.getPredecessorCount() > 0; - } + } - List<ScheduledNode> nodes = blockMap.get(block); - int instructionsFolded = 0; - for (int i = 0; i < nodes.size(); i++) { - Node instr = nodes.get(i); - if (traceLevel >= 3) { - TTY.println("LIRGen for " + instr); - } - if (instructionsFolded > 0) { - instructionsFolded--; - continue; - } - if (!ConstantNodeRecordsUsages && instr instanceof ConstantNode) { - // Loading of constants is done lazily by operand() - } else if (instr instanceof ValueNode) { - ValueNode valueNode = (ValueNode) instr; - if (!hasOperand(valueNode)) { - if (!peephole(valueNode)) { - instructionsFolded = maybeFoldMemory(nodes, i, valueNode); - if (instructionsFolded == 0) { - try { - doRoot((ValueNode) instr); - } catch (GraalInternalError e) { - throw e.addContext(instr); - } catch (Throwable e) { - throw new GraalInternalError(e).addContext(instr); - } - } - } - } else { - // There can be cases in which the result of an instruction is already set - // before by other instructions. - } - } - } - - if (!hasBlockEnd(block)) { - NodeClassIterable successors = block.getEndNode().successors(); - assert successors.count() == block.getSuccessorCount(); - if (block.getSuccessorCount() != 1) { - /* - * If we have more than one successor, we cannot just use the first one. Since - * successors are unordered, this would be a random choice. - */ - throw new GraalInternalError("Block without BlockEndOp: " + block.getEndNode()); - } - emitJump(getLIRBlock((FixedNode) successors.first())); - } - - assert verifyBlock(lir, block); + public final void doBlockEnd(AbstractBlock<?> block) { if (traceLevel >= 1) { TTY.println("END Generating LIR for block B" + block.getId()); @@ -518,324 +356,14 @@ } } - private static final DebugMetric MemoryFoldSuccess = Debug.metric("MemoryFoldSuccess"); - private static final DebugMetric MemoryFoldFailed = Debug.metric("MemoryFoldFailed"); - private static final DebugMetric MemoryFoldFailedNonAdjacent = Debug.metric("MemoryFoldedFailedNonAdjacent"); - private static final DebugMetric MemoryFoldFailedDifferentBlock = Debug.metric("MemoryFoldedFailedDifferentBlock"); - - /** - * Subclass can provide helper to fold memory operations into other operations. - */ - protected MemoryArithmeticLIRLowerer getMemoryLowerer() { - return null; - } - - private static final Object LOG_OUTPUT_LOCK = new Object(); - - /** - * Try to find a sequence of Nodes which can be passed to the backend to look for optimized - * instruction sequences using memory. Currently this basically is a read with a single - * arithmetic user followed by an possible if use. This should generalized to more generic - * pattern matching so that it can be more flexibly used. - */ - private int maybeFoldMemory(List<ScheduledNode> nodes, int i, ValueNode access) { - MemoryArithmeticLIRLowerer lowerer = getMemoryLowerer(); - if (lowerer != null && OptFoldMemory.getValue() && (access instanceof ReadNode || access instanceof FloatingReadNode) && access.usages().count() == 1 && i + 1 < nodes.size()) { - try (Scope s = Debug.scope("MaybeFoldMemory", access)) { - // This is all bit hacky since it's happening on the linearized schedule. This needs - // to be revisited at some point. - - // Find a memory lowerable usage of this operation - if (access.usages().first() instanceof MemoryArithmeticLIRLowerable) { - ValueNode operation = (ValueNode) access.usages().first(); - if (!nodes.contains(operation)) { - Debug.log("node %1s in different block from %1s", access, operation); - MemoryFoldFailedDifferentBlock.increment(); - return 0; - } - ValueNode firstOperation = operation; - if (operation instanceof LogicNode) { - if (operation.usages().count() == 1 && operation.usages().first() instanceof IfNode) { - ValueNode ifNode = (ValueNode) operation.usages().first(); - if (!nodes.contains(ifNode)) { - MemoryFoldFailedDifferentBlock.increment(); - Debug.log("if node %1s in different block from %1s", ifNode, operation); - try (Indent indent = Debug.logAndIndent("checking operations")) { - int start = nodes.indexOf(access); - int end = nodes.indexOf(operation); - for (int i1 = Math.min(start, end); i1 <= Math.max(start, end); i1++) { - indent.log("%d: (%d) %1s", i1, nodes.get(i1).usages().count(), nodes.get(i1)); - } - } - return 0; - } else { - operation = ifNode; - } - } - } - if (Debug.isLogEnabled()) { - synchronized (LOG_OUTPUT_LOCK) { // Hack to ensure the output is grouped. - try (Indent indent = Debug.logAndIndent("checking operations")) { - int start = nodes.indexOf(access); - int end = nodes.indexOf(operation); - for (int i1 = Math.min(start, end); i1 <= Math.max(start, end); i1++) { - indent.log("%d: (%d) %1s", i1, nodes.get(i1).usages().count(), nodes.get(i1)); - } - } - } - } - // Possible lowerable operation in the same block. Check out the dependencies. - int opIndex = nodes.indexOf(operation); - int current = i + 1; - ArrayList<ValueNode> deferred = null; - while (current < opIndex) { - ScheduledNode node = nodes.get(current); - if (node != firstOperation) { - if (node instanceof LocationNode || node instanceof VirtualObjectNode) { - // nothing to do - } else if (node instanceof ConstantNode) { - if (deferred == null) { - deferred = new ArrayList<>(2); - } - // These nodes are collected and the backend is expended to - // evaluate them before generating the lowered form. This - // basically works around unfriendly scheduling of values which - // are defined in a block but not used there. - deferred.add((ValueNode) node); - } else { - Debug.log("unexpected node %1s", node); - // Unexpected inline node - break; - } - } - current++; - } - - if (current == opIndex) { - if (lowerer.memoryPeephole((Access) access, (MemoryArithmeticLIRLowerable) operation, deferred)) { - MemoryFoldSuccess.increment(); - // if this operation had multiple access inputs, then previous attempts - // would be marked as failures which is wrong. Try to adjust the - // counters to account for this. - for (Node input : operation.inputs()) { - if (input == access) { - continue; - } - if (input instanceof Access && nodes.contains(input)) { - MemoryFoldFailedNonAdjacent.add(-1); - } - } - if (deferred != null) { - // Ensure deferred nodes were evaluated - for (ValueNode node : deferred) { - assert hasOperand(node); - } - } - return opIndex - i; - } else { - // This isn't true failure, it just means there wasn't match for the - // pattern. Usually that means it's just not supported by the backend. - MemoryFoldFailed.increment(); - return 0; - } - } else { - MemoryFoldFailedNonAdjacent.increment(); - } - } else { - // memory usage which isn't considered lowerable. Mostly these are - // uninteresting but it might be worth looking at to ensure that interesting - // nodes are being properly handled. - // Debug.log("usage isn't lowerable %1s", access.usages().first()); - } - } - } - return 0; - } - - protected abstract boolean peephole(ValueNode valueNode); - - private boolean hasBlockEnd(Block block) { - List<LIRInstruction> ops = lir.lir(block); - if (ops.size() == 0) { - return false; - } - return ops.get(ops.size() - 1) instanceof BlockEndOp; - } - - private void doRoot(ValueNode instr) { - if (traceLevel >= 2) { - TTY.println("Emitting LIR for instruction " + instr); - } - currentInstruction = instr; - - Debug.log("Visiting %s", instr); - emitNode(instr); - Debug.log("Operand for %s = %s", instr, getOperand(instr)); - } - - protected void emitNode(ValueNode node) { - if (Debug.isLogEnabled() && node.stamp() instanceof IllegalStamp) { - Debug.log("This node has invalid type, we are emitting dead code(?): %s", node); - } - if (node instanceof LIRGenLowerable) { - ((LIRGenLowerable) node).generate(this); - } else if (node instanceof LIRLowerable) { - ((LIRLowerable) node).generate(this); - } else if (node instanceof ArithmeticLIRLowerable) { - ((ArithmeticLIRLowerable) node).generate(this); - } else { - throw GraalInternalError.shouldNotReachHere("node is not LIRLowerable: " + node); - } - } - - protected void emitPrologue(StructuredGraph graph) { - CallingConvention incomingArguments = cc; - - Value[] params = new Value[incomingArguments.getArgumentCount()]; - for (int i = 0; i < params.length; i++) { - params[i] = toStackKind(incomingArguments.getArgument(i)); - if (ValueUtil.isStackSlot(params[i])) { - StackSlot slot = ValueUtil.asStackSlot(params[i]); - if (slot.isInCallerFrame() && !lir.hasArgInCallerFrame()) { - lir.setHasArgInCallerFrame(); - } - } - } - - emitIncomingValues(params); - - for (ParameterNode param : graph.getNodes(ParameterNode.class)) { - Value paramValue = params[param.index()]; - assert paramValue.getKind() == param.getKind().getStackKind(); - setResult(param, emitMove(paramValue)); - } - } - public void emitIncomingValues(Value[] params) { - ((LabelOp) lir.lir(currentBlock).get(0)).setIncomingValues(params); - } - - @Override - public void visitReturn(ReturnNode x) { - AllocatableValue operand = ILLEGAL; - if (x.result() != null) { - operand = resultOperandFor(x.result().getKind()); - emitMove(operand, operand(x.result())); - } - emitReturn(operand); - } - - protected abstract void emitReturn(Value input); - - @Override - public void visitMerge(MergeNode x) { - } - - @Override - public void visitEndNode(AbstractEndNode end) { - moveToPhi(end.merge(), end); - } - - /** - * Runtime specific classes can override this to insert a safepoint at the end of a loop. - */ - @Override - public void visitLoopEnd(LoopEndNode x) { - } - - private void moveToPhi(MergeNode merge, AbstractEndNode pred) { - if (traceLevel >= 1) { - TTY.println("MOVE TO PHI from " + pred + " to " + merge); - } - PhiResolver resolver = new PhiResolver(this); - for (PhiNode phi : merge.phis()) { - if (phi.type() == PhiType.Value) { - ValueNode curVal = phi.valueAt(pred); - resolver.move(operandForPhi(phi), operand(curVal)); - } - } - resolver.dispose(); - - append(new JumpOp(getLIRBlock(merge))); + ((LabelOp) res.getLIR().getLIRforBlock(currentBlock).get(0)).setIncomingValues(params); } protected PlatformKind getPhiKind(PhiNode phi) { return phi.getKind(); } - private Value operandForPhi(PhiNode phi) { - assert phi.type() == PhiType.Value : "wrong phi type: " + phi; - Value result = getOperand(phi); - if (result == null) { - // allocate a variable for this phi - Variable newOperand = newVariable(getPhiKind(phi)); - setResult(phi, newOperand); - return newOperand; - } else { - return result; - } - } - - @Override - public void emitIf(IfNode x) { - emitBranch(x.condition(), getLIRBlock(x.trueSuccessor()), getLIRBlock(x.falseSuccessor()), x.probability(x.trueSuccessor())); - } - - public void emitBranch(LogicNode node, LabelRef trueSuccessor, LabelRef falseSuccessor, double trueSuccessorProbability) { - if (node instanceof IsNullNode) { - emitNullCheckBranch((IsNullNode) node, trueSuccessor, falseSuccessor, trueSuccessorProbability); - } else if (node instanceof CompareNode) { - emitCompareBranch((CompareNode) node, trueSuccessor, falseSuccessor, trueSuccessorProbability); - } else if (node instanceof LogicConstantNode) { - emitConstantBranch(((LogicConstantNode) node).getValue(), trueSuccessor, falseSuccessor); - } else if (node instanceof IntegerTestNode) { - emitIntegerTestBranch((IntegerTestNode) node, trueSuccessor, falseSuccessor, trueSuccessorProbability); - } else { - throw GraalInternalError.unimplemented(node.toString()); - } - } - - private void emitNullCheckBranch(IsNullNode node, LabelRef trueSuccessor, LabelRef falseSuccessor, double trueSuccessorProbability) { - emitCompareBranch(operand(node.object()), Constant.NULL_OBJECT, Condition.EQ, false, trueSuccessor, falseSuccessor, trueSuccessorProbability); - } - - public void emitCompareBranch(CompareNode compare, LabelRef trueSuccessor, LabelRef falseSuccessor, double trueSuccessorProbability) { - emitCompareBranch(operand(compare.x()), operand(compare.y()), compare.condition(), compare.unorderedIsTrue(), trueSuccessor, falseSuccessor, trueSuccessorProbability); - } - - public void emitIntegerTestBranch(IntegerTestNode test, LabelRef trueSuccessor, LabelRef falseSuccessor, double trueSuccessorProbability) { - emitIntegerTestBranch(operand(test.x()), operand(test.y()), trueSuccessor, falseSuccessor, trueSuccessorProbability); - } - - public void emitConstantBranch(boolean value, LabelRef trueSuccessorBlock, LabelRef falseSuccessorBlock) { - LabelRef block = value ? trueSuccessorBlock : falseSuccessorBlock; - emitJump(block); - } - - @Override - public void emitConditional(ConditionalNode conditional) { - Value tVal = operand(conditional.trueValue()); - Value fVal = operand(conditional.falseValue()); - setResult(conditional, emitConditional(conditional.condition(), tVal, fVal)); - } - - public Variable emitConditional(LogicNode node, Value trueValue, Value falseValue) { - if (node instanceof IsNullNode) { - IsNullNode isNullNode = (IsNullNode) node; - return emitConditionalMove(operand(isNullNode.object()), Constant.NULL_OBJECT, Condition.EQ, false, trueValue, falseValue); - } else if (node instanceof CompareNode) { - CompareNode compare = (CompareNode) node; - return emitConditionalMove(operand(compare.x()), operand(compare.y()), compare.condition(), compare.unorderedIsTrue(), trueValue, falseValue); - } else if (node instanceof LogicConstantNode) { - return emitMove(((LogicConstantNode) node).getValue() ? trueValue : falseValue); - } else if (node instanceof IntegerTestNode) { - IntegerTestNode test = (IntegerTestNode) node; - return emitIntegerTestMove(operand(test.x()), operand(test.y()), trueValue, falseValue); - } else { - throw GraalInternalError.unimplemented(node.toString()); - } - } - public abstract void emitJump(LabelRef label); public abstract void emitCompareBranch(Value left, Value right, Condition cond, boolean unorderedIsTrue, LabelRef trueDestination, LabelRef falseDestination, double trueDestinationProbability); @@ -848,42 +376,6 @@ public abstract Variable emitIntegerTestMove(Value leftVal, Value right, Value trueValue, Value falseValue); - @Override - public void emitInvoke(Invoke x) { - LoweredCallTargetNode callTarget = (LoweredCallTargetNode) x.callTarget(); - CallingConvention invokeCc = frameMap.registerConfig.getCallingConvention(callTarget.callType(), x.asNode().stamp().javaType(getMetaAccess()), callTarget.signature(), target(), false); - frameMap.callsMethod(invokeCc); - - Value[] parameters = visitInvokeArguments(invokeCc, callTarget.arguments()); - - LabelRef exceptionEdge = null; - if (x instanceof InvokeWithExceptionNode) { - exceptionEdge = getLIRBlock(((InvokeWithExceptionNode) x).exceptionEdge()); - } - LIRFrameState callState = stateWithExceptionEdge(x, exceptionEdge); - - Value result = invokeCc.getReturn(); - if (callTarget instanceof DirectCallTargetNode) { - emitDirectCall((DirectCallTargetNode) callTarget, result, parameters, AllocatableValue.NONE, callState); - } else if (callTarget instanceof IndirectCallTargetNode) { - emitIndirectCall((IndirectCallTargetNode) callTarget, result, parameters, AllocatableValue.NONE, callState); - } else { - throw GraalInternalError.shouldNotReachHere(); - } - - if (isLegal(result)) { - setResult(x.asNode(), emitMove(result)); - } - - if (x instanceof InvokeWithExceptionNode) { - emitJump(getLIRBlock(((InvokeWithExceptionNode) x).next())); - } - } - - protected abstract void emitDirectCall(DirectCallTargetNode callTarget, Value result, Value[] parameters, Value[] temps, LIRFrameState callState); - - protected abstract void emitIndirectCall(IndirectCallTargetNode callTarget, Value result, Value[] parameters, Value[] temps, LIRFrameState callState); - protected abstract void emitForeignCall(ForeignCallLinkage linkage, Value result, Value[] arguments, Value[] temps, LIRFrameState info); protected static AllocatableValue toStackKind(AllocatableValue value) { @@ -901,23 +393,6 @@ return value; } - public Value[] visitInvokeArguments(CallingConvention invokeCc, Collection<ValueNode> arguments) { - // for each argument, load it into the correct location - Value[] result = new Value[arguments.size()]; - int j = 0; - for (ValueNode arg : arguments) { - if (arg != null) { - AllocatableValue operand = toStackKind(invokeCc.getArgument(j)); - emitMove(operand, operand(arg)); - result[j] = operand; - j++; - } else { - throw GraalInternalError.shouldNotReachHere("I thought we no longer have null entries for two-slot types..."); - } - } - return result; - } - @Override public Variable emitForeignCall(ForeignCallLinkage linkage, DeoptimizingNode info, Value... args) { LIRFrameState state = null; @@ -932,7 +407,7 @@ // move the arguments into the correct location CallingConvention linkageCc = linkage.getOutgoingCallingConvention(); - frameMap.callsMethod(linkageCc); + res.getFrameMap().callsMethod(linkageCc); assert linkageCc.getArgumentCount() == args.length : "argument count mismatch"; Value[] argLocations = new Value[args.length]; for (int i = 0; i < args.length; i++) { @@ -941,7 +416,7 @@ emitMove(loc, arg); argLocations[i] = loc; } - this.hasForeignCall = true; + res.setForeignCall(true); emitForeignCall(linkage, linkageCc.getReturn(), argLocations, linkage.getTemporaries(), state); if (isLegal(linkageCc.getReturn())) { @@ -951,46 +426,6 @@ } } - /** - * This method tries to create a switch implementation that is optimal for the given switch. It - * will either generate a sequential if/then/else cascade, a set of range tests or a table - * switch. - * - * If the given switch does not contain int keys, it will always create a sequential - * implementation. - */ - @Override - public void emitSwitch(SwitchNode x) { - assert x.defaultSuccessor() != null; - LabelRef defaultTarget = getLIRBlock(x.defaultSuccessor()); - int keyCount = x.keyCount(); - if (keyCount == 0) { - emitJump(defaultTarget); - } else { - Variable value = load(operand(x.value())); - if (keyCount == 1) { - assert defaultTarget != null; - double probability = x.probability(x.keySuccessor(0)); - emitCompareBranch(load(operand(x.value())), x.keyAt(0), Condition.EQ, false, getLIRBlock(x.keySuccessor(0)), defaultTarget, probability); - } else { - LabelRef[] keyTargets = new LabelRef[keyCount]; - Constant[] keyConstants = new Constant[keyCount]; - double[] keyProbabilities = new double[keyCount]; - for (int i = 0; i < keyCount; i++) { - keyTargets[i] = getLIRBlock(x.keySuccessor(i)); - keyConstants[i] = x.keyAt(i); - keyProbabilities[i] = x.keyProbability(i); - } - if (value.getKind() != Kind.Int || !x.isSorted()) { - // hopefully only a few entries - emitStrategySwitch(new SwitchStrategy.SequentialStrategy(keyProbabilities, keyConstants), value, keyTargets, defaultTarget); - } else { - emitStrategySwitch(keyConstants, keyProbabilities, keyTargets, defaultTarget, value); - } - } - } - } - protected void emitStrategySwitch(Constant[] keyConstants, double[] keyProbabilities, LabelRef[] keyTargets, LabelRef defaultTarget, Variable value) { int keyCount = keyConstants.length; SwitchStrategy strategy = SwitchStrategy.getBestStrategy(keyProbabilities, keyConstants, keyTargets); @@ -1022,8 +457,13 @@ protected abstract void emitTableSwitch(int lowKey, LabelRef defaultTarget, LabelRef[] targets, Value key); - public FrameMap frameMap() { - return frameMap; + public CallingConvention getCallingConvention() { + return cc; + } + + public DebugInfoBuilder getDebugInfoBuilder() { + assert debugInfoBuilder != null; + return debugInfoBuilder; } @Override @@ -1049,13 +489,13 @@ outOfLoopDominator = outOfLoopDominator.getDominator(); } if (outOfLoopDominator != lc.block) { - lc.unpin(lir); + lc.unpin(res.getLIR()); lc.block = outOfLoopDominator; } } if (lc.index != -1) { - assert lir.lir(lc.block).get(lc.index) == lc.op; + assert res.getLIR().getLIRforBlock(lc.block).get(lc.index) == lc.op; iter.remove(); } } @@ -1076,7 +516,7 @@ } int groupSize = groupEnd - groupBegin; - List<LIRInstruction> ops = lir.lir(block); + List<LIRInstruction> ops = res.getLIR().getLIRforBlock(block); int lastIndex = ops.size() - 1; assert ops.get(lastIndex) instanceof BlockEndOp; int insertionIndex = lastIndex; @@ -1175,4 +615,12 @@ public abstract void emitByteSwap(Variable result, Value operand); public abstract void emitArrayEquals(Kind kind, Variable result, Value array1, Value array2, Value length); + + public AbstractBlock<?> getCurrentBlock() { + return currentBlock; + } + + void setCurrentBlock(AbstractBlock<?> block) { + currentBlock = block; + } }
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/gen/NodeLIRGenerator.java Wed Mar 26 20:44:11 2014 +0100 @@ -0,0 +1,874 @@ +/* + * Copyright (c) 2009, 2012, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package com.oracle.graal.compiler.gen; + +import static com.oracle.graal.api.code.ValueUtil.*; +import static com.oracle.graal.api.meta.Value.*; +import static com.oracle.graal.lir.LIR.*; +import static com.oracle.graal.nodes.ConstantNode.*; + +import java.lang.reflect.*; +import java.util.*; +import java.util.Map.Entry; + +import com.oracle.graal.api.code.*; +import com.oracle.graal.api.meta.*; +import com.oracle.graal.asm.*; +import com.oracle.graal.compiler.gen.LIRGenerator.LoadConstant; +import com.oracle.graal.compiler.target.*; +import com.oracle.graal.debug.*; +import com.oracle.graal.debug.Debug.Scope; +import com.oracle.graal.graph.*; +import com.oracle.graal.lir.*; +import com.oracle.graal.lir.StandardOp.BlockEndOp; +import com.oracle.graal.lir.StandardOp.JumpOp; +import com.oracle.graal.lir.StandardOp.LabelOp; +import com.oracle.graal.nodes.*; +import com.oracle.graal.nodes.PhiNode.PhiType; +import com.oracle.graal.nodes.calc.*; +import com.oracle.graal.nodes.cfg.*; +import com.oracle.graal.nodes.extended.*; +import com.oracle.graal.nodes.spi.*; +import com.oracle.graal.nodes.type.*; +import com.oracle.graal.nodes.virtual.*; +import com.oracle.graal.phases.*; + +/** + * This class traverses the HIR instructions and generates LIR instructions from them. + */ +public abstract class NodeLIRGenerator implements NodeLIRGeneratorTool { + + public static class Options { + // @formatter:off +// @Option(help = "Print HIR along side LIR as the latter is generated") +// public static final OptionValue<Boolean> PrintIRWithLIR = new OptionValue<>(false); +// @Option(help = "The trace level for the LIR generator") +// public static final OptionValue<Integer> TraceLIRGeneratorLevel = new OptionValue<>(0); + // @formatter:on + } + + private final NodeMap<Value> nodeOperands; + private final DebugInfoBuilder debugInfoBuilder; + + private final int traceLevel; + private final boolean printIRWithLIR; + + protected final LIRGenerator gen; + + private ValueNode currentInstruction; + private ValueNode lastInstructionPrinted; // Debugging only + + protected LIRGenerationResult res; + + public NodeLIRGenerator(StructuredGraph graph, LIRGenerationResult res, LIRGenerator gen) { + this.res = res; + this.nodeOperands = graph.createNodeMap(); + this.debugInfoBuilder = createDebugInfoBuilder(nodeOperands); + this.gen = gen; + this.traceLevel = LIRGenerator.Options.TraceLIRGeneratorLevel.getValue(); + this.printIRWithLIR = LIRGenerator.Options.PrintIRWithLIR.getValue(); + gen.setDebugInfoBuilder(debugInfoBuilder); + } + + @SuppressWarnings("hiding") + protected DebugInfoBuilder createDebugInfoBuilder(NodeMap<Value> nodeOperands) { + return new DebugInfoBuilder(nodeOperands); + } + + /** + * Returns the operand that has been previously initialized by + * {@link #setResult(ValueNode, Value)} with the result of an instruction. It's a code + * generation error to ask for the operand of ValueNode that doesn't have one yet. + * + * @param node A node that produces a result value. + */ + @Override + public Value operand(ValueNode node) { + Value operand = getOperand(node); + assert operand != null : String.format("missing operand for %1s", node); + return operand; + } + + @Override + public boolean hasOperand(ValueNode node) { + return getOperand(node) != null; + } + + private Value getOperand(ValueNode node) { + if (nodeOperands == null) { + return null; + } + Value operand = nodeOperands.get(node); + if (operand == null) { + operand = getConstantOperand(node); + } + return operand; + } + + private Value getConstantOperand(ValueNode node) { + if (!ConstantNodeRecordsUsages) { + Constant value = node.asConstant(); + if (value != null) { + if (gen.canInlineConstant(value)) { + return setResult(node, value); + } else { + Variable loadedValue; + if (gen.constantLoads == null) { + gen.constantLoads = new HashMap<>(); + } + LoadConstant load = gen.constantLoads.get(value); + assert gen.getCurrentBlock() instanceof Block; + if (load == null) { + int index = res.getLIR().getLIRforBlock(gen.getCurrentBlock()).size(); + loadedValue = gen.emitMove(value); + LIRInstruction op = res.getLIR().getLIRforBlock(gen.getCurrentBlock()).get(index); + gen.constantLoads.put(value, new LoadConstant(loadedValue, (Block) gen.getCurrentBlock(), index, op)); + } else { + Block dominator = ControlFlowGraph.commonDominator(load.block, (Block) gen.getCurrentBlock()); + loadedValue = load.variable; + if (dominator != load.block) { + load.unpin(res.getLIR()); + } else { + assert load.block != gen.getCurrentBlock() || load.index < res.getLIR().getLIRforBlock(gen.getCurrentBlock()).size(); + } + load.block = dominator; + } + return loadedValue; + } + } + } else { + // Constant is loaded by ConstantNode.generate() + } + return null; + } + + public ValueNode valueForOperand(Value value) { + for (Entry<Node, Value> entry : getNodeOperands().entries()) { + if (entry.getValue().equals(value)) { + return (ValueNode) entry.getKey(); + } + } + return null; + } + + @Override + public Value setResult(ValueNode x, Value operand) { + assert (!isRegister(operand) || !gen.attributes(asRegister(operand)).isAllocatable()); + assert nodeOperands == null || nodeOperands.get(x) == null : "operand cannot be set twice"; + assert operand != null && isLegal(operand) : "operand must be legal"; + assert operand.getKind().getStackKind() == x.getKind() || x.getKind() == Kind.Illegal : operand.getKind().getStackKind() + " must match " + x.getKind(); + assert !(x instanceof VirtualObjectNode); + nodeOperands.set(x, operand); + return operand; + } + + public LabelRef getLIRBlock(FixedNode b) { + assert res.getLIR().getControlFlowGraph() instanceof ControlFlowGraph; + Block result = ((ControlFlowGraph) res.getLIR().getControlFlowGraph()).blockFor(b); + int suxIndex = gen.getCurrentBlock().getSuccessors().indexOf(result); + assert suxIndex != -1 : "Block not in successor list of current block"; + + assert gen.getCurrentBlock() instanceof Block; + return LabelRef.forSuccessor(res.getLIR(), (Block) gen.getCurrentBlock(), suxIndex); + } + + @Deprecated + private static FrameState getFrameState(DeoptimizingNode deopt) { + if (deopt instanceof DeoptimizingNode.DeoptBefore) { + return ((DeoptimizingNode.DeoptBefore) deopt).stateBefore(); + } else if (deopt instanceof DeoptimizingNode.DeoptDuring) { + return ((DeoptimizingNode.DeoptDuring) deopt).stateDuring(); + } else { + assert deopt instanceof DeoptimizingNode.DeoptAfter; + return ((DeoptimizingNode.DeoptAfter) deopt).stateAfter(); + } + } + + @Deprecated + public LIRFrameState state(DeoptimizingNode deopt) { + if (!deopt.canDeoptimize()) { + return null; + } + return stateFor(getFrameState(deopt)); + } + + @Deprecated + public LIRFrameState stateWithExceptionEdge(DeoptimizingNode deopt, LabelRef exceptionEdge) { + if (!deopt.canDeoptimize()) { + return null; + } + return stateForWithExceptionEdge(getFrameState(deopt), exceptionEdge); + } + + @Deprecated + public LIRFrameState stateFor(FrameState state) { + return stateForWithExceptionEdge(state, null); + } + + @Deprecated + public LIRFrameState stateForWithExceptionEdge(FrameState state, LabelRef exceptionEdge) { + if (gen.needOnlyOopMaps()) { + return new LIRFrameState(null, null, null); + } + assert state != null; + return getDebugInfoBuilder().build(state, exceptionEdge); + } + + public final void append(LIRInstruction op) { + if (printIRWithLIR && !TTY.isSuppressed()) { + if (currentInstruction != null && lastInstructionPrinted != currentInstruction) { + lastInstructionPrinted = currentInstruction; + InstructionPrinter ip = new InstructionPrinter(TTY.out()); + ip.printInstructionListing(currentInstruction); + } + } + gen.append(op); + } + + public final void doBlockStart(AbstractBlock<?> block) { + if (printIRWithLIR) { + TTY.print(block.toString()); + } + + gen.setCurrentBlock(block); + + // set up the list of LIR instructions + assert res.getLIR().getLIRforBlock(block) == null : "LIR list already computed for this block"; + res.getLIR().setLIRforBlock(block, new ArrayList<LIRInstruction>()); + + append(new LabelOp(new Label(block.getId()), block.isAligned())); + + if (traceLevel >= 1) { + TTY.println("BEGIN Generating LIR for block B" + block.getId()); + } + } + + public final void doBlockEnd(AbstractBlock<?> block) { + + if (traceLevel >= 1) { + TTY.println("END Generating LIR for block B" + block.getId()); + } + + gen.setCurrentBlock(null); + + if (printIRWithLIR) { + TTY.println(); + } + } + + /** + * For Baseline compilation + */ + + public <T extends AbstractBlock<T>> void doBlock(T block, ResolvedJavaMethod method, BytecodeParser<T> parser) { + doBlockStart(block); + + if (block == res.getLIR().getControlFlowGraph().getStartBlock()) { + assert block.getPredecessorCount() == 0; + emitPrologue(method, parser); + } else { + assert block.getPredecessorCount() > 0; + } + parser.processBlock(block); + + doBlockEnd(block); + } + + public void doBlock(Block block, StructuredGraph graph, BlockMap<List<ScheduledNode>> blockMap) { + doBlockStart(block); + + if (block == res.getLIR().getControlFlowGraph().getStartBlock()) { + assert block.getPredecessorCount() == 0; + emitPrologue(graph); + } else { + assert block.getPredecessorCount() > 0; + } + + List<ScheduledNode> nodes = blockMap.get(block); + int instructionsFolded = 0; + for (int i = 0; i < nodes.size(); i++) { + Node instr = nodes.get(i); + if (traceLevel >= 3) { + TTY.println("LIRGen for " + instr); + } + if (instructionsFolded > 0) { + instructionsFolded--; + continue; + } + if (!ConstantNodeRecordsUsages && instr instanceof ConstantNode) { + // Loading of constants is done lazily by operand() + + } else if (instr instanceof ValueNode) { + ValueNode valueNode = (ValueNode) instr; + if (!hasOperand(valueNode)) { + if (!peephole(valueNode)) { + instructionsFolded = maybeFoldMemory(nodes, i, valueNode); + if (instructionsFolded == 0) { + try { + doRoot((ValueNode) instr); + } catch (GraalInternalError e) { + throw e.addContext(instr); + } catch (Throwable e) { + throw new GraalInternalError(e).addContext(instr); + } + } + } + } else { + // There can be cases in which the result of an instruction is already set + // before by other instructions. + } + } + } + + if (!hasBlockEnd(block)) { + NodeClassIterable successors = block.getEndNode().successors(); + assert successors.count() == block.getSuccessorCount(); + if (block.getSuccessorCount() != 1) { + /* + * If we have more than one successor, we cannot just use the first one. Since + * successors are unordered, this would be a random choice. + */ + throw new GraalInternalError("Block without BlockEndOp: " + block.getEndNode()); + } + gen.emitJump(getLIRBlock((FixedNode) successors.first())); + } + + assert verifyBlock(res.getLIR(), block); + doBlockEnd(block); + } + + private static final DebugMetric MemoryFoldSuccess = Debug.metric("MemoryFoldSuccess"); + private static final DebugMetric MemoryFoldFailed = Debug.metric("MemoryFoldFailed"); + private static final DebugMetric MemoryFoldFailedNonAdjacent = Debug.metric("MemoryFoldedFailedNonAdjacent"); + private static final DebugMetric MemoryFoldFailedDifferentBlock = Debug.metric("MemoryFoldedFailedDifferentBlock"); + + /** + * Subclass can provide helper to fold memory operations into other operations. + */ + public MemoryArithmeticLIRLowerer getMemoryLowerer() { + return null; + } + + /** + * Try to find a sequence of Nodes which can be passed to the backend to look for optimized + * instruction sequences using memory. Currently this basically is a read with a single + * arithmetic user followed by an possible if use. This should generalized to more generic + * pattern matching so that it can be more flexibly used. + */ + private int maybeFoldMemory(List<ScheduledNode> nodes, int i, ValueNode access) { + MemoryArithmeticLIRLowerer lowerer = getMemoryLowerer(); + if (lowerer != null && GraalOptions.OptFoldMemory.getValue() && (access instanceof ReadNode || access instanceof FloatingReadNode) && access.usages().count() == 1 && i + 1 < nodes.size()) { + try (Scope s = Debug.scope("MaybeFoldMemory", access)) { + // This is all bit hacky since it's happening on the linearized schedule. This needs + // to be revisited at some point. + + // Find a memory lowerable usage of this operation + if (access.usages().first() instanceof MemoryArithmeticLIRLowerable) { + ValueNode operation = (ValueNode) access.usages().first(); + if (!nodes.contains(operation)) { + Debug.log("node %1s in different block from %1s", access, operation); + MemoryFoldFailedDifferentBlock.increment(); + return 0; + } + ValueNode firstOperation = operation; + if (operation instanceof LogicNode) { + if (operation.usages().count() == 1 && operation.usages().first() instanceof IfNode) { + ValueNode ifNode = (ValueNode) operation.usages().first(); + if (!nodes.contains(ifNode)) { + MemoryFoldFailedDifferentBlock.increment(); + Debug.log("if node %1s in different block from %1s", ifNode, operation); + try (Indent indent = Debug.logAndIndent("checking operations")) { + int start = nodes.indexOf(access); + int end = nodes.indexOf(operation); + for (int i1 = Math.min(start, end); i1 <= Math.max(start, end); i1++) { + indent.log("%d: (%d) %1s", i1, nodes.get(i1).usages().count(), nodes.get(i1)); + } + } + return 0; + } else { + operation = ifNode; + } + } + } + if (Debug.isLogEnabled()) { + synchronized ("lock") { // Hack to ensure the output is grouped. + try (Indent indent = Debug.logAndIndent("checking operations")) { + int start = nodes.indexOf(access); + int end = nodes.indexOf(operation); + for (int i1 = Math.min(start, end); i1 <= Math.max(start, end); i1++) { + indent.log("%d: (%d) %1s", i1, nodes.get(i1).usages().count(), nodes.get(i1)); + } + } + } + } + // Possible lowerable operation in the same block. Check out the dependencies. + int opIndex = nodes.indexOf(operation); + int current = i + 1; + ArrayList<ValueNode> deferred = null; + while (current < opIndex) { + ScheduledNode node = nodes.get(current); + if (node != firstOperation) { + if (node instanceof LocationNode || node instanceof VirtualObjectNode) { + // nothing to do + } else if (node instanceof ConstantNode) { + if (deferred == null) { + deferred = new ArrayList<>(2); + } + // These nodes are collected and the backend is expended to + // evaluate them before generating the lowered form. This + // basically works around unfriendly scheduling of values which + // are defined in a block but not used there. + deferred.add((ValueNode) node); + } else { + Debug.log("unexpected node %1s", node); + // Unexpected inline node + break; + } + } + current++; + } + + if (current == opIndex) { + if (lowerer.memoryPeephole((Access) access, (MemoryArithmeticLIRLowerable) operation, deferred)) { + MemoryFoldSuccess.increment(); + // if this operation had multiple access inputs, then previous attempts + // would be marked as failures which is wrong. Try to adjust the + // counters to account for this. + for (Node input : operation.inputs()) { + if (input == access) { + continue; + } + if (input instanceof Access && nodes.contains(input)) { + MemoryFoldFailedNonAdjacent.add(-1); + } + } + if (deferred != null) { + // Ensure deferred nodes were evaluated + for (ValueNode node : deferred) { + assert hasOperand(node); + } + } + return opIndex - i; + } else { + // This isn't true failure, it just means there wasn't match for the + // pattern. Usually that means it's just not supported by the backend. + MemoryFoldFailed.increment(); + return 0; + } + } else { + MemoryFoldFailedNonAdjacent.increment(); + } + } else { + // memory usage which isn't considered lowerable. Mostly these are + // uninteresting but it might be worth looking at to ensure that interesting + // nodes are being properly handled. + // Debug.log("usage isn't lowerable %1s", access.usages().first()); + } + } + } + return 0; + } + + protected abstract boolean peephole(ValueNode valueNode); + + private boolean hasBlockEnd(Block block) { + List<LIRInstruction> ops = res.getLIR().getLIRforBlock(block); + if (ops.size() == 0) { + return false; + } + return ops.get(ops.size() - 1) instanceof BlockEndOp; + } + + private void doRoot(ValueNode instr) { + if (traceLevel >= 2) { + TTY.println("Emitting LIR for instruction " + instr); + } + currentInstruction = instr; + + Debug.log("Visiting %s", instr); + emitNode(instr); + Debug.log("Operand for %s = %s", instr, getOperand(instr)); + } + + protected void emitNode(ValueNode node) { + if (Debug.isLogEnabled() && node.stamp() instanceof IllegalStamp) { + Debug.log("This node has invalid type, we are emitting dead code(?): %s", node); + } + if (node instanceof LIRGenLowerable) { + ((LIRGenLowerable) node).generate(this); + } else if (node instanceof LIRGenResLowerable) { + ((LIRGenResLowerable) node).generate(this, res); + } else if (node instanceof LIRLowerable) { + ((LIRLowerable) node).generate(this); + } else if (node instanceof ArithmeticLIRLowerable) { + ((ArithmeticLIRLowerable) node).generate(this); + } else { + throw GraalInternalError.shouldNotReachHere("node is not LIRLowerable: " + node); + } + } + + protected void emitPrologue(StructuredGraph graph) { + CallingConvention incomingArguments = gen.getCallingConvention(); + + Value[] params = new Value[incomingArguments.getArgumentCount()]; + for (int i = 0; i < params.length; i++) { + params[i] = toStackKind(incomingArguments.getArgument(i)); + if (ValueUtil.isStackSlot(params[i])) { + StackSlot slot = ValueUtil.asStackSlot(params[i]); + if (slot.isInCallerFrame() && !res.getLIR().hasArgInCallerFrame()) { + res.getLIR().setHasArgInCallerFrame(); + } + } + } + + emitIncomingValues(params); + + for (ParameterNode param : graph.getNodes(ParameterNode.class)) { + Value paramValue = params[param.index()]; + assert paramValue.getKind() == param.getKind().getStackKind(); + setResult(param, gen.emitMove(paramValue)); + } + } + + protected <T extends AbstractBlock<T>> void emitPrologue(ResolvedJavaMethod method, BytecodeParser<T> parser) { + CallingConvention incomingArguments = gen.getCallingConvention(); + + Value[] params = new Value[incomingArguments.getArgumentCount()]; + for (int i = 0; i < params.length; i++) { + params[i] = toStackKind(incomingArguments.getArgument(i)); + if (ValueUtil.isStackSlot(params[i])) { + StackSlot slot = ValueUtil.asStackSlot(params[i]); + if (slot.isInCallerFrame() && !res.getLIR().hasArgInCallerFrame()) { + res.getLIR().setHasArgInCallerFrame(); + } + } + } + + emitIncomingValues(params); + + Signature sig = method.getSignature(); + boolean isStatic = Modifier.isStatic(method.getModifiers()); + for (int i = 0; i < sig.getParameterCount(!isStatic); i++) { + Value paramValue = params[i]; + assert paramValue.getKind() == sig.getParameterKind(i).getStackKind(); + // TODO setResult(param, emitMove(paramValue)); + parser.setParameter(i, gen.emitMove(paramValue)); + } + + // return arguments; + } + + public void emitIncomingValues(Value[] params) { + ((LabelOp) res.getLIR().getLIRforBlock(gen.getCurrentBlock()).get(0)).setIncomingValues(params); + } + + @Override + public void visitReturn(ReturnNode x) { + AllocatableValue operand = ILLEGAL; + if (x.result() != null) { + operand = gen.resultOperandFor(x.result().getKind()); + gen.emitMove(operand, operand(x.result())); + } + gen.emitReturn(operand); + } + + @Override + public void visitMerge(MergeNode x) { + } + + @Override + public void visitEndNode(AbstractEndNode end) { + moveToPhi(end.merge(), end); + } + + /** + * Runtime specific classes can override this to insert a safepoint at the end of a loop. + */ + @Override + public void visitLoopEnd(LoopEndNode x) { + } + + private void moveToPhi(MergeNode merge, AbstractEndNode pred) { + if (traceLevel >= 1) { + TTY.println("MOVE TO PHI from " + pred + " to " + merge); + } + PhiResolver resolver = new PhiResolver(gen); + for (PhiNode phi : merge.phis()) { + if (phi.type() == PhiType.Value) { + ValueNode curVal = phi.valueAt(pred); + resolver.move(operandForPhi(phi), operand(curVal)); + } + } + resolver.dispose(); + + append(new JumpOp(getLIRBlock(merge))); + } + + protected PlatformKind getPhiKind(PhiNode phi) { + return phi.getKind(); + } + + private Value operandForPhi(PhiNode phi) { + assert phi.type() == PhiType.Value : "wrong phi type: " + phi; + Value result = getOperand(phi); + if (result == null) { + // allocate a variable for this phi + Variable newOperand = gen.newVariable(getPhiKind(phi)); + setResult(phi, newOperand); + return newOperand; + } else { + return result; + } + } + + @Override + public void emitIf(IfNode x) { + emitBranch(x.condition(), getLIRBlock(x.trueSuccessor()), getLIRBlock(x.falseSuccessor()), x.probability(x.trueSuccessor())); + } + + public void emitBranch(LogicNode node, LabelRef trueSuccessor, LabelRef falseSuccessor, double trueSuccessorProbability) { + if (node instanceof IsNullNode) { + emitNullCheckBranch((IsNullNode) node, trueSuccessor, falseSuccessor, trueSuccessorProbability); + } else if (node instanceof CompareNode) { + emitCompareBranch((CompareNode) node, trueSuccessor, falseSuccessor, trueSuccessorProbability); + } else if (node instanceof LogicConstantNode) { + emitConstantBranch(((LogicConstantNode) node).getValue(), trueSuccessor, falseSuccessor); + } else if (node instanceof IntegerTestNode) { + emitIntegerTestBranch((IntegerTestNode) node, trueSuccessor, falseSuccessor, trueSuccessorProbability); + } else { + throw GraalInternalError.unimplemented(node.toString()); + } + } + + private void emitNullCheckBranch(IsNullNode node, LabelRef trueSuccessor, LabelRef falseSuccessor, double trueSuccessorProbability) { + gen.emitCompareBranch(operand(node.object()), Constant.NULL_OBJECT, Condition.EQ, false, trueSuccessor, falseSuccessor, trueSuccessorProbability); + } + + public void emitCompareBranch(CompareNode compare, LabelRef trueSuccessor, LabelRef falseSuccessor, double trueSuccessorProbability) { + gen.emitCompareBranch(operand(compare.x()), operand(compare.y()), compare.condition(), compare.unorderedIsTrue(), trueSuccessor, falseSuccessor, trueSuccessorProbability); + } + + public void emitIntegerTestBranch(IntegerTestNode test, LabelRef trueSuccessor, LabelRef falseSuccessor, double trueSuccessorProbability) { + gen.emitIntegerTestBranch(operand(test.x()), operand(test.y()), trueSuccessor, falseSuccessor, trueSuccessorProbability); + } + + public void emitConstantBranch(boolean value, LabelRef trueSuccessorBlock, LabelRef falseSuccessorBlock) { + LabelRef block = value ? trueSuccessorBlock : falseSuccessorBlock; + gen.emitJump(block); + } + + @Override + public void emitConditional(ConditionalNode conditional) { + Value tVal = operand(conditional.trueValue()); + Value fVal = operand(conditional.falseValue()); + setResult(conditional, emitConditional(conditional.condition(), tVal, fVal)); + } + + public Variable emitConditional(LogicNode node, Value trueValue, Value falseValue) { + if (node instanceof IsNullNode) { + IsNullNode isNullNode = (IsNullNode) node; + return gen.emitConditionalMove(operand(isNullNode.object()), Constant.NULL_OBJECT, Condition.EQ, false, trueValue, falseValue); + } else if (node instanceof CompareNode) { + CompareNode compare = (CompareNode) node; + return gen.emitConditionalMove(operand(compare.x()), operand(compare.y()), compare.condition(), compare.unorderedIsTrue(), trueValue, falseValue); + } else if (node instanceof LogicConstantNode) { + return gen.emitMove(((LogicConstantNode) node).getValue() ? trueValue : falseValue); + } else if (node instanceof IntegerTestNode) { + IntegerTestNode test = (IntegerTestNode) node; + return gen.emitIntegerTestMove(operand(test.x()), operand(test.y()), trueValue, falseValue); + } else { + throw GraalInternalError.unimplemented(node.toString()); + } + } + +// public abstract void emitJump(LabelRef label); +// +// public abstract void emitCompareBranch(Value left, Value right, Condition cond, boolean +// unorderedIsTrue, LabelRef trueDestination, LabelRef falseDestination, double +// trueDestinationProbability); +// +// public abstract void emitOverflowCheckBranch(LabelRef overflow, LabelRef noOverflow, double +// overflowProbability); +// +// public abstract void emitIntegerTestBranch(Value left, Value right, LabelRef trueDestination, +// LabelRef falseDestination, double trueSuccessorProbability); +// +// public abstract Variable emitConditionalMove(Value leftVal, Value right, Condition cond, boolean +// unorderedIsTrue, Value trueValue, Value falseValue); +// +// public abstract Variable emitIntegerTestMove(Value leftVal, Value right, Value trueValue, Value +// falseValue); + + @Override + public void emitInvoke(Invoke x) { + LoweredCallTargetNode callTarget = (LoweredCallTargetNode) x.callTarget(); + CallingConvention invokeCc = res.getFrameMap().registerConfig.getCallingConvention(callTarget.callType(), x.asNode().stamp().javaType(gen.getMetaAccess()), callTarget.signature(), + gen.target(), false); + res.getFrameMap().callsMethod(invokeCc); + + Value[] parameters = visitInvokeArguments(invokeCc, callTarget.arguments()); + + LabelRef exceptionEdge = null; + if (x instanceof InvokeWithExceptionNode) { + exceptionEdge = getLIRBlock(((InvokeWithExceptionNode) x).exceptionEdge()); + } + LIRFrameState callState = stateWithExceptionEdge(x, exceptionEdge); + + Value result = invokeCc.getReturn(); + if (callTarget instanceof DirectCallTargetNode) { + emitDirectCall((DirectCallTargetNode) callTarget, result, parameters, AllocatableValue.NONE, callState); + } else if (callTarget instanceof IndirectCallTargetNode) { + emitIndirectCall((IndirectCallTargetNode) callTarget, result, parameters, AllocatableValue.NONE, callState); + } else { + throw GraalInternalError.shouldNotReachHere(); + } + + if (isLegal(result)) { + setResult(x.asNode(), gen.emitMove(result)); + } + + if (x instanceof InvokeWithExceptionNode) { + gen.emitJump(getLIRBlock(((InvokeWithExceptionNode) x).next())); + } + } + + protected abstract void emitDirectCall(DirectCallTargetNode callTarget, Value result, Value[] parameters, Value[] temps, LIRFrameState callState); + + protected abstract void emitIndirectCall(IndirectCallTargetNode callTarget, Value result, Value[] parameters, Value[] temps, LIRFrameState callState); + + protected static AllocatableValue toStackKind(AllocatableValue value) { + if (value.getKind().getStackKind() != value.getKind()) { + // We only have stack-kinds in the LIR, so convert the operand kind for values from the + // calling convention. + if (isRegister(value)) { + return asRegister(value).asValue(value.getKind().getStackKind()); + } else if (isStackSlot(value)) { + return StackSlot.get(value.getKind().getStackKind(), asStackSlot(value).getRawOffset(), asStackSlot(value).getRawAddFrameSize()); + } else { + throw GraalInternalError.shouldNotReachHere(); + } + } + return value; + } + + @Override + public Value[] visitInvokeArguments(CallingConvention invokeCc, Collection<ValueNode> arguments) { + // for each argument, load it into the correct location + Value[] result = new Value[arguments.size()]; + int j = 0; + for (ValueNode arg : arguments) { + if (arg != null) { + AllocatableValue operand = toStackKind(invokeCc.getArgument(j)); + gen.emitMove(operand, operand(arg)); + result[j] = operand; + j++; + } else { + throw GraalInternalError.shouldNotReachHere("I thought we no longer have null entries for two-slot types..."); + } + } + return result; + } + + /** + * This method tries to create a switch implementation that is optimal for the given switch. It + * will either generate a sequential if/then/else cascade, a set of range tests or a table + * switch. + * + * If the given switch does not contain int keys, it will always create a sequential + * implementation. + */ + @Override + public void emitSwitch(SwitchNode x) { + assert x.defaultSuccessor() != null; + LabelRef defaultTarget = getLIRBlock(x.defaultSuccessor()); + int keyCount = x.keyCount(); + if (keyCount == 0) { + gen.emitJump(defaultTarget); + } else { + Variable value = gen.load(operand(x.value())); + if (keyCount == 1) { + assert defaultTarget != null; + double probability = x.probability(x.keySuccessor(0)); + gen.emitCompareBranch(gen.load(operand(x.value())), x.keyAt(0), Condition.EQ, false, getLIRBlock(x.keySuccessor(0)), defaultTarget, probability); + } else { + LabelRef[] keyTargets = new LabelRef[keyCount]; + Constant[] keyConstants = new Constant[keyCount]; + double[] keyProbabilities = new double[keyCount]; + for (int i = 0; i < keyCount; i++) { + keyTargets[i] = getLIRBlock(x.keySuccessor(i)); + keyConstants[i] = x.keyAt(i); + keyProbabilities[i] = x.keyProbability(i); + } + if (value.getKind() != Kind.Int || !x.isSorted()) { + // hopefully only a few entries + gen.emitStrategySwitch(new SwitchStrategy.SequentialStrategy(keyProbabilities, keyConstants), value, keyTargets, defaultTarget); + } else { + gen.emitStrategySwitch(keyConstants, keyProbabilities, keyTargets, defaultTarget, value); + } + } + } + } + + public final NodeMap<Value> getNodeOperands() { + assert nodeOperands != null; + return nodeOperands; + } + + public DebugInfoBuilder getDebugInfoBuilder() { + assert debugInfoBuilder != null; + return debugInfoBuilder; + } + + public void emitOverflowCheckBranch(AbstractBeginNode overflowSuccessor, AbstractBeginNode next, double probability) { + gen.emitOverflowCheckBranch(getLIRBlock(overflowSuccessor), getLIRBlock(next), probability); + } + + public final void emitArrayEquals(Kind kind, Variable result, Value array1, Value array2, Value length) { + gen.emitArrayEquals(kind, result, array1, array2, length); + } + + public final Variable newVariable(Kind i) { + return gen.newVariable(i); + } + + public final void emitBitCount(Variable result, Value operand) { + gen.emitBitCount(result, operand); + } + + public final void emitBitScanForward(Variable result, Value operand) { + gen.emitBitScanForward(result, operand); + } + + final void emitBitScanReverse(Variable result, Value operand) { + gen.emitBitScanReverse(result, operand); + } + + @Override + public LIRGenerator getLIRGeneratorTool() { + return gen; + } + + public LIRGenerator getLIRGenerator() { + return gen; + } +}
--- a/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/target/Backend.java Wed Mar 26 14:43:50 2014 +0100 +++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/target/Backend.java Wed Mar 26 20:44:11 2014 +0100 @@ -65,7 +65,11 @@ public abstract FrameMap newFrameMap(); - public abstract LIRGenerator newLIRGenerator(StructuredGraph graph, Object stub, FrameMap frameMap, CallingConvention cc, LIR lir); + public abstract LIRGenerator newLIRGenerator(CallingConvention cc, LIRGenerationResult lirGenRes); + + public abstract LIRGenerationResult newLIRGenerationResult(LIR lir, FrameMap frameMap, Object stub); + + public abstract NodeLIRGenerator newNodeLIRGenerator(StructuredGraph graph, LIRGenerationResult lirGenRes, LIRGenerator lirGen); /** * Creates the assembler used to emit the machine code. @@ -75,7 +79,7 @@ /** * Creates the object used to fill in the details of a given compilation result. */ - public abstract CompilationResultBuilder newCompilationResultBuilder(LIRGenerator lirGen, CompilationResult compilationResult, CompilationResultBuilderFactory factory); + public abstract CompilationResultBuilder newCompilationResultBuilder(LIRGenerationResult lirGenResult, CompilationResult compilationResult, CompilationResultBuilderFactory factory); public abstract boolean shouldAllocateRegisters(); @@ -87,4 +91,5 @@ * argument can be null. */ public abstract void emitCode(CompilationResultBuilder crb, LIR lir, ResolvedJavaMethod installedCodeOwner); + }
--- a/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/target/LIRGenLowerable.java Wed Mar 26 14:43:50 2014 +0100 +++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/target/LIRGenLowerable.java Wed Mar 26 20:44:11 2014 +0100 @@ -32,5 +32,5 @@ */ public interface LIRGenLowerable { - void generate(LIRGenerator generator); + void generate(NodeLIRGenerator generator); }
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/target/LIRGenResLowerable.java Wed Mar 26 20:44:11 2014 +0100 @@ -0,0 +1,36 @@ +/* + * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package com.oracle.graal.compiler.target; + +import com.oracle.graal.compiler.gen.*; +import com.oracle.graal.lir.*; +import com.oracle.graal.nodes.spi.*; + +/** + * An alternative to {@link LIRLowerable} for lowering that is tightly coupled to + * {@link LIRGenerationResult} and {@link LIRInstruction}. + */ +public interface LIRGenResLowerable { + + void generate(NodeLIRGeneratorTool generator, LIRGenerationResult genRes); +}
--- a/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotBackend.java Wed Mar 26 14:43:50 2014 +0100 +++ b/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotBackend.java Wed Mar 26 20:44:11 2014 +0100 @@ -72,8 +72,18 @@ } @Override - public LIRGenerator newLIRGenerator(StructuredGraph graph, Object stub, FrameMap frameMap, CallingConvention cc, LIR lir) { - return new AMD64HotSpotLIRGenerator(graph, stub, getProviders(), getRuntime().getConfig(), frameMap, cc, lir); + public LIRGenerator newLIRGenerator(CallingConvention cc, LIRGenerationResult lirGenRes) { + return new AMD64HotSpotLIRGenerator(getProviders(), getRuntime().getConfig(), cc, lirGenRes); + } + + @Override + public LIRGenerationResult newLIRGenerationResult(LIR lir, FrameMap frameMap, Object stub) { + return new AMD64HotSpotLIRGenerationResult(lir, frameMap, stub); + } + + @Override + public NodeLIRGenerator newNodeLIRGenerator(StructuredGraph graph, LIRGenerationResult lirGenRes, LIRGenerator lirGen) { + return new AMD64HotSpotNodeLIRGenerator(graph, lirGenRes, lirGen); } /** @@ -192,17 +202,17 @@ } @Override - public CompilationResultBuilder newCompilationResultBuilder(LIRGenerator lirGen, CompilationResult compilationResult, CompilationResultBuilderFactory factory) { + public CompilationResultBuilder newCompilationResultBuilder(LIRGenerationResult lirGenRen, CompilationResult compilationResult, CompilationResultBuilderFactory factory) { // Omit the frame if the method: // - has no spill slots or other slots allocated during register allocation // - has no callee-saved registers // - has no incoming arguments passed on the stack // - has no deoptimization points // - makes no foreign calls (which require an aligned stack) - AMD64HotSpotLIRGenerator gen = (AMD64HotSpotLIRGenerator) lirGen; - FrameMap frameMap = gen.frameMap; - LIR lir = gen.lir; - assert gen.deoptimizationRescueSlot == null || frameMap.frameNeedsAllocating() : "method that can deoptimize must have a frame"; + AMD64HotSpotLIRGenerationResult gen = (AMD64HotSpotLIRGenerationResult) lirGenRen; + FrameMap frameMap = gen.getFrameMap(); + LIR lir = gen.getLIR(); + assert gen.getDeoptimizationRescueSlot() == null || frameMap.frameNeedsAllocating() : "method that can deoptimize must have a frame"; boolean omitFrame = CanOmitFrame.getValue() && !frameMap.frameNeedsAllocating() && !lir.hasArgInCallerFrame() && !gen.hasForeignCall(); Stub stub = gen.getStub(); @@ -210,14 +220,14 @@ HotSpotFrameContext frameContext = new HotSpotFrameContext(stub != null, omitFrame); CompilationResultBuilder crb = factory.createBuilder(getCodeCache(), getForeignCalls(), frameMap, masm, frameContext, compilationResult); crb.setFrameSize(frameMap.frameSize()); - StackSlot deoptimizationRescueSlot = gen.deoptimizationRescueSlot; + StackSlot deoptimizationRescueSlot = gen.getDeoptimizationRescueSlot(); if (deoptimizationRescueSlot != null && stub == null) { crb.compilationResult.setCustomStackAreaOffset(frameMap.offsetForStackSlot(deoptimizationRescueSlot)); } if (stub != null) { Set<Register> definedRegisters = gatherDefinedRegisters(lir); - updateStub(stub, definedRegisters, gen.calleeSaveInfo, frameMap); + updateStub(stub, definedRegisters, gen.getCalleeSaveInfo(), frameMap); } return crb; @@ -318,4 +328,5 @@ }; return new HotSpotNativeFunctionInterface(getProviders(), factory, this, config.dllLoad, config.dllLookup, config.rtldDefault); } + }
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotLIRGenerationResult.java Wed Mar 26 20:44:11 2014 +0100 @@ -0,0 +1,70 @@ +/* + * Copyright (c) 2014, 2014, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package com.oracle.graal.hotspot.amd64; + +import java.util.*; + +import com.oracle.graal.api.code.*; +import com.oracle.graal.compiler.gen.*; +import com.oracle.graal.hotspot.stubs.*; +import com.oracle.graal.lir.*; +import com.oracle.graal.lir.StandardOp.SaveRegistersOp; + +public class AMD64HotSpotLIRGenerationResult extends LIRGenerationResultBase { + + /** + * The slot reserved for storing the original return address when a frame is marked for + * deoptimization. The return address slot in the callee is overwritten with the address of a + * deoptimization stub. + */ + private StackSlot deoptimizationRescueSlot; + private final Object stub; + + /** + * Map from debug infos that need to be updated with callee save information to the operations + * that provide the information. + */ + private Map<LIRFrameState, SaveRegistersOp> calleeSaveInfo = new HashMap<>(); + + public AMD64HotSpotLIRGenerationResult(LIR lir, FrameMap frameMap, Object stub) { + super(lir, frameMap); + this.stub = stub; + } + + StackSlot getDeoptimizationRescueSlot() { + return deoptimizationRescueSlot; + } + + public final void setDeoptimizationRescueSlot(StackSlot deoptimizationRescueSlot) { + this.deoptimizationRescueSlot = deoptimizationRescueSlot; + } + + Stub getStub() { + return (Stub) stub; + } + + Map<LIRFrameState, SaveRegistersOp> getCalleeSaveInfo() { + return calleeSaveInfo; + } + +}
--- a/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotLIRGenerator.java Wed Mar 26 14:43:50 2014 +0100 +++ b/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotLIRGenerator.java Wed Mar 26 20:44:11 2014 +0100 @@ -24,61 +24,45 @@ import static com.oracle.graal.amd64.AMD64.*; import static com.oracle.graal.api.code.ValueUtil.*; -import static com.oracle.graal.hotspot.HotSpotBackend.*; import static com.oracle.graal.hotspot.HotSpotGraalRuntime.*; -import java.lang.reflect.*; import java.util.*; import com.oracle.graal.amd64.*; import com.oracle.graal.api.code.*; import com.oracle.graal.api.meta.*; -import com.oracle.graal.asm.*; -import com.oracle.graal.asm.amd64.AMD64Address.Scale; import com.oracle.graal.compiler.amd64.*; import com.oracle.graal.compiler.gen.*; -import com.oracle.graal.debug.*; import com.oracle.graal.graph.*; import com.oracle.graal.hotspot.*; import com.oracle.graal.hotspot.HotSpotVMConfig.CompressEncoding; -import com.oracle.graal.hotspot.amd64.AMD64HotSpotMove.CompareAndSwapCompressedOp; import com.oracle.graal.hotspot.amd64.AMD64HotSpotMove.LoadCompressedPointer; import com.oracle.graal.hotspot.amd64.AMD64HotSpotMove.StoreCompressedConstantOp; import com.oracle.graal.hotspot.amd64.AMD64HotSpotMove.StoreCompressedPointer; import com.oracle.graal.hotspot.meta.*; -import com.oracle.graal.hotspot.nodes.*; import com.oracle.graal.hotspot.stubs.*; import com.oracle.graal.lir.*; import com.oracle.graal.lir.StandardOp.NoOp; -import com.oracle.graal.lir.StandardOp.SaveRegistersOp; import com.oracle.graal.lir.amd64.*; -import com.oracle.graal.lir.amd64.AMD64ControlFlow.CondMoveOp; -import com.oracle.graal.lir.amd64.AMD64Move.CompareAndSwapOp; +import com.oracle.graal.lir.amd64.AMD64Move.LeaDataOp; import com.oracle.graal.lir.amd64.AMD64Move.LoadOp; import com.oracle.graal.lir.amd64.AMD64Move.MoveFromRegOp; import com.oracle.graal.lir.amd64.AMD64Move.StoreConstantOp; import com.oracle.graal.lir.amd64.AMD64Move.StoreOp; import com.oracle.graal.nodes.*; -import com.oracle.graal.nodes.calc.*; import com.oracle.graal.nodes.extended.*; -import com.oracle.graal.nodes.java.*; -import com.oracle.graal.nodes.java.MethodCallTargetNode.InvokeKind; /** * LIR generator specialized for AMD64 HotSpot. */ public class AMD64HotSpotLIRGenerator extends AMD64LIRGenerator implements HotSpotLIRGenerator { - private final HotSpotVMConfig config; + final HotSpotVMConfig config; - private final Object stub; - - protected AMD64HotSpotLIRGenerator(StructuredGraph graph, Object stub, HotSpotProviders providers, HotSpotVMConfig config, FrameMap frameMap, CallingConvention cc, LIR lir) { - super(graph, providers, frameMap, cc, lir); + protected AMD64HotSpotLIRGenerator(HotSpotProviders providers, HotSpotVMConfig config, CallingConvention cc, LIRGenerationResult lirGenRes) { + super(providers, cc, lirGenRes); assert config.basicLockSize == 8; this.config = config; - this.stub = stub; - memoryPeephole = new AMD64HotSpotMemoryPeephole(this); } @Override @@ -87,13 +71,6 @@ } /** - * The slot reserved for storing the original return address when a frame is marked for - * deoptimization. The return address slot in the callee is overwritten with the address of a - * deoptimization stub. - */ - StackSlot deoptimizationRescueSlot; - - /** * Utility for emitting the instruction to save RBP. */ class SaveRbp { @@ -107,7 +84,7 @@ public SaveRbp(NoOp placeholder) { this.placeholder = placeholder; - this.reservedSlot = frameMap.allocateSpillSlot(Kind.Long); + this.reservedSlot = res.getFrameMap().allocateSpillSlot(Kind.Long); assert reservedSlot.getRawOffset() == -16 : reservedSlot.getRawOffset(); } @@ -121,16 +98,16 @@ if (useStack) { dst = reservedSlot; } else { - frameMap.freeSpillSlot(reservedSlot); + res.getFrameMap().freeSpillSlot(reservedSlot); dst = newVariable(Kind.Long); } - placeholder.replace(lir, new MoveFromRegOp(dst, rbp.asValue(Kind.Long))); + placeholder.replace(res.getLIR(), new MoveFromRegOp(dst, rbp.asValue(Kind.Long))); return dst; } } - private SaveRbp saveRbp; + SaveRbp saveRbp; /** * List of epilogue operations that need to restore RBP. @@ -145,45 +122,9 @@ } } - @SuppressWarnings("hiding") - @Override - protected DebugInfoBuilder createDebugInfoBuilder(NodeMap<Value> nodeOperands) { - HotSpotLockStack lockStack = new HotSpotLockStack(frameMap, Kind.Long); - return new HotSpotDebugInfoBuilder(nodeOperands, lockStack); - } - @Override public StackSlot getLockSlot(int lockDepth) { - return ((HotSpotDebugInfoBuilder) debugInfoBuilder).lockStack().makeLockSlot(lockDepth); - } - - @Override - protected void emitPrologue(StructuredGraph graph) { - - CallingConvention incomingArguments = cc; - - Value[] params = new Value[incomingArguments.getArgumentCount() + 1]; - for (int i = 0; i < params.length - 1; i++) { - params[i] = toStackKind(incomingArguments.getArgument(i)); - if (isStackSlot(params[i])) { - StackSlot slot = ValueUtil.asStackSlot(params[i]); - if (slot.isInCallerFrame() && !lir.hasArgInCallerFrame()) { - lir.setHasArgInCallerFrame(); - } - } - } - params[params.length - 1] = rbp.asValue(Kind.Long); - - emitIncomingValues(params); - - saveRbp = new SaveRbp(new NoOp(currentBlock, lir.lir(currentBlock).size())); - append(saveRbp.placeholder); - - for (ParameterNode param : graph.getNodes(ParameterNode.class)) { - Value paramValue = params[param.index()]; - assert paramValue.getKind() == param.getKind().getStackKind(); - setResult(param, emitMove(paramValue)); - } + return ((HotSpotDebugInfoBuilder) getDebugInfoBuilder()).lockStack().makeLockSlot(lockDepth); } private Register findPollOnReturnScratchRegister() { @@ -199,7 +140,7 @@ private Register pollOnReturnScratchRegister; @Override - protected void emitReturn(Value input) { + public void emitReturn(Value input) { if (pollOnReturnScratchRegister == null) { pollOnReturnScratchRegister = findPollOnReturnScratchRegister(); } @@ -209,14 +150,12 @@ @Override protected boolean needOnlyOopMaps() { // Stubs only need oop maps - return stub != null; + return ((AMD64HotSpotLIRGenerationResult) res).getStub() != null; } - /** - * Map from debug infos that need to be updated with callee save information to the operations - * that provide the information. - */ - Map<LIRFrameState, SaveRegistersOp> calleeSaveInfo = new HashMap<>(); + public void emitData(AllocatableValue dst, byte[] data) { + append(new LeaDataOp(dst, data)); + } private LIRFrameState currentRuntimeCallInfo; @@ -236,8 +175,8 @@ append(new AMD64RestoreRegistersOp(save.getSlots().clone(), save)); } - Stub getStub() { - return (Stub) stub; + public Stub getStub() { + return ((AMD64HotSpotLIRGenerationResult) res).getStub(); } @Override @@ -249,12 +188,12 @@ if (destroysRegisters) { if (getStub() != null) { if (getStub().preservesRegisters()) { - Register[] savedRegisters = frameMap.registerConfig.getAllocatableRegisters(); + Register[] savedRegisters = res.getFrameMap().registerConfig.getAllocatableRegisters(); savedRegisterLocations = new StackSlot[savedRegisters.length]; for (int i = 0; i < savedRegisters.length; i++) { PlatformKind kind = target().arch.getLargestStorableKind(savedRegisters[i].getRegisterCategory()); assert kind != Kind.Illegal; - StackSlot spillSlot = frameMap.allocateSpillSlot(kind); + StackSlot spillSlot = res.getFrameMap().allocateSpillSlot(kind); savedRegisterLocations[i] = spillSlot; } save = emitSaveRegisters(savedRegisters, savedRegisterLocations); @@ -265,7 +204,7 @@ Variable result; if (linkage.canDeoptimize()) { - assert info != null || stub != null; + assert info != null || ((AMD64HotSpotLIRGenerationResult) res).getStub() != null; Register thread = getProviders().getRegisters().getThreadRegister(); append(new AMD64HotSpotCRuntimeCallPrologueOp(config.threadLastJavaSpOffset(), thread)); result = super.emitForeignCall(linkage, info, args); @@ -277,8 +216,8 @@ if (destroysRegisters) { if (getStub() != null) { if (getStub().preservesRegisters()) { - assert !calleeSaveInfo.containsKey(currentRuntimeCallInfo); - calleeSaveInfo.put(currentRuntimeCallInfo, save); + assert !((AMD64HotSpotLIRGenerationResult) res).getCalleeSaveInfo().containsKey(currentRuntimeCallInfo); + ((AMD64HotSpotLIRGenerationResult) res).getCalleeSaveInfo().put(currentRuntimeCallInfo, save); emitRestoreRegisters(save); } else { @@ -297,53 +236,18 @@ } protected boolean zapRegisters() { - Register[] zappedRegisters = frameMap.registerConfig.getAllocatableRegisters(); + Register[] zappedRegisters = res.getFrameMap().registerConfig.getAllocatableRegisters(); Constant[] zapValues = new Constant[zappedRegisters.length]; for (int i = 0; i < zappedRegisters.length; i++) { PlatformKind kind = target().arch.getLargestStorableKind(zappedRegisters[i].getRegisterCategory()); assert kind != Kind.Illegal; zapValues[i] = zapValueForKind(kind); } - calleeSaveInfo.put(currentRuntimeCallInfo, emitZapRegisters(zappedRegisters, zapValues)); + ((AMD64HotSpotLIRGenerationResult) res).getCalleeSaveInfo().put(currentRuntimeCallInfo, emitZapRegisters(zappedRegisters, zapValues)); return true; } @Override - public void visitSafepointNode(SafepointNode i) { - LIRFrameState info = state(i); - append(new AMD64HotSpotSafepointOp(info, config, this)); - } - - @SuppressWarnings("hiding") - @Override - public void visitDirectCompareAndSwap(DirectCompareAndSwapNode x) { - Kind kind = x.newValue().getKind(); - assert kind == x.expectedValue().getKind(); - - Value expected = loadNonConst(operand(x.expectedValue())); - Variable newVal = load(operand(x.newValue())); - - int disp = 0; - AMD64AddressValue address; - Value index = operand(x.offset()); - if (ValueUtil.isConstant(index) && NumUtil.isInt(ValueUtil.asConstant(index).asLong() + disp)) { - assert !getCodeCache().needsDataPatch(asConstant(index)); - disp += (int) ValueUtil.asConstant(index).asLong(); - address = new AMD64AddressValue(kind, load(operand(x.object())), disp); - } else { - address = new AMD64AddressValue(kind, load(operand(x.object())), load(index), Scale.Times1, disp); - } - - RegisterValue rax = AMD64.rax.asValue(kind); - emitMove(rax, expected); - append(new CompareAndSwapOp(rax, address, rax, newVal)); - - Variable result = newVariable(x.getKind()); - emitMove(result, rax); - setResult(x, result); - } - - @Override public void emitTailcall(Value[] args, Value address) { append(new AMD64TailcallOp(args, address)); } @@ -351,7 +255,7 @@ @Override public void emitCCall(long address, CallingConvention nativeCallingConvention, Value[] args, int numberOfFloatingPointArguments) { Value[] argLocations = new Value[args.length]; - frameMap.callsMethod(nativeCallingConvention); + res.getFrameMap().callsMethod(nativeCallingConvention); // TODO(mg): in case a native function uses floating point varargs, the ABI requires that // RAX contains the length of the varargs AllocatableValue numberOfFloatingPointArgumentsRegister = AMD64.rax.asValue(); @@ -367,33 +271,6 @@ } @Override - protected void emitDirectCall(DirectCallTargetNode callTarget, Value result, Value[] parameters, Value[] temps, LIRFrameState callState) { - InvokeKind invokeKind = ((HotSpotDirectCallTargetNode) callTarget).invokeKind(); - if (invokeKind == InvokeKind.Interface || invokeKind == InvokeKind.Virtual) { - append(new AMD64HotspotDirectVirtualCallOp(callTarget.target(), result, parameters, temps, callState, invokeKind)); - } else { - assert invokeKind == InvokeKind.Static || invokeKind == InvokeKind.Special; - HotSpotResolvedJavaMethod resolvedMethod = (HotSpotResolvedJavaMethod) callTarget.target(); - assert !Modifier.isAbstract(resolvedMethod.getModifiers()) : "Cannot make direct call to abstract method."; - Constant metaspaceMethod = resolvedMethod.getMetaspaceMethodConstant(); - append(new AMD64HotspotDirectStaticCallOp(callTarget.target(), result, parameters, temps, callState, invokeKind, metaspaceMethod)); - } - } - - @Override - protected void emitIndirectCall(IndirectCallTargetNode callTarget, Value result, Value[] parameters, Value[] temps, LIRFrameState callState) { - if (callTarget instanceof HotSpotIndirectCallTargetNode) { - AllocatableValue metaspaceMethod = AMD64.rbx.asValue(); - emitMove(metaspaceMethod, operand(((HotSpotIndirectCallTargetNode) callTarget).metaspaceMethod())); - AllocatableValue targetAddress = AMD64.rax.asValue(); - emitMove(targetAddress, operand(callTarget.computedAddress())); - append(new AMD64IndirectCallOp(callTarget.target(), result, parameters, temps, metaspaceMethod, targetAddress, callState)); - } else { - super.emitIndirectCall(callTarget, result, parameters, temps, callState); - } - } - - @Override public void emitUnwind(Value exception) { ForeignCallLinkage linkage = getForeignCalls().lookupForeignCall(HotSpotBackend.UNWIND_EXCEPTION_TO_CALLER); CallingConvention outgoingCc = linkage.getOutgoingCallingConvention(); @@ -428,32 +305,12 @@ } @Override - public void emitPatchReturnAddress(ValueNode address) { - append(new AMD64HotSpotPatchReturnAddressOp(load(operand(address)))); - } - - @Override - public void emitJumpToExceptionHandlerInCaller(ValueNode handlerInCallerPc, ValueNode exception, ValueNode exceptionPc) { - Variable handler = load(operand(handlerInCallerPc)); - ForeignCallLinkage linkage = getForeignCalls().lookupForeignCall(EXCEPTION_HANDLER_IN_CALLER); - CallingConvention outgoingCc = linkage.getOutgoingCallingConvention(); - assert outgoingCc.getArgumentCount() == 2; - RegisterValue exceptionFixed = (RegisterValue) outgoingCc.getArgument(0); - RegisterValue exceptionPcFixed = (RegisterValue) outgoingCc.getArgument(1); - emitMove(exceptionFixed, operand(exception)); - emitMove(exceptionPcFixed, operand(exceptionPc)); - Register thread = getProviders().getRegisters().getThreadRegister(); - AMD64HotSpotJumpToExceptionHandlerInCallerOp op = new AMD64HotSpotJumpToExceptionHandlerInCallerOp(handler, exceptionFixed, exceptionPcFixed, config.threadIsMethodHandleReturnOffset, thread); - append(op); - } - - @Override public void beforeRegisterAllocation() { super.beforeRegisterAllocation(); - boolean hasDebugInfo = lir.hasDebugInfo(); + boolean hasDebugInfo = res.getLIR().hasDebugInfo(); AllocatableValue savedRbp = saveRbp.finalize(hasDebugInfo); if (hasDebugInfo) { - deoptimizationRescueSlot = frameMap.allocateSpillSlot(Kind.Long); + ((AMD64HotSpotLIRGenerationResult) res).setDeoptimizationRescueSlot(res.getFrameMap().allocateSpillSlot(Kind.Long)); } for (AMD64HotSpotEpilogueOp op : epilogueOps) { @@ -561,38 +418,4 @@ } } - @Override - public void visitCompareAndSwap(LoweredCompareAndSwapNode node, Value address) { - Kind kind = node.getNewValue().getKind(); - assert kind == node.getExpectedValue().getKind(); - Value expected = loadNonConst(operand(node.getExpectedValue())); - Variable newValue = load(operand(node.getNewValue())); - AMD64AddressValue addressValue = asAddressValue(address); - RegisterValue raxRes = AMD64.rax.asValue(kind); - emitMove(raxRes, expected); - if (config.useCompressedOops && node.isCompressible()) { - Variable scratch = newVariable(Kind.Long); - Register heapBaseReg = getProviders().getRegisters().getHeapBaseRegister(); - append(new CompareAndSwapCompressedOp(raxRes, addressValue, raxRes, newValue, scratch, config.getOopEncoding(), heapBaseReg)); - } else { - append(new CompareAndSwapOp(raxRes, addressValue, raxRes, newValue)); - } - Variable result = newVariable(node.getKind()); - append(new CondMoveOp(result, Condition.EQ, load(Constant.TRUE), Constant.FALSE)); - setResult(node, result); - } - - @Override - public void visitInfopointNode(InfopointNode i) { - if (i.getState() != null && i.getState().bci == FrameState.AFTER_BCI) { - Debug.log("Ignoring InfopointNode for AFTER_BCI"); - } else { - super.visitInfopointNode(i); - } - } - - public void emitPrefetchAllocate(ValueNode address, ValueNode distance) { - AMD64AddressValue addr = emitAddress(operand(address), 0, loadNonConst(operand(distance)), 1); - append(new AMD64PrefetchOp(addr, config.allocatePrefetchInstr)); - } }
--- a/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotMemoryPeephole.java Wed Mar 26 14:43:50 2014 +0100 +++ b/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotMemoryPeephole.java Wed Mar 26 20:44:11 2014 +0100 @@ -75,7 +75,7 @@ } } - AMD64HotSpotMemoryPeephole(AMD64LIRGenerator gen) { + AMD64HotSpotMemoryPeephole(AMD64NodeLIRGenerator gen) { super(gen); }
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotNodeLIRGenerator.java Wed Mar 26 20:44:11 2014 +0100 @@ -0,0 +1,229 @@ +/* + * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package com.oracle.graal.hotspot.amd64; + +import static com.oracle.graal.amd64.AMD64.*; +import static com.oracle.graal.api.code.ValueUtil.*; +import static com.oracle.graal.hotspot.HotSpotBackend.*; + +import java.lang.reflect.*; + +import com.oracle.graal.amd64.*; +import com.oracle.graal.api.code.*; +import com.oracle.graal.api.meta.*; +import com.oracle.graal.asm.*; +import com.oracle.graal.asm.amd64.AMD64Address.Scale; +import com.oracle.graal.compiler.amd64.*; +import com.oracle.graal.compiler.gen.*; +import com.oracle.graal.debug.*; +import com.oracle.graal.graph.*; +import com.oracle.graal.hotspot.*; +import com.oracle.graal.hotspot.amd64.AMD64HotSpotLIRGenerator.SaveRbp; +import com.oracle.graal.hotspot.amd64.AMD64HotSpotMove.CompareAndSwapCompressedOp; +import com.oracle.graal.hotspot.meta.*; +import com.oracle.graal.hotspot.nodes.*; +import com.oracle.graal.lir.*; +import com.oracle.graal.lir.StandardOp.NoOp; +import com.oracle.graal.lir.amd64.*; +import com.oracle.graal.lir.amd64.AMD64ControlFlow.CondMoveOp; +import com.oracle.graal.lir.amd64.AMD64Move.CompareAndSwapOp; +import com.oracle.graal.nodes.*; +import com.oracle.graal.nodes.calc.*; +import com.oracle.graal.nodes.java.*; +import com.oracle.graal.nodes.java.MethodCallTargetNode.InvokeKind; + +/** + * LIR generator specialized for AMD64 HotSpot. + */ +public class AMD64HotSpotNodeLIRGenerator extends AMD64NodeLIRGenerator implements HotSpotNodeLIRGenerator { + + public AMD64HotSpotNodeLIRGenerator(StructuredGraph graph, LIRGenerationResult res, LIRGenerator gen) { + super(graph, res, gen); + memoryPeephole = new AMD64HotSpotMemoryPeephole(this); + } + + private AMD64HotSpotLIRGenerator getGen() { + return (AMD64HotSpotLIRGenerator) gen; + } + + private SaveRbp getSaveRbp() { + return getGen().saveRbp; + } + + private void setSaveRbp(SaveRbp saveRbp) { + getGen().saveRbp = saveRbp; + } + + @Override + protected DebugInfoBuilder createDebugInfoBuilder(NodeMap<Value> nodeOperands) { + HotSpotLockStack lockStack = new HotSpotLockStack(res.getFrameMap(), Kind.Long); + return new HotSpotDebugInfoBuilder(nodeOperands, lockStack); + } + + @Override + protected void emitPrologue(StructuredGraph graph) { + + CallingConvention incomingArguments = gen.getCallingConvention(); + + Value[] params = new Value[incomingArguments.getArgumentCount() + 1]; + for (int i = 0; i < params.length - 1; i++) { + params[i] = toStackKind(incomingArguments.getArgument(i)); + if (isStackSlot(params[i])) { + StackSlot slot = ValueUtil.asStackSlot(params[i]); + if (slot.isInCallerFrame() && !res.getLIR().hasArgInCallerFrame()) { + res.getLIR().setHasArgInCallerFrame(); + } + } + } + params[params.length - 1] = rbp.asValue(Kind.Long); + + emitIncomingValues(params); + + setSaveRbp(((AMD64HotSpotLIRGenerator) gen).new SaveRbp(new NoOp(gen.getCurrentBlock(), res.getLIR().getLIRforBlock(gen.getCurrentBlock()).size()))); + append(getSaveRbp().placeholder); + + for (ParameterNode param : graph.getNodes(ParameterNode.class)) { + Value paramValue = params[param.index()]; + assert paramValue.getKind() == param.getKind().getStackKind(); + setResult(param, gen.emitMove(paramValue)); + } + } + + @Override + public void visitSafepointNode(SafepointNode i) { + LIRFrameState info = state(i); + append(new AMD64HotSpotSafepointOp(info, getGen().config, this)); + } + + @Override + protected void emitDirectCall(DirectCallTargetNode callTarget, Value result, Value[] parameters, Value[] temps, LIRFrameState callState) { + InvokeKind invokeKind = ((HotSpotDirectCallTargetNode) callTarget).invokeKind(); + if (invokeKind == InvokeKind.Interface || invokeKind == InvokeKind.Virtual) { + append(new AMD64HotspotDirectVirtualCallOp(callTarget.target(), result, parameters, temps, callState, invokeKind)); + } else { + assert invokeKind == InvokeKind.Static || invokeKind == InvokeKind.Special; + HotSpotResolvedJavaMethod resolvedMethod = (HotSpotResolvedJavaMethod) callTarget.target(); + assert !Modifier.isAbstract(resolvedMethod.getModifiers()) : "Cannot make direct call to abstract method."; + Constant metaspaceMethod = resolvedMethod.getMetaspaceMethodConstant(); + append(new AMD64HotspotDirectStaticCallOp(callTarget.target(), result, parameters, temps, callState, invokeKind, metaspaceMethod)); + } + } + + @Override + protected void emitIndirectCall(IndirectCallTargetNode callTarget, Value result, Value[] parameters, Value[] temps, LIRFrameState callState) { + if (callTarget instanceof HotSpotIndirectCallTargetNode) { + AllocatableValue metaspaceMethod = AMD64.rbx.asValue(); + gen.emitMove(metaspaceMethod, operand(((HotSpotIndirectCallTargetNode) callTarget).metaspaceMethod())); + AllocatableValue targetAddress = AMD64.rax.asValue(); + gen.emitMove(targetAddress, operand(callTarget.computedAddress())); + append(new AMD64IndirectCallOp(callTarget.target(), result, parameters, temps, metaspaceMethod, targetAddress, callState)); + } else { + super.emitIndirectCall(callTarget, result, parameters, temps, callState); + } + } + + @Override + public void emitPatchReturnAddress(ValueNode address) { + append(new AMD64HotSpotPatchReturnAddressOp(gen.load(operand(address)))); + } + + @Override + public void emitJumpToExceptionHandlerInCaller(ValueNode handlerInCallerPc, ValueNode exception, ValueNode exceptionPc) { + Variable handler = gen.load(operand(handlerInCallerPc)); + ForeignCallLinkage linkage = gen.getForeignCalls().lookupForeignCall(EXCEPTION_HANDLER_IN_CALLER); + CallingConvention outgoingCc = linkage.getOutgoingCallingConvention(); + assert outgoingCc.getArgumentCount() == 2; + RegisterValue exceptionFixed = (RegisterValue) outgoingCc.getArgument(0); + RegisterValue exceptionPcFixed = (RegisterValue) outgoingCc.getArgument(1); + gen.emitMove(exceptionFixed, operand(exception)); + gen.emitMove(exceptionPcFixed, operand(exceptionPc)); + Register thread = getGen().getProviders().getRegisters().getThreadRegister(); + AMD64HotSpotJumpToExceptionHandlerInCallerOp op = new AMD64HotSpotJumpToExceptionHandlerInCallerOp(handler, exceptionFixed, exceptionPcFixed, getGen().config.threadIsMethodHandleReturnOffset, + thread); + append(op); + } + + @Override + public void visitInfopointNode(InfopointNode i) { + if (i.getState() != null && i.getState().bci == FrameState.AFTER_BCI) { + Debug.log("Ignoring InfopointNode for AFTER_BCI"); + } else { + super.visitInfopointNode(i); + } + } + + public void emitPrefetchAllocate(ValueNode address, ValueNode distance) { + AMD64AddressValue addr = getGen().emitAddress(operand(address), 0, gen.loadNonConst(operand(distance)), 1); + append(new AMD64PrefetchOp(addr, getGen().config.allocatePrefetchInstr)); + } + + @Override + public void visitDirectCompareAndSwap(DirectCompareAndSwapNode x) { + Kind kind = x.newValue().getKind(); + assert kind == x.expectedValue().getKind(); + + Value expected = gen.loadNonConst(operand(x.expectedValue())); + Variable newVal = gen.load(operand(x.newValue())); + + int disp = 0; + AMD64AddressValue address; + Value index = operand(x.offset()); + if (ValueUtil.isConstant(index) && NumUtil.isInt(ValueUtil.asConstant(index).asLong() + disp)) { + assert !gen.getCodeCache().needsDataPatch(asConstant(index)); + disp += (int) ValueUtil.asConstant(index).asLong(); + address = new AMD64AddressValue(kind, gen.load(operand(x.object())), disp); + } else { + address = new AMD64AddressValue(kind, gen.load(operand(x.object())), gen.load(index), Scale.Times1, disp); + } + + RegisterValue rax_local = AMD64.rax.asValue(kind); + gen.emitMove(rax_local, expected); + append(new CompareAndSwapOp(rax_local, address, rax_local, newVal)); + + Variable result = newVariable(x.getKind()); + gen.emitMove(result, rax_local); + setResult(x, result); + } + + @Override + public void visitCompareAndSwap(LoweredCompareAndSwapNode node, Value address) { + Kind kind = node.getNewValue().getKind(); + assert kind == node.getExpectedValue().getKind(); + Value expected = gen.loadNonConst(operand(node.getExpectedValue())); + Variable newValue = gen.load(operand(node.getNewValue())); + AMD64AddressValue addressValue = getGen().asAddressValue(address); + RegisterValue raxRes = AMD64.rax.asValue(kind); + gen.emitMove(raxRes, expected); + if (getGen().config.useCompressedOops && node.isCompressible()) { + Variable scratch = newVariable(Kind.Long); + Register heapBaseReg = getGen().getProviders().getRegisters().getHeapBaseRegister(); + append(new CompareAndSwapCompressedOp(raxRes, addressValue, raxRes, newValue, scratch, getGen().config.getOopEncoding(), heapBaseReg)); + } else { + append(new CompareAndSwapOp(raxRes, addressValue, raxRes, newValue)); + } + Variable result = newVariable(node.getKind()); + append(new CondMoveOp(result, Condition.EQ, gen.load(Constant.TRUE), Constant.FALSE)); + setResult(node, result); + } + +}
--- a/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotSafepointOp.java Wed Mar 26 14:43:50 2014 +0100 +++ b/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotSafepointOp.java Wed Mar 26 20:44:11 2014 +0100 @@ -47,11 +47,11 @@ private final HotSpotVMConfig config; - public AMD64HotSpotSafepointOp(LIRFrameState state, HotSpotVMConfig config, LIRGeneratorTool tool) { + public AMD64HotSpotSafepointOp(LIRFrameState state, HotSpotVMConfig config, NodeLIRGeneratorTool tool) { this.state = state; this.config = config; if (isPollingPageFar(config) || ImmutableCode.getValue()) { - temp = tool.newVariable(tool.target().wordKind); + temp = tool.getLIRGeneratorTool().newVariable(tool.getLIRGeneratorTool().target().wordKind); } else { // Don't waste a register if it's unneeded temp = Value.ILLEGAL;
--- a/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64RawNativeCallNode.java Wed Mar 26 14:43:50 2014 +0100 +++ b/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64RawNativeCallNode.java Wed Mar 26 20:44:11 2014 +0100 @@ -44,19 +44,20 @@ } @Override - public void generate(LIRGenerator generator) { - AMD64LIRGenerator gen = (AMD64LIRGenerator) generator; + public void generate(NodeLIRGenerator generator) { + AMD64NodeLIRGenerator gen = (AMD64NodeLIRGenerator) generator; Value[] parameter = new Value[args.count()]; JavaType[] parameterTypes = new JavaType[args.count()]; for (int i = 0; i < args.count(); i++) { parameter[i] = generator.operand(args.get(i)); - parameterTypes[i] = args.get(i).stamp().javaType(gen.getMetaAccess()); + parameterTypes[i] = args.get(i).stamp().javaType(gen.getLIRGeneratorTool().getMetaAccess()); } - ResolvedJavaType returnType = stamp().javaType(gen.getMetaAccess()); - CallingConvention cc = generator.getCodeCache().getRegisterConfig().getCallingConvention(Type.NativeCall, returnType, parameterTypes, generator.target(), false); - gen.emitCCall(functionPointer.asLong(), cc, parameter, countFloatingTypeArguments(args)); + ResolvedJavaType returnType = stamp().javaType(gen.getLIRGeneratorTool().getMetaAccess()); + CallingConvention cc = generator.getLIRGeneratorTool().getCodeCache().getRegisterConfig().getCallingConvention(Type.NativeCall, returnType, parameterTypes, + generator.getLIRGeneratorTool().target(), false); + ((AMD64LIRGenerator) gen.getLIRGeneratorTool()).emitCCall(functionPointer.asLong(), cc, parameter, countFloatingTypeArguments(args)); if (this.getKind() != Kind.Void) { - generator.setResult(this, gen.emitMove(cc.getReturn())); + generator.setResult(this, gen.getLIRGeneratorTool().emitMove(cc.getReturn())); } }
--- a/graal/com.oracle.graal.hotspot.hsail/src/com/oracle/graal/hotspot/hsail/HSAILHotSpotBackend.java Wed Mar 26 14:43:50 2014 +0100 +++ b/graal/com.oracle.graal.hotspot.hsail/src/com/oracle/graal/hotspot/hsail/HSAILHotSpotBackend.java Wed Mar 26 20:44:11 2014 +0100 @@ -188,8 +188,18 @@ } @Override - public LIRGenerator newLIRGenerator(StructuredGraph graph, Object stub, FrameMap frameMap, CallingConvention cc, LIR lir) { - return new HSAILHotSpotLIRGenerator(graph, getProviders(), getRuntime().getConfig(), frameMap, cc, lir); + public LIRGenerator newLIRGenerator(CallingConvention cc, LIRGenerationResult lirGenRes) { + return new HSAILHotSpotLIRGenerator(getProviders(), getRuntime().getConfig(), cc, lirGenRes); + } + + @Override + public LIRGenerationResult newLIRGenerationResult(LIR lir, FrameMap frameMap, Object stub) { + return new LIRGenerationResultBase(lir, frameMap); + } + + @Override + public NodeLIRGenerator newNodeLIRGenerator(StructuredGraph graph, LIRGenerationResult lirGenRes, LIRGenerator lirGen) { + return new HSAILHotSpotNodeLIRGenerator(graph, lirGenRes, lirGen); } class HotSpotFrameContext implements FrameContext { @@ -215,8 +225,8 @@ } @Override - public CompilationResultBuilder newCompilationResultBuilder(LIRGenerator lirGen, CompilationResult compilationResult, CompilationResultBuilderFactory factory) { - FrameMap frameMap = lirGen.frameMap; + public CompilationResultBuilder newCompilationResultBuilder(LIRGenerationResult lirGenRes, CompilationResult compilationResult, CompilationResultBuilderFactory factory) { + FrameMap frameMap = lirGenRes.getFrameMap(); Assembler masm = createAssembler(frameMap); HotSpotFrameContext frameContext = new HotSpotFrameContext(); CompilationResultBuilder crb = factory.createBuilder(getCodeCache(), getForeignCalls(), frameMap, masm, frameContext, compilationResult); @@ -402,4 +412,5 @@ asm.emitString0("};"); asm.emitString(""); } + }
--- a/graal/com.oracle.graal.hotspot.hsail/src/com/oracle/graal/hotspot/hsail/HSAILHotSpotLIRGenerator.java Wed Mar 26 14:43:50 2014 +0100 +++ b/graal/com.oracle.graal.hotspot.hsail/src/com/oracle/graal/hotspot/hsail/HSAILHotSpotLIRGenerator.java Wed Mar 26 20:44:11 2014 +0100 @@ -23,37 +23,39 @@ package com.oracle.graal.hotspot.hsail; -import sun.misc.*; +import static com.oracle.graal.api.code.ValueUtil.*; import com.oracle.graal.api.code.*; -import static com.oracle.graal.api.code.ValueUtil.asConstant; -import static com.oracle.graal.api.code.ValueUtil.isConstant; import com.oracle.graal.api.meta.*; +import com.oracle.graal.compiler.gen.*; import com.oracle.graal.compiler.hsail.*; +import com.oracle.graal.graph.*; import com.oracle.graal.hotspot.*; import com.oracle.graal.hotspot.HotSpotVMConfig.CompressEncoding; import com.oracle.graal.hotspot.meta.*; -import com.oracle.graal.hotspot.nodes.*; import com.oracle.graal.lir.*; import com.oracle.graal.lir.hsail.*; -import com.oracle.graal.lir.hsail.HSAILControlFlow.*; -import com.oracle.graal.lir.hsail.HSAILMove.*; -import com.oracle.graal.phases.util.*; +import com.oracle.graal.lir.hsail.HSAILControlFlow.ForeignCall1ArgOp; +import com.oracle.graal.lir.hsail.HSAILControlFlow.ForeignCall2ArgOp; +import com.oracle.graal.lir.hsail.HSAILControlFlow.ForeignCallNoArgOp; +import com.oracle.graal.lir.hsail.HSAILMove.LoadCompressedPointer; +import com.oracle.graal.lir.hsail.HSAILMove.LoadOp; +import com.oracle.graal.lir.hsail.HSAILMove.StoreCompressedPointer; +import com.oracle.graal.lir.hsail.HSAILMove.StoreConstantOp; +import com.oracle.graal.lir.hsail.HSAILMove.StoreOp; import com.oracle.graal.nodes.*; -import com.oracle.graal.nodes.calc.*; import com.oracle.graal.nodes.extended.*; -import com.oracle.graal.nodes.java.*; -import com.oracle.graal.graph.*; +import com.oracle.graal.phases.util.*; /** * The HotSpot specific portion of the HSAIL LIR generator. */ -public class HSAILHotSpotLIRGenerator extends HSAILLIRGenerator implements HotSpotLIRGenerator { +public class HSAILHotSpotLIRGenerator extends HSAILLIRGenerator { - private final HotSpotVMConfig config; + final HotSpotVMConfig config; - public HSAILHotSpotLIRGenerator(StructuredGraph graph, Providers providers, HotSpotVMConfig config, FrameMap frameMap, CallingConvention cc, LIR lir) { - super(graph, providers, frameMap, cc, lir); + public HSAILHotSpotLIRGenerator(Providers providers, HotSpotVMConfig config, CallingConvention cc, LIRGenerationResult lirGenRes) { + super(providers, cc, lirGenRes); this.config = config; } @@ -62,27 +64,27 @@ return (HotSpotProviders) super.getProviders(); } - private int getLogMinObjectAlignment() { + int getLogMinObjectAlignment() { return config.logMinObjAlignment(); } - private int getNarrowOopShift() { + int getNarrowOopShift() { return config.narrowOopShift; } - private long getNarrowOopBase() { + long getNarrowOopBase() { return config.narrowOopBase; } - private int getLogKlassAlignment() { + int getLogKlassAlignment() { return config.logKlassAlignment; } - private int getNarrowKlassShift() { + int getNarrowKlassShift() { return config.narrowKlassShift; } - private long getNarrowKlassBase() { + long getNarrowKlassBase() { return config.narrowKlassBase; } @@ -95,76 +97,6 @@ return true; } - @Override - public StackSlot getLockSlot(int lockDepth) { - throw GraalInternalError.shouldNotReachHere("NYI"); - } - - @Override - public void visitDirectCompareAndSwap(DirectCompareAndSwapNode x) { - throw GraalInternalError.shouldNotReachHere("NYI"); - } - - @Override - public void emitPrefetchAllocate(ValueNode address, ValueNode distance) { - throw GraalInternalError.shouldNotReachHere("NYI"); - } - - @Override - public void emitJumpToExceptionHandlerInCaller(ValueNode handlerInCallerPc, ValueNode exception, ValueNode exceptionPc) { - throw GraalInternalError.shouldNotReachHere("NYI"); - } - - @Override - public void emitPatchReturnAddress(ValueNode address) { - throw GraalInternalError.shouldNotReachHere("NYI"); - } - - @Override - public void emitDeoptimizeCaller(DeoptimizationAction action, DeoptimizationReason reason) { - throw GraalInternalError.shouldNotReachHere("NYI"); - } - - @Override - public void emitTailcall(Value[] args, Value address) { - throw GraalInternalError.shouldNotReachHere("NYI"); - } - - /** - * Appends either a {@link CompareAndSwapOp} or a {@link CompareAndSwapCompressedOp} depending - * on whether the memory location of a given {@link LoweredCompareAndSwapNode} contains a - * compressed oop. For the {@link CompareAndSwapCompressedOp} case, allocates a number of - * scratch registers. The result {@link #operand(ValueNode) operand} for {@code node} complies - * with the API for {@link Unsafe#compareAndSwapInt(Object, long, int, int)}. - * - * @param address the memory location targeted by the operation - */ - @Override - public void visitCompareAndSwap(LoweredCompareAndSwapNode node, Value address) { - Kind kind = node.getNewValue().getKind(); - assert kind == node.getExpectedValue().getKind(); - Variable expected = load(operand(node.getExpectedValue())); - Variable newValue = load(operand(node.getNewValue())); - HSAILAddressValue addressValue = asAddressValue(address); - Variable casResult = newVariable(kind); - if (config.useCompressedOops && node.isCompressible()) { - // make 64-bit scratch variables for expected and new - Variable scratchExpected64 = newVariable(Kind.Long); - Variable scratchNewValue64 = newVariable(Kind.Long); - // make 32-bit scratch variables for expected and new and result - Variable scratchExpected32 = newVariable(Kind.Int); - Variable scratchNewValue32 = newVariable(Kind.Int); - Variable scratchCasResult32 = newVariable(Kind.Int); - append(new CompareAndSwapCompressedOp(casResult, addressValue, expected, newValue, scratchExpected64, scratchNewValue64, scratchExpected32, scratchNewValue32, scratchCasResult32, - getNarrowOopBase(), getNarrowOopShift(), getLogMinObjectAlignment())); - } else { - append(new CompareAndSwapOp(casResult, addressValue, expected, newValue)); - } - Variable nodeResult = newVariable(node.getKind()); - append(new CondMoveOp(mapKindToCompareOp(kind), casResult, expected, nodeResult, Condition.EQ, Constant.INT_1, Constant.INT_0)); - setResult(node, nodeResult); - } - /** * Returns whether or not the input access should be (de)compressed. */
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.hotspot.hsail/src/com/oracle/graal/hotspot/hsail/HSAILHotSpotNodeLIRGenerator.java Wed Mar 26 20:44:11 2014 +0100 @@ -0,0 +1,100 @@ +/* + * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package com.oracle.graal.hotspot.hsail; + +import sun.misc.*; + +import com.oracle.graal.api.meta.*; +import com.oracle.graal.compiler.gen.*; +import com.oracle.graal.compiler.hsail.*; +import com.oracle.graal.graph.*; +import com.oracle.graal.hotspot.HotSpotVMConfig.CompressEncoding; +import com.oracle.graal.lir.*; +import com.oracle.graal.lir.hsail.*; +import com.oracle.graal.lir.hsail.HSAILControlFlow.CondMoveOp; +import com.oracle.graal.lir.hsail.HSAILMove.CompareAndSwapCompressedOp; +import com.oracle.graal.lir.hsail.HSAILMove.CompareAndSwapOp; +import com.oracle.graal.nodes.*; +import com.oracle.graal.nodes.calc.*; +import com.oracle.graal.nodes.java.*; + +/** + * The HotSpot specific portion of the HSAIL LIR generator. + */ +public class HSAILHotSpotNodeLIRGenerator extends HSAILNodeLIRGenerator { + + public HSAILHotSpotNodeLIRGenerator(StructuredGraph graph, LIRGenerationResult lirGenRes, LIRGenerator lirGen) { + super(graph, lirGenRes, lirGen); + } + + private HSAILHotSpotLIRGenerator getGen() { + return (HSAILHotSpotLIRGenerator) gen; + } + + /** + * Appends either a {@link CompareAndSwapOp} or a {@link CompareAndSwapCompressedOp} depending + * on whether the memory location of a given {@link LoweredCompareAndSwapNode} contains a + * compressed oop. For the {@link CompareAndSwapCompressedOp} case, allocates a number of + * scratch registers. The result {@link #operand(ValueNode) operand} for {@code node} complies + * with the API for {@link Unsafe#compareAndSwapInt(Object, long, int, int)}. + * + * @param address the memory location targeted by the operation + */ + @Override + public void visitCompareAndSwap(LoweredCompareAndSwapNode node, Value address) { + Kind kind = node.getNewValue().getKind(); + assert kind == node.getExpectedValue().getKind(); + Variable expected = gen.load(operand(node.getExpectedValue())); + Variable newValue = gen.load(operand(node.getNewValue())); + HSAILAddressValue addressValue = getGen().asAddressValue(address); + Variable casResult = newVariable(kind); + if (getGen().config.useCompressedOops && node.isCompressible()) { + // make 64-bit scratch variables for expected and new + Variable scratchExpected64 = newVariable(Kind.Long); + Variable scratchNewValue64 = newVariable(Kind.Long); + // make 32-bit scratch variables for expected and new and result + Variable scratchExpected32 = newVariable(Kind.Int); + Variable scratchNewValue32 = newVariable(Kind.Int); + Variable scratchCasResult32 = newVariable(Kind.Int); + append(new CompareAndSwapCompressedOp(casResult, addressValue, expected, newValue, scratchExpected64, scratchNewValue64, scratchExpected32, scratchNewValue32, scratchCasResult32, + getGen().getNarrowOopBase(), getGen().getNarrowOopShift(), getGen().getLogMinObjectAlignment())); + } else { + append(new CompareAndSwapOp(casResult, addressValue, expected, newValue)); + } + Variable nodeResult = newVariable(node.getKind()); + append(new CondMoveOp(HSAILLIRGenerator.mapKindToCompareOp(kind), casResult, expected, nodeResult, Condition.EQ, Constant.INT_1, Constant.INT_0)); + setResult(node, nodeResult); + } + + /** + * @return a compressed version of the incoming constant lifted from AMD64HotSpotLIRGenerator + */ + protected static Constant compress(Constant c, CompressEncoding encoding) { + if (c.getKind() == Kind.Long) { + return Constant.forIntegerKind(Kind.Int, (int) (((c.asLong() - encoding.base) >> encoding.shift) & 0xffffffffL), c.getPrimitiveAnnotation()); + } else { + throw GraalInternalError.shouldNotReachHere(); + } + } +}
--- a/graal/com.oracle.graal.hotspot.ptx/src/com/oracle/graal/hotspot/ptx/PTXHotSpotBackend.java Wed Mar 26 14:43:50 2014 +0100 +++ b/graal/com.oracle.graal.hotspot.ptx/src/com/oracle/graal/hotspot/ptx/PTXHotSpotBackend.java Wed Mar 26 20:44:11 2014 +0100 @@ -327,13 +327,13 @@ } @Override - public CompilationResultBuilder newCompilationResultBuilder(LIRGenerator lirGen, CompilationResult compilationResult, CompilationResultBuilderFactory factory) { + public CompilationResultBuilder newCompilationResultBuilder(LIRGenerationResult lirGenRes, CompilationResult compilationResult, CompilationResultBuilderFactory factory) { // Omit the frame of the method: // - has no spill slots or other slots allocated during register allocation // - has no callee-saved registers // - has no incoming arguments passed on the stack // - has no instructions with debug info - FrameMap frameMap = lirGen.frameMap; + FrameMap frameMap = lirGenRes.getFrameMap(); Assembler masm = createAssembler(frameMap); PTXFrameContext frameContext = new PTXFrameContext(); CompilationResultBuilder crb = factory.createBuilder(getCodeCache(), getForeignCalls(), frameMap, masm, frameContext, compilationResult); @@ -342,13 +342,23 @@ } @Override + public LIRGenerationResult newLIRGenerationResult(LIR lir, FrameMap frameMap, Object stub) { + return new LIRGenerationResultBase(lir, frameMap); + } + + @Override protected Assembler createAssembler(FrameMap frameMap) { return new PTXMacroAssembler(getTarget(), frameMap.registerConfig); } @Override - public LIRGenerator newLIRGenerator(StructuredGraph graph, Object stub, FrameMap frameMap, CallingConvention cc, LIR lir) { - return new PTXHotSpotLIRGenerator(graph, getProviders(), getRuntime().getConfig(), frameMap, cc, lir); + public LIRGenerator newLIRGenerator(CallingConvention cc, LIRGenerationResult lirGenRes) { + return new PTXHotSpotLIRGenerator(getProviders(), getRuntime().getConfig(), cc, lirGenRes); + } + + @Override + public NodeLIRGenerator newNodeLIRGenerator(StructuredGraph graph, LIRGenerationResult lirGenRes, LIRGenerator lirGen) { + return new PTXHotSpotNodeLIRGenerator(graph, lirGenRes, lirGen); } private static void emitKernelEntry(CompilationResultBuilder crb, LIR lir, ResolvedJavaMethod codeCacheOwner) { @@ -367,14 +377,14 @@ asm.emitString(""); // Get the start block - Block startBlock = lir.getControlFlowGraph().getStartBlock(); + AbstractBlock<?> startBlock = lir.getControlFlowGraph().getStartBlock(); // Keep a list of ParameterOp instructions to delete from the // list of instructions in the block. ArrayList<LIRInstruction> deleteOps = new ArrayList<>(); // Emit .param arguments to kernel entry based on ParameterOp // instruction. - for (LIRInstruction op : lir.lir(startBlock)) { + for (LIRInstruction op : lir.getLIRforBlock(startBlock)) { if (op instanceof PTXParameterOp) { op.emitCode(crb); deleteOps.add(op); @@ -383,7 +393,7 @@ // Delete ParameterOp instructions. for (LIRInstruction op : deleteOps) { - lir.lir(startBlock).remove(op); + lir.getLIRforBlock(startBlock).remove(op); } // Start emiting body of the PTX kernel. @@ -398,8 +408,8 @@ RegisterAnalysis registerAnalysis = new RegisterAnalysis(); - for (Block b : lir.codeEmittingOrder()) { - for (LIRInstruction op : lir.lir(b)) { + for (AbstractBlock<?> b : lir.codeEmittingOrder()) { + for (LIRInstruction op : lir.getLIRforBlock(b)) { if (op instanceof LabelOp) { // Don't consider this as a definition } else {
--- a/graal/com.oracle.graal.hotspot.ptx/src/com/oracle/graal/hotspot/ptx/PTXHotSpotLIRGenerator.java Wed Mar 26 14:43:50 2014 +0100 +++ b/graal/com.oracle.graal.hotspot.ptx/src/com/oracle/graal/hotspot/ptx/PTXHotSpotLIRGenerator.java Wed Mar 26 20:44:11 2014 +0100 @@ -23,36 +23,24 @@ package com.oracle.graal.hotspot.ptx; -import com.oracle.graal.api.code.CallingConvention; -import com.oracle.graal.api.code.StackSlot; -import com.oracle.graal.api.meta.DeoptimizationAction; -import com.oracle.graal.api.meta.DeoptimizationReason; -import com.oracle.graal.api.meta.Value; -import com.oracle.graal.compiler.ptx.PTXLIRGenerator; -import com.oracle.graal.graph.GraalInternalError; -import com.oracle.graal.hotspot.HotSpotLIRGenerator; -import com.oracle.graal.hotspot.HotSpotVMConfig; -import com.oracle.graal.hotspot.meta.HotSpotProviders; -import com.oracle.graal.hotspot.nodes.DirectCompareAndSwapNode; -import com.oracle.graal.lir.FrameMap; -import com.oracle.graal.lir.LIR; -import com.oracle.graal.nodes.StructuredGraph; -import com.oracle.graal.nodes.ValueNode; +import com.oracle.graal.api.code.*; +import com.oracle.graal.api.meta.*; +import com.oracle.graal.compiler.gen.*; +import com.oracle.graal.compiler.ptx.*; +import com.oracle.graal.graph.*; +import com.oracle.graal.hotspot.*; +import com.oracle.graal.hotspot.meta.*; /** * LIR generator specialized for PTX HotSpot. */ public class PTXHotSpotLIRGenerator extends PTXLIRGenerator implements HotSpotLIRGenerator { - protected PTXHotSpotLIRGenerator(StructuredGraph graph, HotSpotProviders providers, HotSpotVMConfig config, FrameMap frameMap, CallingConvention cc, LIR lir) { - super(graph, providers, frameMap, cc, lir); + protected PTXHotSpotLIRGenerator(HotSpotProviders providers, HotSpotVMConfig config, CallingConvention cc, LIRGenerationResult lirGenRes) { + super(providers, cc, lirGenRes); assert config.basicLockSize == 8; } - public void emitPrefetchAllocate(ValueNode address, ValueNode distance) { - // nop - } - public void emitTailcall(Value[] args, Value address) { throw GraalInternalError.unimplemented(); } @@ -61,18 +49,6 @@ throw GraalInternalError.unimplemented(); } - public void emitPatchReturnAddress(ValueNode address) { - throw GraalInternalError.unimplemented(); - } - - public void emitJumpToExceptionHandlerInCaller(ValueNode handlerInCallerPc, ValueNode exception, ValueNode exceptionPc) { - throw GraalInternalError.unimplemented(); - } - - public void visitDirectCompareAndSwap(DirectCompareAndSwapNode x) { - throw GraalInternalError.unimplemented(); - } - public StackSlot getLockSlot(int lockDepth) { throw GraalInternalError.unimplemented(); }
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.hotspot.ptx/src/com/oracle/graal/hotspot/ptx/PTXHotSpotNodeLIRGenerator.java Wed Mar 26 20:44:11 2014 +0100 @@ -0,0 +1,58 @@ +/* + * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package com.oracle.graal.hotspot.ptx; + +import com.oracle.graal.compiler.gen.*; +import com.oracle.graal.compiler.ptx.*; +import com.oracle.graal.graph.*; +import com.oracle.graal.hotspot.*; +import com.oracle.graal.hotspot.nodes.*; +import com.oracle.graal.nodes.*; + +/** + * LIR generator specialized for PTX HotSpot. + */ +public class PTXHotSpotNodeLIRGenerator extends PTXNodeLIRGenerator implements HotSpotNodeLIRGenerator { + + protected PTXHotSpotNodeLIRGenerator(StructuredGraph graph, LIRGenerationResult lirGenRes, LIRGenerator lirGen) { + super(graph, lirGenRes, lirGen); + } + + public void emitPrefetchAllocate(ValueNode address, ValueNode distance) { + // nop + } + + public void emitPatchReturnAddress(ValueNode address) { + throw GraalInternalError.unimplemented(); + } + + public void emitJumpToExceptionHandlerInCaller(ValueNode handlerInCallerPc, ValueNode exception, ValueNode exceptionPc) { + throw GraalInternalError.unimplemented(); + } + + public void visitDirectCompareAndSwap(DirectCompareAndSwapNode x) { + throw GraalInternalError.unimplemented(); + } + +}
--- a/graal/com.oracle.graal.hotspot.ptx/src/com/oracle/graal/hotspot/ptx/PTXWrapperBuilder.java Wed Mar 26 14:43:50 2014 +0100 +++ b/graal/com.oracle.graal.hotspot.ptx/src/com/oracle/graal/hotspot/ptx/PTXWrapperBuilder.java Wed Mar 26 20:44:11 2014 +0100 @@ -244,7 +244,7 @@ append(new WriteNode(buf, nullWord, location, BarrierType.NONE, false, false)); } - FrameStateBuilder fsb = new FrameStateBuilder(method, getGraph(), true); + HIRFrameStateBuilder fsb = new HIRFrameStateBuilder(method, getGraph(), true); FrameState fs = fsb.create(0); getGraph().start().setStateAfter(fs);
--- a/graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCHotSpotBackend.java Wed Mar 26 14:43:50 2014 +0100 +++ b/graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCHotSpotBackend.java Wed Mar 26 20:44:11 2014 +0100 @@ -22,6 +22,12 @@ */ package com.oracle.graal.hotspot.sparc; +import static com.oracle.graal.api.code.CallingConvention.Type.*; +import static com.oracle.graal.api.code.ValueUtil.*; +import static com.oracle.graal.phases.GraalOptions.*; +import static com.oracle.graal.sparc.SPARC.*; +import static java.lang.reflect.Modifier.*; + import java.util.*; import sun.misc.*; @@ -30,26 +36,27 @@ import com.oracle.graal.api.meta.*; import com.oracle.graal.asm.*; import com.oracle.graal.asm.sparc.*; -import com.oracle.graal.asm.sparc.SPARCAssembler.*; -import com.oracle.graal.compiler.gen.LIRGenerator; +import com.oracle.graal.asm.sparc.SPARCAssembler.Bpne; +import com.oracle.graal.asm.sparc.SPARCAssembler.CC; +import com.oracle.graal.asm.sparc.SPARCAssembler.Ldx; +import com.oracle.graal.asm.sparc.SPARCAssembler.Save; +import com.oracle.graal.asm.sparc.SPARCAssembler.Stx; +import com.oracle.graal.asm.sparc.SPARCMacroAssembler.Cmp; +import com.oracle.graal.asm.sparc.SPARCMacroAssembler.Nop; +import com.oracle.graal.asm.sparc.SPARCMacroAssembler.RestoreWindow; +import com.oracle.graal.asm.sparc.SPARCMacroAssembler.Setx; +import com.oracle.graal.compiler.gen.*; import com.oracle.graal.graph.*; import com.oracle.graal.hotspot.*; import com.oracle.graal.hotspot.meta.*; import com.oracle.graal.hotspot.meta.HotSpotCodeCacheProvider.MarkId; -import com.oracle.graal.hotspot.stubs.Stub; +import com.oracle.graal.hotspot.stubs.*; import com.oracle.graal.lir.*; -import com.oracle.graal.lir.StandardOp.*; +import com.oracle.graal.lir.StandardOp.SaveRegistersOp; import com.oracle.graal.lir.asm.*; import com.oracle.graal.lir.sparc.*; import com.oracle.graal.nodes.*; -import static com.oracle.graal.sparc.SPARC.*; -import static com.oracle.graal.asm.sparc.SPARCMacroAssembler.*; -import static com.oracle.graal.api.code.CallingConvention.Type.*; -import static com.oracle.graal.api.code.ValueUtil.*; -import static com.oracle.graal.phases.GraalOptions.*; -import static java.lang.reflect.Modifier.*; - /** * HotSpot SPARC specific backend. */ @@ -72,8 +79,13 @@ } @Override - public LIRGenerator newLIRGenerator(StructuredGraph graph, Object stub, FrameMap frameMap, CallingConvention cc, LIR lir) { - return new SPARCHotSpotLIRGenerator(graph, stub, getProviders(), getRuntime().getConfig(), frameMap, cc, lir); + public LIRGenerator newLIRGenerator(CallingConvention cc, LIRGenerationResult lirGenRes) { + return new SPARCHotSpotLIRGenerator(getProviders(), getRuntime().getConfig(), cc, lirGenRes); + } + + @Override + public NodeLIRGenerator newNodeLIRGenerator(StructuredGraph graph, LIRGenerationResult lirGenRes, LIRGenerator lirGen) { + return new SPARCHotSpotNodeLIRGenerator(graph, lirGenRes, lirGen); } /** @@ -152,10 +164,10 @@ } @Override - public CompilationResultBuilder newCompilationResultBuilder(LIRGenerator lirGen, CompilationResult compilationResult, CompilationResultBuilderFactory factory) { - SPARCHotSpotLIRGenerator gen = (SPARCHotSpotLIRGenerator) lirGen; - FrameMap frameMap = gen.frameMap; - assert gen.deoptimizationRescueSlot == null || frameMap.frameNeedsAllocating() : "method that can deoptimize must have a frame"; + public CompilationResultBuilder newCompilationResultBuilder(LIRGenerationResult lirGenRes, CompilationResult compilationResult, CompilationResultBuilderFactory factory) { + SPARCHotSpotLIRGenerationResult gen = (SPARCHotSpotLIRGenerationResult) lirGenRes; + FrameMap frameMap = gen.getFrameMap(); + assert gen.getDeoptimizationRescueSlot() == null || frameMap.frameNeedsAllocating() : "method that can deoptimize must have a frame"; Stub stub = gen.getStub(); Assembler masm = createAssembler(frameMap); @@ -163,7 +175,7 @@ HotSpotFrameContext frameContext = new HotSpotFrameContext(stub != null); CompilationResultBuilder crb = factory.createBuilder(getProviders().getCodeCache(), getProviders().getForeignCalls(), frameMap, masm, frameContext, compilationResult); crb.setFrameSize(frameMap.frameSize()); - StackSlot deoptimizationRescueSlot = gen.deoptimizationRescueSlot; + StackSlot deoptimizationRescueSlot = gen.getDeoptimizationRescueSlot(); if (deoptimizationRescueSlot != null && stub == null) { crb.compilationResult.setCustomStackAreaOffset(frameMap.offsetForStackSlot(deoptimizationRescueSlot)); } @@ -179,6 +191,11 @@ } @Override + public LIRGenerationResult newLIRGenerationResult(LIR lir, FrameMap frameMap, Object stub) { + return new LIRGenerationResultBase(lir, frameMap); + } + + @Override public void emitCode(CompilationResultBuilder crb, LIR lir, ResolvedJavaMethod installedCodeOwner) { SPARCMacroAssembler masm = (SPARCMacroAssembler) crb.asm; FrameMap frameMap = crb.frameMap; @@ -233,4 +250,5 @@ public NativeFunctionInterface getNativeFunctionInterface() { throw GraalInternalError.unimplemented("No NativeFunctionInterface of SPARC"); } + }
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCHotSpotLIRGenerationResult.java Wed Mar 26 20:44:11 2014 +0100 @@ -0,0 +1,35 @@ +/* + * Copyright (c) 2014, 2014, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package com.oracle.graal.hotspot.sparc; + +import com.oracle.graal.api.code.*; +import com.oracle.graal.compiler.gen.*; +import com.oracle.graal.hotspot.stubs.*; + +public interface SPARCHotSpotLIRGenerationResult extends LIRGenerationResult { + + StackSlot getDeoptimizationRescueSlot(); + + Stub getStub(); + +}
--- a/graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCHotSpotLIRGenerator.java Wed Mar 26 14:43:50 2014 +0100 +++ b/graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCHotSpotLIRGenerator.java Wed Mar 26 20:44:11 2014 +0100 @@ -23,11 +23,7 @@ package com.oracle.graal.hotspot.sparc; import static com.oracle.graal.api.code.ValueUtil.*; -import static com.oracle.graal.hotspot.HotSpotBackend.*; import static com.oracle.graal.hotspot.HotSpotGraalRuntime.*; -import static com.oracle.graal.sparc.SPARC.*; - -import java.lang.reflect.*; import com.oracle.graal.api.code.*; import com.oracle.graal.api.meta.*; @@ -36,27 +32,22 @@ import com.oracle.graal.graph.*; import com.oracle.graal.hotspot.*; import com.oracle.graal.hotspot.meta.*; -import com.oracle.graal.hotspot.nodes.*; import com.oracle.graal.hotspot.stubs.*; import com.oracle.graal.lir.*; import com.oracle.graal.lir.sparc.*; -import com.oracle.graal.lir.sparc.SPARCMove.CompareAndSwapOp; import com.oracle.graal.lir.sparc.SPARCMove.LoadOp; import com.oracle.graal.lir.sparc.SPARCMove.StoreConstantOp; import com.oracle.graal.lir.sparc.SPARCMove.StoreOp; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.extended.*; -import com.oracle.graal.nodes.java.MethodCallTargetNode.InvokeKind; public class SPARCHotSpotLIRGenerator extends SPARCLIRGenerator implements HotSpotLIRGenerator { - private final HotSpotVMConfig config; - private final Object stub; + final HotSpotVMConfig config; - public SPARCHotSpotLIRGenerator(StructuredGraph graph, Object stub, HotSpotProviders providers, HotSpotVMConfig config, FrameMap frameMap, CallingConvention cc, LIR lir) { - super(graph, providers, frameMap, cc, lir); + public SPARCHotSpotLIRGenerator(HotSpotProviders providers, HotSpotVMConfig config, CallingConvention cc, LIRGenerationResult lirGenRes) { + super(providers, cc, lirGenRes); this.config = config; - this.stub = stub; } @Override @@ -69,28 +60,21 @@ * deoptimization. The return address slot in the callee is overwritten with the address of a * deoptimization stub. */ - StackSlot deoptimizationRescueSlot; - - @SuppressWarnings("hiding") - @Override - protected DebugInfoBuilder createDebugInfoBuilder(NodeMap<Value> nodeOperands) { - HotSpotLockStack lockStack = new HotSpotLockStack(frameMap, Kind.Long); - return new HotSpotDebugInfoBuilder(nodeOperands, lockStack); - } + private StackSlot deoptimizationRescueSlot; @Override public StackSlot getLockSlot(int lockDepth) { - return ((HotSpotDebugInfoBuilder) debugInfoBuilder).lockStack().makeLockSlot(lockDepth); + return ((HotSpotDebugInfoBuilder) getDebugInfoBuilder()).lockStack().makeLockSlot(lockDepth); } @Override protected boolean needOnlyOopMaps() { // Stubs only need oop maps - return stub != null; + return getStub() != null; } - Stub getStub() { - return (Stub) stub; + public Stub getStub() { + return ((SPARCHotSpotLIRGenerationResult) res).getStub(); } @Override @@ -113,74 +97,17 @@ } @Override - protected void emitReturn(Value input) { + public void emitReturn(Value input) { append(new SPARCHotSpotReturnOp(input, getStub() != null)); } @Override - public void visitSafepointNode(SafepointNode i) { - LIRFrameState info = state(i); - append(new SPARCHotSpotSafepointOp(info, config, this)); - } - - @Override - public void visitDirectCompareAndSwap(DirectCompareAndSwapNode x) { - Kind kind = x.newValue().getKind(); - assert kind == x.expectedValue().getKind(); - - Variable address = load(operand(x.object())); - Value offset = operand(x.offset()); - Variable cmpValue = (Variable) loadNonConst(operand(x.expectedValue())); - Variable newValue = load(operand(x.newValue())); - - if (ValueUtil.isConstant(offset)) { - assert !getCodeCache().needsDataPatch(asConstant(offset)); - Variable longAddress = newVariable(Kind.Long); - emitMove(longAddress, address); - address = emitAdd(longAddress, asConstant(offset)); - } else { - if (isLegal(offset)) { - address = emitAdd(address, offset); - } - } - - append(new CompareAndSwapOp(address, cmpValue, newValue)); - - Variable result = newVariable(x.getKind()); - emitMove(result, newValue); - setResult(x, result); - } - - @Override public void emitTailcall(Value[] args, Value address) { // append(new AMD64TailcallOp(args, address)); throw GraalInternalError.unimplemented(); } @Override - protected void emitDirectCall(DirectCallTargetNode callTarget, Value result, Value[] parameters, Value[] temps, LIRFrameState callState) { - InvokeKind invokeKind = ((HotSpotDirectCallTargetNode) callTarget).invokeKind(); - if (invokeKind == InvokeKind.Interface || invokeKind == InvokeKind.Virtual) { - append(new SPARCHotspotDirectVirtualCallOp(callTarget.target(), result, parameters, temps, callState, invokeKind)); - } else { - assert invokeKind == InvokeKind.Static || invokeKind == InvokeKind.Special; - HotSpotResolvedJavaMethod resolvedMethod = (HotSpotResolvedJavaMethod) callTarget.target(); - assert !Modifier.isAbstract(resolvedMethod.getModifiers()) : "Cannot make direct call to abstract method."; - Constant metaspaceMethod = resolvedMethod.getMetaspaceMethodConstant(); - append(new SPARCHotspotDirectStaticCallOp(callTarget.target(), result, parameters, temps, callState, invokeKind, metaspaceMethod)); - } - } - - @Override - protected void emitIndirectCall(IndirectCallTargetNode callTarget, Value result, Value[] parameters, Value[] temps, LIRFrameState callState) { - AllocatableValue metaspaceMethod = g5.asValue(); - emitMove(metaspaceMethod, operand(((HotSpotIndirectCallTargetNode) callTarget).metaspaceMethod())); - AllocatableValue targetAddress = g3.asValue(); - emitMove(targetAddress, operand(callTarget.computedAddress())); - append(new SPARCIndirectCallOp(callTarget.target(), result, parameters, temps, metaspaceMethod, targetAddress, callState)); - } - - @Override public void emitUnwind(Value exception) { ForeignCallLinkage linkage = getForeignCalls().lookupForeignCall(HotSpotBackend.UNWIND_EXCEPTION_TO_CALLER); CallingConvention linkageCc = linkage.getOutgoingCallingConvention(); @@ -214,26 +141,6 @@ append(new SPARCHotSpotDeoptimizeCallerOp()); } - @Override - public void emitPatchReturnAddress(ValueNode address) { - append(new SPARCHotSpotPatchReturnAddressOp(load(operand(address)))); - } - - @Override - public void emitJumpToExceptionHandlerInCaller(ValueNode handlerInCallerPc, ValueNode exception, ValueNode exceptionPc) { - Variable handler = load(operand(handlerInCallerPc)); - ForeignCallLinkage linkage = getForeignCalls().lookupForeignCall(EXCEPTION_HANDLER_IN_CALLER); - CallingConvention linkageCc = linkage.getOutgoingCallingConvention(); - assert linkageCc.getArgumentCount() == 2; - RegisterValue exceptionFixed = (RegisterValue) linkageCc.getArgument(0); - RegisterValue exceptionPcFixed = (RegisterValue) linkageCc.getArgument(1); - emitMove(exceptionFixed, operand(exception)); - emitMove(exceptionPcFixed, operand(exceptionPc)); - Register thread = getProviders().getRegisters().getThreadRegister(); - SPARCHotSpotJumpToExceptionHandlerInCallerOp op = new SPARCHotSpotJumpToExceptionHandlerInCallerOp(handler, exceptionFixed, exceptionPcFixed, config.threadIsMethodHandleReturnOffset, thread); - append(op); - } - private static boolean isCompressCandidate(Access access) { return access != null && access.isCompressible(); } @@ -321,8 +228,7 @@ return null; } - public void emitPrefetchAllocate(ValueNode address, ValueNode distance) { - SPARCAddressValue addr = emitAddress(operand(address), 0, loadNonConst(operand(distance)), 1); - append(new SPARCPrefetchOp(addr, config.allocatePrefetchInstr)); + public StackSlot getDeoptimizationRescueSlot() { + return deoptimizationRescueSlot; } }
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCHotSpotNodeLIRGenerator.java Wed Mar 26 20:44:11 2014 +0100 @@ -0,0 +1,144 @@ +/* + * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package com.oracle.graal.hotspot.sparc; + +import static com.oracle.graal.api.code.ValueUtil.*; +import static com.oracle.graal.hotspot.HotSpotBackend.*; +import static com.oracle.graal.sparc.SPARC.*; + +import java.lang.reflect.*; + +import com.oracle.graal.api.code.*; +import com.oracle.graal.api.meta.*; +import com.oracle.graal.compiler.gen.*; +import com.oracle.graal.compiler.sparc.*; +import com.oracle.graal.graph.*; +import com.oracle.graal.hotspot.*; +import com.oracle.graal.hotspot.meta.*; +import com.oracle.graal.hotspot.nodes.*; +import com.oracle.graal.lir.*; +import com.oracle.graal.lir.sparc.*; +import com.oracle.graal.lir.sparc.SPARCMove.CompareAndSwapOp; +import com.oracle.graal.nodes.*; +import com.oracle.graal.nodes.java.MethodCallTargetNode.InvokeKind; + +public class SPARCHotSpotNodeLIRGenerator extends SPARCNodeLIRGenerator implements HotSpotNodeLIRGenerator { + + public SPARCHotSpotNodeLIRGenerator(StructuredGraph graph, LIRGenerationResult lirGenRes, LIRGenerator lirGen) { + super(graph, lirGenRes, lirGen); + } + + @Override + protected DebugInfoBuilder createDebugInfoBuilder(NodeMap<Value> nodeOperands) { + HotSpotLockStack lockStack = new HotSpotLockStack(res.getFrameMap(), Kind.Long); + return new HotSpotDebugInfoBuilder(nodeOperands, lockStack); + } + + private SPARCHotSpotLIRGenerator getGen() { + return (SPARCHotSpotLIRGenerator) gen; + } + + @Override + public void visitSafepointNode(SafepointNode i) { + LIRFrameState info = state(i); + append(new SPARCHotSpotSafepointOp(info, getGen().config, gen)); + } + + @Override + public void visitDirectCompareAndSwap(DirectCompareAndSwapNode x) { + Kind kind = x.newValue().getKind(); + assert kind == x.expectedValue().getKind(); + + Variable address = gen.load(operand(x.object())); + Value offset = operand(x.offset()); + Variable cmpValue = (Variable) gen.loadNonConst(operand(x.expectedValue())); + Variable newValue = gen.load(operand(x.newValue())); + + if (ValueUtil.isConstant(offset)) { + assert !gen.getCodeCache().needsDataPatch(asConstant(offset)); + Variable longAddress = newVariable(Kind.Long); + gen.emitMove(longAddress, address); + address = getGen().emitAdd(longAddress, asConstant(offset)); + } else { + if (isLegal(offset)) { + address = getGen().emitAdd(address, offset); + } + } + + append(new CompareAndSwapOp(address, cmpValue, newValue)); + + Variable result = newVariable(x.getKind()); + gen.emitMove(result, newValue); + setResult(x, result); + } + + @Override + protected void emitDirectCall(DirectCallTargetNode callTarget, Value result, Value[] parameters, Value[] temps, LIRFrameState callState) { + InvokeKind invokeKind = ((HotSpotDirectCallTargetNode) callTarget).invokeKind(); + if (invokeKind == InvokeKind.Interface || invokeKind == InvokeKind.Virtual) { + append(new SPARCHotspotDirectVirtualCallOp(callTarget.target(), result, parameters, temps, callState, invokeKind)); + } else { + assert invokeKind == InvokeKind.Static || invokeKind == InvokeKind.Special; + HotSpotResolvedJavaMethod resolvedMethod = (HotSpotResolvedJavaMethod) callTarget.target(); + assert !Modifier.isAbstract(resolvedMethod.getModifiers()) : "Cannot make direct call to abstract method."; + Constant metaspaceMethod = resolvedMethod.getMetaspaceMethodConstant(); + append(new SPARCHotspotDirectStaticCallOp(callTarget.target(), result, parameters, temps, callState, invokeKind, metaspaceMethod)); + } + } + + @Override + protected void emitIndirectCall(IndirectCallTargetNode callTarget, Value result, Value[] parameters, Value[] temps, LIRFrameState callState) { + AllocatableValue metaspaceMethod = g5.asValue(); + gen.emitMove(metaspaceMethod, operand(((HotSpotIndirectCallTargetNode) callTarget).metaspaceMethod())); + AllocatableValue targetAddress = g3.asValue(); + gen.emitMove(targetAddress, operand(callTarget.computedAddress())); + append(new SPARCIndirectCallOp(callTarget.target(), result, parameters, temps, metaspaceMethod, targetAddress, callState)); + } + + @Override + public void emitPatchReturnAddress(ValueNode address) { + append(new SPARCHotSpotPatchReturnAddressOp(gen.load(operand(address)))); + } + + @Override + public void emitJumpToExceptionHandlerInCaller(ValueNode handlerInCallerPc, ValueNode exception, ValueNode exceptionPc) { + Variable handler = gen.load(operand(handlerInCallerPc)); + ForeignCallLinkage linkage = gen.getForeignCalls().lookupForeignCall(EXCEPTION_HANDLER_IN_CALLER); + CallingConvention linkageCc = linkage.getOutgoingCallingConvention(); + assert linkageCc.getArgumentCount() == 2; + RegisterValue exceptionFixed = (RegisterValue) linkageCc.getArgument(0); + RegisterValue exceptionPcFixed = (RegisterValue) linkageCc.getArgument(1); + gen.emitMove(exceptionFixed, operand(exception)); + gen.emitMove(exceptionPcFixed, operand(exceptionPc)); + Register thread = getGen().getProviders().getRegisters().getThreadRegister(); + SPARCHotSpotJumpToExceptionHandlerInCallerOp op = new SPARCHotSpotJumpToExceptionHandlerInCallerOp(handler, exceptionFixed, exceptionPcFixed, getGen().config.threadIsMethodHandleReturnOffset, + thread); + append(op); + } + + public void emitPrefetchAllocate(ValueNode address, ValueNode distance) { + SPARCAddressValue addr = getGen().emitAddress(operand(address), 0, getGen().loadNonConst(operand(distance)), 1); + append(new SPARCPrefetchOp(addr, getGen().config.allocatePrefetchInstr)); + } + +}
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/CompilationTask.java Wed Mar 26 14:43:50 2014 +0100 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/CompilationTask.java Wed Mar 26 20:44:11 2014 +0100 @@ -40,6 +40,7 @@ import com.oracle.graal.api.code.*; import com.oracle.graal.api.code.CallingConvention.Type; import com.oracle.graal.api.meta.*; +import com.oracle.graal.baseline.*; import com.oracle.graal.compiler.*; import com.oracle.graal.debug.*; import com.oracle.graal.debug.Debug.Scope; @@ -47,6 +48,7 @@ import com.oracle.graal.hotspot.bridge.*; import com.oracle.graal.hotspot.meta.*; import com.oracle.graal.hotspot.phases.*; +import com.oracle.graal.java.*; import com.oracle.graal.lir.asm.*; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.spi.*; @@ -248,34 +250,41 @@ final long allocatedBytesBefore = threadMXBean.getThreadAllocatedBytes(threadId); try (Scope s = Debug.scope("Compiling", new DebugDumpScope(String.valueOf(id), true))) { - Map<ResolvedJavaMethod, StructuredGraph> graphCache = null; - if (GraalOptions.CacheGraphs.getValue()) { - graphCache = new HashMap<>(); - } + + if (UseBaselineCompiler.getValue() == true) { + HotSpotProviders providers = backend.getProviders(); + BaselineCompiler baselineCompiler = new BaselineCompiler(GraphBuilderConfiguration.getDefault(), providers.getMetaAccess()); + result = baselineCompiler.generate(method, -1, backend, new CompilationResult(), method, CompilationResultBuilderFactory.Default); + } else { + Map<ResolvedJavaMethod, StructuredGraph> graphCache = null; + if (GraalOptions.CacheGraphs.getValue()) { + graphCache = new HashMap<>(); + } - HotSpotProviders providers = backend.getProviders(); - Replacements replacements = providers.getReplacements(); - graph = replacements.getMethodSubstitution(method); - if (graph == null || entryBCI != INVOCATION_ENTRY_BCI) { - graph = new StructuredGraph(method, entryBCI); - } else { - // Compiling method substitution - must clone the graph - graph = graph.copy(); + HotSpotProviders providers = backend.getProviders(); + Replacements replacements = providers.getReplacements(); + graph = replacements.getMethodSubstitution(method); + if (graph == null || entryBCI != INVOCATION_ENTRY_BCI) { + graph = new StructuredGraph(method, entryBCI); + } else { + // Compiling method substitution - must clone the graph + graph = graph.copy(); + } + InlinedBytecodes.add(method.getCodeSize()); + CallingConvention cc = getCallingConvention(providers.getCodeCache(), Type.JavaCallee, graph.method(), false); + if (graph.getEntryBCI() != StructuredGraph.INVOCATION_ENTRY_BCI) { + // for OSR, only a pointer is passed to the method. + JavaType[] parameterTypes = new JavaType[]{providers.getMetaAccess().lookupJavaType(long.class)}; + CallingConvention tmp = providers.getCodeCache().getRegisterConfig().getCallingConvention(JavaCallee, providers.getMetaAccess().lookupJavaType(void.class), parameterTypes, + backend.getTarget(), false); + cc = new CallingConvention(cc.getStackSize(), cc.getReturn(), tmp.getArgument(0)); + } + Suites suites = getSuites(providers); + ProfilingInfo profilingInfo = getProfilingInfo(); + OptimisticOptimizations optimisticOpts = getOptimisticOpts(profilingInfo); + result = compileGraph(graph, null, cc, method, providers, backend, backend.getTarget(), graphCache, getGraphBuilderSuite(providers), optimisticOpts, profilingInfo, + method.getSpeculationLog(), suites, new CompilationResult(), CompilationResultBuilderFactory.Default); } - InlinedBytecodes.add(method.getCodeSize()); - CallingConvention cc = getCallingConvention(providers.getCodeCache(), Type.JavaCallee, graph.method(), false); - if (graph.getEntryBCI() != StructuredGraph.INVOCATION_ENTRY_BCI) { - // for OSR, only a pointer is passed to the method. - JavaType[] parameterTypes = new JavaType[]{providers.getMetaAccess().lookupJavaType(long.class)}; - CallingConvention tmp = providers.getCodeCache().getRegisterConfig().getCallingConvention(JavaCallee, providers.getMetaAccess().lookupJavaType(void.class), parameterTypes, - backend.getTarget(), false); - cc = new CallingConvention(cc.getStackSize(), cc.getReturn(), tmp.getArgument(0)); - } - Suites suites = getSuites(providers); - ProfilingInfo profilingInfo = getProfilingInfo(); - OptimisticOptimizations optimisticOpts = getOptimisticOpts(profilingInfo); - result = compileGraph(graph, null, cc, method, providers, backend, backend.getTarget(), graphCache, getGraphBuilderSuite(providers), optimisticOpts, profilingInfo, - method.getSpeculationLog(), suites, new CompilationResult(), CompilationResultBuilderFactory.Default); result.setId(getId()); result.setEntryBCI(entryBCI); } catch (Throwable e) {
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotBackend.java Wed Mar 26 14:43:50 2014 +0100 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotBackend.java Wed Mar 26 20:44:11 2014 +0100 @@ -113,8 +113,8 @@ return value; } }; - for (Block block : lir.codeEmittingOrder()) { - for (LIRInstruction op : lir.lir(block)) { + for (AbstractBlock<?> block : lir.codeEmittingOrder()) { + for (LIRInstruction op : lir.getLIRforBlock(block)) { if (op instanceof LabelOp) { // Don't consider this as a definition } else {
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotLIRGenerator.java Wed Mar 26 14:43:50 2014 +0100 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotLIRGenerator.java Wed Mar 26 20:44:11 2014 +0100 @@ -26,13 +26,11 @@ import com.oracle.graal.api.meta.*; import com.oracle.graal.compiler.gen.*; import com.oracle.graal.hotspot.meta.*; -import com.oracle.graal.hotspot.nodes.*; -import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.spi.*; /** * This interface defines the contract a HotSpot backend LIR generator needs to fulfill in addition - * to abstract methods from {@link LIRGenerator} and {@link LIRGeneratorTool}. + * to abstract methods from {@link LIRGenerator} and {@link NodeLIRGeneratorTool}. */ public interface HotSpotLIRGenerator { @@ -46,14 +44,6 @@ void emitDeoptimizeCaller(DeoptimizationAction action, DeoptimizationReason reason); - void emitPatchReturnAddress(ValueNode address); - - void emitJumpToExceptionHandlerInCaller(ValueNode handlerInCallerPc, ValueNode exception, ValueNode exceptionPc); - - void emitPrefetchAllocate(ValueNode address, ValueNode distance); - - void visitDirectCompareAndSwap(DirectCompareAndSwapNode x); - /** * Gets a stack slot for a lock at a given lock nesting depth. */
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotNodeLIRGenerator.java Wed Mar 26 20:44:11 2014 +0100 @@ -0,0 +1,44 @@ +/* + * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package com.oracle.graal.hotspot; + +import com.oracle.graal.compiler.gen.*; +import com.oracle.graal.hotspot.nodes.*; +import com.oracle.graal.nodes.*; +import com.oracle.graal.nodes.spi.*; + +/** + * This interface defines the contract a HotSpot backend LIR generator needs to fulfill in addition + * to abstract methods from {@link LIRGenerator} and {@link NodeLIRGeneratorTool}. + */ +public interface HotSpotNodeLIRGenerator { + + void emitPatchReturnAddress(ValueNode address); + + void emitJumpToExceptionHandlerInCaller(ValueNode handlerInCallerPc, ValueNode exception, ValueNode exceptionPc); + + void emitPrefetchAllocate(ValueNode address, ValueNode distance); + + void visitDirectCompareAndSwap(DirectCompareAndSwapNode x); + +}
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotLoweringProvider.java Wed Mar 26 14:43:50 2014 +0100 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotLoweringProvider.java Wed Mar 26 20:44:11 2014 +0100 @@ -520,7 +520,7 @@ // mirroring the calculations in c1_GraphBuilder.cpp (setup_osr_entry_block) int localsOffset = (graph.method().getMaxLocals() - 1) * 8; for (OSRLocalNode osrLocal : graph.getNodes(OSRLocalNode.class)) { - int size = FrameStateBuilder.stackSlots(osrLocal.getKind()); + int size = HIRFrameStateBuilder.stackSlots(osrLocal.getKind()); int offset = localsOffset - (osrLocal.index() + size - 1) * 8; IndexedLocationNode location = IndexedLocationNode.create(ANY_LOCATION, osrLocal.getKind(), offset, ConstantNode.forLong(0, graph), graph, 1); ReadNode load = graph.add(new ReadNode(buffer, location, osrLocal.stamp(), BarrierType.NONE, false));
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotSignature.java Wed Mar 26 14:43:50 2014 +0100 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotSignature.java Wed Mar 26 20:44:11 2014 +0100 @@ -122,7 +122,7 @@ public int getParameterSlots(boolean withReceiver) { int argSlots = 0; for (int i = 0; i < getParameterCount(false); i++) { - argSlots += FrameStateBuilder.stackSlots(getParameterKind(i)); + argSlots += HIRFrameStateBuilder.stackSlots(getParameterKind(i)); } return argSlots + (withReceiver ? 1 : 0); }
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/AllocaNode.java Wed Mar 26 14:43:50 2014 +0100 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/AllocaNode.java Wed Mar 26 20:44:11 2014 +0100 @@ -30,13 +30,14 @@ import com.oracle.graal.compiler.target.*; import com.oracle.graal.hotspot.*; import com.oracle.graal.nodes.*; +import com.oracle.graal.nodes.spi.*; import com.oracle.graal.nodes.type.*; /** * Reserves a block of memory in the stack frame of a method. The block is reserved in the frame for * the entire execution of the associated method. */ -public final class AllocaNode extends FixedWithNextNode implements LIRGenLowerable { +public final class AllocaNode extends FixedWithNextNode implements LIRGenResLowerable { /** * The number of slots in block. @@ -57,9 +58,9 @@ } @Override - public void generate(LIRGenerator gen) { - StackSlot array = gen.frameMap().allocateStackSlots(slots, objects, null); - Value result = gen.emitAddress(array); + public void generate(NodeLIRGeneratorTool gen, LIRGenerationResult res) { + StackSlot array = res.getFrameMap().allocateStackSlots(slots, objects, null); + Value result = gen.getLIRGeneratorTool().emitAddress(array); gen.setResult(this, result); } }
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/BeginLockScopeNode.java Wed Mar 26 14:43:50 2014 +0100 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/BeginLockScopeNode.java Wed Mar 26 20:44:11 2014 +0100 @@ -57,11 +57,11 @@ } @Override - public void generate(LIRGenerator gen) { + public void generate(NodeLIRGenerator gen) { assert lockDepth != -1; - HotSpotLIRGenerator hsGen = (HotSpotLIRGenerator) gen; + HotSpotLIRGenerator hsGen = (HotSpotLIRGenerator) gen.getLIRGeneratorTool(); StackSlot slot = hsGen.getLockSlot(lockDepth); - Value result = gen.emitAddress(slot); + Value result = gen.getLIRGeneratorTool().emitAddress(slot); gen.setResult(this, result); }
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/CStringNode.java Wed Mar 26 14:43:50 2014 +0100 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/CStringNode.java Wed Mar 26 20:44:11 2014 +0100 @@ -41,13 +41,13 @@ this.string = string; } - public void generate(LIRGenerator gen) { + public void generate(NodeLIRGenerator gen) { gen.setResult(this, emitCString(gen, string)); } - public static AllocatableValue emitCString(LIRGeneratorTool gen, String value) { - AllocatableValue dst = gen.newVariable(gen.target().wordKind); - gen.emitData(dst, toCString(value)); + public static AllocatableValue emitCString(NodeLIRGeneratorTool gen, String value) { + AllocatableValue dst = gen.getLIRGeneratorTool().newVariable(gen.getLIRGeneratorTool().target().wordKind); + gen.getLIRGeneratorTool().emitData(dst, toCString(value)); return dst; }
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/CurrentJavaThreadNode.java Wed Mar 26 14:43:50 2014 +0100 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/CurrentJavaThreadNode.java Wed Mar 26 20:44:11 2014 +0100 @@ -41,8 +41,8 @@ } @Override - public void generate(LIRGeneratorTool gen) { - Register rawThread = ((HotSpotLIRGenerator) gen).getProviders().getRegisters().getThreadRegister(); + public void generate(NodeLIRGeneratorTool gen) { + Register rawThread = ((HotSpotLIRGenerator) gen.getLIRGeneratorTool()).getProviders().getRegisters().getThreadRegister(); gen.setResult(this, rawThread.asValue(this.getKind())); }
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/CurrentLockNode.java Wed Mar 26 14:43:50 2014 +0100 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/CurrentLockNode.java Wed Mar 26 20:44:11 2014 +0100 @@ -24,16 +24,15 @@ import com.oracle.graal.api.code.*; import com.oracle.graal.api.meta.*; -import com.oracle.graal.compiler.gen.*; -import com.oracle.graal.compiler.target.*; import com.oracle.graal.hotspot.*; import com.oracle.graal.nodes.*; +import com.oracle.graal.nodes.spi.*; import com.oracle.graal.word.*; /** * Intrinsic for getting the lock in the current {@linkplain BeginLockScopeNode lock scope}. */ -public final class CurrentLockNode extends FixedWithNextNode implements LIRGenLowerable { +public final class CurrentLockNode extends FixedWithNextNode implements LIRLowerable { private int lockDepth; @@ -43,12 +42,12 @@ } @Override - public void generate(LIRGenerator gen) { + public void generate(NodeLIRGeneratorTool gen) { assert lockDepth != -1; - HotSpotLIRGenerator hsGen = (HotSpotLIRGenerator) gen; + HotSpotLIRGenerator hsGen = (HotSpotLIRGenerator) gen.getLIRGeneratorTool(); StackSlot slot = hsGen.getLockSlot(lockDepth); // The register allocator cannot handle stack -> register moves so we use an LEA here - Value result = gen.emitMove(gen.emitAddress(slot)); + Value result = gen.getLIRGeneratorTool().emitMove(gen.getLIRGeneratorTool().emitAddress(slot)); gen.setResult(this, result); }
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/DeoptimizeCallerNode.java Wed Mar 26 14:43:50 2014 +0100 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/DeoptimizeCallerNode.java Wed Mar 26 20:44:11 2014 +0100 @@ -45,8 +45,8 @@ } @Override - public void generate(LIRGeneratorTool gen) { - ((HotSpotLIRGenerator) gen).emitDeoptimizeCaller(action, reason); + public void generate(NodeLIRGeneratorTool gen) { + ((HotSpotLIRGenerator) gen.getLIRGeneratorTool()).emitDeoptimizeCaller(action, reason); } @NodeIntrinsic
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/DimensionsNode.java Wed Mar 26 14:43:50 2014 +0100 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/DimensionsNode.java Wed Mar 26 20:44:11 2014 +0100 @@ -31,13 +31,14 @@ import com.oracle.graal.compiler.gen.*; import com.oracle.graal.compiler.target.*; import com.oracle.graal.nodes.*; +import com.oracle.graal.nodes.spi.*; import com.oracle.graal.word.*; /** * Intrinsic for allocating an on-stack array of integers to hold the dimensions of a multianewarray * instruction. */ -public final class DimensionsNode extends FixedWithNextNode implements LIRGenLowerable { +public final class DimensionsNode extends FixedWithNextNode implements LIRGenResLowerable { private final int rank; @@ -47,12 +48,12 @@ } @Override - public void generate(LIRGenerator gen) { + public void generate(NodeLIRGeneratorTool gen, LIRGenerationResult res) { int size = rank * 4; - int wordSize = gen.target().wordSize; + int wordSize = gen.getLIRGeneratorTool().target().wordSize; int slots = roundUp(size, wordSize) / wordSize; - StackSlot array = gen.frameMap().allocateStackSlots(slots, new BitSet(0), null); - Value result = gen.emitAddress(array); + StackSlot array = res.getFrameMap().allocateStackSlots(slots, new BitSet(0), null); + Value result = gen.getLIRGeneratorTool().emitAddress(array); gen.setResult(this, result); }
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/DirectCompareAndSwapNode.java Wed Mar 26 14:43:50 2014 +0100 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/DirectCompareAndSwapNode.java Wed Mar 26 20:44:11 2014 +0100 @@ -77,8 +77,8 @@ } @Override - public void generate(LIRGenerator gen) { - ((HotSpotLIRGenerator) gen).visitDirectCompareAndSwap(this); + public void generate(NodeLIRGenerator gen) { + ((HotSpotNodeLIRGenerator) gen).visitDirectCompareAndSwap(this); } /**
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/EndLockScopeNode.java Wed Mar 26 14:43:50 2014 +0100 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/EndLockScopeNode.java Wed Mar 26 20:44:11 2014 +0100 @@ -23,17 +23,16 @@ package com.oracle.graal.hotspot.nodes; import com.oracle.graal.api.meta.*; -import com.oracle.graal.compiler.gen.*; -import com.oracle.graal.compiler.target.*; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.extended.*; +import com.oracle.graal.nodes.spi.*; import com.oracle.graal.nodes.type.*; /** * Intrinsic for closing a {@linkplain BeginLockScopeNode scope} binding a stack-based lock with an * object. */ -public final class EndLockScopeNode extends AbstractMemoryCheckpoint implements LIRGenLowerable, MonitorExit, MemoryCheckpoint.Single { +public final class EndLockScopeNode extends AbstractMemoryCheckpoint implements LIRLowerable, MonitorExit, MemoryCheckpoint.Single { public EndLockScopeNode() { super(StampFactory.forVoid()); @@ -50,7 +49,7 @@ } @Override - public void generate(LIRGenerator gen) { + public void generate(NodeLIRGeneratorTool gen) { } @NodeIntrinsic
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/GetObjectAddressNode.java Wed Mar 26 14:43:50 2014 +0100 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/GetObjectAddressNode.java Wed Mar 26 20:44:11 2014 +0100 @@ -45,9 +45,9 @@ public static native long get(Object array); @Override - public void generate(LIRGeneratorTool gen) { - AllocatableValue obj = gen.newVariable(gen.target().wordKind); - gen.emitMove(obj, gen.operand(object)); + public void generate(NodeLIRGeneratorTool gen) { + AllocatableValue obj = gen.getLIRGeneratorTool().newVariable(gen.getLIRGeneratorTool().target().wordKind); + gen.getLIRGeneratorTool().emitMove(obj, gen.operand(object)); gen.setResult(this, obj); } }
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/JumpToExceptionHandlerInCallerNode.java Wed Mar 26 14:43:50 2014 +0100 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/JumpToExceptionHandlerInCallerNode.java Wed Mar 26 20:44:11 2014 +0100 @@ -46,8 +46,8 @@ } @Override - public void generate(LIRGeneratorTool gen) { - ((HotSpotLIRGenerator) gen).emitJumpToExceptionHandlerInCaller(handlerInCallerPc, exception, exceptionPc); + public void generate(NodeLIRGeneratorTool gen) { + ((HotSpotNodeLIRGenerator) gen).emitJumpToExceptionHandlerInCaller(handlerInCallerPc, exception, exceptionPc); } @NodeIntrinsic
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/MonitorCounterNode.java Wed Mar 26 14:43:50 2014 +0100 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/MonitorCounterNode.java Wed Mar 26 20:44:11 2014 +0100 @@ -29,22 +29,23 @@ import com.oracle.graal.compiler.gen.*; import com.oracle.graal.compiler.target.*; import com.oracle.graal.nodes.calc.*; +import com.oracle.graal.nodes.spi.*; import com.oracle.graal.word.*; /** * Node that is used to maintain a stack based counter of how many locks are currently held. */ -public final class MonitorCounterNode extends FloatingNode implements LIRGenLowerable { +public final class MonitorCounterNode extends FloatingNode implements LIRGenResLowerable { private MonitorCounterNode() { super(null); } @Override - public void generate(LIRGenerator gen) { + public void generate(NodeLIRGeneratorTool gen, LIRGenerationResult res) { assert graph().getNodes().filter(MonitorCounterNode.class).count() == 1 : "monitor counters not canonicalized to single instance"; - StackSlot counter = gen.frameMap().allocateStackSlots(1, new BitSet(0), null); - Value result = gen.emitAddress(counter); + StackSlot counter = res.getFrameMap().allocateStackSlots(1, new BitSet(0), null); + Value result = gen.getLIRGeneratorTool().emitAddress(counter); gen.setResult(this, result); }
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/MonitorExitStubCall.java Wed Mar 26 14:43:50 2014 +0100 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/MonitorExitStubCall.java Wed Mar 26 20:44:11 2014 +0100 @@ -47,12 +47,12 @@ } @Override - public void generate(LIRGenerator gen) { + public void generate(NodeLIRGenerator gen) { assert lockDepth != -1; - HotSpotLIRGenerator hsGen = (HotSpotLIRGenerator) gen; + HotSpotLIRGenerator hsGen = (HotSpotLIRGenerator) gen.getLIRGeneratorTool(); StackSlot slot = hsGen.getLockSlot(lockDepth); - ForeignCallLinkage linkage = gen.getForeignCalls().lookupForeignCall(MonitorExitStubCall.MONITOREXIT); - gen.emitForeignCall(linkage, this, gen.operand(object), gen.emitAddress(slot)); + ForeignCallLinkage linkage = gen.getLIRGeneratorTool().getForeignCalls().lookupForeignCall(MonitorExitStubCall.MONITOREXIT); + gen.getLIRGeneratorTool().emitForeignCall(linkage, this, gen.operand(object), gen.getLIRGeneratorTool().emitAddress(slot)); } @NodeIntrinsic
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/NewArrayStubCall.java Wed Mar 26 14:43:50 2014 +0100 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/NewArrayStubCall.java Wed Mar 26 20:44:11 2014 +0100 @@ -61,9 +61,9 @@ } @Override - public void generate(LIRGenerator gen) { - ForeignCallLinkage linkage = gen.getForeignCalls().lookupForeignCall(NEW_ARRAY); - Variable result = gen.emitForeignCall(linkage, this, gen.operand(hub), gen.operand(length)); + public void generate(NodeLIRGenerator gen) { + ForeignCallLinkage linkage = gen.getLIRGeneratorTool().getForeignCalls().lookupForeignCall(NEW_ARRAY); + Variable result = gen.getLIRGenerator().emitForeignCall(linkage, this, gen.operand(hub), gen.operand(length)); gen.setResult(this, result); }
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/NewInstanceStubCall.java Wed Mar 26 14:43:50 2014 +0100 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/NewInstanceStubCall.java Wed Mar 26 20:44:11 2014 +0100 @@ -24,19 +24,17 @@ import com.oracle.graal.api.code.*; import com.oracle.graal.api.meta.*; -import com.oracle.graal.compiler.gen.*; -import com.oracle.graal.compiler.target.*; import com.oracle.graal.hotspot.meta.*; import com.oracle.graal.hotspot.stubs.*; -import com.oracle.graal.lir.*; import com.oracle.graal.nodes.*; +import com.oracle.graal.nodes.spi.*; import com.oracle.graal.nodes.type.*; import com.oracle.graal.word.*; /** * A call to the {@link NewInstanceStub}. */ -public class NewInstanceStubCall extends DeoptimizingStubCall implements LIRGenLowerable { +public class NewInstanceStubCall extends DeoptimizingStubCall implements LIRLowerable { private static final Stamp defaultStamp = StampFactory.objectNonNull(); @@ -59,9 +57,9 @@ } @Override - public void generate(LIRGenerator gen) { - ForeignCallLinkage linkage = gen.getForeignCalls().lookupForeignCall(NEW_INSTANCE); - Variable result = gen.emitForeignCall(linkage, this, gen.operand(hub)); + public void generate(NodeLIRGeneratorTool gen) { + ForeignCallLinkage linkage = gen.getLIRGeneratorTool().getForeignCalls().lookupForeignCall(NEW_INSTANCE); + Value result = gen.getLIRGeneratorTool().emitForeignCall(linkage, this, gen.operand(hub)); gen.setResult(this, result); }
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/NewMultiArrayStubCall.java Wed Mar 26 14:43:50 2014 +0100 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/NewMultiArrayStubCall.java Wed Mar 26 20:44:11 2014 +0100 @@ -61,7 +61,7 @@ } @Override - protected Value[] operands(LIRGeneratorTool gen) { + protected Value[] operands(NodeLIRGeneratorTool gen) { return new Value[]{gen.operand(hub), Constant.forInt(rank), gen.operand(dims)}; }
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/PatchReturnAddressNode.java Wed Mar 26 14:43:50 2014 +0100 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/PatchReturnAddressNode.java Wed Mar 26 20:44:11 2014 +0100 @@ -41,8 +41,8 @@ } @Override - public void generate(LIRGeneratorTool gen) { - ((HotSpotLIRGenerator) gen).emitPatchReturnAddress(address); + public void generate(NodeLIRGeneratorTool gen) { + ((HotSpotNodeLIRGenerator) gen).emitPatchReturnAddress(address); } @NodeIntrinsic
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/PrefetchAllocateNode.java Wed Mar 26 14:43:50 2014 +0100 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/PrefetchAllocateNode.java Wed Mar 26 20:44:11 2014 +0100 @@ -42,8 +42,8 @@ } @Override - public void generate(LIRGenerator gen) { - ((HotSpotLIRGenerator) gen).emitPrefetchAllocate(address, distance); + public void generate(NodeLIRGenerator gen) { + ((HotSpotNodeLIRGenerator) gen).emitPrefetchAllocate(address, distance); } @NodeIntrinsic
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/StubForeignCallNode.java Wed Mar 26 14:43:50 2014 +0100 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/StubForeignCallNode.java Wed Mar 26 20:44:11 2014 +0100 @@ -57,7 +57,7 @@ return foreignCalls.getKilledLocations(descriptor); } - protected Value[] operands(LIRGeneratorTool gen) { + protected Value[] operands(NodeLIRGeneratorTool gen) { Value[] operands = new Value[arguments.size()]; for (int i = 0; i < operands.length; i++) { operands[i] = gen.operand(arguments.get(i)); @@ -66,11 +66,11 @@ } @Override - public void generate(LIRGeneratorTool gen) { + public void generate(NodeLIRGeneratorTool gen) { assert graph().start() instanceof StubStartNode; - ForeignCallLinkage linkage = gen.getForeignCalls().lookupForeignCall(descriptor); + ForeignCallLinkage linkage = gen.getLIRGeneratorTool().getForeignCalls().lookupForeignCall(descriptor); Value[] operands = operands(gen); - Value result = gen.emitForeignCall(linkage, null, operands); + Value result = gen.getLIRGeneratorTool().emitForeignCall(linkage, null, operands); if (result != null) { gen.setResult(this, result); }
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/TailcallNode.java Wed Mar 26 14:43:50 2014 +0100 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/TailcallNode.java Wed Mar 26 20:44:11 2014 +0100 @@ -30,6 +30,7 @@ import com.oracle.graal.api.code.*; import com.oracle.graal.api.meta.*; import com.oracle.graal.compiler.gen.*; +import com.oracle.graal.compiler.target.*; import com.oracle.graal.hotspot.*; import com.oracle.graal.java.*; import com.oracle.graal.nodes.*; @@ -40,7 +41,7 @@ * Performs a tail call to the specified target compiled method, with the parameter taken from the * supplied FrameState. */ -public class TailcallNode extends FixedWithNextNode implements LIRLowerable { +public class TailcallNode extends FixedWithNextNode implements LIRGenResLowerable { @Input private FrameState frameState; @Input private ValueNode target; @@ -57,22 +58,20 @@ this.frameState = frameState; } - @Override - public void generate(LIRGeneratorTool generator) { - LIRGenerator gen = (LIRGenerator) generator; + public void generate(NodeLIRGeneratorTool gen, LIRGenerationResult res) { HotSpotVMConfig config = runtime().getConfig(); ResolvedJavaMethod method = frameState.method(); boolean isStatic = Modifier.isStatic(method.getModifiers()); JavaType[] signature = MetaUtil.signatureToTypes(method.getSignature(), isStatic ? null : method.getDeclaringClass()); - CallingConvention cc = gen.frameMap().registerConfig.getCallingConvention(CallingConvention.Type.JavaCall, null, signature, gen.target(), false); + CallingConvention cc = res.getFrameMap().registerConfig.getCallingConvention(CallingConvention.Type.JavaCall, null, signature, gen.getLIRGeneratorTool().target(), false); List<ValueNode> parameters = new ArrayList<>(); - for (int i = 0, slot = 0; i < cc.getArgumentCount(); i++, slot += FrameStateBuilder.stackSlots(frameState.localAt(slot).getKind())) { + for (int i = 0, slot = 0; i < cc.getArgumentCount(); i++, slot += HIRFrameStateBuilder.stackSlots(frameState.localAt(slot).getKind())) { parameters.add(frameState.localAt(slot)); } Value[] args = gen.visitInvokeArguments(cc, parameters); - Value address = gen.emitAddress(gen.operand(target), config.nmethodEntryOffset, Value.ILLEGAL, 0); - Value entry = gen.emitLoad(Kind.Long, address, null); + Value address = gen.getLIRGeneratorTool().emitAddress(gen.operand(target), config.nmethodEntryOffset, Value.ILLEGAL, 0); + Value entry = gen.getLIRGeneratorTool().emitLoad(Kind.Long, address, null); HotSpotLIRGenerator hsgen = (HotSpotLIRGenerator) gen; hsgen.emitTailcall(args, entry); }
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/VMErrorNode.java Wed Mar 26 14:43:50 2014 +0100 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/VMErrorNode.java Wed Mar 26 20:44:11 2014 +0100 @@ -27,9 +27,8 @@ import com.oracle.graal.api.code.*; import com.oracle.graal.api.meta.*; -import com.oracle.graal.compiler.gen.*; -import com.oracle.graal.compiler.target.*; import com.oracle.graal.nodes.*; +import com.oracle.graal.nodes.spi.*; import com.oracle.graal.nodes.type.*; import com.oracle.graal.replacements.*; @@ -37,11 +36,11 @@ * Causes the VM to exit with a description of the current Java location and an optional * {@linkplain Log#printf(String, long) formatted} error message specified. */ -public final class VMErrorNode extends DeoptimizingStubCall implements LIRGenLowerable { +public final class VMErrorNode extends DeoptimizingStubCall implements LIRLowerable { private final String format; @Input private ValueNode value; - public static final ForeignCallDescriptor VM_ERROR = new ForeignCallDescriptor("vm_error", void.class, long.class, long.class, long.class); + public static final ForeignCallDescriptor VM_ERROR = new ForeignCallDescriptor("vm_error", void.class, Object.class, Object.class, long.class); private VMErrorNode(String format, ValueNode value) { super(StampFactory.forVoid()); @@ -50,7 +49,7 @@ } @Override - public void generate(LIRGenerator gen) { + public void generate(NodeLIRGeneratorTool gen) { String whereString; if (stateBefore() != null) { String nl = CodeUtil.NEW_LINE; @@ -68,8 +67,8 @@ Value whereArg = emitCString(gen, whereString); Value formatArg = emitCString(gen, format); - ForeignCallLinkage linkage = gen.getForeignCalls().lookupForeignCall(VMErrorNode.VM_ERROR); - gen.emitForeignCall(linkage, null, whereArg, formatArg, gen.operand(value)); + ForeignCallLinkage linkage = gen.getLIRGeneratorTool().getForeignCalls().lookupForeignCall(VMErrorNode.VM_ERROR); + gen.getLIRGeneratorTool().emitForeignCall(linkage, null, whereArg, formatArg, gen.operand(value)); } @NodeIntrinsic
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.java/src/com/oracle/graal/java/AbstractFrameStateBuilder.java Wed Mar 26 20:44:11 2014 +0100 @@ -0,0 +1,204 @@ +package com.oracle.graal.java; + +import com.oracle.graal.api.meta.*; + +public abstract class AbstractFrameStateBuilder<T extends KindInterface> { + + protected final ResolvedJavaMethod method; + protected int stackSize; + + public AbstractFrameStateBuilder(ResolvedJavaMethod method) { + this.method = method; + } + + protected AbstractFrameStateBuilder(AbstractFrameStateBuilder other) { + this.method = other.method; + } + + /** + * Returns the size of the local variables. + * + * @return the size of the local variables + */ + public abstract int localsSize(); + + /** + * Gets the current size (height) of the stack. + */ + public int stackSize() { + return stackSize; + } + + /** + * Gets the value in the local variables at the specified index, without any sanity checking. + * + * @param i the index into the locals + * @return the instruction that produced the value for the specified local + */ + public abstract T localAt(int i); + + /** + * Get the value on the stack at the specified stack index. + * + * @param i the index into the stack, with {@code 0} being the bottom of the stack + * @return the instruction at the specified position in the stack + */ + public abstract T stackAt(int i); + + /** + * Loads the local variable at the specified index, checking that the returned value is non-null + * and that two-stack values are properly handled. + * + * @param i the index of the local variable to load + * @return the instruction that produced the specified local + */ + public abstract T loadLocal(int i); + + /** + * Stores a given local variable at the specified index. If the value occupies two slots, then + * the next local variable index is also overwritten. + * + * @param i the index at which to store + * @param x the instruction which produces the value for the local + */ + public abstract void storeLocal(int i, T x); + + public abstract void storeStack(int i, T x); + + /** + * Pushes an instruction onto the stack with the expected type. + * + * @param kind the type expected for this instruction + * @param x the instruction to push onto the stack + */ + public abstract void push(Kind kind, T x); + + /** + * Pushes a value onto the stack without checking the type. + * + * @param x the instruction to push onto the stack + */ + public abstract void xpush(T x); + + /** + * Pushes a value onto the stack and checks that it is an int. + * + * @param x the instruction to push onto the stack + */ + public abstract void ipush(T x); + + /** + * Pushes a value onto the stack and checks that it is a float. + * + * @param x the instruction to push onto the stack + */ + public abstract void fpush(T x); + + /** + * Pushes a value onto the stack and checks that it is an object. + * + * @param x the instruction to push onto the stack + */ + public abstract void apush(T x); + + /** + * Pushes a value onto the stack and checks that it is a long. + * + * @param x the instruction to push onto the stack + */ + public abstract void lpush(T x); + + /** + * Pushes a value onto the stack and checks that it is a double. + * + * @param x the instruction to push onto the stack + */ + public abstract void dpush(T x); + + public abstract void pushReturn(Kind kind, T x); + + /** + * Pops an instruction off the stack with the expected type. + * + * @param kind the expected type + * @return the instruction on the top of the stack + */ + public abstract T pop(Kind kind); + + /** + * Pops a value off of the stack without checking the type. + * + * @return x the instruction popped off the stack + */ + public abstract T xpop(); + + /** + * Pops a value off of the stack and checks that it is an int. + * + * @return x the instruction popped off the stack + */ + public abstract T ipop(); + + /** + * Pops a value off of the stack and checks that it is a float. + * + * @return x the instruction popped off the stack + */ + public abstract T fpop(); + + /** + * Pops a value off of the stack and checks that it is an object. + * + * @return x the instruction popped off the stack + */ + public abstract T apop(); + + /** + * Pops a value off of the stack and checks that it is a long. + * + * @return x the instruction popped off the stack + */ + public abstract T lpop(); + + /** + * Pops a value off of the stack and checks that it is a double. + * + * @return x the instruction popped off the stack + */ + public abstract T dpop(); + + /** + * Pop the specified number of slots off of this stack and return them as an array of + * instructions. + * + * @return an array containing the arguments off of the stack + */ + public abstract T[] popArguments(int slotSize, int argSize); + + /** + * Peeks an element from the operand stack. + * + * @param argumentNumber The number of the argument, relative from the top of the stack (0 = + * top). Long and double arguments only count as one argument, i.e., null-slots are + * ignored. + * @return The peeked argument. + */ + public abstract T peek(int argumentNumber); + + public static int stackSlots(Kind kind) { + return isTwoSlot(kind) ? 2 : 1; + } + + /** + * Clears all values on this stack. + */ + public void clearStack() { + stackSize = 0; + } + + protected static boolean isTwoSlot(Kind kind) { + assert kind != Kind.Void && kind != Kind.Illegal; + return kind == Kind.Long || kind == Kind.Double; + } + +}
--- a/graal/com.oracle.graal.java/src/com/oracle/graal/java/BciBlockMapping.java Wed Mar 26 14:43:50 2014 +0100 +++ b/graal/com.oracle.graal.java/src/com/oracle/graal/java/BciBlockMapping.java Wed Mar 26 20:44:11 2014 +0100 @@ -33,6 +33,7 @@ import com.oracle.graal.debug.*; import com.oracle.graal.debug.Debug.Scope; import com.oracle.graal.nodes.*; +import com.oracle.graal.nodes.cfg.*; /** * Builds a mapping between bytecodes and basic blocks and builds a conservative control flow graph @@ -73,33 +74,40 @@ */ public final class BciBlockMapping { - public static class Block implements Cloneable { + public static class BciBlock extends AbstractBlockBase<BciBlock> implements Cloneable { public int startBci; public int endBci; public boolean isExceptionEntry; public boolean isLoopHeader; public int loopId; - public int blockID; public FixedWithNextNode firstInstruction; - public FrameStateBuilder entryState; + public HIRFrameStateBuilder entryState; - public ArrayList<Block> successors = new ArrayList<>(2); + // public ArrayList<BciBlock> successors = new ArrayList<>(2); + // public ArrayList<BciBlock> predecessors = new ArrayList<>(2); // only used in the +// baseline + public long exits; private boolean visited; private boolean active; public long loops; - public HashMap<JsrScope, Block> jsrAlternatives; + public HashMap<JsrScope, BciBlock> jsrAlternatives; public JsrScope jsrScope = JsrScope.EMPTY_SCOPE; - public Block jsrSuccessor; + public BciBlock jsrSuccessor; public int jsrReturnBci; - public Block retSuccessor; + public BciBlock retSuccessor; public boolean endsWithRet = false; - public Block exceptionDispatchBlock() { + public BciBlock() { + this.successors = new ArrayList<>(); + this.predecessors = new ArrayList<>(); + } + + public BciBlock exceptionDispatchBlock() { if (successors.size() > 0 && successors.get(successors.size() - 1) instanceof ExceptionDispatchBlock) { return successors.get(successors.size() - 1); } @@ -113,9 +121,9 @@ return successors.size(); } - public Block copy() { + public BciBlock copy() { try { - Block block = (Block) super.clone(); + BciBlock block = (BciBlock) super.clone(); block.successors = new ArrayList<>(successors); return block; } catch (CloneNotSupportedException e) { @@ -125,7 +133,7 @@ @Override public String toString() { - StringBuilder sb = new StringBuilder("B").append(blockID); + StringBuilder sb = new StringBuilder("B").append(getId()); sb.append('[').append(startBci).append("->").append(endBci); if (isLoopHeader || isExceptionEntry) { sb.append(' '); @@ -139,9 +147,41 @@ sb.append(']'); return sb.toString(); } + + public Loop getLoop() { + // TODO Auto-generated method stub + return null; + } + + public int getLoopDepth() { + // TODO Auto-generated method stub + return 0; + } + + public boolean isLoopHeader() { + return isLoopHeader; + } + + public boolean isLoopEnd() { + // TODO Auto-generated method stub + return false; + } + + public boolean isExceptionEntry() { + // TODO Auto-generated method stub + return false; + } + + public BciBlock getSuccessor(int index) { + return successors.get(index); + } + + public BciBlock getPredecessor(int index) { + return predecessors.get(index); + } } - public static class ExceptionDispatchBlock extends Block { + public static class ExceptionDispatchBlock extends BciBlock { private HashMap<ExceptionHandler, ExceptionDispatchBlock> exceptionDispatch = new HashMap<>(); @@ -152,15 +192,15 @@ /** * The blocks found in this method, in reverse postorder. */ - public final List<Block> blocks; + public final List<BciBlock> blocks; public final ResolvedJavaMethod method; public boolean hasJsrBytecodes; - public Block startBlock; + public BciBlock startBlock; private final BytecodeStream stream; private final ExceptionHandler[] exceptionHandlers; - private Block[] blockMap; - public Block[] loopHeaders; + private BciBlock[] blockMap; + public BciBlock[] loopHeaders; public LocalLiveness liveness; @@ -173,9 +213,9 @@ this.method = method; exceptionHandlers = method.getExceptionHandlers(); stream = new BytecodeStream(method.getCode()); - this.blockMap = new Block[method.getCodeSize()]; + this.blockMap = new BciBlock[method.getCodeSize()]; this.blocks = new ArrayList<>(); - this.loopHeaders = new Block[64]; + this.loopHeaders = new BciBlock[64]; } /** @@ -218,13 +258,13 @@ } private boolean verify() { - for (Block block : blocks) { - assert blocks.get(block.blockID) == block; + for (BciBlock block : blocks) { + assert blocks.get(block.getId()) == block; - for (int i = 0; i < block.successors.size(); i++) { - Block sux = block.successors.get(i); + for (int i = 0; i < block.getSuccessorCount(); i++) { + BciBlock sux = block.getSuccessor(i); if (sux instanceof ExceptionDispatchBlock) { - assert i == block.successors.size() - 1 : "Only one exception handler allowed, and it must be last in successors list"; + assert i == block.getSuccessorCount() - 1 : "Only one exception handler allowed, and it must be last in successors list"; } } } @@ -234,14 +274,14 @@ private void initializeBlockIds() { for (int i = 0; i < blocks.size(); i++) { - blocks.get(i).blockID = i; + blocks.get(i).setId(i); } } private void makeExceptionEntries() { // start basic blocks at all exception handler blocks and mark them as exception entries for (ExceptionHandler h : this.exceptionHandlers) { - Block xhandler = makeBlock(h.getHandlerBCI()); + BciBlock xhandler = makeBlock(h.getHandlerBCI()); xhandler.isExceptionEntry = true; } } @@ -250,13 +290,13 @@ // iterate over the bytecodes top to bottom. // mark the entrypoints of basic blocks and build lists of successors for // all bytecodes that end basic blocks (i.e. goto, ifs, switches, throw, jsr, returns, ret) - Block current = null; + BciBlock current = null; stream.setBCI(0); while (stream.currentBC() != Bytecodes.END) { int bci = stream.currentBCI(); if (current == null || blockMap[bci] != null) { - Block b = makeBlock(bci); + BciBlock b = makeBlock(bci); if (current != null) { addSuccessor(current.endBci, b); } @@ -327,7 +367,7 @@ if (target == 0) { throw new JsrNotSupportedBailout("jsr target bci 0 not allowed"); } - Block b1 = makeBlock(target); + BciBlock b1 = makeBlock(target); current.jsrSuccessor = b1; current.jsrReturnBci = stream.nextBCI(); current = null; @@ -382,10 +422,10 @@ } } - private Block makeBlock(int startBci) { - Block oldBlock = blockMap[startBci]; + private BciBlock makeBlock(int startBci) { + BciBlock oldBlock = blockMap[startBci]; if (oldBlock == null) { - Block newBlock = new Block(); + BciBlock newBlock = new BciBlock(); newBlock.startBci = startBci; blockMap[startBci] = newBlock; return newBlock; @@ -393,14 +433,14 @@ } else if (oldBlock.startBci != startBci) { // Backward branch into the middle of an already processed block. // Add the correct fall-through successor. - Block newBlock = new Block(); + BciBlock newBlock = new BciBlock(); newBlock.startBci = startBci; newBlock.endBci = oldBlock.endBci; - newBlock.successors.addAll(oldBlock.successors); + newBlock.getSuccessors().addAll(oldBlock.getSuccessors()); oldBlock.endBci = startBci - 1; - oldBlock.successors.clear(); - oldBlock.successors.add(newBlock); + oldBlock.getSuccessors().clear(); + oldBlock.getSuccessors().add(newBlock); for (int i = startBci; i <= newBlock.endBci; i++) { blockMap[i] = newBlock; @@ -424,30 +464,30 @@ } } - private void addSuccessor(int predBci, Block sux) { - Block predecessor = blockMap[predBci]; + private void addSuccessor(int predBci, BciBlock sux) { + BciBlock predecessor = blockMap[predBci]; if (sux.isExceptionEntry) { throw new BailoutException("Exception handler can be reached by both normal and exceptional control flow"); } - predecessor.successors.add(sux); + predecessor.getSuccessors().add(sux); } - private final ArrayList<Block> jsrVisited = new ArrayList<>(); + private final ArrayList<BciBlock> jsrVisited = new ArrayList<>(); - private void createJsrAlternatives(Block block) { + private void createJsrAlternatives(BciBlock block) { jsrVisited.add(block); JsrScope scope = block.jsrScope; if (block.endsWithRet) { block.retSuccessor = blockMap[scope.nextReturnAddress()]; - block.successors.add(block.retSuccessor); + block.getSuccessors().add(block.retSuccessor); assert block.retSuccessor != block.jsrSuccessor; } - Debug.log("JSR alternatives block %s sux %s jsrSux %s retSux %s jsrScope %s", block, block.successors, block.jsrSuccessor, block.retSuccessor, block.jsrScope); + Debug.log("JSR alternatives block %s sux %s jsrSux %s retSux %s jsrScope %s", block, block.getSuccessors(), block.jsrSuccessor, block.retSuccessor, block.jsrScope); if (block.jsrSuccessor != null || !scope.isEmpty()) { - for (int i = 0; i < block.successors.size(); i++) { - Block successor = block.successors.get(i); + for (int i = 0; i < block.getSuccessorCount(); i++) { + BciBlock successor = block.getSuccessor(i); JsrScope nextScope = scope; if (successor == block.jsrSuccessor) { nextScope = scope.push(block.jsrReturnBci); @@ -459,7 +499,7 @@ throw new JsrNotSupportedBailout("unstructured control flow (" + successor.jsrScope + " " + nextScope + ")"); } if (!nextScope.isEmpty()) { - Block clone; + BciBlock clone; if (successor.jsrAlternatives != null && successor.jsrAlternatives.containsKey(nextScope)) { clone = successor.jsrAlternatives.get(nextScope); } else { @@ -470,7 +510,7 @@ clone.jsrScope = nextScope; successor.jsrAlternatives.put(nextScope, clone); } - block.successors.set(i, clone); + block.getSuccessors().set(i, clone); if (successor == block.jsrSuccessor) { block.jsrSuccessor = clone; } @@ -480,7 +520,7 @@ } } } - for (Block successor : block.successors) { + for (BciBlock successor : block.getSuccessors()) { if (!jsrVisited.contains(successor)) { createJsrAlternatives(successor); } @@ -509,9 +549,9 @@ curHandler.endBci = -1; curHandler.deoptBci = bci; curHandler.handler = h; - curHandler.successors.add(blockMap[h.getHandlerBCI()]); + curHandler.getSuccessors().add(blockMap[h.getHandlerBCI()]); if (lastHandler != null) { - curHandler.successors.add(lastHandler); + curHandler.getSuccessors().add(lastHandler); } exceptionDispatch.put(h, curHandler); } @@ -526,7 +566,7 @@ private void fixLoopBits() { do { loopChanges = false; - for (Block b : blocks) { + for (BciBlock b : blocks) { b.visited = false; } @@ -563,17 +603,17 @@ String n = System.lineSeparator(); StringBuilder sb = new StringBuilder(Debug.currentScope()).append("BlockMap ").append(name).append(" :"); sb.append(n); - Iterable<Block> it; + Iterable<BciBlock> it; if (blocks.isEmpty()) { it = new HashSet<>(Arrays.asList(blockMap)); } else { it = blocks; } - for (Block b : it) { + for (BciBlock b : it) { if (b == null) { continue; } - sb.append("B").append(b.blockID).append(" (").append(b.startBci).append(" -> ").append(b.endBci).append(")"); + sb.append("B").append(b.getId()).append(" (").append(b.startBci).append(" -> ").append(b.endBci).append(")"); if (b.isLoopHeader) { sb.append(" LoopHeader"); } @@ -581,8 +621,8 @@ sb.append(" ExceptionEntry"); } sb.append(n).append(" Sux : "); - for (Block s : b.successors) { - sb.append("B").append(s.blockID).append(" (").append(s.startBci).append(" -> ").append(s.endBci).append(")"); + for (BciBlock s : b.getSuccessors()) { + sb.append("B").append(s.getId()).append(" (").append(s.startBci).append(" -> ").append(s.endBci).append(")"); if (s.isExceptionEntry) { sb.append("!"); } @@ -594,7 +634,7 @@ while (l != 0) { int lMask = 1 << pos; if ((l & lMask) != 0) { - sb.append("B").append(loopHeaders[pos].blockID).append(" "); + sb.append("B").append(loopHeaders[pos].getId()).append(" "); l &= ~lMask; } pos++; @@ -605,7 +645,7 @@ while (l != 0) { int lMask = 1 << pos; if ((l & lMask) != 0) { - sb.append("B").append(loopHeaders[pos].blockID).append(" "); + sb.append("B").append(loopHeaders[pos].getId()).append(" "); l &= ~lMask; } pos++; @@ -625,7 +665,7 @@ * Mark the block as a loop header, using the next available loop number. Also checks for corner * cases that we don't want to compile. */ - private void makeLoopHeader(Block block) { + private void makeLoopHeader(BciBlock block) { if (!block.isLoopHeader) { block.isLoopHeader = true; @@ -655,11 +695,11 @@ } /** - * Depth-first traversal of the control flow graph. The flag {@linkplain Block#visited} is used - * to visit every block only once. The flag {@linkplain Block#active} is used to detect cycles - * (backward edges). + * Depth-first traversal of the control flow graph. The flag {@linkplain BciBlock#visited} is + * used to visit every block only once. The flag {@linkplain BciBlock#active} is used to detect + * cycles (backward edges). */ - private long computeBlockOrder(Block block) { + private long computeBlockOrder(BciBlock block) { if (block.visited) { if (block.active) { // Reached block via backward branch. @@ -677,7 +717,7 @@ block.active = true; long loops = 0; - for (Block successor : block.successors) { + for (BciBlock successor : block.getSuccessors()) { // Recursively process successors. loops |= computeBlockOrder(successor); } @@ -695,7 +735,7 @@ return loops; } - private long fixLoopBits(Block block) { + private long fixLoopBits(BciBlock block) { if (block.visited) { // Return cached loop information for this block. if (block.isLoopHeader) { @@ -707,11 +747,11 @@ block.visited = true; long loops = block.loops; - for (Block successor : block.successors) { + for (BciBlock successor : block.getSuccessors()) { // Recursively process successors. loops |= fixLoopBits(successor); } - for (Block successor : block.successors) { + for (BciBlock successor : block.getSuccessors()) { successor.exits = loops & ~successor.loops; } if (block.loops != loops) { @@ -734,7 +774,7 @@ public abstract class LocalLiveness { private void computeLiveness() { - for (Block block : blocks) { + for (BciBlock block : blocks) { computeLocalLiveness(block); } @@ -744,22 +784,22 @@ Debug.log("Iteration %d", iteration); changed = false; for (int i = blocks.size() - 1; i >= 0; i--) { - Block block = blocks.get(i); - int blockID = block.blockID; + BciBlock block = blocks.get(i); + int blockID = block.getId(); // log statements in IFs because debugLiveX creates a new String if (Debug.isLogEnabled()) { - Debug.logv(" start B%d [%d, %d] in: %s out: %s gen: %s kill: %s", block.blockID, block.startBci, block.endBci, debugLiveIn(blockID), debugLiveOut(blockID), + Debug.logv(" start B%d [%d, %d] in: %s out: %s gen: %s kill: %s", block.getId(), block.startBci, block.endBci, debugLiveIn(blockID), debugLiveOut(blockID), debugLiveGen(blockID), debugLiveKill(blockID)); } boolean blockChanged = (iteration == 0); - if (block.successors.size() > 0) { + if (block.getSuccessorCount() > 0) { int oldCardinality = liveOutCardinality(blockID); - for (Block sux : block.successors) { + for (BciBlock sux : block.getSuccessors()) { if (Debug.isLogEnabled()) { - Debug.log(" Successor B%d: %s", sux.blockID, debugLiveIn(sux.blockID)); + Debug.log(" Successor B%d: %s", sux.getId(), debugLiveIn(sux.getId())); } - propagateLiveness(blockID, sux.blockID); + propagateLiveness(blockID, sux.getId()); } blockChanged |= (oldCardinality != liveOutCardinality(blockID)); } @@ -767,7 +807,7 @@ if (blockChanged) { updateLiveness(blockID); if (Debug.isLogEnabled()) { - Debug.logv(" end B%d [%d, %d] in: %s out: %s gen: %s kill: %s", block.blockID, block.startBci, block.endBci, debugLiveIn(blockID), debugLiveOut(blockID), + Debug.logv(" end B%d [%d, %d] in: %s out: %s gen: %s kill: %s", block.getId(), block.startBci, block.endBci, debugLiveIn(blockID), debugLiveOut(blockID), debugLiveGen(blockID), debugLiveKill(blockID)); } } @@ -780,12 +820,12 @@ /** * Returns whether the local is live at the beginning of the given block. */ - public abstract boolean localIsLiveIn(Block block, int local); + public abstract boolean localIsLiveIn(BciBlock block, int local); /** * Returns whether the local is live at the end of the given block. */ - public abstract boolean localIsLiveOut(Block block, int local); + public abstract boolean localIsLiveOut(BciBlock block, int local); /** * Returns a string representation of the liveIn values of the given block. @@ -832,11 +872,11 @@ */ protected abstract void storeOne(int blockID, int local); - private void computeLocalLiveness(Block block) { + private void computeLocalLiveness(BciBlock block) { if (block.startBci < 0 || block.endBci < 0) { return; } - int blockID = block.blockID; + int blockID = block.getId(); stream.setBCI(block.startBci); while (stream.currentBCI() <= block.endBci) { switch (stream.currentBC()) { @@ -1043,14 +1083,14 @@ } @Override - public boolean localIsLiveIn(Block block, int local) { - int blockID = block.blockID; + public boolean localIsLiveIn(BciBlock block, int local) { + int blockID = block.getId(); return blockID >= Integer.MAX_VALUE ? false : (localsLiveIn[blockID] & (1L << local)) != 0L; } @Override - public boolean localIsLiveOut(Block block, int local) { - int blockID = block.blockID; + public boolean localIsLiveOut(BciBlock block, int local) { + int blockID = block.getId(); return blockID >= Integer.MAX_VALUE ? false : (localsLiveOut[blockID] & (1L << local)) != 0L; } } @@ -1128,13 +1168,13 @@ } @Override - public boolean localIsLiveIn(Block block, int local) { - return block.blockID >= Integer.MAX_VALUE ? true : localsLiveIn[block.blockID].get(local); + public boolean localIsLiveIn(BciBlock block, int local) { + return block.getId() >= Integer.MAX_VALUE ? true : localsLiveIn[block.getId()].get(local); } @Override - public boolean localIsLiveOut(Block block, int local) { - return block.blockID >= Integer.MAX_VALUE ? true : localsLiveOut[block.blockID].get(local); + public boolean localIsLiveOut(BciBlock block, int local) { + return block.getId() >= Integer.MAX_VALUE ? true : localsLiveOut[block.getId()].get(local); } } }
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.java/src/com/oracle/graal/java/BytecodeParseHelper.java Wed Mar 26 20:44:11 2014 +0100 @@ -0,0 +1,115 @@ +package com.oracle.graal.java; + +import static com.oracle.graal.bytecode.Bytecodes.*; + +import com.oracle.graal.api.meta.*; +import com.oracle.graal.graph.*; + +public class BytecodeParseHelper<T extends KindInterface> { + + private AbstractFrameStateBuilder<T> frameState; + + public BytecodeParseHelper(AbstractFrameStateBuilder<T> frameState) { + this.frameState = frameState; + } + + public void setCurrentFrameState(AbstractFrameStateBuilder<T> frameState) { + this.frameState = frameState; + } + + public void loadLocal(int index, Kind kind) { + frameState.push(kind, frameState.loadLocal(index)); + } + + public void storeLocal(Kind kind, int index) { + T value; + if (kind == Kind.Object) { + value = frameState.xpop(); + // astore and astore_<n> may be used to store a returnAddress (jsr) + assert value.getKind() == Kind.Object || value.getKind() == Kind.Int; + } else { + value = frameState.pop(kind); + } + frameState.storeLocal(index, value); + } + + public void stackOp(int opcode) { + switch (opcode) { + case POP: { + frameState.xpop(); + break; + } + case POP2: { + frameState.xpop(); + frameState.xpop(); + break; + } + case DUP: { + T w = frameState.xpop(); + frameState.xpush(w); + frameState.xpush(w); + break; + } + case DUP_X1: { + T w1 = frameState.xpop(); + T w2 = frameState.xpop(); + frameState.xpush(w1); + frameState.xpush(w2); + frameState.xpush(w1); + break; + } + case DUP_X2: { + T w1 = frameState.xpop(); + T w2 = frameState.xpop(); + T w3 = frameState.xpop(); + frameState.xpush(w1); + frameState.xpush(w3); + frameState.xpush(w2); + frameState.xpush(w1); + break; + } + case DUP2: { + T w1 = frameState.xpop(); + T w2 = frameState.xpop(); + frameState.xpush(w2); + frameState.xpush(w1); + frameState.xpush(w2); + frameState.xpush(w1); + break; + } + case DUP2_X1: { + T w1 = frameState.xpop(); + T w2 = frameState.xpop(); + T w3 = frameState.xpop(); + frameState.xpush(w2); + frameState.xpush(w1); + frameState.xpush(w3); + frameState.xpush(w2); + frameState.xpush(w1); + break; + } + case DUP2_X2: { + T w1 = frameState.xpop(); + T w2 = frameState.xpop(); + T w3 = frameState.xpop(); + T w4 = frameState.xpop(); + frameState.xpush(w2); + frameState.xpush(w1); + frameState.xpush(w4); + frameState.xpush(w3); + frameState.xpush(w2); + frameState.xpush(w1); + break; + } + case SWAP: { + T w1 = frameState.xpop(); + T w2 = frameState.xpop(); + frameState.xpush(w1); + frameState.xpush(w2); + break; + } + default: + throw GraalInternalError.shouldNotReachHere(); + } + } +}
--- a/graal/com.oracle.graal.java/src/com/oracle/graal/java/FrameStateBuilder.java Wed Mar 26 14:43:50 2014 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,707 +0,0 @@ -/* - * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ -package com.oracle.graal.java; - -import static com.oracle.graal.graph.iterators.NodePredicates.*; -import static com.oracle.graal.nodes.ValueNodeUtil.*; -import static java.lang.reflect.Modifier.*; - -import java.util.*; - -import com.oracle.graal.api.code.*; -import com.oracle.graal.api.meta.*; -import com.oracle.graal.debug.*; -import com.oracle.graal.graph.Node.Verbosity; -import com.oracle.graal.java.BciBlockMapping.Block; -import com.oracle.graal.java.BciBlockMapping.LocalLiveness; -import com.oracle.graal.nodes.*; -import com.oracle.graal.nodes.calc.*; -import com.oracle.graal.nodes.java.*; -import com.oracle.graal.nodes.type.*; -import com.oracle.graal.nodes.util.*; - -public class FrameStateBuilder { - - private static final ValueNode[] EMPTY_ARRAY = new ValueNode[0]; - private static final MonitorIdNode[] EMPTY_MONITOR_ARRAY = new MonitorIdNode[0]; - - private final ResolvedJavaMethod method; - private final StructuredGraph graph; - - private final ValueNode[] locals; - private final ValueNode[] stack; - private ValueNode[] lockedObjects; - private MonitorIdNode[] monitorIds; - - private int stackSize; - - /** - * @see BytecodeFrame#rethrowException - */ - private boolean rethrowException; - - public FrameStateBuilder(ResolvedJavaMethod method, StructuredGraph graph, boolean eagerResolve) { - assert graph != null; - this.method = method; - this.graph = graph; - this.locals = new ValueNode[method.getMaxLocals()]; - // we always need at least one stack slot (for exceptions) - this.stack = new ValueNode[Math.max(1, method.getMaxStackSize())]; - this.lockedObjects = EMPTY_ARRAY; - this.monitorIds = EMPTY_MONITOR_ARRAY; - - int javaIndex = 0; - int index = 0; - if (!isStatic(method.getModifiers())) { - // add the receiver - ParameterNode receiver = graph.unique(new ParameterNode(javaIndex, StampFactory.declaredNonNull(method.getDeclaringClass()))); - storeLocal(javaIndex, receiver); - javaIndex = 1; - index = 1; - } - Signature sig = method.getSignature(); - int max = sig.getParameterCount(false); - ResolvedJavaType accessingClass = method.getDeclaringClass(); - for (int i = 0; i < max; i++) { - JavaType type = sig.getParameterType(i, accessingClass); - if (eagerResolve) { - type = type.resolve(accessingClass); - } - Kind kind = type.getKind().getStackKind(); - Stamp stamp; - if (kind == Kind.Object && type instanceof ResolvedJavaType) { - stamp = StampFactory.declared((ResolvedJavaType) type); - } else { - stamp = StampFactory.forKind(kind); - } - ParameterNode param = graph.unique(new ParameterNode(index, stamp)); - storeLocal(javaIndex, param); - javaIndex += stackSlots(kind); - index++; - } - } - - private FrameStateBuilder(FrameStateBuilder other) { - method = other.method; - graph = other.graph; - locals = other.locals.clone(); - stack = other.stack.clone(); - lockedObjects = other.lockedObjects == EMPTY_ARRAY ? EMPTY_ARRAY : other.lockedObjects.clone(); - monitorIds = other.monitorIds == EMPTY_MONITOR_ARRAY ? EMPTY_MONITOR_ARRAY : other.monitorIds.clone(); - stackSize = other.stackSize; - rethrowException = other.rethrowException; - - assert locals.length == method.getMaxLocals(); - assert stack.length == Math.max(1, method.getMaxStackSize()); - assert lockedObjects.length == monitorIds.length; - } - - @Override - public String toString() { - StringBuilder sb = new StringBuilder(); - sb.append("[locals: ["); - for (int i = 0; i < locals.length; i++) { - sb.append(i == 0 ? "" : ",").append(locals[i] == null ? "_" : locals[i].toString(Verbosity.Id)); - } - sb.append("] stack: ["); - for (int i = 0; i < stackSize; i++) { - sb.append(i == 0 ? "" : ",").append(stack[i] == null ? "_" : stack[i].toString(Verbosity.Id)); - } - sb.append("] locks: ["); - for (int i = 0; i < lockedObjects.length; i++) { - sb.append(i == 0 ? "" : ",").append(lockedObjects[i].toString(Verbosity.Id)).append(" / ").append(monitorIds[i].toString(Verbosity.Id)); - } - sb.append("]"); - if (rethrowException) { - sb.append(" rethrowException"); - } - sb.append("]"); - return sb.toString(); - } - - public FrameState create(int bci) { - return graph.add(new FrameState(method, bci, locals, Arrays.asList(stack).subList(0, stackSize), lockedObjects, monitorIds, rethrowException, false)); - } - - public FrameStateBuilder copy() { - return new FrameStateBuilder(this); - } - - public boolean isCompatibleWith(FrameStateBuilder other) { - assert method.equals(other.method) && graph == other.graph && localsSize() == other.localsSize() : "Can only compare frame states of the same method"; - assert lockedObjects.length == monitorIds.length && other.lockedObjects.length == other.monitorIds.length : "mismatch between lockedObjects and monitorIds"; - - if (stackSize() != other.stackSize()) { - return false; - } - for (int i = 0; i < stackSize(); i++) { - ValueNode x = stackAt(i); - ValueNode y = other.stackAt(i); - if (x != y && (x == null || x.isDeleted() || y == null || y.isDeleted() || x.getKind() != y.getKind())) { - return false; - } - } - if (lockedObjects.length != other.lockedObjects.length) { - return false; - } - for (int i = 0; i < lockedObjects.length; i++) { - if (GraphUtil.originalValue(lockedObjects[i]) != GraphUtil.originalValue(other.lockedObjects[i]) || monitorIds[i] != other.monitorIds[i]) { - throw new BailoutException("unbalanced monitors"); - } - } - return true; - } - - public void merge(MergeNode block, FrameStateBuilder other) { - assert isCompatibleWith(other); - - for (int i = 0; i < localsSize(); i++) { - storeLocal(i, merge(localAt(i), other.localAt(i), block)); - } - for (int i = 0; i < stackSize(); i++) { - storeStack(i, merge(stackAt(i), other.stackAt(i), block)); - } - for (int i = 0; i < lockedObjects.length; i++) { - lockedObjects[i] = merge(lockedObjects[i], other.lockedObjects[i], block); - assert monitorIds[i] == other.monitorIds[i]; - } - } - - private ValueNode merge(ValueNode currentValue, ValueNode otherValue, MergeNode block) { - if (currentValue == null || currentValue.isDeleted()) { - return null; - - } else if (block.isPhiAtMerge(currentValue)) { - if (otherValue == null || otherValue.isDeleted() || currentValue.getKind() != otherValue.getKind()) { - propagateDelete((PhiNode) currentValue); - return null; - } - ((PhiNode) currentValue).addInput(otherValue); - return currentValue; - - } else if (currentValue != otherValue) { - assert !(block instanceof LoopBeginNode) : "Phi functions for loop headers are create eagerly for all locals and stack slots"; - if (otherValue == null || otherValue.isDeleted() || currentValue.getKind() != otherValue.getKind()) { - return null; - } - - PhiNode phi = graph.addWithoutUnique(new PhiNode(currentValue.stamp().unrestricted(), block)); - for (int i = 0; i < block.phiPredecessorCount(); i++) { - phi.addInput(currentValue); - } - phi.addInput(otherValue); - assert phi.valueCount() == block.phiPredecessorCount() + 1 : "valueCount=" + phi.valueCount() + " predSize= " + block.phiPredecessorCount(); - return phi; - - } else { - return currentValue; - } - } - - private void propagateDelete(FloatingNode node) { - assert node instanceof PhiNode || node instanceof ProxyNode; - if (node.isDeleted()) { - return; - } - // Collect all phi functions that use this phi so that we can delete them recursively (after - // we delete ourselves to avoid circles). - List<FloatingNode> propagateUsages = node.usages().filter(FloatingNode.class).filter(isA(PhiNode.class).or(ProxyNode.class)).snapshot(); - - // Remove the phi function from all FrameStates where it is used and then delete it. - assert node.usages().filter(isNotA(FrameState.class).nor(PhiNode.class).nor(ProxyNode.class)).isEmpty() : "phi function that gets deletes must only be used in frame states"; - node.replaceAtUsages(null); - node.safeDelete(); - - for (FloatingNode phiUsage : propagateUsages) { - propagateDelete(phiUsage); - } - } - - public void insertLoopPhis(LoopBeginNode loopBegin) { - for (int i = 0; i < localsSize(); i++) { - storeLocal(i, createLoopPhi(loopBegin, localAt(i))); - } - for (int i = 0; i < stackSize(); i++) { - storeStack(i, createLoopPhi(loopBegin, stackAt(i))); - } - for (int i = 0; i < lockedObjects.length; i++) { - lockedObjects[i] = createLoopPhi(loopBegin, lockedObjects[i]); - } - } - - public void insertLoopProxies(LoopExitNode loopExit, FrameStateBuilder loopEntryState) { - for (int i = 0; i < localsSize(); i++) { - ValueNode value = localAt(i); - if (value != null && (!loopEntryState.contains(value) || loopExit.loopBegin().isPhiAtMerge(value))) { - Debug.log(" inserting proxy for %s", value); - storeLocal(i, ProxyNode.forValue(value, loopExit, graph)); - } - } - for (int i = 0; i < stackSize(); i++) { - ValueNode value = stackAt(i); - if (value != null && (!loopEntryState.contains(value) || loopExit.loopBegin().isPhiAtMerge(value))) { - Debug.log(" inserting proxy for %s", value); - storeStack(i, ProxyNode.forValue(value, loopExit, graph)); - } - } - for (int i = 0; i < lockedObjects.length; i++) { - ValueNode value = lockedObjects[i]; - if (value != null && (!loopEntryState.contains(value) || loopExit.loopBegin().isPhiAtMerge(value))) { - Debug.log(" inserting proxy for %s", value); - lockedObjects[i] = ProxyNode.forValue(value, loopExit, graph); - } - } - } - - public void insertProxies(AbstractBeginNode begin) { - for (int i = 0; i < localsSize(); i++) { - ValueNode value = localAt(i); - if (value != null) { - Debug.log(" inserting proxy for %s", value); - storeLocal(i, ProxyNode.forValue(value, begin, graph)); - } - } - for (int i = 0; i < stackSize(); i++) { - ValueNode value = stackAt(i); - if (value != null) { - Debug.log(" inserting proxy for %s", value); - storeStack(i, ProxyNode.forValue(value, begin, graph)); - } - } - for (int i = 0; i < lockedObjects.length; i++) { - ValueNode value = lockedObjects[i]; - if (value != null) { - Debug.log(" inserting proxy for %s", value); - lockedObjects[i] = ProxyNode.forValue(value, begin, graph); - } - } - } - - private PhiNode createLoopPhi(MergeNode block, ValueNode value) { - if (value == null) { - return null; - } - assert !block.isPhiAtMerge(value) : "phi function for this block already created"; - - PhiNode phi = graph.addWithoutUnique(new PhiNode(value.stamp().unrestricted(), block)); - phi.addInput(value); - return phi; - } - - public void cleanupDeletedPhis() { - for (int i = 0; i < localsSize(); i++) { - if (localAt(i) != null && localAt(i).isDeleted()) { - assert localAt(i) instanceof PhiNode || localAt(i) instanceof ProxyNode : "Only phi and value proxies can be deleted during parsing: " + localAt(i); - storeLocal(i, null); - } - } - } - - public void clearNonLiveLocals(Block block, LocalLiveness liveness, boolean liveIn) { - if (liveness == null) { - return; - } - if (liveIn) { - for (int i = 0; i < locals.length; i++) { - if (!liveness.localIsLiveIn(block, i)) { - locals[i] = null; - } - } - } else { - for (int i = 0; i < locals.length; i++) { - if (!liveness.localIsLiveOut(block, i)) { - locals[i] = null; - } - } - } - } - - /** - * @see BytecodeFrame#rethrowException - */ - public boolean rethrowException() { - return rethrowException; - } - - /** - * @see BytecodeFrame#rethrowException - */ - public void setRethrowException(boolean b) { - rethrowException = b; - } - - /** - * Returns the size of the local variables. - * - * @return the size of the local variables - */ - public int localsSize() { - return locals.length; - } - - /** - * Gets the current size (height) of the stack. - */ - public int stackSize() { - return stackSize; - } - - /** - * Gets the value in the local variables at the specified index, without any sanity checking. - * - * @param i the index into the locals - * @return the instruction that produced the value for the specified local - */ - public final ValueNode localAt(int i) { - return locals[i]; - } - - /** - * Get the value on the stack at the specified stack index. - * - * @param i the index into the stack, with {@code 0} being the bottom of the stack - * @return the instruction at the specified position in the stack - */ - public final ValueNode stackAt(int i) { - return stack[i]; - } - - public final ValueNode lockAt(int i) { - return lockedObjects[i]; - } - - /** - * Adds a locked monitor to this frame state. - * - * @param object the object whose monitor will be locked. - */ - public void pushLock(ValueNode object, MonitorIdNode monitorId) { - assert object.isAlive() && object.getKind() == Kind.Object : "unexpected value: " + object; - lockedObjects = Arrays.copyOf(lockedObjects, lockedObjects.length + 1); - monitorIds = Arrays.copyOf(monitorIds, monitorIds.length + 1); - lockedObjects[lockedObjects.length - 1] = object; - monitorIds[monitorIds.length - 1] = monitorId; - assert lockedObjects.length == monitorIds.length; - } - - /** - * Removes a locked monitor from this frame state. - * - * @return the object whose monitor was removed from the locks list. - */ - public ValueNode popLock() { - try { - return lockedObjects[lockedObjects.length - 1]; - } finally { - lockedObjects = lockedObjects.length == 1 ? EMPTY_ARRAY : Arrays.copyOf(lockedObjects, lockedObjects.length - 1); - monitorIds = monitorIds.length == 1 ? EMPTY_MONITOR_ARRAY : Arrays.copyOf(monitorIds, monitorIds.length - 1); - } - } - - public MonitorIdNode peekMonitorId() { - return monitorIds[monitorIds.length - 1]; - } - - /** - * @return the current lock depth - */ - public int lockDepth() { - assert lockedObjects.length == monitorIds.length; - return lockedObjects.length; - } - - /** - * Loads the local variable at the specified index, checking that the returned value is non-null - * and that two-stack values are properly handled. - * - * @param i the index of the local variable to load - * @return the instruction that produced the specified local - */ - public ValueNode loadLocal(int i) { - ValueNode x = locals[i]; - assert !x.isDeleted(); - assert !isTwoSlot(x.getKind()) || locals[i + 1] == null; - assert i == 0 || locals[i - 1] == null || !isTwoSlot(locals[i - 1].getKind()); - return x; - } - - /** - * Stores a given local variable at the specified index. If the value occupies - * {@linkplain FrameStateBuilder#isTwoSlot(Kind) two slots}, then the next local variable index - * is also overwritten. - * - * @param i the index at which to store - * @param x the instruction which produces the value for the local - */ - public void storeLocal(int i, ValueNode x) { - assert x == null || x.isAlive() && x.getKind() != Kind.Void && x.getKind() != Kind.Illegal : "unexpected value: " + x; - locals[i] = x; - if (x != null && isTwoSlot(x.getKind())) { - // if this is a double word, then kill i+1 - locals[i + 1] = null; - } - if (x != null && i > 0) { - ValueNode p = locals[i - 1]; - if (p != null && isTwoSlot(p.getKind())) { - // if there was a double word at i - 1, then kill it - locals[i - 1] = null; - } - } - } - - public void storeStack(int i, ValueNode x) { - assert x == null || x.isAlive() && (stack[i] == null || x.getKind() == stack[i].getKind()) : "Method does not handle changes from one-slot to two-slot values or non-alive values"; - stack[i] = x; - } - - public void storeLock(int i, ValueNode x) { - assert x == null || x.isAlive() && (lockedObjects[i] == null || x.getKind() == lockedObjects[i].getKind()) : "unexpected lock value: " + x; - lockedObjects[i] = x; - } - - /** - * Pushes an instruction onto the stack with the expected type. - * - * @param kind the type expected for this instruction - * @param x the instruction to push onto the stack - */ - public void push(Kind kind, ValueNode x) { - assert x.isAlive() && x.getKind() != Kind.Void && x.getKind() != Kind.Illegal; - xpush(assertKind(kind, x)); - if (isTwoSlot(kind)) { - xpush(null); - } - } - - /** - * Pushes a value onto the stack without checking the type. - * - * @param x the instruction to push onto the stack - */ - public void xpush(ValueNode x) { - assert x == null || (x.isAlive() && x.getKind() != Kind.Void && x.getKind() != Kind.Illegal); - stack[stackSize++] = x; - } - - /** - * Pushes a value onto the stack and checks that it is an int. - * - * @param x the instruction to push onto the stack - */ - public void ipush(ValueNode x) { - xpush(assertInt(x)); - } - - /** - * Pushes a value onto the stack and checks that it is a float. - * - * @param x the instruction to push onto the stack - */ - public void fpush(ValueNode x) { - xpush(assertFloat(x)); - } - - /** - * Pushes a value onto the stack and checks that it is an object. - * - * @param x the instruction to push onto the stack - */ - public void apush(ValueNode x) { - xpush(assertObject(x)); - } - - /** - * Pushes a value onto the stack and checks that it is a long. - * - * @param x the instruction to push onto the stack - */ - public void lpush(ValueNode x) { - xpush(assertLong(x)); - xpush(null); - } - - /** - * Pushes a value onto the stack and checks that it is a double. - * - * @param x the instruction to push onto the stack - */ - public void dpush(ValueNode x) { - xpush(assertDouble(x)); - xpush(null); - } - - public void pushReturn(Kind kind, ValueNode x) { - if (kind != Kind.Void) { - push(kind.getStackKind(), x); - } - } - - /** - * Pops an instruction off the stack with the expected type. - * - * @param kind the expected type - * @return the instruction on the top of the stack - */ - public ValueNode pop(Kind kind) { - assert kind != Kind.Void; - if (isTwoSlot(kind)) { - xpop(); - } - return assertKind(kind, xpop()); - } - - /** - * Pops a value off of the stack without checking the type. - * - * @return x the instruction popped off the stack - */ - public ValueNode xpop() { - ValueNode result = stack[--stackSize]; - assert result == null || !result.isDeleted(); - return result; - } - - /** - * Pops a value off of the stack and checks that it is an int. - * - * @return x the instruction popped off the stack - */ - public ValueNode ipop() { - return assertInt(xpop()); - } - - /** - * Pops a value off of the stack and checks that it is a float. - * - * @return x the instruction popped off the stack - */ - public ValueNode fpop() { - return assertFloat(xpop()); - } - - /** - * Pops a value off of the stack and checks that it is an object. - * - * @return x the instruction popped off the stack - */ - public ValueNode apop() { - return assertObject(xpop()); - } - - /** - * Pops a value off of the stack and checks that it is a long. - * - * @return x the instruction popped off the stack - */ - public ValueNode lpop() { - assertHigh(xpop()); - return assertLong(xpop()); - } - - /** - * Pops a value off of the stack and checks that it is a double. - * - * @return x the instruction popped off the stack - */ - public ValueNode dpop() { - assertHigh(xpop()); - return assertDouble(xpop()); - } - - /** - * Pop the specified number of slots off of this stack and return them as an array of - * instructions. - * - * @return an array containing the arguments off of the stack - */ - public ValueNode[] popArguments(int slotSize, int argSize) { - int base = stackSize - slotSize; - ValueNode[] r = new ValueNode[argSize]; - int argIndex = 0; - int stackindex = 0; - while (stackindex < slotSize) { - ValueNode element = stack[base + stackindex]; - assert element != null; - r[argIndex++] = element; - stackindex += stackSlots(element.getKind()); - } - stackSize = base; - return r; - } - - /** - * Peeks an element from the operand stack. - * - * @param argumentNumber The number of the argument, relative from the top of the stack (0 = - * top). Long and double arguments only count as one argument, i.e., null-slots are - * ignored. - * @return The peeked argument. - */ - public ValueNode peek(int argumentNumber) { - int idx = stackSize() - 1; - for (int i = 0; i < argumentNumber; i++) { - if (stackAt(idx) == null) { - idx--; - assert isTwoSlot(stackAt(idx).getKind()); - } - idx--; - } - return stackAt(idx); - } - - /** - * Clears all values on this stack. - */ - public void clearStack() { - stackSize = 0; - } - - public static int stackSlots(Kind kind) { - return isTwoSlot(kind) ? 2 : 1; - } - - public static boolean isTwoSlot(Kind kind) { - assert kind != Kind.Void && kind != Kind.Illegal; - return kind == Kind.Long || kind == Kind.Double; - } - - public boolean contains(ValueNode value) { - for (int i = 0; i < localsSize(); i++) { - if (localAt(i) == value) { - return true; - } - } - for (int i = 0; i < stackSize(); i++) { - if (stackAt(i) == value) { - return true; - } - } - assert lockedObjects.length == monitorIds.length; - for (int i = 0; i < lockedObjects.length; i++) { - if (lockedObjects[i] == value || monitorIds[i] == value) { - return true; - } - } - return false; - } -}
--- a/graal/com.oracle.graal.java/src/com/oracle/graal/java/GraphBuilderPhase.java Wed Mar 26 14:43:50 2014 +0100 +++ b/graal/com.oracle.graal.java/src/com/oracle/graal/java/GraphBuilderPhase.java Wed Mar 26 20:44:11 2014 +0100 @@ -40,7 +40,7 @@ import com.oracle.graal.bytecode.*; import com.oracle.graal.debug.*; import com.oracle.graal.graph.*; -import com.oracle.graal.java.BciBlockMapping.Block; +import com.oracle.graal.java.BciBlockMapping.BciBlock; import com.oracle.graal.java.BciBlockMapping.ExceptionDispatchBlock; import com.oracle.graal.java.BciBlockMapping.LocalLiveness; import com.oracle.graal.nodes.*; @@ -117,8 +117,9 @@ private BytecodeStream stream; // the bytecode stream - protected FrameStateBuilder frameState; // the current execution state - private Block currentBlock; + protected HIRFrameStateBuilder frameState; // the current execution state + private BytecodeParseHelper<ValueNode> parseHelper; + private BciBlock currentBlock; private ValueNode methodSynchronizedObject; private ExceptionDispatchBlock unwindBlock; @@ -159,13 +160,13 @@ } } - private Block[] loopHeaders; + private BciBlock[] loopHeaders; private LocalLiveness liveness; /** * Gets the current frame state being processed by this builder. */ - protected FrameStateBuilder getCurrentFrameState() { + protected HIRFrameStateBuilder getCurrentFrameState() { return frameState; } @@ -202,7 +203,8 @@ unwindBlock = null; methodSynchronizedObject = null; this.currentGraph = graph; - this.frameState = new FrameStateBuilder(method, graph, graphBuilderConfig.eagerResolving()); + this.frameState = new HIRFrameStateBuilder(method, graph, graphBuilderConfig.eagerResolving()); + this.parseHelper = new BytecodeParseHelper<>(frameState); TTY.Filter filter = new TTY.Filter(PrintFilter.getValue(), method); try { build(); @@ -260,7 +262,7 @@ blockMap.startBlock.firstInstruction = lastInstr; } - for (Block block : blockMap.blocks) { + for (BciBlock block : blockMap.blocks) { processBlock(block); } processBlock(unwindBlock); @@ -295,13 +297,13 @@ protected void finishPrepare(FixedWithNextNode startInstr) { } - private Block unwindBlock(int bci) { + private BciBlock unwindBlock(int bci) { if (unwindBlock == null) { unwindBlock = new ExceptionDispatchBlock(); unwindBlock.startBci = -1; unwindBlock.endBci = -1; unwindBlock.deoptBci = bci; - unwindBlock.blockID = Integer.MAX_VALUE; + unwindBlock.setId(Integer.MAX_VALUE); } return unwindBlock; } @@ -438,7 +440,7 @@ assert bci == FrameState.BEFORE_BCI || bci == bci() : "invalid bci"; Debug.log("Creating exception dispatch edges at %d, exception object=%s, exception seen=%s", bci, exceptionObject, profilingInfo.getExceptionSeen(bci)); - Block dispatchBlock = currentBlock.exceptionDispatchBlock(); + BciBlock dispatchBlock = currentBlock.exceptionDispatchBlock(); /* * The exception dispatch block is always for the last bytecode of a block, so if we are * not at the endBci yet, there is no exception handler for this bci and we can unwind @@ -448,7 +450,7 @@ dispatchBlock = unwindBlock(bci); } - FrameStateBuilder dispatchState = frameState.copy(); + HIRFrameStateBuilder dispatchState = frameState.copy(); dispatchState.clearStack(); DispatchBeginNode dispatchBegin; @@ -582,7 +584,6 @@ default: throw GraalInternalError.shouldNotReachHere(); } - } private void genArithmeticOp(Kind result, int opcode) { @@ -740,15 +741,15 @@ } private void genGoto() { - appendGoto(createTarget(currentBlock.successors.get(0), frameState)); + appendGoto(createTarget(currentBlock.getSuccessor(0), frameState)); assert currentBlock.numNormalSuccessors() == 1; } private void ifNode(ValueNode x, Condition cond, ValueNode y) { assert !x.isDeleted() && !y.isDeleted(); assert currentBlock.numNormalSuccessors() == 2; - Block trueBlock = currentBlock.successors.get(0); - Block falseBlock = currentBlock.successors.get(1); + BciBlock trueBlock = currentBlock.getSuccessor(0); + BciBlock falseBlock = currentBlock.getSuccessor(1); if (trueBlock == falseBlock) { appendGoto(createTarget(trueBlock, frameState)); return; @@ -1210,7 +1211,7 @@ InvokeWithExceptionNode invoke = createInvokeWithException(callTarget, resultType); - Block nextBlock = currentBlock.successors.get(0); + BciBlock nextBlock = currentBlock.getSuccessor(0); invoke.setNext(createTarget(nextBlock, frameState)); } } @@ -1229,7 +1230,7 @@ DispatchBeginNode exceptionEdge = handleException(null, bci()); InvokeWithExceptionNode invoke = append(new InvokeWithExceptionNode(callTarget, exceptionEdge, bci())); frameState.pushReturn(resultType, invoke); - Block nextBlock = currentBlock.successors.get(0); + BciBlock nextBlock = currentBlock.getSuccessor(0); invoke.setStateAfter(frameState.create(nextBlock.startBci)); return invoke; } @@ -1267,7 +1268,7 @@ } private void genJsr(int dest) { - Block successor = currentBlock.jsrSuccessor; + BciBlock successor = currentBlock.jsrSuccessor; assert successor.startBci == dest : successor.startBci + " != " + dest + " @" + bci(); JsrScope scope = currentBlock.jsrScope; if (!successor.jsrScope.pop().equals(scope)) { @@ -1281,7 +1282,7 @@ } private void genRet(int localIndex) { - Block successor = currentBlock.retSuccessor; + BciBlock successor = currentBlock.retSuccessor; ValueNode local = frameState.loadLocal(localIndex); JsrScope scope = currentBlock.jsrScope; int retAddress = scope.nextReturnAddress(); @@ -1339,14 +1340,14 @@ double[] keyProbabilities = switchProbability(nofCases + 1, bci); Map<Integer, SuccessorInfo> bciToBlockSuccessorIndex = new HashMap<>(); - for (int i = 0; i < currentBlock.successors.size(); i++) { - assert !bciToBlockSuccessorIndex.containsKey(currentBlock.successors.get(i).startBci); - if (!bciToBlockSuccessorIndex.containsKey(currentBlock.successors.get(i).startBci)) { - bciToBlockSuccessorIndex.put(currentBlock.successors.get(i).startBci, new SuccessorInfo(i)); + for (int i = 0; i < currentBlock.getSuccessorCount(); i++) { + assert !bciToBlockSuccessorIndex.containsKey(currentBlock.getSuccessor(i).startBci); + if (!bciToBlockSuccessorIndex.containsKey(currentBlock.getSuccessor(i).startBci)) { + bciToBlockSuccessorIndex.put(currentBlock.getSuccessor(i).startBci, new SuccessorInfo(i)); } } - ArrayList<Block> actualSuccessors = new ArrayList<>(); + ArrayList<BciBlock> actualSuccessors = new ArrayList<>(); int[] keys = new int[nofCases]; int[] keySuccessors = new int[nofCases + 1]; int deoptSuccessorIndex = -1; @@ -1367,7 +1368,7 @@ SuccessorInfo info = bciToBlockSuccessorIndex.get(targetBci); if (info.actualIndex < 0) { info.actualIndex = nextSuccessorIndex++; - actualSuccessors.add(currentBlock.successors.get(info.blockIndex)); + actualSuccessors.add(currentBlock.getSuccessor(info.blockIndex)); } keySuccessors[i] = info.actualIndex; } @@ -1433,15 +1434,15 @@ private static class Target { FixedNode fixed; - FrameStateBuilder state; + HIRFrameStateBuilder state; - public Target(FixedNode fixed, FrameStateBuilder state) { + public Target(FixedNode fixed, HIRFrameStateBuilder state) { this.fixed = fixed; this.state = state; } } - private Target checkLoopExit(FixedNode target, Block targetBlock, FrameStateBuilder state) { + private Target checkLoopExit(FixedNode target, BciBlock targetBlock, HIRFrameStateBuilder state) { if (currentBlock != null) { long exits = currentBlock.loops & ~targetBlock.loops; if (exits != 0) { @@ -1449,7 +1450,7 @@ LoopExitNode lastLoopExit = null; int pos = 0; - ArrayList<Block> exitLoops = new ArrayList<>(Long.bitCount(exits)); + ArrayList<BciBlock> exitLoops = new ArrayList<>(Long.bitCount(exits)); do { long lMask = 1L << pos; if ((exits & lMask) != 0) { @@ -1459,10 +1460,10 @@ pos++; } while (exits != 0); - Collections.sort(exitLoops, new Comparator<Block>() { + Collections.sort(exitLoops, new Comparator<BciBlock>() { @Override - public int compare(Block o1, Block o2) { + public int compare(BciBlock o1, BciBlock o2) { return Long.bitCount(o2.loops) - Long.bitCount(o1.loops); } }); @@ -1471,8 +1472,8 @@ if (targetBlock instanceof ExceptionDispatchBlock) { bci = ((ExceptionDispatchBlock) targetBlock).deoptBci; } - FrameStateBuilder newState = state.copy(); - for (Block loop : exitLoops) { + HIRFrameStateBuilder newState = state.copy(); + for (BciBlock loop : exitLoops) { LoopBeginNode loopBegin = (LoopBeginNode) loop.firstInstruction; LoopExitNode loopExit = currentGraph.add(new LoopExitNode(loopBegin)); if (lastLoopExit != null) { @@ -1494,7 +1495,7 @@ return new Target(target, state); } - private FixedNode createTarget(double probability, Block block, FrameStateBuilder stateAfter) { + private FixedNode createTarget(double probability, BciBlock block, HIRFrameStateBuilder stateAfter) { assert probability >= 0 && probability <= 1.01 : probability; if (isNeverExecutedCode(probability)) { return currentGraph.add(new DeoptimizeNode(InvalidateReprofile, UnreachedCode)); @@ -1508,7 +1509,7 @@ return probability == 0 && optimisticOpts.removeNeverExecutedCode() && entryBCI == StructuredGraph.INVOCATION_ENTRY_BCI; } - private FixedNode createTarget(Block block, FrameStateBuilder state) { + private FixedNode createTarget(BciBlock block, HIRFrameStateBuilder state) { assert block != null && state != null; assert !block.isExceptionEntry || state.stackSize() == 1; @@ -1534,7 +1535,7 @@ } if (block.firstInstruction instanceof LoopBeginNode) { - assert block.isLoopHeader && currentBlock.blockID >= block.blockID : "must be backward branch"; + assert block.isLoopHeader && currentBlock.getId() >= block.getId() : "must be backward branch"; /* * Backward loop edge. We need to create a special LoopEndNode and merge with the * loop begin node created before. @@ -1547,7 +1548,7 @@ Debug.log("createTarget %s: merging backward branch to loop header %s, result: %s", block, loopBegin, result); return result; } - assert currentBlock == null || currentBlock.blockID < block.blockID : "must not be backward branch"; + assert currentBlock == null || currentBlock.getId() < block.getId() : "must not be backward branch"; assert block.firstInstruction.next() == null : "bytecodes already parsed for block"; if (block.firstInstruction instanceof BlockPlaceholderNode) { @@ -1588,7 +1589,7 @@ * Returns a block begin node with the specified state. If the specified probability is 0, * the block deoptimizes immediately. */ - private AbstractBeginNode createBlockTarget(double probability, Block block, FrameStateBuilder stateAfter) { + private AbstractBeginNode createBlockTarget(double probability, BciBlock block, HIRFrameStateBuilder stateAfter) { FixedNode target = createTarget(probability, block, stateAfter); AbstractBeginNode begin = AbstractBeginNode.begin(target); @@ -1597,7 +1598,7 @@ return begin; } - private ValueNode synchronizedObject(FrameStateBuilder state, ResolvedJavaMethod target) { + private ValueNode synchronizedObject(HIRFrameStateBuilder state, ResolvedJavaMethod target) { if (isStatic(target.getModifiers())) { return appendConstant(target.getDeclaringClass().getEncoding(Representation.JavaClass)); } else { @@ -1605,7 +1606,7 @@ } } - private void processBlock(Block block) { + private void processBlock(BciBlock block) { // Ignore blocks that have no predecessors by the time their bytecodes are parsed if (block == null || block.firstInstruction == null) { Debug.log("Ignoring block %s", block); @@ -1615,6 +1616,7 @@ lastInstr = block.firstInstruction; frameState = block.entryState; + parseHelper.setCurrentFrameState(frameState); currentBlock = block; frameState.cleanupDeletedPhis(); @@ -1681,8 +1683,8 @@ private void createExceptionDispatch(ExceptionDispatchBlock block) { assert frameState.stackSize() == 1 : frameState; if (block.handler.isCatchAll()) { - assert block.successors.size() == 1; - appendGoto(createTarget(block.successors.get(0), frameState)); + assert block.getSuccessorCount() == 1; + appendGoto(createTarget(block.getSuccessor(0), frameState)); return; } @@ -1695,7 +1697,7 @@ ResolvedJavaType resolvedCatchType = (ResolvedJavaType) catchType; for (ResolvedJavaType skippedType : graphBuilderConfig.getSkippedExceptionTypes()) { if (skippedType.isAssignableFrom(resolvedCatchType)) { - Block nextBlock = block.successors.size() == 1 ? unwindBlock(block.deoptBci) : block.successors.get(1); + BciBlock nextBlock = block.getSuccessorCount() == 1 ? unwindBlock(block.deoptBci) : block.getSuccessor(1); ValueNode exception = frameState.stackAt(0); FixedNode trueSuccessor = currentGraph.add(new DeoptimizeNode(InvalidateReprofile, UnreachedCode)); FixedNode nextDispatch = createTarget(nextBlock, frameState); @@ -1706,12 +1708,12 @@ } if (initialized) { - Block nextBlock = block.successors.size() == 1 ? unwindBlock(block.deoptBci) : block.successors.get(1); + BciBlock nextBlock = block.getSuccessorCount() == 1 ? unwindBlock(block.deoptBci) : block.getSuccessor(1); ValueNode exception = frameState.stackAt(0); CheckCastNode checkCast = currentGraph.add(new CheckCastNode((ResolvedJavaType) catchType, exception, null, false)); frameState.apop(); frameState.push(Kind.Object, checkCast); - FixedNode catchSuccessor = createTarget(block.successors.get(0), frameState); + FixedNode catchSuccessor = createTarget(block.getSuccessor(0), frameState); frameState.apop(); frameState.push(Kind.Object, exception); FixedNode nextDispatch = createTarget(nextBlock, frameState); @@ -1732,7 +1734,7 @@ return n instanceof ControlSplitNode || n instanceof ControlSinkNode; } - private void iterateBytecodesForBlock(Block block) { + private void iterateBytecodesForBlock(BciBlock block) { if (block.isLoopHeader) { // Create the loop header block, which later will merge the backward branches of the // loop. @@ -1818,10 +1820,10 @@ lastInstr = finishInstruction(lastInstr, frameState); if (bci < endBCI) { if (bci > block.endBci) { - assert !block.successors.get(0).isExceptionEntry; + assert !block.getSuccessor(0).isExceptionEntry; assert block.numNormalSuccessors() == 1; // we fell through to the next block, add a goto and break - appendGoto(createTarget(block.successors.get(0), frameState)); + appendGoto(createTarget(block.getSuccessor(0), frameState)); break; } } @@ -1835,7 +1837,7 @@ * @param state The current frame state. * @Returns Returns the (new) last instruction. */ - protected FixedWithNextNode finishInstruction(FixedWithNextNode instr, FrameStateBuilder state) { + protected FixedWithNextNode finishInstruction(FixedWithNextNode instr, HIRFrameStateBuilder state) { return instr; } @@ -1882,31 +1884,31 @@ case LDC : // fall through case LDC_W : // fall through case LDC2_W : genLoadConstant(stream.readCPI(), opcode); break; - case ILOAD : loadLocal(stream.readLocalIndex(), Kind.Int); break; - case LLOAD : loadLocal(stream.readLocalIndex(), Kind.Long); break; - case FLOAD : loadLocal(stream.readLocalIndex(), Kind.Float); break; - case DLOAD : loadLocal(stream.readLocalIndex(), Kind.Double); break; - case ALOAD : loadLocal(stream.readLocalIndex(), Kind.Object); break; + case ILOAD : parseHelper.loadLocal(stream.readLocalIndex(), Kind.Int); break; + case LLOAD : parseHelper.loadLocal(stream.readLocalIndex(), Kind.Long); break; + case FLOAD : parseHelper.loadLocal(stream.readLocalIndex(), Kind.Float); break; + case DLOAD : parseHelper.loadLocal(stream.readLocalIndex(), Kind.Double); break; + case ALOAD : parseHelper.loadLocal(stream.readLocalIndex(), Kind.Object); break; case ILOAD_0 : // fall through case ILOAD_1 : // fall through case ILOAD_2 : // fall through - case ILOAD_3 : loadLocal(opcode - ILOAD_0, Kind.Int); break; + case ILOAD_3 : parseHelper.loadLocal(opcode - ILOAD_0, Kind.Int); break; case LLOAD_0 : // fall through case LLOAD_1 : // fall through case LLOAD_2 : // fall through - case LLOAD_3 : loadLocal(opcode - LLOAD_0, Kind.Long); break; + case LLOAD_3 : parseHelper.loadLocal(opcode - LLOAD_0, Kind.Long); break; case FLOAD_0 : // fall through case FLOAD_1 : // fall through case FLOAD_2 : // fall through - case FLOAD_3 : loadLocal(opcode - FLOAD_0, Kind.Float); break; + case FLOAD_3 : parseHelper.loadLocal(opcode - FLOAD_0, Kind.Float); break; case DLOAD_0 : // fall through case DLOAD_1 : // fall through case DLOAD_2 : // fall through - case DLOAD_3 : loadLocal(opcode - DLOAD_0, Kind.Double); break; + case DLOAD_3 : parseHelper.loadLocal(opcode - DLOAD_0, Kind.Double); break; case ALOAD_0 : // fall through case ALOAD_1 : // fall through case ALOAD_2 : // fall through - case ALOAD_3 : loadLocal(opcode - ALOAD_0, Kind.Object); break; + case ALOAD_3 : parseHelper.loadLocal(opcode - ALOAD_0, Kind.Object); break; case IALOAD : genLoadIndexed(Kind.Int ); break; case LALOAD : genLoadIndexed(Kind.Long ); break; case FALOAD : genLoadIndexed(Kind.Float ); break;
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.java/src/com/oracle/graal/java/HIRFrameStateBuilder.java Wed Mar 26 20:44:11 2014 +0100 @@ -0,0 +1,579 @@ +/* + * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package com.oracle.graal.java; + +import static com.oracle.graal.graph.iterators.NodePredicates.*; +import static com.oracle.graal.nodes.ValueNodeUtil.*; +import static java.lang.reflect.Modifier.*; + +import java.util.*; + +import com.oracle.graal.api.code.*; +import com.oracle.graal.api.meta.*; +import com.oracle.graal.debug.*; +import com.oracle.graal.graph.Node.Verbosity; +import com.oracle.graal.java.BciBlockMapping.BciBlock; +import com.oracle.graal.java.BciBlockMapping.LocalLiveness; +import com.oracle.graal.nodes.*; +import com.oracle.graal.nodes.calc.*; +import com.oracle.graal.nodes.java.*; +import com.oracle.graal.nodes.type.*; +import com.oracle.graal.nodes.util.*; + +public class HIRFrameStateBuilder extends AbstractFrameStateBuilder<ValueNode> { + + private static final ValueNode[] EMPTY_ARRAY = new ValueNode[0]; + private static final MonitorIdNode[] EMPTY_MONITOR_ARRAY = new MonitorIdNode[0]; + + private final ValueNode[] locals; + private final ValueNode[] stack; + private ValueNode[] lockedObjects; + private MonitorIdNode[] monitorIds; + private final StructuredGraph graph; + + /** + * @see BytecodeFrame#rethrowException + */ + private boolean rethrowException; + + public HIRFrameStateBuilder(ResolvedJavaMethod method, StructuredGraph graph, boolean eagerResolve) { + super(method); + + assert graph != null; + + this.locals = new ValueNode[method.getMaxLocals()]; + // we always need at least one stack slot (for exceptions) + this.stack = new ValueNode[Math.max(1, method.getMaxStackSize())]; + this.lockedObjects = EMPTY_ARRAY; + this.monitorIds = EMPTY_MONITOR_ARRAY; + this.graph = graph; + + int javaIndex = 0; + int index = 0; + if (!isStatic(method.getModifiers())) { + // add the receiver + ParameterNode receiver = graph.unique(new ParameterNode(javaIndex, StampFactory.declaredNonNull(method.getDeclaringClass()))); + storeLocal(javaIndex, receiver); + javaIndex = 1; + index = 1; + } + Signature sig = method.getSignature(); + int max = sig.getParameterCount(false); + ResolvedJavaType accessingClass = method.getDeclaringClass(); + for (int i = 0; i < max; i++) { + JavaType type = sig.getParameterType(i, accessingClass); + if (eagerResolve) { + type = type.resolve(accessingClass); + } + Kind kind = type.getKind().getStackKind(); + Stamp stamp; + if (kind == Kind.Object && type instanceof ResolvedJavaType) { + stamp = StampFactory.declared((ResolvedJavaType) type); + } else { + stamp = StampFactory.forKind(kind); + } + ParameterNode param = graph.unique(new ParameterNode(index, stamp)); + storeLocal(javaIndex, param); + javaIndex += stackSlots(kind); + index++; + } + } + + private HIRFrameStateBuilder(HIRFrameStateBuilder other) { + super(other); + assert other.graph != null; + graph = other.graph; + locals = other.locals.clone(); + stack = other.stack.clone(); + lockedObjects = other.lockedObjects == EMPTY_ARRAY ? EMPTY_ARRAY : other.lockedObjects.clone(); + monitorIds = other.monitorIds == EMPTY_MONITOR_ARRAY ? EMPTY_MONITOR_ARRAY : other.monitorIds.clone(); + stackSize = other.stackSize; + rethrowException = other.rethrowException; + + assert locals.length == method.getMaxLocals(); + assert stack.length == Math.max(1, method.getMaxStackSize()); + assert lockedObjects.length == monitorIds.length; + } + + @Override + public String toString() { + StringBuilder sb = new StringBuilder(); + sb.append("[locals: ["); + for (int i = 0; i < locals.length; i++) { + sb.append(i == 0 ? "" : ",").append(locals[i] == null ? "_" : locals[i].toString(Verbosity.Id)); + } + sb.append("] stack: ["); + for (int i = 0; i < stackSize; i++) { + sb.append(i == 0 ? "" : ",").append(stack[i] == null ? "_" : stack[i].toString(Verbosity.Id)); + } + sb.append("] locks: ["); + for (int i = 0; i < lockedObjects.length; i++) { + sb.append(i == 0 ? "" : ",").append(lockedObjects[i].toString(Verbosity.Id)).append(" / ").append(monitorIds[i].toString(Verbosity.Id)); + } + sb.append("]"); + if (rethrowException) { + sb.append(" rethrowException"); + } + sb.append("]"); + return sb.toString(); + } + + public FrameState create(int bci) { + return graph.add(new FrameState(method, bci, locals, Arrays.asList(stack).subList(0, stackSize), lockedObjects, monitorIds, rethrowException, false)); + } + + public HIRFrameStateBuilder copy() { + return new HIRFrameStateBuilder(this); + } + + public boolean isCompatibleWith(HIRFrameStateBuilder other) { + assert method.equals(other.method) && graph == other.graph && localsSize() == other.localsSize() : "Can only compare frame states of the same method"; + assert lockedObjects.length == monitorIds.length && other.lockedObjects.length == other.monitorIds.length : "mismatch between lockedObjects and monitorIds"; + + if (stackSize() != other.stackSize()) { + return false; + } + for (int i = 0; i < stackSize(); i++) { + ValueNode x = stackAt(i); + ValueNode y = other.stackAt(i); + if (x != y && (x == null || x.isDeleted() || y == null || y.isDeleted() || x.getKind() != y.getKind())) { + return false; + } + } + if (lockedObjects.length != other.lockedObjects.length) { + return false; + } + for (int i = 0; i < lockedObjects.length; i++) { + if (GraphUtil.originalValue(lockedObjects[i]) != GraphUtil.originalValue(other.lockedObjects[i]) || monitorIds[i] != other.monitorIds[i]) { + throw new BailoutException("unbalanced monitors"); + } + } + return true; + } + + public void merge(MergeNode block, HIRFrameStateBuilder other) { + assert isCompatibleWith(other); + + for (int i = 0; i < localsSize(); i++) { + storeLocal(i, merge(localAt(i), other.localAt(i), block)); + } + for (int i = 0; i < stackSize(); i++) { + storeStack(i, merge(stackAt(i), other.stackAt(i), block)); + } + for (int i = 0; i < lockedObjects.length; i++) { + lockedObjects[i] = merge(lockedObjects[i], other.lockedObjects[i], block); + assert monitorIds[i] == other.monitorIds[i]; + } + } + + private ValueNode merge(ValueNode currentValue, ValueNode otherValue, MergeNode block) { + if (currentValue == null || currentValue.isDeleted()) { + return null; + + } else if (block.isPhiAtMerge(currentValue)) { + if (otherValue == null || otherValue.isDeleted() || currentValue.getKind() != otherValue.getKind()) { + propagateDelete((PhiNode) currentValue); + return null; + } + ((PhiNode) currentValue).addInput(otherValue); + return currentValue; + + } else if (currentValue != otherValue) { + assert !(block instanceof LoopBeginNode) : "Phi functions for loop headers are create eagerly for all locals and stack slots"; + if (otherValue == null || otherValue.isDeleted() || currentValue.getKind() != otherValue.getKind()) { + return null; + } + + PhiNode phi = graph.addWithoutUnique(new PhiNode(currentValue.stamp().unrestricted(), block)); + for (int i = 0; i < block.phiPredecessorCount(); i++) { + phi.addInput(currentValue); + } + phi.addInput(otherValue); + assert phi.valueCount() == block.phiPredecessorCount() + 1 : "valueCount=" + phi.valueCount() + " predSize= " + block.phiPredecessorCount(); + return phi; + + } else { + return currentValue; + } + } + + private void propagateDelete(FloatingNode node) { + assert node instanceof PhiNode || node instanceof ProxyNode; + if (node.isDeleted()) { + return; + } + // Collect all phi functions that use this phi so that we can delete them recursively (after + // we delete ourselves to avoid circles). + List<FloatingNode> propagateUsages = node.usages().filter(FloatingNode.class).filter(isA(PhiNode.class).or(ProxyNode.class)).snapshot(); + + // Remove the phi function from all FrameStates where it is used and then delete it. + assert node.usages().filter(isNotA(FrameState.class).nor(PhiNode.class).nor(ProxyNode.class)).isEmpty() : "phi function that gets deletes must only be used in frame states"; + node.replaceAtUsages(null); + node.safeDelete(); + + for (FloatingNode phiUsage : propagateUsages) { + propagateDelete(phiUsage); + } + } + + public void insertLoopPhis(LoopBeginNode loopBegin) { + for (int i = 0; i < localsSize(); i++) { + storeLocal(i, createLoopPhi(loopBegin, localAt(i))); + } + for (int i = 0; i < stackSize(); i++) { + storeStack(i, createLoopPhi(loopBegin, stackAt(i))); + } + for (int i = 0; i < lockedObjects.length; i++) { + lockedObjects[i] = createLoopPhi(loopBegin, lockedObjects[i]); + } + } + + public void insertLoopProxies(LoopExitNode loopExit, HIRFrameStateBuilder loopEntryState) { + for (int i = 0; i < localsSize(); i++) { + ValueNode value = localAt(i); + if (value != null && (!loopEntryState.contains(value) || loopExit.loopBegin().isPhiAtMerge(value))) { + Debug.log(" inserting proxy for %s", value); + storeLocal(i, ProxyNode.forValue(value, loopExit, graph)); + } + } + for (int i = 0; i < stackSize(); i++) { + ValueNode value = stackAt(i); + if (value != null && (!loopEntryState.contains(value) || loopExit.loopBegin().isPhiAtMerge(value))) { + Debug.log(" inserting proxy for %s", value); + storeStack(i, ProxyNode.forValue(value, loopExit, graph)); + } + } + for (int i = 0; i < lockedObjects.length; i++) { + ValueNode value = lockedObjects[i]; + if (value != null && (!loopEntryState.contains(value) || loopExit.loopBegin().isPhiAtMerge(value))) { + Debug.log(" inserting proxy for %s", value); + lockedObjects[i] = ProxyNode.forValue(value, loopExit, graph); + } + } + } + + public void insertProxies(AbstractBeginNode begin) { + for (int i = 0; i < localsSize(); i++) { + ValueNode value = localAt(i); + if (value != null) { + Debug.log(" inserting proxy for %s", value); + storeLocal(i, ProxyNode.forValue(value, begin, graph)); + } + } + for (int i = 0; i < stackSize(); i++) { + ValueNode value = stackAt(i); + if (value != null) { + Debug.log(" inserting proxy for %s", value); + storeStack(i, ProxyNode.forValue(value, begin, graph)); + } + } + for (int i = 0; i < lockedObjects.length; i++) { + ValueNode value = lockedObjects[i]; + if (value != null) { + Debug.log(" inserting proxy for %s", value); + lockedObjects[i] = ProxyNode.forValue(value, begin, graph); + } + } + } + + private PhiNode createLoopPhi(MergeNode block, ValueNode value) { + if (value == null) { + return null; + } + assert !block.isPhiAtMerge(value) : "phi function for this block already created"; + + PhiNode phi = graph.addWithoutUnique(new PhiNode(value.stamp().unrestricted(), block)); + phi.addInput(value); + return phi; + } + + public void cleanupDeletedPhis() { + for (int i = 0; i < localsSize(); i++) { + if (localAt(i) != null && localAt(i).isDeleted()) { + assert localAt(i) instanceof PhiNode || localAt(i) instanceof ProxyNode : "Only phi and value proxies can be deleted during parsing: " + localAt(i); + storeLocal(i, null); + } + } + } + + public void clearNonLiveLocals(BciBlock block, LocalLiveness liveness, boolean liveIn) { + if (liveness == null) { + return; + } + if (liveIn) { + for (int i = 0; i < locals.length; i++) { + if (!liveness.localIsLiveIn(block, i)) { + locals[i] = null; + } + } + } else { + for (int i = 0; i < locals.length; i++) { + if (!liveness.localIsLiveOut(block, i)) { + locals[i] = null; + } + } + } + } + + /** + * @see BytecodeFrame#rethrowException + */ + public boolean rethrowException() { + return rethrowException; + } + + /** + * @see BytecodeFrame#rethrowException + */ + public void setRethrowException(boolean b) { + rethrowException = b; + } + + @Override + public int localsSize() { + return locals.length; + } + + @Override + public ValueNode localAt(int i) { + return locals[i]; + } + + @Override + public ValueNode stackAt(int i) { + return stack[i]; + } + + /** + * Adds a locked monitor to this frame state. + * + * @param object the object whose monitor will be locked. + */ + public void pushLock(ValueNode object, MonitorIdNode monitorId) { + assert object.isAlive() && object.getKind() == Kind.Object : "unexpected value: " + object; + lockedObjects = Arrays.copyOf(lockedObjects, lockedObjects.length + 1); + monitorIds = Arrays.copyOf(monitorIds, monitorIds.length + 1); + lockedObjects[lockedObjects.length - 1] = object; + monitorIds[monitorIds.length - 1] = monitorId; + assert lockedObjects.length == monitorIds.length; + } + + /** + * Removes a locked monitor from this frame state. + * + * @return the object whose monitor was removed from the locks list. + */ + public ValueNode popLock() { + try { + return lockedObjects[lockedObjects.length - 1]; + } finally { + lockedObjects = lockedObjects.length == 1 ? EMPTY_ARRAY : Arrays.copyOf(lockedObjects, lockedObjects.length - 1); + monitorIds = monitorIds.length == 1 ? EMPTY_MONITOR_ARRAY : Arrays.copyOf(monitorIds, monitorIds.length - 1); + } + } + + public MonitorIdNode peekMonitorId() { + return monitorIds[monitorIds.length - 1]; + } + + /** + * @return the current lock depth + */ + public int lockDepth() { + assert lockedObjects.length == monitorIds.length; + return lockedObjects.length; + } + + @Override + public ValueNode loadLocal(int i) { + ValueNode x = locals[i]; + assert !x.isDeleted(); + assert !isTwoSlot(x.getKind()) || locals[i + 1] == null; + assert i == 0 || locals[i - 1] == null || !isTwoSlot(locals[i - 1].getKind()); + return x; + } + + @Override + public void storeLocal(int i, ValueNode x) { + assert x == null || x.isAlive() && x.getKind() != Kind.Void && x.getKind() != Kind.Illegal : "unexpected value: " + x; + locals[i] = x; + if (x != null && isTwoSlot(x.getKind())) { + // if this is a double word, then kill i+1 + locals[i + 1] = null; + } + if (x != null && i > 0) { + ValueNode p = locals[i - 1]; + if (p != null && isTwoSlot(p.getKind())) { + // if there was a double word at i - 1, then kill it + locals[i - 1] = null; + } + } + } + + @Override + public void storeStack(int i, ValueNode x) { + assert x == null || x.isAlive() && (stack[i] == null || x.getKind() == stack[i].getKind()) : "Method does not handle changes from one-slot to two-slot values or non-alive values"; + stack[i] = x; + } + + @Override + public void push(Kind kind, ValueNode x) { + assert x.isAlive() && x.getKind() != Kind.Void && x.getKind() != Kind.Illegal; + xpush(assertKind(kind, x)); + if (isTwoSlot(kind)) { + xpush(null); + } + } + + @Override + public void xpush(ValueNode x) { + assert x == null || (x.isAlive() && x.getKind() != Kind.Void && x.getKind() != Kind.Illegal); + stack[stackSize++] = x; + } + + @Override + public void ipush(ValueNode x) { + xpush(assertInt(x)); + } + + @Override + public void fpush(ValueNode x) { + xpush(assertFloat(x)); + } + + @Override + public void apush(ValueNode x) { + xpush(assertObject(x)); + } + + @Override + public void lpush(ValueNode x) { + xpush(assertLong(x)); + xpush(null); + } + + @Override + public void dpush(ValueNode x) { + xpush(assertDouble(x)); + xpush(null); + } + + @Override + public void pushReturn(Kind kind, ValueNode x) { + if (kind != Kind.Void) { + push(kind.getStackKind(), x); + } + } + + @Override + public ValueNode pop(Kind kind) { + assert kind != Kind.Void; + if (isTwoSlot(kind)) { + xpop(); + } + return assertKind(kind, xpop()); + } + + @Override + public ValueNode xpop() { + ValueNode result = stack[--stackSize]; + assert result == null || !result.isDeleted(); + return result; + } + + @Override + public ValueNode ipop() { + return assertInt(xpop()); + } + + @Override + public ValueNode fpop() { + return assertFloat(xpop()); + } + + @Override + public ValueNode apop() { + return assertObject(xpop()); + } + + @Override + public ValueNode lpop() { + assertHigh(xpop()); + return assertLong(xpop()); + } + + @Override + public ValueNode dpop() { + assertHigh(xpop()); + return assertDouble(xpop()); + } + + @Override + public ValueNode[] popArguments(int slotSize, int argSize) { + int base = stackSize - slotSize; + ValueNode[] r = new ValueNode[argSize]; + int argIndex = 0; + int stackindex = 0; + while (stackindex < slotSize) { + ValueNode element = stack[base + stackindex]; + assert element != null; + r[argIndex++] = element; + stackindex += stackSlots(element.getKind()); + } + stackSize = base; + return r; + } + + @Override + public ValueNode peek(int argumentNumber) { + int idx = stackSize() - 1; + for (int i = 0; i < argumentNumber; i++) { + if (stackAt(idx) == null) { + idx--; + assert isTwoSlot(stackAt(idx).getKind()); + } + idx--; + } + return stackAt(idx); + } + + public boolean contains(ValueNode value) { + for (int i = 0; i < localsSize(); i++) { + if (localAt(i) == value) { + return true; + } + } + for (int i = 0; i < stackSize(); i++) { + if (stackAt(i) == value) { + return true; + } + } + assert lockedObjects.length == monitorIds.length; + for (int i = 0; i < lockedObjects.length; i++) { + if (lockedObjects[i] == value || monitorIds[i] == value) { + return true; + } + } + return false; + } +}
--- a/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/ControlFlowOptimizer.java Wed Mar 26 14:43:50 2014 +0100 +++ b/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/ControlFlowOptimizer.java Wed Mar 26 20:44:11 2014 +0100 @@ -37,9 +37,8 @@ /** * Performs control flow optimizations on the given LIR graph. */ - public static void optimize(LIR lir) { - List<Block> blocks = lir.codeEmittingOrder(); - ControlFlowOptimizer.deleteEmptyBlocks(lir, blocks); + public static <T extends AbstractBlock<T>> void optimize(LIR lir, List<T> codeEmittingOrder) { + ControlFlowOptimizer.deleteEmptyBlocks(lir, codeEmittingOrder); } private ControlFlowOptimizer() { @@ -54,41 +53,41 @@ * @param block the block checked for deletion * @return whether the block can be deleted */ - private static boolean canDeleteBlock(LIR lir, Block block) { - if (block.getSuccessorCount() != 1 || block.getPredecessorCount() == 0 || block.getFirstSuccessor() == block) { + private static boolean canDeleteBlock(LIR lir, AbstractBlock<?> block) { + if (block.getSuccessorCount() != 1 || block.getPredecessorCount() == 0 || block.getSuccessors().iterator().next() == block) { return false; } - List<LIRInstruction> instructions = lir.lir(block); + List<LIRInstruction> instructions = lir.getLIRforBlock(block); assert instructions.size() >= 2 : "block must have label and branch"; assert instructions.get(0) instanceof StandardOp.LabelOp : "first instruction must always be a label"; assert instructions.get(instructions.size() - 1) instanceof StandardOp.JumpOp : "last instruction must always be a branch"; - assert ((StandardOp.JumpOp) instructions.get(instructions.size() - 1)).destination().label() == ((StandardOp.LabelOp) lir.lir(block.getFirstSuccessor()).get(0)).getLabel() : "branch target must be the successor"; + assert ((StandardOp.JumpOp) instructions.get(instructions.size() - 1)).destination().label() == ((StandardOp.LabelOp) lir.getLIRforBlock(block.getSuccessors().iterator().next()).get(0)).getLabel() : "branch target must be the successor"; // Block must have exactly one successor. return instructions.size() == 2 && !instructions.get(instructions.size() - 1).hasState() && !block.isExceptionEntry(); } - private static void alignBlock(LIR lir, Block block) { + private static void alignBlock(LIR lir, AbstractBlock<?> block) { if (!block.isAligned()) { block.setAlign(true); - List<LIRInstruction> instructions = lir.lir(block); + List<LIRInstruction> instructions = lir.getLIRforBlock(block); assert instructions.get(0) instanceof StandardOp.LabelOp : "first instruction must always be a label"; StandardOp.LabelOp label = (StandardOp.LabelOp) instructions.get(0); instructions.set(0, new StandardOp.LabelOp(label.getLabel(), true)); } } - private static void deleteEmptyBlocks(LIR lir, List<Block> blocks) { + private static <T extends AbstractBlock<T>> void deleteEmptyBlocks(LIR lir, List<T> blocks) { assert verifyBlocks(lir, blocks); - Iterator<Block> iterator = blocks.iterator(); + Iterator<T> iterator = blocks.iterator(); while (iterator.hasNext()) { - Block block = iterator.next(); + T block = iterator.next(); if (canDeleteBlock(lir, block)) { // adjust successor and predecessor lists - Block other = block.getFirstSuccessor(); - for (Block pred : block.getPredecessors()) { + T other = block.getSuccessors().iterator().next(); + for (AbstractBlock<T> pred : block.getPredecessors()) { Collections.replaceAll(pred.getSuccessors(), block, other); } for (int i = 0; i < other.getPredecessorCount(); i++) {
--- a/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/EdgeMoveOptimizer.java Wed Mar 26 14:43:50 2014 +0100 +++ b/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/EdgeMoveOptimizer.java Wed Mar 26 20:44:11 2014 +0100 @@ -53,10 +53,10 @@ public static void optimize(LIR ir) { EdgeMoveOptimizer optimizer = new EdgeMoveOptimizer(ir); - List<Block> blockList = ir.linearScanOrder(); + List<? extends AbstractBlock<?>> blockList = ir.linearScanOrder(); // ignore the first block in the list (index 0 is not processed) for (int i = blockList.size() - 1; i >= 1; i--) { - Block block = blockList.get(i); + AbstractBlock<?> block = blockList.get(i); if (block.getPredecessorCount() > 1) { optimizer.optimizeMovesAtBlockEnd(block); @@ -103,8 +103,8 @@ * Moves the longest {@linkplain #same common} subsequence at the end all predecessors of * {@code block} to the start of {@code block}. */ - private void optimizeMovesAtBlockEnd(Block block) { - for (Block pred : block.getPredecessors()) { + private void optimizeMovesAtBlockEnd(AbstractBlock<?> block) { + for (AbstractBlock<?> pred : block.getPredecessors()) { if (pred == block) { // currently we can't handle this correctly. return; @@ -118,10 +118,10 @@ assert numPreds > 1 : "do not call otherwise"; // setup a list with the LIR instructions of all predecessors - for (Block pred : block.getPredecessors()) { + for (AbstractBlock<?> pred : block.getPredecessors()) { assert pred != null; - assert ir.lir(pred) != null; - List<LIRInstruction> predInstructions = ir.lir(pred); + assert ir.getLIRforBlock(pred) != null; + List<LIRInstruction> predInstructions = ir.getLIRforBlock(pred); if (pred.getSuccessorCount() != 1) { // this can happen with switch-statements where multiple edges are between @@ -129,7 +129,7 @@ return; } - assert pred.getFirstSuccessor() == block : "invalid control flow"; + assert pred.getSuccessors().iterator().next() == block : "invalid control flow"; assert predInstructions.get(predInstructions.size() - 1) instanceof StandardOp.JumpOp : "block must end with unconditional jump"; if (predInstructions.get(predInstructions.size() - 1).hasState()) { @@ -158,7 +158,7 @@ } // insert the instruction at the beginning of the current block - ir.lir(block).add(1, op); + ir.getLIRforBlock(block).add(1, op); // delete the instruction at the end of all predecessors for (int i = 0; i < numPreds; i++) { @@ -173,12 +173,12 @@ * {@code block} to the end of {@code block} just prior to the branch instruction ending * {@code block}. */ - private void optimizeMovesAtBlockBegin(Block block) { + private void optimizeMovesAtBlockBegin(AbstractBlock<?> block) { edgeInstructionSeqences.clear(); int numSux = block.getSuccessorCount(); - List<LIRInstruction> instructions = ir.lir(block); + List<LIRInstruction> instructions = ir.getLIRforBlock(block); assert numSux == 2 : "method should not be called otherwise"; @@ -203,8 +203,8 @@ int insertIdx = instructions.size() - 1; // setup a list with the lir-instructions of all successors - for (Block sux : block.getSuccessors()) { - List<LIRInstruction> suxInstructions = ir.lir(sux); + for (AbstractBlock<?> sux : block.getSuccessors()) { + List<LIRInstruction> suxInstructions = ir.getLIRforBlock(sux); assert suxInstructions.get(0) instanceof StandardOp.LabelOp : "block must start with label"; @@ -213,7 +213,7 @@ // the same blocks. return; } - assert sux.getFirstPredecessor() == block : "invalid control flow"; + assert sux.getPredecessors().iterator().next() == block : "invalid control flow"; // ignore the label at the beginning of the block List<LIRInstruction> seq = suxInstructions.subList(1, suxInstructions.size()); @@ -238,7 +238,7 @@ } // insert instruction at end of current block - ir.lir(block).add(insertIdx, op); + ir.getLIRforBlock(block).add(insertIdx, op); insertIdx++; // delete the instructions at the beginning of all successors
--- a/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/LIR.java Wed Mar 26 14:43:50 2014 +0100 +++ b/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/LIR.java Wed Mar 26 20:44:11 2014 +0100 @@ -35,17 +35,17 @@ */ public class LIR { - private final ControlFlowGraph cfg; + private final AbstractControlFlowGraph<?> cfg; /** * The linear-scan ordered list of blocks. */ - private final List<Block> linearScanOrder; + private final List<? extends AbstractBlock<?>> linearScanOrder; /** * The order in which the code is emitted. */ - private final List<Block> codeEmittingOrder; + private final List<? extends AbstractBlock<?>> codeEmittingOrder; private int firstVariableNumber; @@ -65,14 +65,14 @@ /** * Creates a new LIR instance for the specified compilation. */ - public LIR(ControlFlowGraph cfg, List<Block> linearScanOrder, List<Block> codeEmittingOrder) { + public LIR(AbstractControlFlowGraph<?> cfg, List<? extends AbstractBlock<?>> linearScanOrder, List<? extends AbstractBlock<?>> codeEmittingOrder) { this.cfg = cfg; this.codeEmittingOrder = codeEmittingOrder; this.linearScanOrder = linearScanOrder; this.lirInstructions = new BlockMap<>(cfg); } - public ControlFlowGraph getControlFlowGraph() { + public AbstractControlFlowGraph<?> getControlFlowGraph() { return cfg; } @@ -80,8 +80,8 @@ * Determines if any instruction in the LIR has debug info associated with it. */ public boolean hasDebugInfo() { - for (Block b : linearScanOrder()) { - for (LIRInstruction op : lir(b)) { + for (AbstractBlock<?> b : linearScanOrder()) { + for (LIRInstruction op : getLIRforBlock(b)) { if (op.hasState()) { return true; } @@ -94,12 +94,12 @@ return spillMoveFactory; } - public List<LIRInstruction> lir(AbstractBlock<?> block) { + public List<LIRInstruction> getLIRforBlock(AbstractBlock<?> block) { return lirInstructions.get(block); } - public void setLir(Block block, List<LIRInstruction> list) { - assert lir(block) == null : "lir instruction list should only be initialized once"; + public void setLIRforBlock(AbstractBlock<?> block, List<LIRInstruction> list) { + assert getLIRforBlock(block) == null : "lir instruction list should only be initialized once"; lirInstructions.put(block, list); } @@ -108,11 +108,11 @@ * * @return the blocks in linear scan order */ - public List<Block> linearScanOrder() { + public List<? extends AbstractBlock<?>> linearScanOrder() { return linearScanOrder; } - public List<Block> codeEmittingOrder() { + public List<? extends AbstractBlock<?>> codeEmittingOrder() { return codeEmittingOrder; } @@ -169,8 +169,8 @@ */ public static final int MAX_EXCEPTION_EDGE_OP_DISTANCE_FROM_END = 3; - public static boolean verifyBlock(LIR lir, Block block) { - List<LIRInstruction> ops = lir.lir(block); + public static boolean verifyBlock(LIR lir, AbstractBlock<?> block) { + List<LIRInstruction> ops = lir.getLIRforBlock(block); if (ops.size() == 0) { return false; } @@ -193,12 +193,12 @@ return true; } - public static boolean verifyBlocks(LIR lir, List<Block> blocks) { - for (Block block : blocks) { - for (Block sux : block.getSuccessors()) { + public static boolean verifyBlocks(LIR lir, List<? extends AbstractBlock<?>> blocks) { + for (AbstractBlock<?> block : blocks) { + for (AbstractBlock<?> sux : block.getSuccessors()) { assert blocks.contains(sux) : "missing successor from: " + block + "to: " + sux; } - for (Block pred : block.getPredecessors()) { + for (AbstractBlock<?> pred : block.getPredecessors()) { assert blocks.contains(pred) : "missing predecessor from: " + block + "to: " + pred; } if (!verifyBlock(lir, block)) {
--- a/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/LIRVerifier.java Wed Mar 26 14:43:50 2014 +0100 +++ b/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/LIRVerifier.java Wed Mar 26 20:44:11 2014 +0100 @@ -46,11 +46,11 @@ private final BitSet[] blockLiveOut; private final Object[] variableDefinitions; - private BitSet liveOutFor(Block block) { + private BitSet liveOutFor(AbstractBlock<?> block) { return blockLiveOut[block.getId()]; } - private void setLiveOutFor(Block block, BitSet liveOut) { + private void setLiveOutFor(AbstractBlock<?> block, BitSet liveOut) { blockLiveOut[block.getId()] = liveOut; } @@ -98,7 +98,7 @@ private BitSet curVariablesLive; private Value[] curRegistersLive; - private Block curBlock; + private AbstractBlock<?> curBlock; private Object curInstruction; private BitSet curRegistersDefined; @@ -120,7 +120,7 @@ int maxRegisterNum = maxRegisterNum(); curRegistersDefined = new BitSet(); - for (Block block : lir.linearScanOrder()) { + for (AbstractBlock<?> block : lir.linearScanOrder()) { curBlock = block; curVariablesLive = new BitSet(); curRegistersLive = new Value[maxRegisterNum]; @@ -129,14 +129,14 @@ curVariablesLive.or(liveOutFor(block.getDominator())); } - assert lir.lir(block).get(0) instanceof StandardOp.LabelOp : "block must start with label"; + assert lir.getLIRforBlock(block).get(0) instanceof StandardOp.LabelOp : "block must start with label"; if (block.getSuccessorCount() > 0) { - LIRInstruction last = lir.lir(block).get(lir.lir(block).size() - 1); + LIRInstruction last = lir.getLIRforBlock(block).get(lir.getLIRforBlock(block).size() - 1); assert last instanceof StandardOp.JumpOp : "block with successor must end with unconditional jump"; } - for (LIRInstruction op : lir.lir(block)) { + for (LIRInstruction op : lir.getLIRforBlock(block)) { curInstruction = op; op.forEachInput(useProc);
--- a/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/LabelRef.java Wed Mar 26 14:43:50 2014 +0100 +++ b/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/LabelRef.java Wed Mar 26 20:44:11 2014 +0100 @@ -73,7 +73,7 @@ } public Label label() { - return ((StandardOp.LabelOp) lir.lir(getTargetBlock()).get(0)).getLabel(); + return ((StandardOp.LabelOp) lir.getLIRforBlock(getTargetBlock()).get(0)).getLabel(); } @Override
--- a/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/NullCheckOptimizer.java Wed Mar 26 14:43:50 2014 +0100 +++ b/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/NullCheckOptimizer.java Wed Mar 26 20:44:11 2014 +0100 @@ -31,16 +31,16 @@ public final class NullCheckOptimizer { public static void optimize(LIR ir, int implicitNullCheckLimit) { - List<Block> blocks = ir.codeEmittingOrder(); + List<? extends AbstractBlock<?>> blocks = ir.codeEmittingOrder(); NullCheckOptimizer.foldNullChecks(ir, blocks, implicitNullCheckLimit); } private NullCheckOptimizer() { } - private static void foldNullChecks(LIR ir, List<Block> blocks, int implicitNullCheckLimit) { - for (Block block : blocks) { - List<LIRInstruction> list = ir.lir(block); + private static void foldNullChecks(LIR ir, List<? extends AbstractBlock<?>> blocks, int implicitNullCheckLimit) { + for (AbstractBlock<?> block : blocks) { + List<LIRInstruction> list = ir.getLIRforBlock(block); if (!list.isEmpty()) {
--- a/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/RedundantMoveElimination.java Wed Mar 26 14:43:50 2014 +0100 +++ b/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/RedundantMoveElimination.java Wed Mar 26 20:44:11 2014 +0100 @@ -79,7 +79,7 @@ int entryValueNum; } - Map<Block, BlockData> blockData = new HashMap<>(); + Map<AbstractBlock<?>, BlockData> blockData = new HashMap<>(); Register[] callerSaveRegs; @@ -134,7 +134,7 @@ private void initBlockData(LIR lir) { - List<Block> blocks = lir.linearScanOrder(); + List<? extends AbstractBlock<?>> blocks = lir.linearScanOrder(); numRegs = 0; int maxStackLocations = COMPLEXITY_LIMIT / blocks.size(); @@ -143,8 +143,8 @@ * Search for relevant locations which can be optimized. These are register or stack slots * which occur as destinations of move instructions. */ - for (Block block : blocks) { - List<LIRInstruction> instructions = lir.lir(block); + for (AbstractBlock<?> block : blocks) { + List<LIRInstruction> instructions = lir.getLIRforBlock(block); for (LIRInstruction op : instructions) { if (isEligibleMove(op)) { Value dest = ((MoveOp) op).getResult(); @@ -168,7 +168,7 @@ */ int numLocations = numRegs + stackIndices.size(); Debug.log("num locations = %d (regs = %d, stack = %d)", numLocations, numRegs, stackIndices.size()); - for (Block block : blocks) { + for (AbstractBlock<?> block : blocks) { BlockData data = new BlockData(numLocations); blockData.put(block, data); } @@ -183,7 +183,7 @@ Indent indent = Debug.logAndIndent("solve data flow"); - List<Block> blocks = lir.linearScanOrder(); + List<? extends AbstractBlock<?>> blocks = lir.linearScanOrder(); int numIter = 0; @@ -197,7 +197,7 @@ changed = false; Indent indent2 = indent.logAndIndent("new iteration"); - for (Block block : blocks) { + for (AbstractBlock<?> block : blocks) { BlockData data = blockData.get(block); /* @@ -226,7 +226,7 @@ /* * Merge the states of predecessor blocks */ - for (Block predecessor : block.getPredecessors()) { + for (AbstractBlock<?> predecessor : block.getPredecessors()) { BlockData predData = blockData.get(predecessor); newState |= mergeState(data.entryState, predData.exitState, valueNum); } @@ -244,7 +244,7 @@ */ int[] iterState = data.exitState; copyState(iterState, data.entryState); - List<LIRInstruction> instructions = lir.lir(block); + List<LIRInstruction> instructions = lir.getLIRforBlock(block); for (LIRInstruction op : instructions) { valueNum = updateState(iterState, op, valueNum); @@ -281,13 +281,13 @@ Indent indent = Debug.logAndIndent("eliminate moves"); - List<Block> blocks = lir.linearScanOrder(); + List<? extends AbstractBlock<?>> blocks = lir.linearScanOrder(); - for (Block block : blocks) { + for (AbstractBlock<?> block : blocks) { Indent indent2 = indent.logAndIndent("eliminate moves in block %d", block.getId()); - List<LIRInstruction> instructions = lir.lir(block); + List<LIRInstruction> instructions = lir.getLIRforBlock(block); BlockData data = blockData.get(block); boolean hasDead = false;
--- a/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/StandardOp.java Wed Mar 26 14:43:50 2014 +0100 +++ b/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/StandardOp.java Wed Mar 26 20:44:11 2014 +0100 @@ -182,20 +182,20 @@ /** * The block in which this instruction is located. */ - final Block block; + final AbstractBlock<?> block; /** * The block index of this instruction. */ final int index; - public NoOp(Block block, int index) { + public NoOp(AbstractBlock<?> block, int index) { this.block = block; this.index = index; } public void replace(LIR lir, LIRInstruction replacement) { - lir.lir(block).set(index, replacement); + lir.getLIRforBlock(block).set(index, replacement); } @Override
--- a/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/asm/CompilationResultBuilder.java Wed Mar 26 14:43:50 2014 +0100 +++ b/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/asm/CompilationResultBuilder.java Wed Mar 26 20:44:11 2014 +0100 @@ -301,7 +301,7 @@ */ public boolean isSuccessorEdge(LabelRef edge) { assert lir != null; - List<Block> order = lir.codeEmittingOrder(); + List<? extends AbstractBlock<?>> order = lir.codeEmittingOrder(); assert order.get(currentBlockIndex) == edge.getSourceBlock(); return currentBlockIndex < order.size() - 1 && order.get(currentBlockIndex + 1) == edge.getTargetBlock(); } @@ -315,7 +315,7 @@ this.lir = lir; this.currentBlockIndex = 0; frameContext.enter(this); - for (Block b : lir.codeEmittingOrder()) { + for (AbstractBlock<?> b : lir.codeEmittingOrder()) { emitBlock(b); currentBlockIndex++; } @@ -323,12 +323,12 @@ this.currentBlockIndex = 0; } - private void emitBlock(Block block) { + private void emitBlock(AbstractBlock<?> block) { if (Debug.isDumpEnabled()) { blockComment(String.format("block B%d %s", block.getId(), block.getLoop())); } - for (LIRInstruction op : lir.lir(block)) { + for (LIRInstruction op : lir.getLIRforBlock(block)) { if (Debug.isDumpEnabled()) { blockComment(String.format("%d %s", op.id(), op)); }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/AbstractBeginNode.java Wed Mar 26 14:43:50 2014 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/AbstractBeginNode.java Wed Mar 26 20:44:11 2014 +0100 @@ -128,7 +128,7 @@ } @Override - public void generate(LIRGeneratorTool gen) { + public void generate(NodeLIRGeneratorTool gen) { // nop }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/AbstractEndNode.java Wed Mar 26 14:43:50 2014 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/AbstractEndNode.java Wed Mar 26 20:44:11 2014 +0100 @@ -35,7 +35,7 @@ } @Override - public void generate(LIRGeneratorTool gen) { + public void generate(NodeLIRGeneratorTool gen) { gen.visitEndNode(this); }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/BreakpointNode.java Wed Mar 26 14:43:50 2014 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/BreakpointNode.java Wed Mar 26 20:44:11 2014 +0100 @@ -54,7 +54,7 @@ } @Override - public void generate(LIRGeneratorTool gen) { + public void generate(NodeLIRGeneratorTool gen) { gen.visitBreakpointNode(this); }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/CallTargetNode.java Wed Mar 26 14:43:50 2014 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/CallTargetNode.java Wed Mar 26 20:44:11 2014 +0100 @@ -54,7 +54,7 @@ public abstract String targetName(); @Override - public void generate(LIRGeneratorTool gen) { + public void generate(NodeLIRGeneratorTool gen) { // nop } }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/ConstantNode.java Wed Mar 26 14:43:50 2014 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/ConstantNode.java Wed Mar 26 20:44:11 2014 +0100 @@ -120,12 +120,12 @@ } @Override - public void generate(LIRGeneratorTool gen) { + public void generate(NodeLIRGeneratorTool gen) { assert ConstantNodeRecordsUsages : "LIR generator should generate constants per-usage"; - if (gen.canInlineConstant(value) || onlyUsedInVirtualState()) { + if (gen.getLIRGeneratorTool().canInlineConstant(value) || onlyUsedInVirtualState()) { gen.setResult(this, value); } else { - gen.setResult(this, gen.emitMove(value)); + gen.setResult(this, gen.getLIRGeneratorTool().emitMove(value)); } }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/DeoptimizeNode.java Wed Mar 26 14:43:50 2014 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/DeoptimizeNode.java Wed Mar 26 20:44:11 2014 +0100 @@ -62,8 +62,8 @@ } @Override - public void generate(LIRGeneratorTool gen) { - gen.emitDeoptimize(gen.getMetaAccess().encodeDeoptActionAndReason(action, reason, debugId), speculation, this); + public void generate(NodeLIRGeneratorTool gen) { + gen.getLIRGeneratorTool().emitDeoptimize(gen.getLIRGeneratorTool().getMetaAccess().encodeDeoptActionAndReason(action, reason, debugId), speculation, this); } @Override
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/DynamicDeoptimizeNode.java Wed Mar 26 14:43:50 2014 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/DynamicDeoptimizeNode.java Wed Mar 26 20:44:11 2014 +0100 @@ -54,8 +54,8 @@ return getSpeculation(); } - public void generate(LIRGeneratorTool generator) { - generator.emitDeoptimize(generator.operand(actionAndReason), generator.operand(speculation), this); + public void generate(NodeLIRGeneratorTool generator) { + generator.getLIRGeneratorTool().emitDeoptimize(generator.operand(actionAndReason), generator.operand(speculation), this); } @Override
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/EntryMarkerNode.java Wed Mar 26 14:43:50 2014 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/EntryMarkerNode.java Wed Mar 26 20:44:11 2014 +0100 @@ -38,7 +38,7 @@ } @Override - public void generate(LIRGeneratorTool gen) { + public void generate(NodeLIRGeneratorTool gen) { throw new GraalInternalError("OnStackReplacementNode should not survive"); } }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/GuardedValueNode.java Wed Mar 26 14:43:50 2014 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/GuardedValueNode.java Wed Mar 26 20:44:11 2014 +0100 @@ -53,7 +53,7 @@ } @Override - public void generate(LIRGeneratorTool generator) { + public void generate(NodeLIRGeneratorTool generator) { if (object.getKind() != Kind.Void && object.getKind() != Kind.Illegal) { generator.setResult(this, generator.operand(object)); }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/IfNode.java Wed Mar 26 14:43:50 2014 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/IfNode.java Wed Mar 26 20:44:11 2014 +0100 @@ -127,7 +127,7 @@ } @Override - public void generate(LIRGeneratorTool gen) { + public void generate(NodeLIRGeneratorTool gen) { gen.emitIf(this); }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/InfopointNode.java Wed Mar 26 14:43:50 2014 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/InfopointNode.java Wed Mar 26 20:44:11 2014 +0100 @@ -41,7 +41,7 @@ } @Override - public void generate(LIRGeneratorTool generator) { + public void generate(NodeLIRGeneratorTool generator) { generator.visitInfopointNode(this); }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/InvokeNode.java Wed Mar 26 14:43:50 2014 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/InvokeNode.java Wed Mar 26 20:44:11 2014 +0100 @@ -113,7 +113,7 @@ } @Override - public void generate(LIRGeneratorTool gen) { + public void generate(NodeLIRGeneratorTool gen) { gen.emitInvoke(this); }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/InvokeWithExceptionNode.java Wed Mar 26 14:43:50 2014 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/InvokeWithExceptionNode.java Wed Mar 26 20:44:11 2014 +0100 @@ -133,7 +133,7 @@ } @Override - public void generate(LIRGeneratorTool gen) { + public void generate(NodeLIRGeneratorTool gen) { gen.emitInvoke(this); }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/LogicConstantNode.java Wed Mar 26 14:43:50 2014 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/LogicConstantNode.java Wed Mar 26 20:44:11 2014 +0100 @@ -68,7 +68,7 @@ } @Override - public void generate(LIRGeneratorTool generator) { + public void generate(NodeLIRGeneratorTool generator) { // nothing to do } }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/LoopBeginNode.java Wed Mar 26 14:43:50 2014 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/LoopBeginNode.java Wed Mar 26 20:44:11 2014 +0100 @@ -98,7 +98,7 @@ } @Override - public void generate(LIRGeneratorTool gen) { + public void generate(NodeLIRGeneratorTool gen) { // Nothing to emit, since this is node is used for structural purposes only. }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/LoopEndNode.java Wed Mar 26 14:43:50 2014 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/LoopEndNode.java Wed Mar 26 20:44:11 2014 +0100 @@ -64,7 +64,7 @@ } @Override - public void generate(LIRGeneratorTool gen) { + public void generate(NodeLIRGeneratorTool gen) { gen.visitLoopEnd(this); super.generate(gen); }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/MemoryProxyNode.java Wed Mar 26 14:43:50 2014 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/MemoryProxyNode.java Wed Mar 26 20:44:11 2014 +0100 @@ -42,7 +42,7 @@ } @Override - public void generate(LIRGeneratorTool generator) { + public void generate(NodeLIRGeneratorTool generator) { } @Override
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/MergeNode.java Wed Mar 26 14:43:50 2014 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/MergeNode.java Wed Mar 26 20:44:11 2014 +0100 @@ -41,7 +41,7 @@ @Input(notDataflow = true) private final NodeInputList<AbstractEndNode> ends = new NodeInputList<>(this); @Override - public void generate(LIRGeneratorTool gen) { + public void generate(NodeLIRGeneratorTool gen) { gen.visitMerge(this); }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/PiNode.java Wed Mar 26 14:43:50 2014 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/PiNode.java Wed Mar 26 20:44:11 2014 +0100 @@ -62,7 +62,7 @@ } @Override - public void generate(LIRGeneratorTool generator) { + public void generate(NodeLIRGeneratorTool generator) { if (object.getKind() != Kind.Void && object.getKind() != Kind.Illegal) { generator.setResult(this, generator.operand(object)); }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/ReturnNode.java Wed Mar 26 14:43:50 2014 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/ReturnNode.java Wed Mar 26 20:44:11 2014 +0100 @@ -57,7 +57,7 @@ } @Override - public void generate(LIRGeneratorTool gen) { + public void generate(NodeLIRGeneratorTool gen) { gen.visitReturn(this); }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/SafepointNode.java Wed Mar 26 14:43:50 2014 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/SafepointNode.java Wed Mar 26 20:44:11 2014 +0100 @@ -35,7 +35,7 @@ } @Override - public void generate(LIRGeneratorTool gen) { + public void generate(NodeLIRGeneratorTool gen) { gen.visitSafepointNode(this); }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/UnwindNode.java Wed Mar 26 14:43:50 2014 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/UnwindNode.java Wed Mar 26 20:44:11 2014 +0100 @@ -49,7 +49,7 @@ } @Override - public void generate(LIRGeneratorTool gen) { - gen.emitUnwind(gen.operand(exception())); + public void generate(NodeLIRGeneratorTool gen) { + gen.getLIRGeneratorTool().emitUnwind(gen.operand(exception())); } }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/ValueNode.java Wed Mar 26 14:43:50 2014 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/ValueNode.java Wed Mar 26 20:44:11 2014 +0100 @@ -31,7 +31,7 @@ * This class represents a value within the graph, including local variables, phis, and all other * instructions. */ -public abstract class ValueNode extends ScheduledNode implements StampProvider { +public abstract class ValueNode extends ScheduledNode implements StampProvider, KindInterface { /** * The kind of this value. This is {@link Kind#Void} for instructions that produce no value.
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/AndNode.java Wed Mar 26 14:43:50 2014 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/AndNode.java Wed Mar 26 20:44:11 2014 +0100 @@ -81,8 +81,8 @@ } @Override - public void generate(ArithmeticLIRGenerator gen) { - gen.setResult(this, gen.emitAnd(gen.operand(x()), gen.operand(y()))); + public void generate(NodeLIRGeneratorTool gen) { + gen.setResult(this, gen.getLIRGeneratorTool().emitAnd(gen.operand(x()), gen.operand(y()))); } @Override
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/CompareNode.java Wed Mar 26 14:43:50 2014 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/CompareNode.java Wed Mar 26 20:44:11 2014 +0100 @@ -75,7 +75,7 @@ public abstract boolean unorderedIsTrue(); @Override - public void generate(LIRGeneratorTool gen) { + public void generate(NodeLIRGeneratorTool gen) { } private LogicNode optimizeConditional(Constant constant, ConditionalNode conditionalNode, ConstantReflectionProvider constantReflection, Condition cond) {
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/ConditionalNode.java Wed Mar 26 14:43:50 2014 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/ConditionalNode.java Wed Mar 26 20:44:11 2014 +0100 @@ -109,7 +109,7 @@ } @Override - public void generate(LIRGeneratorTool generator) { + public void generate(NodeLIRGeneratorTool generator) { generator.emitConditional(this); }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/FloatAddNode.java Wed Mar 26 14:43:50 2014 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/FloatAddNode.java Wed Mar 26 20:44:11 2014 +0100 @@ -65,7 +65,7 @@ } @Override - public void generate(ArithmeticLIRGenerator gen) { + public void generate(NodeLIRGeneratorTool gen) { Value op1 = gen.operand(x()); Value op2 = gen.operand(y()); if (!y().isConstant() && !livesLonger(this, y(), gen)) { @@ -73,10 +73,10 @@ op1 = op2; op2 = op; } - gen.setResult(this, gen.emitAdd(op1, op2)); + gen.setResult(this, gen.getLIRGeneratorTool().emitAdd(op1, op2)); } - public static boolean livesLonger(ValueNode after, ValueNode value, ArithmeticLIRGenerator gen) { + public static boolean livesLonger(ValueNode after, ValueNode value, NodeLIRGeneratorTool gen) { for (Node usage : value.usages()) { if (usage != after && usage instanceof ValueNode && gen.hasOperand(((ValueNode) usage))) { return true;
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/FloatConvertNode.java Wed Mar 26 14:43:50 2014 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/FloatConvertNode.java Wed Mar 26 20:44:11 2014 +0100 @@ -192,8 +192,8 @@ tool.getLowerer().lower(this, tool); } - public void generate(ArithmeticLIRGenerator gen) { - gen.setResult(this, gen.emitFloatConvert(op, gen.operand(getInput()))); + public void generate(NodeLIRGeneratorTool gen) { + gen.setResult(this, gen.getLIRGeneratorTool().emitFloatConvert(op, gen.operand(getInput()))); } public boolean generate(MemoryArithmeticLIRLowerer gen, Access access) {
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/FloatDivNode.java Wed Mar 26 14:43:50 2014 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/FloatDivNode.java Wed Mar 26 20:44:11 2014 +0100 @@ -57,8 +57,8 @@ } @Override - public void generate(ArithmeticLIRGenerator gen) { - gen.setResult(this, gen.emitDiv(gen.operand(x()), gen.operand(y()), null)); + public void generate(NodeLIRGeneratorTool gen) { + gen.setResult(this, gen.getLIRGeneratorTool().emitDiv(gen.operand(x()), gen.operand(y()), null)); } @Override
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/FloatMulNode.java Wed Mar 26 14:43:50 2014 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/FloatMulNode.java Wed Mar 26 20:44:11 2014 +0100 @@ -60,7 +60,7 @@ } @Override - public void generate(ArithmeticLIRGenerator gen) { + public void generate(NodeLIRGeneratorTool gen) { Value op1 = gen.operand(x()); Value op2 = gen.operand(y()); if (!y().isConstant() && !FloatAddNode.livesLonger(this, y(), gen)) { @@ -68,7 +68,7 @@ op1 = op2; op2 = op; } - gen.setResult(this, gen.emitMul(op1, op2)); + gen.setResult(this, gen.getLIRGeneratorTool().emitMul(op1, op2)); } @Override
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/FloatRemNode.java Wed Mar 26 14:43:50 2014 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/FloatRemNode.java Wed Mar 26 20:44:11 2014 +0100 @@ -57,8 +57,8 @@ } @Override - public void generate(ArithmeticLIRGenerator gen) { - gen.setResult(this, gen.emitRem(gen.operand(x()), gen.operand(y()), null)); + public void generate(NodeLIRGeneratorTool gen) { + gen.setResult(this, gen.getLIRGeneratorTool().emitRem(gen.operand(x()), gen.operand(y()), null)); } @Override
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/FloatSubNode.java Wed Mar 26 14:43:50 2014 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/FloatSubNode.java Wed Mar 26 20:44:11 2014 +0100 @@ -76,8 +76,8 @@ } @Override - public void generate(ArithmeticLIRGenerator gen) { - gen.setResult(this, gen.emitSub(gen.operand(x()), gen.operand(y()))); + public void generate(NodeLIRGeneratorTool gen) { + gen.setResult(this, gen.getLIRGeneratorTool().emitSub(gen.operand(x()), gen.operand(y()))); } @Override
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/IntegerAddNode.java Wed Mar 26 14:43:50 2014 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/IntegerAddNode.java Wed Mar 26 20:44:11 2014 +0100 @@ -89,7 +89,7 @@ } @Override - public void generate(ArithmeticLIRGenerator gen) { + public void generate(NodeLIRGeneratorTool gen) { Value op1 = gen.operand(x()); assert op1 != null : x() + ", this=" + this; Value op2 = gen.operand(y()); @@ -98,7 +98,7 @@ op1 = op2; op2 = op; } - gen.setResult(this, gen.emitAdd(op1, op2)); + gen.setResult(this, gen.getLIRGeneratorTool().emitAdd(op1, op2)); } @Override
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/IntegerDivNode.java Wed Mar 26 14:43:50 2014 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/IntegerDivNode.java Wed Mar 26 20:44:11 2014 +0100 @@ -106,8 +106,8 @@ } @Override - public void generate(LIRGeneratorTool gen) { - gen.setResult(this, gen.emitDiv(gen.operand(x()), gen.operand(y()), this)); + public void generate(NodeLIRGeneratorTool gen) { + gen.setResult(this, gen.getLIRGeneratorTool().emitDiv(gen.operand(x()), gen.operand(y()), this)); } @Override
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/IntegerMulNode.java Wed Mar 26 14:43:50 2014 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/IntegerMulNode.java Wed Mar 26 20:44:11 2014 +0100 @@ -75,7 +75,7 @@ } @Override - public void generate(ArithmeticLIRGenerator gen) { + public void generate(NodeLIRGeneratorTool gen) { Value op1 = gen.operand(x()); Value op2 = gen.operand(y()); if (!y().isConstant() && !FloatAddNode.livesLonger(this, y(), gen)) { @@ -83,7 +83,7 @@ op1 = op2; op2 = op; } - gen.setResult(this, gen.emitMul(op1, op2)); + gen.setResult(this, gen.getLIRGeneratorTool().emitMul(op1, op2)); } @Override
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/IntegerRemNode.java Wed Mar 26 14:43:50 2014 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/IntegerRemNode.java Wed Mar 26 20:44:11 2014 +0100 @@ -61,8 +61,8 @@ } @Override - public void generate(LIRGeneratorTool gen) { - gen.setResult(this, gen.emitRem(gen.operand(x()), gen.operand(y()), this)); + public void generate(NodeLIRGeneratorTool gen) { + gen.setResult(this, gen.getLIRGeneratorTool().emitRem(gen.operand(x()), gen.operand(y()), this)); } @Override
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/IntegerSubNode.java Wed Mar 26 14:43:50 2014 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/IntegerSubNode.java Wed Mar 26 20:44:11 2014 +0100 @@ -117,8 +117,8 @@ } @Override - public void generate(ArithmeticLIRGenerator gen) { - gen.setResult(this, gen.emitSub(gen.operand(x()), gen.operand(y()))); + public void generate(NodeLIRGeneratorTool gen) { + gen.setResult(this, gen.getLIRGeneratorTool().emitSub(gen.operand(x()), gen.operand(y()))); } @Override
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/IntegerTestNode.java Wed Mar 26 14:43:50 2014 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/IntegerTestNode.java Wed Mar 26 20:44:11 2014 +0100 @@ -60,7 +60,7 @@ } @Override - public void generate(LIRGeneratorTool gen) { + public void generate(NodeLIRGeneratorTool gen) { } @Override
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/IsNullNode.java Wed Mar 26 14:43:50 2014 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/IsNullNode.java Wed Mar 26 20:44:11 2014 +0100 @@ -50,7 +50,7 @@ } @Override - public void generate(LIRGeneratorTool gen) { + public void generate(NodeLIRGeneratorTool gen) { // Nothing to do. }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/LeftShiftNode.java Wed Mar 26 14:43:50 2014 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/LeftShiftNode.java Wed Mar 26 20:44:11 2014 +0100 @@ -92,7 +92,7 @@ } @Override - public void generate(ArithmeticLIRGenerator gen) { - gen.setResult(this, gen.emitShl(gen.operand(x()), gen.operand(y()))); + public void generate(NodeLIRGeneratorTool gen) { + gen.setResult(this, gen.getLIRGeneratorTool().emitShl(gen.operand(x()), gen.operand(y()))); } }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/NarrowNode.java Wed Mar 26 14:43:50 2014 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/NarrowNode.java Wed Mar 26 20:44:11 2014 +0100 @@ -110,8 +110,8 @@ } @Override - public void generate(ArithmeticLIRGenerator gen) { - gen.setResult(this, gen.emitNarrow(gen.operand(getInput()), getResultBits())); + public void generate(NodeLIRGeneratorTool gen) { + gen.setResult(this, gen.getLIRGeneratorTool().emitNarrow(gen.operand(getInput()), getResultBits())); } @Override
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/NegateNode.java Wed Mar 26 14:43:50 2014 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/NegateNode.java Wed Mar 26 20:44:11 2014 +0100 @@ -88,7 +88,7 @@ } @Override - public void generate(ArithmeticLIRGenerator gen) { - gen.setResult(this, gen.emitNegate(gen.operand(x()))); + public void generate(NodeLIRGeneratorTool gen) { + gen.setResult(this, gen.getLIRGeneratorTool().emitNegate(gen.operand(x()))); } }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/NotNode.java Wed Mar 26 14:43:50 2014 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/NotNode.java Wed Mar 26 20:44:11 2014 +0100 @@ -73,7 +73,7 @@ } @Override - public void generate(ArithmeticLIRGenerator gen) { - gen.setResult(this, gen.emitNot(gen.operand(x()))); + public void generate(NodeLIRGeneratorTool gen) { + gen.setResult(this, gen.getLIRGeneratorTool().emitNot(gen.operand(x()))); } }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/OrNode.java Wed Mar 26 14:43:50 2014 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/OrNode.java Wed Mar 26 20:44:11 2014 +0100 @@ -73,8 +73,8 @@ } @Override - public void generate(ArithmeticLIRGenerator gen) { - gen.setResult(this, gen.emitOr(gen.operand(x()), gen.operand(y()))); + public void generate(NodeLIRGeneratorTool gen) { + gen.setResult(this, gen.getLIRGeneratorTool().emitOr(gen.operand(x()), gen.operand(y()))); } @Override
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/ReinterpretNode.java Wed Mar 26 14:43:50 2014 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/ReinterpretNode.java Wed Mar 26 20:44:11 2014 +0100 @@ -102,9 +102,9 @@ } @Override - public void generate(ArithmeticLIRGenerator gen) { - PlatformKind kind = gen.getPlatformKind(stamp()); - gen.setResult(this, gen.emitReinterpret(kind, gen.operand(value()))); + public void generate(NodeLIRGeneratorTool gen) { + PlatformKind kind = gen.getLIRGeneratorTool().getPlatformKind(stamp()); + gen.setResult(this, gen.getLIRGeneratorTool().emitReinterpret(kind, gen.operand(value()))); } @Override
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/RightShiftNode.java Wed Mar 26 14:43:50 2014 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/RightShiftNode.java Wed Mar 26 20:44:11 2014 +0100 @@ -98,7 +98,7 @@ } @Override - public void generate(ArithmeticLIRGenerator gen) { - gen.setResult(this, gen.emitShr(gen.operand(x()), gen.operand(y()))); + public void generate(NodeLIRGeneratorTool gen) { + gen.setResult(this, gen.getLIRGeneratorTool().emitShr(gen.operand(x()), gen.operand(y()))); } }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/SignExtendNode.java Wed Mar 26 14:43:50 2014 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/SignExtendNode.java Wed Mar 26 20:44:11 2014 +0100 @@ -105,8 +105,8 @@ } @Override - public void generate(ArithmeticLIRGenerator gen) { - gen.setResult(this, gen.emitSignExtend(gen.operand(getInput()), getInputBits(), getResultBits())); + public void generate(NodeLIRGeneratorTool gen) { + gen.setResult(this, gen.getLIRGeneratorTool().emitSignExtend(gen.operand(getInput()), getInputBits(), getResultBits())); } @Override
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/UnsignedDivNode.java Wed Mar 26 14:43:50 2014 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/UnsignedDivNode.java Wed Mar 26 20:44:11 2014 +0100 @@ -71,8 +71,8 @@ } @Override - public void generate(LIRGeneratorTool gen) { - gen.setResult(this, gen.emitUDiv(gen.operand(x()), gen.operand(y()), this)); + public void generate(NodeLIRGeneratorTool gen) { + gen.setResult(this, gen.getLIRGeneratorTool().emitUDiv(gen.operand(x()), gen.operand(y()), this)); } @Override
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/UnsignedRemNode.java Wed Mar 26 14:43:50 2014 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/UnsignedRemNode.java Wed Mar 26 20:44:11 2014 +0100 @@ -70,8 +70,8 @@ } @Override - public void generate(LIRGeneratorTool gen) { - gen.setResult(this, gen.emitURem(gen.operand(x()), gen.operand(y()), this)); + public void generate(NodeLIRGeneratorTool gen) { + gen.setResult(this, gen.getLIRGeneratorTool().emitURem(gen.operand(x()), gen.operand(y()), this)); } @Override
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/UnsignedRightShiftNode.java Wed Mar 26 14:43:50 2014 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/UnsignedRightShiftNode.java Wed Mar 26 20:44:11 2014 +0100 @@ -92,7 +92,7 @@ } @Override - public void generate(ArithmeticLIRGenerator gen) { - gen.setResult(this, gen.emitUShr(gen.operand(x()), gen.operand(y()))); + public void generate(NodeLIRGeneratorTool gen) { + gen.setResult(this, gen.getLIRGeneratorTool().emitUShr(gen.operand(x()), gen.operand(y()))); } }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/XorNode.java Wed Mar 26 14:43:50 2014 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/XorNode.java Wed Mar 26 20:44:11 2014 +0100 @@ -72,8 +72,8 @@ } @Override - public void generate(ArithmeticLIRGenerator gen) { - gen.setResult(this, gen.emitXor(gen.operand(x()), gen.operand(y()))); + public void generate(NodeLIRGeneratorTool gen) { + gen.setResult(this, gen.getLIRGeneratorTool().emitXor(gen.operand(x()), gen.operand(y()))); } @Override
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/ZeroExtendNode.java Wed Mar 26 14:43:50 2014 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/ZeroExtendNode.java Wed Mar 26 20:44:11 2014 +0100 @@ -85,8 +85,8 @@ } @Override - public void generate(ArithmeticLIRGenerator gen) { - gen.setResult(this, gen.emitZeroExtend(gen.operand(getInput()), getInputBits(), getResultBits())); + public void generate(NodeLIRGeneratorTool gen) { + gen.setResult(this, gen.getLIRGeneratorTool().emitZeroExtend(gen.operand(getInput()), getInputBits(), getResultBits())); } @Override
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/cfg/AbstractBlock.java Wed Mar 26 14:43:50 2014 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/cfg/AbstractBlock.java Wed Mar 26 20:44:11 2014 +0100 @@ -22,14 +22,12 @@ */ package com.oracle.graal.nodes.cfg; -import com.oracle.graal.nodes.*; +import java.util.*; public interface AbstractBlock<T extends AbstractBlock<?>> { int getId(); - AbstractBeginNode getBeginNode(); - Loop getLoop(); int getLoopDepth(); @@ -40,11 +38,11 @@ boolean isExceptionEntry(); - Iterable<T> getPredecessors(); + List<T> getPredecessors(); int getPredecessorCount(); - Iterable<T> getSuccessors(); + List<T> getSuccessors(); int getSuccessorCount(); @@ -55,4 +53,6 @@ boolean isAligned(); void setAlign(boolean align); + + T getDominator(); }
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/cfg/AbstractBlockBase.java Wed Mar 26 20:44:11 2014 +0100 @@ -0,0 +1,92 @@ +/* + * Copyright (c) 2009, 2012, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package com.oracle.graal.nodes.cfg; + +import java.util.*; + +public abstract class AbstractBlockBase<T extends AbstractBlock<T>> implements AbstractBlock<T> { + + protected int id; + + protected List<T> predecessors; + protected List<T> successors; + + protected T dominator; + + private boolean align; + private int linearScanNumber; + + protected AbstractBlockBase() { + this.id = ControlFlowGraph.BLOCK_ID_INITIAL; + this.linearScanNumber = -1; + } + + public int getId() { + return id; + } + + public void setId(int id) { + this.id = id; + } + + public List<T> getPredecessors() { + return predecessors; + } + + public List<T> getSuccessors() { + return successors; + } + + public T getDominator() { + return dominator; + } + + @Override + public String toString() { + return "B" + id; + } + + public int getPredecessorCount() { + return getPredecessors().size(); + } + + public int getSuccessorCount() { + return getSuccessors().size(); + } + + public int getLinearScanNumber() { + return linearScanNumber; + } + + public void setLinearScanNumber(int linearScanNumber) { + this.linearScanNumber = linearScanNumber; + } + + public boolean isAligned() { + return align; + } + + public void setAlign(boolean align) { + this.align = align; + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/cfg/AbstractControlFlowGraph.java Wed Mar 26 20:44:11 2014 +0100 @@ -0,0 +1,32 @@ +/* + * Copyright (c) 2014, 2014, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package com.oracle.graal.nodes.cfg; + +public interface AbstractControlFlowGraph<T extends AbstractBlock<T>> { + + T[] getBlocks(); + + Loop[] getLoops(); + + T getStartBlock(); +}
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/cfg/Block.java Wed Mar 26 14:43:50 2014 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/cfg/Block.java Wed Mar 26 20:44:11 2014 +0100 @@ -27,34 +27,18 @@ import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.java.*; -public final class Block implements AbstractBlock<Block> { +public final class Block extends AbstractBlockBase<Block> { protected final AbstractBeginNode beginNode; - protected int id; - protected FixedNode endNode; protected Loop loop; - protected List<Block> predecessors; - protected List<Block> successors; - - protected Block dominator; protected List<Block> dominated; protected Block postdominator; - private boolean align; - private int linearScanNumber; - protected Block(AbstractBeginNode node) { this.beginNode = node; - - this.id = ControlFlowGraph.BLOCK_ID_INITIAL; - this.linearScanNumber = -1; - } - - public int getId() { - return id; } public AbstractBeginNode getBeginNode() { @@ -89,22 +73,10 @@ return predecessors.get(0); } - public List<Block> getPredecessors() { - return predecessors; - } - public Block getFirstSuccessor() { return successors.get(0); } - public List<Block> getSuccessors() { - return successors; - } - - public Block getDominator() { - return dominator; - } - public Block getEarliestPostDominated() { Block b = this; while (true) { @@ -187,14 +159,6 @@ return "B" + id; } - public int getPredecessorCount() { - return getPredecessors().size(); - } - - public int getSuccessorCount() { - return getSuccessors().size(); - } - public boolean dominates(Block block) { return block.isDominatedBy(this); } @@ -209,19 +173,4 @@ return dominator.isDominatedBy(block); } - public int getLinearScanNumber() { - return linearScanNumber; - } - - public void setLinearScanNumber(int linearScanNumber) { - this.linearScanNumber = linearScanNumber; - } - - public boolean isAligned() { - return align; - } - - public void setAlign(boolean align) { - this.align = align; - } }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/cfg/BlockMap.java Wed Mar 26 14:43:50 2014 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/cfg/BlockMap.java Wed Mar 26 20:44:11 2014 +0100 @@ -27,7 +27,7 @@ private final T[] data; @SuppressWarnings("unchecked") - public BlockMap(ControlFlowGraph cfg) { + public BlockMap(AbstractControlFlowGraph<?> cfg) { data = (T[]) new Object[cfg.getBlocks().length]; }
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/cfg/BlocksToDoubles.java Wed Mar 26 20:44:11 2014 +0100 @@ -0,0 +1,73 @@ +/* + * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package com.oracle.graal.nodes.cfg; + +import java.util.*; + +import com.oracle.graal.nodes.*; +import com.oracle.graal.nodes.util.*; + +public class BlocksToDoubles { + + private final IdentityHashMap<AbstractBlock<?>, Double> nodeProbabilities; + + public BlocksToDoubles(int numberOfNodes) { + this.nodeProbabilities = new IdentityHashMap<>(numberOfNodes); + } + + public void put(AbstractBlock<?> n, double value) { + assert value >= 0.0 : value; + nodeProbabilities.put(n, value); + } + + public boolean contains(AbstractBlock<?> n) { + return nodeProbabilities.containsKey(n); + } + + public double get(AbstractBlock<?> n) { + Double value = nodeProbabilities.get(n); + assert value != null; + return value; + } + + public static BlocksToDoubles createFromNodeProbability(NodesToDoubles nodeProbabilities, ControlFlowGraph cfg) { + BlocksToDoubles blockProbabilities = new BlocksToDoubles(cfg.getBlocks().length); + for (Block block : cfg.getBlocks()) { + blockProbabilities.put(block, nodeProbabilities.get(block.getBeginNode())); + } + assert verify(nodeProbabilities, cfg, blockProbabilities) : "Probabilities differ for nodes in the same block."; + return blockProbabilities; + } + + static private boolean verify(NodesToDoubles nodeProbabilities, ControlFlowGraph cfg, BlocksToDoubles blockProbabilities) { + for (Block b : cfg.getBlocks()) { + double p = blockProbabilities.get(b); + for (FixedNode n : b.getNodes()) { + if (nodeProbabilities.get(n) != p) { + return false; + } + } + } + return true; + } +}
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/cfg/ControlFlowGraph.java Wed Mar 26 14:43:50 2014 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/cfg/ControlFlowGraph.java Wed Mar 26 20:44:11 2014 +0100 @@ -28,7 +28,7 @@ import com.oracle.graal.graph.*; import com.oracle.graal.nodes.*; -public class ControlFlowGraph { +public class ControlFlowGraph implements AbstractControlFlowGraph<Block> { public final StructuredGraph graph;
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/AddLocationNode.java Wed Mar 26 14:43:50 2014 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/AddLocationNode.java Wed Mar 26 20:44:11 2014 +0100 @@ -107,7 +107,7 @@ } @Override - public Value generateAddress(LIRGeneratorTool gen, Value base) { + public Value generateAddress(NodeLIRGeneratorTool gen, Value base) { Value xAddr = getX().generateAddress(gen, base); return getY().generateAddress(gen, xAddr); }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/ComputeAddressNode.java Wed Mar 26 14:43:50 2014 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/ComputeAddressNode.java Wed Mar 26 20:44:11 2014 +0100 @@ -48,7 +48,7 @@ } @Override - public void generate(LIRGeneratorTool gen) { + public void generate(NodeLIRGeneratorTool gen) { Value addr = getLocation().generateAddress(gen, gen.operand(getObject())); gen.setResult(this, addr); }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/ConstantLocationNode.java Wed Mar 26 14:43:50 2014 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/ConstantLocationNode.java Wed Mar 26 20:44:11 2014 +0100 @@ -65,7 +65,7 @@ } @Override - public Value generateAddress(LIRGeneratorTool gen, Value base) { - return gen.emitAddress(base, getDisplacement(), Value.ILLEGAL, 0); + public Value generateAddress(NodeLIRGeneratorTool gen, Value base) { + return gen.getLIRGeneratorTool().emitAddress(base, getDisplacement(), Value.ILLEGAL, 0); } }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/FixedValueAnchorNode.java Wed Mar 26 14:43:50 2014 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/FixedValueAnchorNode.java Wed Mar 26 20:44:11 2014 +0100 @@ -49,7 +49,7 @@ public static native <T> T getObject(Object object); @Override - public void generate(LIRGeneratorTool generator) { + public void generate(NodeLIRGeneratorTool generator) { generator.setResult(this, generator.operand(object)); }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/FloatingReadNode.java Wed Mar 26 14:43:50 2014 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/FloatingReadNode.java Wed Mar 26 20:44:11 2014 +0100 @@ -60,9 +60,9 @@ } @Override - public void generate(LIRGeneratorTool gen) { + public void generate(NodeLIRGeneratorTool gen) { Value address = location().generateAddress(gen, gen.operand(object())); - gen.setResult(this, gen.emitLoad(location().getValueKind(), address, this)); + gen.setResult(this, gen.getLIRGeneratorTool().emitLoad(location().getValueKind(), address, this)); } @Override
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/ForeignCallNode.java Wed Mar 26 14:43:50 2014 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/ForeignCallNode.java Wed Mar 26 20:44:11 2014 +0100 @@ -82,7 +82,7 @@ return foreignCalls.getKilledLocations(descriptor); } - protected Value[] operands(LIRGeneratorTool gen) { + protected Value[] operands(NodeLIRGeneratorTool gen) { Value[] operands = new Value[arguments.size()]; for (int i = 0; i < operands.length; i++) { operands[i] = gen.operand(arguments.get(i)); @@ -91,10 +91,10 @@ } @Override - public void generate(LIRGeneratorTool gen) { - ForeignCallLinkage linkage = gen.getForeignCalls().lookupForeignCall(descriptor); + public void generate(NodeLIRGeneratorTool gen) { + ForeignCallLinkage linkage = gen.getLIRGeneratorTool().getForeignCalls().lookupForeignCall(descriptor); Value[] operands = operands(gen); - Value result = gen.emitForeignCall(linkage, this, operands); + Value result = gen.getLIRGeneratorTool().emitForeignCall(linkage, this, operands); if (result != null) { gen.setResult(this, result); }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/IndexedLocationNode.java Wed Mar 26 14:43:50 2014 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/IndexedLocationNode.java Wed Mar 26 20:44:11 2014 +0100 @@ -96,7 +96,7 @@ } @Override - public Value generateAddress(LIRGeneratorTool gen, Value base) { - return gen.emitAddress(base, displacement, gen.operand(getIndex()), getIndexScaling()); + public Value generateAddress(NodeLIRGeneratorTool gen, Value base) { + return gen.getLIRGeneratorTool().emitAddress(base, displacement, gen.operand(getIndex()), getIndexScaling()); } }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/IntegerSwitchNode.java Wed Mar 26 14:43:50 2014 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/IntegerSwitchNode.java Wed Mar 26 20:44:11 2014 +0100 @@ -101,7 +101,7 @@ } @Override - public void generate(LIRGeneratorTool gen) { + public void generate(NodeLIRGeneratorTool gen) { gen.emitSwitch(this); }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/LocationNode.java Wed Mar 26 14:43:50 2014 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/LocationNode.java Wed Mar 26 20:44:11 2014 +0100 @@ -56,9 +56,9 @@ public abstract LocationIdentity getLocationIdentity(); @Override - public final void generate(LIRGeneratorTool generator) { + public final void generate(NodeLIRGeneratorTool generator) { // nothing to do... } - public abstract Value generateAddress(LIRGeneratorTool gen, Value base); + public abstract Value generateAddress(NodeLIRGeneratorTool gen, Value base); }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/MembarNode.java Wed Mar 26 14:43:50 2014 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/MembarNode.java Wed Mar 26 20:44:11 2014 +0100 @@ -56,8 +56,8 @@ } @Override - public void generate(LIRGeneratorTool generator) { - generator.emitMembar(barriers); + public void generate(NodeLIRGeneratorTool generator) { + generator.getLIRGeneratorTool().emitMembar(barriers); } public MemoryCheckpoint asMemoryCheckpoint() {
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/NullCheckNode.java Wed Mar 26 14:43:50 2014 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/NullCheckNode.java Wed Mar 26 20:44:11 2014 +0100 @@ -40,7 +40,7 @@ } @Override - public void generate(LIRGeneratorTool generator) { + public void generate(NodeLIRGeneratorTool generator) { generator.emitNullCheck(object, this); }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/ReadNode.java Wed Mar 26 14:43:50 2014 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/ReadNode.java Wed Mar 26 20:44:11 2014 +0100 @@ -53,9 +53,9 @@ } @Override - public void generate(LIRGeneratorTool gen) { + public void generate(NodeLIRGeneratorTool gen) { Value address = location().generateAddress(gen, gen.operand(object())); - gen.setResult(this, gen.emitLoad(location().getValueKind(), address, this)); + gen.setResult(this, gen.getLIRGeneratorTool().emitLoad(location().getValueKind(), address, this)); } @Override
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/SnippetLocationNode.java Wed Mar 26 14:43:50 2014 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/SnippetLocationNode.java Wed Mar 26 20:44:11 2014 +0100 @@ -100,7 +100,7 @@ } @Override - public Value generateAddress(LIRGeneratorTool gen, Value base) { + public Value generateAddress(NodeLIRGeneratorTool gen, Value base) { throw new GraalInternalError("locationIdentity must be a constant so that this node can be canonicalized: " + locationIdentity); }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/UnsafeCastNode.java Wed Mar 26 14:43:50 2014 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/UnsafeCastNode.java Wed Mar 26 20:44:11 2014 +0100 @@ -94,7 +94,7 @@ } @Override - public void generate(LIRGeneratorTool generator) { + public void generate(NodeLIRGeneratorTool generator) { assert getKind() == Kind.Object && object.getKind() == Kind.Object; /* * The LIR only cares about the kind of an operand, not the actual type of an object. So we
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/ValueAnchorNode.java Wed Mar 26 14:43:50 2014 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/ValueAnchorNode.java Wed Mar 26 20:44:11 2014 +0100 @@ -42,7 +42,7 @@ } @Override - public void generate(LIRGeneratorTool gen) { + public void generate(NodeLIRGeneratorTool gen) { // Nothing to emit, since this node is used for structural purposes only. }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/WriteNode.java Wed Mar 26 14:43:50 2014 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/WriteNode.java Wed Mar 26 20:44:11 2014 +0100 @@ -80,17 +80,17 @@ } @Override - public void generate(LIRGeneratorTool gen) { + public void generate(NodeLIRGeneratorTool gen) { Value address = location().generateAddress(gen, gen.operand(object())); // It's possible a constant was forced for other usages so inspect the value directly and // use a constant if it can be directly stored. Value v; - if (value().isConstant() && gen.canStoreConstant(value().asConstant(), isCompressible())) { + if (value().isConstant() && gen.getLIRGeneratorTool().canStoreConstant(value().asConstant(), isCompressible())) { v = value().asConstant(); } else { v = gen.operand(value()); } - gen.emitStore(location().getValueKind(), address, v, this); + gen.getLIRGeneratorTool().emitStore(location().getValueKind(), address, v, this); } @Override
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/LoweredCompareAndSwapNode.java Wed Mar 26 14:43:50 2014 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/LoweredCompareAndSwapNode.java Wed Mar 26 20:44:11 2014 +0100 @@ -72,7 +72,7 @@ } @Override - public void generate(LIRGeneratorTool gen) { + public void generate(NodeLIRGeneratorTool gen) { gen.visitCompareAndSwap(this, location().generateAddress(gen, gen.operand(object()))); }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/MonitorIdNode.java Wed Mar 26 14:43:50 2014 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/MonitorIdNode.java Wed Mar 26 20:44:11 2014 +0100 @@ -49,7 +49,7 @@ this.lockDepth = lockDepth; } - public void generate(LIRGeneratorTool generator) { + public void generate(NodeLIRGeneratorTool generator) { // nothing to do } }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/RegisterFinalizerNode.java Wed Mar 26 14:43:50 2014 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/RegisterFinalizerNode.java Wed Mar 26 20:44:11 2014 +0100 @@ -51,9 +51,9 @@ } @Override - public void generate(LIRGeneratorTool gen) { - ForeignCallLinkage linkage = gen.getForeignCalls().lookupForeignCall(REGISTER_FINALIZER); - gen.emitForeignCall(linkage, this, gen.operand(object())); + public void generate(NodeLIRGeneratorTool gen) { + ForeignCallLinkage linkage = gen.getLIRGeneratorTool().getForeignCalls().lookupForeignCall(REGISTER_FINALIZER); + gen.getLIRGeneratorTool().emitForeignCall(linkage, this, gen.operand(object())); } @Override
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/SelfReplacingMethodCallTargetNode.java Wed Mar 26 14:43:50 2014 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/SelfReplacingMethodCallTargetNode.java Wed Mar 26 20:44:11 2014 +0100 @@ -29,7 +29,7 @@ import com.oracle.graal.graph.GraalInternalError; import com.oracle.graal.graph.NodeInputList; import com.oracle.graal.nodes.*; -import com.oracle.graal.nodes.spi.LIRGeneratorTool; +import com.oracle.graal.nodes.spi.NodeLIRGeneratorTool; import com.oracle.graal.nodes.spi.Lowerable; import com.oracle.graal.nodes.spi.LoweringTool; @@ -78,7 +78,7 @@ } @Override - public void generate(LIRGeneratorTool gen) { + public void generate(NodeLIRGeneratorTool gen) { throw GraalInternalError.shouldNotReachHere("should have replaced itself"); } }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/TypeSwitchNode.java Wed Mar 26 14:43:50 2014 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/TypeSwitchNode.java Wed Mar 26 20:44:11 2014 +0100 @@ -92,7 +92,7 @@ } @Override - public void generate(LIRGeneratorTool gen) { + public void generate(NodeLIRGeneratorTool gen) { gen.emitSwitch(this); }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/spi/ArithmeticLIRGenerator.java Wed Mar 26 14:43:50 2014 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/spi/ArithmeticLIRGenerator.java Wed Mar 26 20:44:11 2014 +0100 @@ -28,17 +28,12 @@ import com.oracle.graal.nodes.type.*; /** - * This interface can be used to generate LIR for arithmetic operations (@see - * ArithmeticLIRLowerable). + * This interface can be used to generate LIR for arithmetic operations. */ public interface ArithmeticLIRGenerator { - - Value operand(ValueNode object); - - boolean hasOperand(ValueNode object); - - Value setResult(ValueNode x, Value operand); - + /** + * TODO remove reference to {@link Stamp}. + */ PlatformKind getPlatformKind(Stamp stamp); Value emitNegate(Value input); @@ -49,12 +44,24 @@ Value emitMul(Value a, Value b); + /** + * TODO remove {@link DeoptimizeNode} + */ Value emitDiv(Value a, Value b, DeoptimizingNode deopting); + /** + * TODO remove {@link DeoptimizeNode} + */ Value emitRem(Value a, Value b, DeoptimizingNode deopting); + /** + * TODO remove {@link DeoptimizeNode} + */ Value emitUDiv(Value a, Value b, DeoptimizingNode deopting); + /** + * TODO remove {@link DeoptimizeNode} + */ Value emitURem(Value a, Value b, DeoptimizingNode deopting); Value emitNot(Value input);
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/spi/ArithmeticLIRLowerable.java Wed Mar 26 14:43:50 2014 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/spi/ArithmeticLIRLowerable.java Wed Mar 26 20:44:11 2014 +0100 @@ -26,5 +26,5 @@ public interface ArithmeticLIRLowerable extends ArithmeticOperation { - void generate(ArithmeticLIRGenerator gen); + void generate(NodeLIRGeneratorTool gen); }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/spi/LIRGeneratorTool.java Wed Mar 26 14:43:50 2014 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/spi/LIRGeneratorTool.java Wed Mar 26 20:44:11 2014 +0100 @@ -25,9 +25,7 @@ import com.oracle.graal.api.code.*; import com.oracle.graal.api.meta.*; import com.oracle.graal.nodes.*; -import com.oracle.graal.nodes.calc.*; import com.oracle.graal.nodes.extended.*; -import com.oracle.graal.nodes.java.*; public interface LIRGeneratorTool extends ArithmeticLIRGenerator { @@ -39,6 +37,14 @@ ForeignCallsProvider getForeignCalls(); + Value emitLoad(Kind kind, Value address, Access access); + + void emitStore(Kind kind, Value address, Value input, Access access); + + void emitDeoptimize(Value actionAndReason, Value failedSpeculation, DeoptimizingNode deopting); + + Value emitForeignCall(ForeignCallLinkage linkage, DeoptimizingNode info, Value... args); + /** * Checks whether the supplied constant can be used without loading it into a register for most * operations, i.e., for commonly used arithmetic, logical, and comparison operations. @@ -71,43 +77,8 @@ Value emitAddress(StackSlot slot); - Value emitLoad(Kind kind, Value address, Access access); - - void emitStore(Kind kind, Value address, Value input, Access access); - void emitMembar(int barriers); - void emitDeoptimize(Value actionAndReason, Value failedSpeculation, DeoptimizingNode deopting); - - void emitNullCheck(ValueNode v, DeoptimizingNode deopting); - - Value emitForeignCall(ForeignCallLinkage linkage, DeoptimizingNode info, Value... args); - - void emitIf(IfNode i); - - void emitConditional(ConditionalNode i); - - void emitSwitch(SwitchNode i); - - void emitInvoke(Invoke i); - - // Handling of block-end nodes still needs to be unified in the LIRGenerator. - void visitMerge(MergeNode i); - - void visitEndNode(AbstractEndNode i); - - void visitLoopEnd(LoopEndNode i); - - void visitCompareAndSwap(LoweredCompareAndSwapNode i, Value address); - - // These methods define the contract a runtime specific backend must provide. - - void visitReturn(ReturnNode i); - - void visitSafepointNode(SafepointNode i); - - void visitBreakpointNode(BreakpointNode i); - void emitUnwind(Value operand); /** @@ -116,5 +87,7 @@ */ void beforeRegisterAllocation(); - void visitInfopointNode(InfopointNode i); + void emitIncomingValues(Value[] params); + + void emitReturn(Value input); }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/spi/LIRLowerable.java Wed Mar 26 14:43:50 2014 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/spi/LIRLowerable.java Wed Mar 26 20:44:11 2014 +0100 @@ -24,5 +24,5 @@ public interface LIRLowerable { - void generate(LIRGeneratorTool generator); + void generate(NodeLIRGeneratorTool generator); }
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/spi/NodeLIRGeneratorTool.java Wed Mar 26 20:44:11 2014 +0100 @@ -0,0 +1,72 @@ +/* + * Copyright (c) 2011, 2012, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package com.oracle.graal.nodes.spi; + +import java.util.*; + +import com.oracle.graal.api.code.*; +import com.oracle.graal.api.meta.*; +import com.oracle.graal.nodes.*; +import com.oracle.graal.nodes.calc.*; +import com.oracle.graal.nodes.extended.*; +import com.oracle.graal.nodes.java.*; + +public interface NodeLIRGeneratorTool extends NodeMappableLIRGenerator { + + void emitNullCheck(ValueNode v, DeoptimizingNode deopting); + + void emitIf(IfNode i); + + void emitConditional(ConditionalNode i); + + void emitSwitch(SwitchNode i); + + void emitInvoke(Invoke i); + + // Handling of block-end nodes still needs to be unified in the LIRGenerator. + void visitMerge(MergeNode i); + + void visitEndNode(AbstractEndNode i); + + void visitLoopEnd(LoopEndNode i); + + void visitCompareAndSwap(LoweredCompareAndSwapNode i, Value address); + + // These methods define the contract a runtime specific backend must provide. + + void visitReturn(ReturnNode i); + + void visitSafepointNode(SafepointNode i); + + void visitBreakpointNode(BreakpointNode i); + + void visitInfopointNode(InfopointNode i); + + LIRGeneratorTool getLIRGeneratorTool(); + + void emitOverflowCheckBranch(AbstractBeginNode overflowSuccessor, AbstractBeginNode next, double probability); + + Value[] visitInvokeArguments(CallingConvention cc, Collection<ValueNode> arguments); + + MemoryArithmeticLIRLowerer getMemoryLowerer(); +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/spi/NodeMappableArithmeticLIRGenerator.java Wed Mar 26 20:44:11 2014 +0100 @@ -0,0 +1,30 @@ +/* + * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package com.oracle.graal.nodes.spi; + +/** + * This interface can be used to generate LIR for arithmetic operations (@see + * ArithmeticLIRLowerable). + */ +public interface NodeMappableArithmeticLIRGenerator extends ArithmeticLIRGenerator, NodeMappableLIRGenerator { +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/spi/NodeMappableLIRGenerator.java Wed Mar 26 20:44:11 2014 +0100 @@ -0,0 +1,14 @@ +package com.oracle.graal.nodes.spi; + +import com.oracle.graal.api.meta.*; +import com.oracle.graal.nodes.*; + +public interface NodeMappableLIRGenerator { + + Value operand(ValueNode object); + + boolean hasOperand(ValueNode object); + + Value setResult(ValueNode x, Value operand); + +} \ No newline at end of file
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/virtual/VirtualArrayNode.java Wed Mar 26 14:43:50 2014 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/virtual/VirtualArrayNode.java Wed Mar 26 20:44:11 2014 +0100 @@ -56,7 +56,7 @@ } @Override - public void generate(LIRGeneratorTool gen) { + public void generate(NodeLIRGeneratorTool gen) { // nothing to do... }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/virtual/VirtualObjectNode.java Wed Mar 26 14:43:50 2014 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/virtual/VirtualObjectNode.java Wed Mar 26 20:44:11 2014 +0100 @@ -91,7 +91,7 @@ public abstract ValueNode getMaterializedRepresentation(FixedNode fixed, ValueNode[] entries, LockState locks); @Override - public void generate(LIRGeneratorTool gen) { + public void generate(NodeLIRGeneratorTool gen) { // nothing to do... } }
--- a/graal/com.oracle.graal.printer/src/com/oracle/graal/printer/CFGPrinter.java Wed Mar 26 14:43:50 2014 +0100 +++ b/graal/com.oracle.graal.printer/src/com/oracle/graal/printer/CFGPrinter.java Wed Mar 26 20:44:11 2014 +0100 @@ -50,7 +50,7 @@ protected TargetDescription target; protected LIR lir; - protected LIRGenerator lirGenerator; + protected NodeLIRGenerator nodeLirGenerator; protected ControlFlowGraph cfg; protected SchedulePhase schedule; @@ -73,7 +73,7 @@ public void printCFG(String label, BciBlockMapping blockMap) { begin("cfg"); out.print("name \"").print(label).println('"'); - for (BciBlockMapping.Block block : blockMap.blocks) { + for (BciBlockMapping.BciBlock block : blockMap.blocks) { begin("block"); printBlock(block); end("block"); @@ -81,7 +81,7 @@ end("cfg"); } - private void printBlock(BciBlockMapping.Block block) { + private void printBlock(BciBlockMapping.BciBlock block) { out.print("name \"B").print(block.startBci).println('"'); out.print("from_bci ").println(block.startBci); out.print("to_bci ").println(block.endBci); @@ -89,7 +89,7 @@ out.println("predecessors "); out.print("successors "); - for (BciBlockMapping.Block succ : block.successors) { + for (BciBlockMapping.BciBlock succ : block.getSuccessors()) { if (!succ.isExceptionEntry) { out.print("\"B").print(succ.startBci).print("\" "); } @@ -97,7 +97,7 @@ out.println(); out.print("xhandlers"); - for (BciBlockMapping.Block succ : block.successors) { + for (BciBlockMapping.BciBlock succ : block.getSuccessors()) { if (succ.isExceptionEntry) { out.print("\"B").print(succ.startBci).print("\" "); } @@ -129,10 +129,11 @@ * @param label A label describing the compilation phase that produced the control flow graph. * @param blocks The list of blocks to be printed. */ - public void printCFG(String label, List<Block> blocks, boolean printNodes) { + public void printCFG(String label, List<? extends AbstractBlock<?>> blocks, boolean printNodes) { if (lir == null) { latestScheduling = new NodeMap<>(cfg.getNodeToBlock()); - for (Block block : blocks) { + for (AbstractBlock<?> abstractBlock : blocks) { + Block block = (Block) abstractBlock; Node cur = block.getBeginNode(); while (true) { assert inFixedSchedule(cur) && latestScheduling.get(cur) == block; @@ -146,17 +147,15 @@ } } } - printedNodes = new NodeBitMap(cfg.graph); begin("cfg"); out.print("name \"").print(label).println('"'); - for (Block block : blocks) { + for (AbstractBlock<?> block : blocks) { printBlock(block, printNodes); } end("cfg"); latestScheduling = null; - printedNodes = null; } private void scheduleInputs(Node node, Block nodeBlock) { @@ -187,20 +186,21 @@ } } - private void printBlock(Block block, boolean printNodes) { + private void printBlock(AbstractBlock<?> block, boolean printNodes) { printBlockProlog(block); if (printNodes) { - printNodes(block); + assert block instanceof Block; + printNodes((Block) block); } printBlockEpilog(block); } - private void printBlockEpilog(Block block) { + private void printBlockEpilog(AbstractBlock<?> block) { printLIR(block); end("block"); } - private void printBlockProlog(Block block) { + private void printBlockProlog(AbstractBlock<?> block) { begin("block"); out.print("name \"").print(blockToString(block)).println('"'); @@ -208,13 +208,13 @@ out.println("to_bci -1"); out.print("predecessors "); - for (Block pred : block.getPredecessors()) { + for (AbstractBlock<?> pred : block.getPredecessors()) { out.print("\"").print(blockToString(pred)).print("\" "); } out.println(); out.print("successors "); - for (Block succ : block.getSuccessors()) { + for (AbstractBlock<?> succ : block.getSuccessors()) { if (!succ.isExceptionEntry()) { out.print("\"").print(blockToString(succ)).print("\" "); } @@ -222,7 +222,7 @@ out.println(); out.print("xhandlers"); - for (Block succ : block.getSuccessors()) { + for (AbstractBlock<?> succ : block.getSuccessors()) { if (succ.isExceptionEntry()) { out.print("\"").print(blockToString(succ)).print("\" "); } @@ -248,6 +248,7 @@ } private void printNodes(Block block) { + printedNodes = new NodeBitMap(cfg.graph); begin("IR"); out.println("HIR"); out.disableIndentation(); @@ -281,6 +282,7 @@ out.enableIndentation(); end("IR"); + printedNodes = null; } private void printNode(Node node, boolean unscheduled) { @@ -307,8 +309,8 @@ } out.print("tid ").print(nodeToString(node)).println(COLUMN_END); - if (lirGenerator != null) { - Value operand = lirGenerator.nodeOperands.get(node); + if (nodeLirGenerator != null) { + Value operand = nodeLirGenerator.getNodeOperands().get(node); if (operand != null) { out.print("result ").print(operand.toString()).println(COLUMN_END); } @@ -412,8 +414,8 @@ private String stateValueToString(ValueNode value) { String result = nodeToString(value); - if (lirGenerator != null && lirGenerator.nodeOperands != null && value != null) { - Value operand = lirGenerator.nodeOperands.get(value); + if (nodeLirGenerator != null && nodeLirGenerator.getNodeOperands() != null && value != null) { + Value operand = nodeLirGenerator.getNodeOperands().get(value); if (operand != null) { result += ": " + operand; } @@ -426,11 +428,11 @@ * * @param block the block to print */ - private void printLIR(Block block) { + private void printLIR(AbstractBlock<?> block) { if (lir == null) { return; } - List<LIRInstruction> lirInstructions = lir.lir(block); + List<LIRInstruction> lirInstructions = lir.getLIRforBlock(block); if (lirInstructions == null) { return; } @@ -488,13 +490,13 @@ return prefix + node.toString(Verbosity.Id); } - private String blockToString(Block block) { - if (lir == null && schedule == null) { + private String blockToString(AbstractBlock<?> block) { + if (lir == null && schedule == null && block instanceof Block) { // During all the front-end phases, the block schedule is built only for the debug // output. // Therefore, the block numbers would be different for every CFG printed -> use the id // of the first instruction. - return "B" + block.getBeginNode().toString(Verbosity.Id); + return "B" + ((Block) block).getBeginNode().toString(Verbosity.Id); } else { // LIR instructions contain references to blocks and these blocks are printed as the // blockID -> use the blockID.
--- a/graal/com.oracle.graal.printer/src/com/oracle/graal/printer/CFGPrinterObserver.java Wed Mar 26 14:43:50 2014 +0100 +++ b/graal/com.oracle.graal.printer/src/com/oracle/graal/printer/CFGPrinterObserver.java Wed Mar 26 20:44:11 2014 +0100 @@ -137,12 +137,12 @@ } else { cfgPrinter.lir = Debug.contextLookup(LIR.class); } - cfgPrinter.lirGenerator = Debug.contextLookup(LIRGenerator.class); - if (cfgPrinter.lirGenerator != null) { - cfgPrinter.target = cfgPrinter.lirGenerator.target(); + cfgPrinter.nodeLirGenerator = Debug.contextLookup(NodeLIRGenerator.class); + if (cfgPrinter.nodeLirGenerator != null) { + cfgPrinter.target = cfgPrinter.nodeLirGenerator.getLIRGeneratorTool().target(); } - if (cfgPrinter.lir != null) { - cfgPrinter.cfg = cfgPrinter.lir.getControlFlowGraph(); + if (cfgPrinter.lir != null && cfgPrinter.lir.getControlFlowGraph() instanceof ControlFlowGraph) { + cfgPrinter.cfg = (ControlFlowGraph) cfgPrinter.lir.getControlFlowGraph(); } CodeCacheProvider codeCache = Debug.contextLookup(CodeCacheProvider.class); @@ -160,7 +160,7 @@ } else if (object instanceof LIR) { // No need to print the HIR nodes again if this is not the first // time dumping the same LIR since the HIR will not have changed. - boolean printNodes = previousObject != object; + boolean printNodes = previousObject != object && cfgPrinter.cfg != null; cfgPrinter.printCFG(message, cfgPrinter.lir.codeEmittingOrder(), printNodes); } else if (object instanceof SchedulePhase) { @@ -185,7 +185,7 @@ cfgPrinter.target = null; cfgPrinter.lir = null; - cfgPrinter.lirGenerator = null; + cfgPrinter.nodeLirGenerator = null; cfgPrinter.cfg = null; cfgPrinter.flush();
--- a/graal/com.oracle.graal.replacements.amd64/src/com/oracle/graal/replacements/amd64/AMD64FloatConvertNode.java Wed Mar 26 14:43:50 2014 +0100 +++ b/graal/com.oracle.graal.replacements.amd64/src/com/oracle/graal/replacements/amd64/AMD64FloatConvertNode.java Wed Mar 26 20:44:11 2014 +0100 @@ -51,7 +51,7 @@ throw GraalInternalError.shouldNotReachHere(); } - public void generate(ArithmeticLIRGenerator gen) { - gen.setResult(this, gen.emitFloatConvert(op, gen.operand(value))); + public void generate(NodeLIRGeneratorTool gen) { + gen.setResult(this, gen.getLIRGeneratorTool().emitFloatConvert(op, gen.operand(value))); } }
--- a/graal/com.oracle.graal.replacements.hsail/src/com/oracle/graal/replacements/hsail/HSAILMathIntrinsicsNode.java Wed Mar 26 14:43:50 2014 +0100 +++ b/graal/com.oracle.graal.replacements.hsail/src/com/oracle/graal/replacements/hsail/HSAILMathIntrinsicsNode.java Wed Mar 26 20:44:11 2014 +0100 @@ -33,8 +33,7 @@ import com.oracle.graal.nodes.calc.FloatingNode; import com.oracle.graal.nodes.ConstantNode; import com.oracle.graal.nodes.ValueNode; -import com.oracle.graal.nodes.spi.ArithmeticLIRGenerator; -import com.oracle.graal.nodes.spi.ArithmeticLIRLowerable; +import com.oracle.graal.nodes.spi.*; import com.oracle.graal.nodes.type.StampFactory; /** @@ -86,24 +85,24 @@ * Generates the LIR instructions for the math operation represented by this node. */ @Override - public void generate(ArithmeticLIRGenerator gen) { + public void generate(NodeLIRGeneratorTool gen) { Value input = gen.operand(getParameter()); Value result; switch (operation()) { case ABS: - result = gen.emitMathAbs(input); + result = gen.getLIRGeneratorTool().emitMathAbs(input); break; case CEIL: - result = ((HSAILLIRGenerator) (gen)).emitMathCeil(input); + result = ((HSAILLIRGenerator) (gen.getLIRGeneratorTool())).emitMathCeil(input); break; case FLOOR: - result = ((HSAILLIRGenerator) (gen)).emitMathFloor(input); + result = ((HSAILLIRGenerator) (gen.getLIRGeneratorTool())).emitMathFloor(input); break; case RINT: - result = ((HSAILLIRGenerator) (gen)).emitMathRint(input); + result = ((HSAILLIRGenerator) (gen.getLIRGeneratorTool())).emitMathRint(input); break; case SQRT: - result = gen.emitMathSqrt(input); + result = gen.getLIRGeneratorTool().emitMathSqrt(input); break; default: @@ -175,4 +174,5 @@ */ @NodeIntrinsic public static native double compute(double value, @ConstantNodeParameter HSAILArithmetic op); + }
--- a/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/GraphKit.java Wed Mar 26 14:43:50 2014 +0100 +++ b/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/GraphKit.java Wed Mar 26 20:44:11 2014 +0100 @@ -106,7 +106,7 @@ * @param name the name of the invoked method * @param args the arguments to the invocation */ - public InvokeNode createInvoke(Class<?> declaringClass, String name, InvokeKind invokeKind, FrameStateBuilder frameStateBuilder, int bci, ValueNode... args) { + public InvokeNode createInvoke(Class<?> declaringClass, String name, InvokeKind invokeKind, HIRFrameStateBuilder frameStateBuilder, int bci, ValueNode... args) { boolean isStatic = invokeKind == InvokeKind.Static; ResolvedJavaMethod method = null; for (Method m : declaringClass.getDeclaredMethods()) { @@ -123,7 +123,7 @@ * Creates and appends an {@link InvokeNode} for a call to a given method with a given set of * arguments. */ - public InvokeNode createInvoke(ResolvedJavaMethod method, InvokeKind invokeKind, FrameStateBuilder frameStateBuilder, int bci, ValueNode... args) { + public InvokeNode createInvoke(ResolvedJavaMethod method, InvokeKind invokeKind, HIRFrameStateBuilder frameStateBuilder, int bci, ValueNode... args) { assert Modifier.isStatic(method.getModifiers()) == (invokeKind == InvokeKind.Static); Signature signature = method.getSignature(); JavaType returnType = signature.getReturnType(null);
--- a/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/nodes/ArrayEqualsNode.java Wed Mar 26 14:43:50 2014 +0100 +++ b/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/nodes/ArrayEqualsNode.java Wed Mar 26 20:44:11 2014 +0100 @@ -131,7 +131,7 @@ public static native boolean equals(double[] array1, double[] array2, int length); @Override - public void generate(LIRGenerator gen) { + public void generate(NodeLIRGenerator gen) { Variable result = gen.newVariable(Kind.Int); gen.emitArrayEquals(kind, result, gen.operand(array1), gen.operand(array2), gen.operand(length)); gen.setResult(this, result);
--- a/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/nodes/BitCountNode.java Wed Mar 26 14:43:50 2014 +0100 +++ b/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/nodes/BitCountNode.java Wed Mar 26 20:44:11 2014 +0100 @@ -65,7 +65,7 @@ } @Override - public void generate(LIRGenerator gen) { + public void generate(NodeLIRGenerator gen) { Variable result = gen.newVariable(Kind.Int); gen.emitBitCount(result, gen.operand(value)); gen.setResult(this, result);
--- a/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/nodes/BitScanForwardNode.java Wed Mar 26 14:43:50 2014 +0100 +++ b/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/nodes/BitScanForwardNode.java Wed Mar 26 20:44:11 2014 +0100 @@ -72,7 +72,7 @@ } @Override - public void generate(LIRGenerator gen) { + public void generate(NodeLIRGenerator gen) { Variable result = gen.newVariable(Kind.Int); gen.emitBitScanForward(result, gen.operand(value)); gen.setResult(this, result);
--- a/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/nodes/BitScanReverseNode.java Wed Mar 26 14:43:50 2014 +0100 +++ b/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/nodes/BitScanReverseNode.java Wed Mar 26 20:44:11 2014 +0100 @@ -79,9 +79,9 @@ } @Override - public void generate(LIRGenerator gen) { + public void generate(NodeLIRGenerator gen) { Variable result = gen.newVariable(Kind.Int); - gen.emitBitScanReverse(result, gen.operand(value)); + gen.getLIRGeneratorTool().emitBitScanReverse(result, gen.operand(value)); gen.setResult(this, result); }
--- a/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/nodes/DirectReadNode.java Wed Mar 26 14:43:50 2014 +0100 +++ b/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/nodes/DirectReadNode.java Wed Mar 26 20:44:11 2014 +0100 @@ -46,8 +46,8 @@ } @Override - public void generate(LIRGeneratorTool gen) { - gen.setResult(this, gen.emitLoad(readKind, gen.operand(address), null)); + public void generate(NodeLIRGeneratorTool gen) { + gen.setResult(this, gen.getLIRGeneratorTool().emitLoad(readKind, gen.operand(address), null)); } @SuppressWarnings("unchecked")
--- a/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/nodes/DirectStoreNode.java Wed Mar 26 14:43:50 2014 +0100 +++ b/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/nodes/DirectStoreNode.java Wed Mar 26 20:44:11 2014 +0100 @@ -48,9 +48,9 @@ } @Override - public void generate(LIRGeneratorTool gen) { + public void generate(NodeLIRGeneratorTool gen) { Value v = gen.operand(value); - gen.emitStore(kind, gen.operand(address), v, null); + gen.getLIRGeneratorTool().emitStore(kind, gen.operand(address), v, null); } /*
--- a/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/nodes/MathIntrinsicNode.java Wed Mar 26 14:43:50 2014 +0100 +++ b/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/nodes/MathIntrinsicNode.java Wed Mar 26 20:44:11 2014 +0100 @@ -55,30 +55,30 @@ } @Override - public void generate(ArithmeticLIRGenerator gen) { + public void generate(NodeLIRGeneratorTool gen) { Value input = gen.operand(x()); Value result; switch (operation()) { case ABS: - result = gen.emitMathAbs(input); + result = gen.getLIRGeneratorTool().emitMathAbs(input); break; case SQRT: - result = gen.emitMathSqrt(input); + result = gen.getLIRGeneratorTool().emitMathSqrt(input); break; case LOG: - result = gen.emitMathLog(input, false); + result = gen.getLIRGeneratorTool().emitMathLog(input, false); break; case LOG10: - result = gen.emitMathLog(input, true); + result = gen.getLIRGeneratorTool().emitMathLog(input, true); break; case SIN: - result = gen.emitMathSin(input); + result = gen.getLIRGeneratorTool().emitMathSin(input); break; case COS: - result = gen.emitMathCos(input); + result = gen.getLIRGeneratorTool().emitMathCos(input); break; case TAN: - result = gen.emitMathTan(input); + result = gen.getLIRGeneratorTool().emitMathTan(input); break; default: throw GraalInternalError.shouldNotReachHere();
--- a/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/nodes/ReadRegisterNode.java Wed Mar 26 14:43:50 2014 +0100 +++ b/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/nodes/ReadRegisterNode.java Wed Mar 26 20:44:11 2014 +0100 @@ -24,17 +24,16 @@ import com.oracle.graal.api.code.*; import com.oracle.graal.api.meta.*; -import com.oracle.graal.compiler.gen.*; -import com.oracle.graal.compiler.target.*; import com.oracle.graal.graph.*; import com.oracle.graal.nodes.*; +import com.oracle.graal.nodes.spi.*; import com.oracle.graal.nodes.type.*; /** * Access the value of a specific register. */ @NodeInfo(nameTemplate = "ReadRegister %{p#register}") -public final class ReadRegisterNode extends FixedWithNextNode implements LIRGenLowerable { +public final class ReadRegisterNode extends FixedWithNextNode implements LIRLowerable { /** * The fixed register to access. @@ -75,13 +74,13 @@ } @Override - public void generate(LIRGenerator generator) { + public void generate(NodeLIRGeneratorTool generator) { Value result = register.asValue(getKind()); if (incoming) { - generator.emitIncomingValues(new Value[]{result}); + generator.getLIRGeneratorTool().emitIncomingValues(new Value[]{result}); } if (!directUse) { - result = generator.emitMove(result); + result = generator.getLIRGeneratorTool().emitMove(result); } generator.setResult(this, result); }
--- a/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/nodes/ReverseBytesNode.java Wed Mar 26 14:43:50 2014 +0100 +++ b/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/nodes/ReverseBytesNode.java Wed Mar 26 20:44:11 2014 +0100 @@ -66,9 +66,9 @@ } @Override - public void generate(LIRGenerator gen) { + public void generate(NodeLIRGenerator gen) { Variable result = gen.newVariable(value.getKind()); - gen.emitByteSwap(result, gen.operand(value)); + gen.getLIRGenerator().emitByteSwap(result, gen.operand(value)); gen.setResult(this, result); } }
--- a/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/nodes/WriteRegisterNode.java Wed Mar 26 14:43:50 2014 +0100 +++ b/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/nodes/WriteRegisterNode.java Wed Mar 26 20:44:11 2014 +0100 @@ -52,9 +52,9 @@ } @Override - public void generate(LIRGeneratorTool generator) { + public void generate(NodeLIRGeneratorTool generator) { Value val = generator.operand(value); - generator.emitMove(register.asValue(val.getKind()), val); + generator.getLIRGeneratorTool().emitMove(register.asValue(val.getKind()), val); } @Override
--- a/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/arithmetic/IntegerAddExactSplitNode.java Wed Mar 26 14:43:50 2014 +0100 +++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/arithmetic/IntegerAddExactSplitNode.java Wed Mar 26 20:44:11 2014 +0100 @@ -34,7 +34,7 @@ } @Override - protected Value generateArithmetic(LIRGeneratorTool gen) { - return gen.emitAdd(gen.operand(getX()), gen.operand(getY())); + protected Value generateArithmetic(NodeLIRGeneratorTool gen) { + return gen.getLIRGeneratorTool().emitAdd(gen.operand(getX()), gen.operand(getY())); } }
--- a/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/arithmetic/IntegerExactArithmeticSplitNode.java Wed Mar 26 14:43:50 2014 +0100 +++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/arithmetic/IntegerExactArithmeticSplitNode.java Wed Mar 26 20:44:11 2014 +0100 @@ -23,14 +23,12 @@ package com.oracle.graal.truffle.nodes.arithmetic; import com.oracle.graal.api.meta.*; -import com.oracle.graal.compiler.gen.*; -import com.oracle.graal.compiler.target.*; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.calc.*; import com.oracle.graal.nodes.spi.*; import com.oracle.graal.nodes.type.*; -public abstract class IntegerExactArithmeticSplitNode extends ControlSplitNode implements LIRGenLowerable { +public abstract class IntegerExactArithmeticSplitNode extends ControlSplitNode implements LIRLowerable { @Successor private AbstractBeginNode overflowSuccessor; @Successor private AbstractBeginNode next; @@ -72,12 +70,12 @@ } @Override - public void generate(LIRGenerator generator) { + public void generate(NodeLIRGeneratorTool generator) { generator.setResult(this, generateArithmetic(generator)); - generator.emitOverflowCheckBranch(generator.getLIRBlock(getOverflowSuccessor()), generator.getLIRBlock(getNext()), probability(getOverflowSuccessor())); + generator.emitOverflowCheckBranch(getOverflowSuccessor(), getNext(), probability(getOverflowSuccessor())); } - protected abstract Value generateArithmetic(LIRGeneratorTool generator); + protected abstract Value generateArithmetic(NodeLIRGeneratorTool generator); static void lower(LoweringTool tool, IntegerExactArithmeticNode node) { if (node.asNode().graph().getGuardsStage() == StructuredGraph.GuardsStage.FIXED_DEOPTS) {
--- a/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/arithmetic/IntegerMulExactSplitNode.java Wed Mar 26 14:43:50 2014 +0100 +++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/arithmetic/IntegerMulExactSplitNode.java Wed Mar 26 20:44:11 2014 +0100 @@ -34,7 +34,7 @@ } @Override - protected Value generateArithmetic(LIRGeneratorTool gen) { - return gen.emitMul(gen.operand(getX()), gen.operand(getY())); + protected Value generateArithmetic(NodeLIRGeneratorTool gen) { + return gen.getLIRGeneratorTool().emitMul(gen.operand(getX()), gen.operand(getY())); } }
--- a/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/arithmetic/IntegerSubExactSplitNode.java Wed Mar 26 14:43:50 2014 +0100 +++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/arithmetic/IntegerSubExactSplitNode.java Wed Mar 26 20:44:11 2014 +0100 @@ -34,7 +34,7 @@ } @Override - protected Value generateArithmetic(LIRGeneratorTool gen) { - return gen.emitSub(gen.operand(getX()), gen.operand(getY())); + protected Value generateArithmetic(NodeLIRGeneratorTool gen) { + return gen.getLIRGeneratorTool().emitSub(gen.operand(getX()), gen.operand(getY())); } }
--- a/graal/com.oracle.graal.word/src/com/oracle/graal/word/nodes/WordCastNode.java Wed Mar 26 14:43:50 2014 +0100 +++ b/graal/com.oracle.graal.word/src/com/oracle/graal/word/nodes/WordCastNode.java Wed Mar 26 20:44:11 2014 +0100 @@ -67,12 +67,12 @@ } @Override - public void generate(LIRGeneratorTool generator) { + public void generate(NodeLIRGeneratorTool generator) { assert getKind() != input.getKind(); - assert generator.target().getSizeInBytes(getKind()) == generator.target().getSizeInBytes(input.getKind()); + assert generator.getLIRGeneratorTool().target().getSizeInBytes(getKind()) == generator.getLIRGeneratorTool().target().getSizeInBytes(input.getKind()); - AllocatableValue result = generator.newVariable(getKind()); - generator.emitMove(result, generator.operand(input)); + AllocatableValue result = generator.getLIRGeneratorTool().newVariable(getKind()); + generator.getLIRGeneratorTool().emitMove(result, generator.operand(input)); generator.setResult(this, result); } }
--- a/mx/projects Wed Mar 26 14:43:50 2014 +0100 +++ b/mx/projects Wed Mar 26 20:44:11 2014 +0100 @@ -141,7 +141,7 @@ # graal.hotspot project@com.oracle.graal.hotspot@subDir=graal project@com.oracle.graal.hotspot@sourceDirs=src -project@com.oracle.graal.hotspot@dependencies=com.oracle.graal.replacements,com.oracle.graal.runtime,com.oracle.graal.printer +project@com.oracle.graal.hotspot@dependencies=com.oracle.graal.replacements,com.oracle.graal.runtime,com.oracle.graal.printer, com.oracle.graal.baseline project@com.oracle.graal.hotspot@checkstyle=com.oracle.graal.graph project@com.oracle.graal.hotspot@annotationProcessors=com.oracle.graal.replacements.verifier,com.oracle.graal.service.processor project@com.oracle.graal.hotspot@javaCompliance=1.8 @@ -483,7 +483,7 @@ # graal.baseline project@com.oracle.graal.baseline@subDir=graal project@com.oracle.graal.baseline@sourceDirs=src -project@com.oracle.graal.baseline@dependencies=com.oracle.graal.java,com.oracle.graal.lir +project@com.oracle.graal.baseline@dependencies=com.oracle.graal.java,com.oracle.graal.lir,com.oracle.graal.compiler project@com.oracle.graal.baseline@checkstyle=com.oracle.graal.graph project@com.oracle.graal.baseline@javaCompliance=1.8 project@com.oracle.graal.baseline@workingSets=Graal,Java