Mercurial > hg > truffle
view graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/GraalCompilation.java @ 4199:aaac4894175c
Renamed cri packages from sun to oracle.
author | Thomas Wuerthinger <thomas.wuerthinger@oracle.com> |
---|---|
date | Tue, 03 Jan 2012 16:29:28 +0100 |
parents | 9e0c1b4cfef5 |
children | 847e9dcb4980 |
line wrap: on
line source
/* * Copyright (c) 2009, 2012, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 only, as * published by the Free Software Foundation. * * This code is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * version 2 for more details (a copy is included in the LICENSE file that * accompanied this code). * * You should have received a copy of the GNU General Public License version * 2 along with this work; if not, write to the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. * * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA * or visit www.oracle.com if you need additional information or have any * questions. */ package com.oracle.max.graal.compiler; import static com.oracle.max.cri.ci.CiValueUtil.*; import java.util.*; import com.oracle.max.asm.*; import com.oracle.max.cri.ci.*; import com.oracle.max.cri.ci.CiCompiler.*; import com.oracle.max.cri.ri.*; import com.oracle.max.cri.xir.*; import com.oracle.max.criutils.*; import com.oracle.max.graal.alloc.simple.*; import com.oracle.max.graal.compiler.alloc.*; import com.oracle.max.graal.compiler.asm.*; import com.oracle.max.graal.compiler.gen.*; import com.oracle.max.graal.compiler.graphbuilder.*; import com.oracle.max.graal.compiler.lir.*; import com.oracle.max.graal.compiler.observer.*; import com.oracle.max.graal.compiler.phases.*; import com.oracle.max.graal.compiler.phases.PhasePlan.PhasePosition; import com.oracle.max.graal.compiler.schedule.*; import com.oracle.max.graal.graph.*; import com.oracle.max.graal.nodes.*; import com.oracle.max.graal.nodes.virtual.*; /** * This class encapsulates global information about the compilation of a particular method, * including a reference to the runtime, statistics about the compiled code, etc. */ public final class GraalCompilation { public final GraalCompiler compiler; public final RiResolvedMethod method; public final RiRegisterConfig registerConfig; public final CiStatistics stats; public final FrameState placeholderState; public final StructuredGraph graph; public final CiAssumptions assumptions = GraalOptions.OptAssumptions ? new CiAssumptions() : null; public NodeMap<CiValue> nodeOperands; private FrameMap frameMap; private LIR lir; /** * Creates a new compilation for the specified method and runtime. * * @param context the compilation context * @param compiler the compiler * @param method the method to be compiled or {@code null} if generating code for a stub * @param osrBCI the bytecode index for on-stack replacement, if requested * @param stats externally supplied statistics object to be used if not {@code null} * @param debugInfoLevel TODO */ public GraalCompilation(GraalContext context, GraalCompiler compiler, RiResolvedMethod method, StructuredGraph graph, int osrBCI, CiStatistics stats, DebugInfoLevel debugInfoLevel) { if (osrBCI != -1) { throw new CiBailout("No OSR supported"); } this.compiler = compiler; this.graph = graph; this.method = method; this.stats = stats == null ? new CiStatistics() : stats; this.registerConfig = method == null ? compiler.compilerStubRegisterConfig : compiler.runtime.getRegisterConfig(method); this.placeholderState = debugInfoLevel == DebugInfoLevel.REF_MAPS ? new FrameState(method, 0, 0, 0, 0, false) : null; if (context().isObserved() && method != null) { context().observable.fireCompilationStarted(this); } } public GraalCompilation(GraalContext context, GraalCompiler compiler, RiResolvedMethod method, int osrBCI, CiStatistics stats, DebugInfoLevel debugInfoLevel) { this(context, compiler, method, new StructuredGraph(), osrBCI, stats, debugInfoLevel); } public void close() { // TODO(tw): Check if we can delete this method. } public LIR lir() { return lir; } public CiValue operand(ValueNode valueNode) { if (nodeOperands == null) { return null; } return nodeOperands.get(valueNode); } public void setOperand(ValueNode valueNode, CiValue operand) { assert operand(valueNode) == null : "operand cannot be set twice"; assert operand != null && isLegal(operand) : "operand must be legal"; assert operand.kind.stackKind() == valueNode.kind(); assert !(valueNode instanceof VirtualObjectNode); nodeOperands.set(valueNode, operand); } /** * Converts this compilation to a string. * @return a string representation of this compilation */ @Override public String toString() { return "compile: " + method; } /** * Returns the frame map of this compilation. * @return the frame map */ public FrameMap frameMap() { return frameMap; } private TargetMethodAssembler createAssembler() { AbstractAssembler masm = compiler.backend.newAssembler(registerConfig); TargetMethodAssembler tasm = new TargetMethodAssembler(this, masm); tasm.setFrameSize(frameMap.frameSize()); tasm.targetMethod.setCustomStackAreaOffset(frameMap.offsetToCustomArea()); return tasm; } public CiTargetMethod compile(PhasePlan plan) { CiTargetMethod targetMethod; try { try { emitHIR(plan); emitLIR(compiler.xir); targetMethod = emitCode(); if (GraalOptions.Meter) { context().metrics.BytecodesCompiled += method.codeSize(); } } catch (CiBailout bailout) { throw bailout; } catch (GraalInternalError e) { throw e.addContext("method", CiUtil.format("%H.%n(%p):%r", method)); } catch (Throwable t) { throw new RuntimeException("Exception while compiling: " + method, t); } } catch (GraalInternalError error) { if (context().isObserved()) { if (error.node() != null) { context().observable.fireCompilationEvent("VerificationError on Node " + error.node(), CompilationEvent.ERROR, this, error.node().graph()); } else if (error.graph() != null) { context().observable.fireCompilationEvent("VerificationError on Graph " + error.graph(), CompilationEvent.ERROR, this, error.graph()); } } throw error; } finally { if (context().isObserved()) { context().observable.fireCompilationFinished(this); } } return targetMethod; } /** * Builds the graph, optimizes it. */ public void emitHIR(PhasePlan plan) { try { context().timers.startScope("HIR"); if (graph.start().next() == null) { GraphBuilderPhase graphBuilderPhase = new GraphBuilderPhase(compiler.runtime, method, stats); graphBuilderPhase.apply(graph, context()); plan.runPhases(PhasePosition.AFTER_PARSING, graph, context()); new DeadCodeEliminationPhase().apply(graph, context()); } else { if (context().isObserved()) { context().observable.fireCompilationEvent("initial state", graph); } } new PhiStampPhase().apply(graph); if (GraalOptions.ProbabilityAnalysis && graph.start().probability() == 0) { new ComputeProbabilityPhase().apply(graph, context()); } if (GraalOptions.Intrinsify) { new IntrinsificationPhase(compiler.runtime).apply(graph, context()); } if (GraalOptions.Inline && !plan.isPhaseDisabled(InliningPhase.class)) { new InliningPhase(compiler.target, compiler.runtime, null, assumptions, plan).apply(graph, context()); new DeadCodeEliminationPhase().apply(graph, context()); new PhiStampPhase().apply(graph); } if (GraalOptions.OptCanonicalizer) { new CanonicalizerPhase(compiler.target, compiler.runtime, assumptions).apply(graph, context()); } plan.runPhases(PhasePosition.HIGH_LEVEL, graph, context()); if (GraalOptions.OptLoops) { graph.mark(); new FindInductionVariablesPhase().apply(graph, context()); if (GraalOptions.OptCanonicalizer) { new CanonicalizerPhase(compiler.target, compiler.runtime, true, assumptions).apply(graph, context()); } new SafepointPollingEliminationPhase().apply(graph, context()); } if (GraalOptions.EscapeAnalysis && !plan.isPhaseDisabled(EscapeAnalysisPhase.class)) { new EscapeAnalysisPhase(compiler.target, compiler.runtime, assumptions, plan).apply(graph, context()); new PhiStampPhase().apply(graph); new CanonicalizerPhase(compiler.target, compiler.runtime, assumptions).apply(graph, context()); } if (GraalOptions.OptGVN) { new GlobalValueNumberingPhase().apply(graph, context()); } graph.mark(); new LoweringPhase(compiler.runtime).apply(graph, context()); new CanonicalizerPhase(compiler.target, compiler.runtime, true, assumptions).apply(graph, context()); if (GraalOptions.OptLoops) { graph.mark(); new RemoveInductionVariablesPhase().apply(graph, context()); if (GraalOptions.OptCanonicalizer) { new CanonicalizerPhase(compiler.target, compiler.runtime, true, assumptions).apply(graph, context()); } } if (GraalOptions.Lower) { new FloatingReadPhase().apply(graph, context()); if (GraalOptions.OptReadElimination) { new ReadEliminationPhase().apply(graph, context()); } } new RemovePlaceholderPhase().apply(graph, context()); new DeadCodeEliminationPhase().apply(graph, context()); plan.runPhases(PhasePosition.MID_LEVEL, graph, context()); plan.runPhases(PhasePosition.LOW_LEVEL, graph, context()); IdentifyBlocksPhase schedule = new IdentifyBlocksPhase(true, LIRBlock.FACTORY); schedule.apply(graph, context()); if (stats != null) { stats.loopCount = schedule.loopCount(); } if (context().isObserved()) { context().observable.fireCompilationEvent("After IdentifyBlocksPhase", this, graph, schedule); } List<Block> blocks = schedule.getBlocks(); NodeMap<LIRBlock> valueToBlock = new NodeMap<>(graph); for (Block b : blocks) { for (Node i : b.getInstructions()) { valueToBlock.set(i, (LIRBlock) b); } } LIRBlock startBlock = valueToBlock.get(graph.start()); assert startBlock != null; assert startBlock.numberOfPreds() == 0; context().timers.startScope("Compute Linear Scan Order"); try { ComputeLinearScanOrder clso = new ComputeLinearScanOrder(blocks.size(), stats.loopCount, startBlock); List<LIRBlock> linearScanOrder = clso.linearScanOrder(); List<LIRBlock> codeEmittingOrder = clso.codeEmittingOrder(); int z = 0; for (LIRBlock b : linearScanOrder) { b.setLinearScanNumber(z++); } lir = new LIR(startBlock, linearScanOrder, codeEmittingOrder, valueToBlock); if (context().isObserved()) { context().observable.fireCompilationEvent("After linear scan order", this, graph, lir); } } catch (AssertionError t) { context().observable.fireCompilationEvent("AssertionError in ComputeLinearScanOrder", CompilationEvent.ERROR, this, graph); throw t; } catch (RuntimeException t) { context().observable.fireCompilationEvent("RuntimeException in ComputeLinearScanOrder", CompilationEvent.ERROR, this, graph); throw t; } finally { context().timers.endScope(); } } finally { context().timers.endScope(); } } public void initFrameMap() { frameMap = this.compiler.backend.newFrameMap(this); } private void emitLIR(RiXirGenerator xir) { context().timers.startScope("LIR"); try { if (GraalOptions.GenLIR) { context().timers.startScope("Create LIR"); nodeOperands = graph.createNodeMap(); LIRGenerator lirGenerator = null; try { initFrameMap(); lirGenerator = compiler.backend.newLIRGenerator(this, xir); for (LIRBlock b : lir.linearScanOrder()) { lirGenerator.doBlock(b); } for (LIRBlock b : lir.linearScanOrder()) { if (b.phis != null) { b.phis.fillInputs(lirGenerator); } } } finally { context().timers.endScope(); } if (context().isObserved()) { context().observable.fireCompilationEvent("After LIR generation", this, graph, lir); } if (GraalOptions.PrintLIR && !TTY.isSuppressed()) { LIR.printLIR(lir.linearScanOrder()); } if (GraalOptions.AllocSSA) { new SpillAllAllocator(context(), lir, this, lirGenerator.operands, registerConfig, lirGenerator.incomingArguments).execute(); } else { new LinearScan(this, lir, lirGenerator, frameMap()).allocate(); } } } catch (Error e) { if (context().isObserved() && GraalOptions.PlotOnError) { context().observable.fireCompilationEvent(e.getClass().getSimpleName() + " in emitLIR", CompilationEvent.ERROR, this, graph); } throw e; } catch (RuntimeException e) { if (context().isObserved() && GraalOptions.PlotOnError) { context().observable.fireCompilationEvent(e.getClass().getSimpleName() + " in emitLIR", CompilationEvent.ERROR, this, graph); } throw e; } finally { context().timers.endScope(); } } private CiTargetMethod emitCode() { if (GraalOptions.GenLIR && GraalOptions.GenCode) { context().timers.startScope("Create Code"); try { TargetMethodAssembler tasm = createAssembler(); lir.emitCode(tasm); CiTargetMethod targetMethod = tasm.finishTargetMethod(method, compiler.runtime, false); if (assumptions != null && !assumptions.isEmpty()) { targetMethod.setAssumptions(assumptions); } if (context().isObserved()) { context().observable.fireCompilationEvent("After code generation", this, lir, targetMethod); } return targetMethod; } finally { context().timers.endScope(); } } return null; } /** * Gets the maximum number of locks in the graph's frame states. */ public int maxLocks() { int maxLocks = 0; for (FrameState node : graph.getNodes(FrameState.class)) { int lockCount = 0; FrameState current = node; while (current != null) { lockCount += current.locksSize(); current = current.outerFrameState(); } if (lockCount > maxLocks) { maxLocks = lockCount; } } return maxLocks; } private GraalContext context() { return compiler.context; } public void printGraph(String phase, Graph printedGraph) { if (context().isObserved()) { context().observable.fireCompilationEvent(phase, this, printedGraph); } } }