/* * This file is part of the Jikes RVM project (http://jikesrvm.org). * * This file is licensed to You under the Eclipse Public License (EPL); * You may not use this file except in compliance with the License. You * may obtain a copy of the License at * * http://www.opensource.org/licenses/eclipse-1.0.php * * See the COPYRIGHT.txt file distributed with this work for information * regarding copyright ownership. */ package org.jikesrvm.compilers.opt.regalloc; import java.lang.reflect.Constructor; import org.jikesrvm.compilers.opt.OptOptions; import org.jikesrvm.compilers.opt.OptimizingCompilerException; import org.jikesrvm.compilers.opt.driver.CompilerPhase; import org.jikesrvm.compilers.opt.ir.IR; public final class LinearScanPhase extends CompilerPhase { /** * An object which manages spill location assignments. */ private SpillLocationManager spillManager; private static final Constructor<CompilerPhase> constructor = getCompilerPhaseConstructor(LinearScanPhase.class); /** * {@inheritDoc} * @return compiler phase constructor */ @Override public Constructor<CompilerPhase> getClassConstructor() { return constructor; } /** * @return {@code true} because register allocation is required */ @Override public boolean shouldPerform(OptOptions options) { return true; } @Override public String getName() { return "Linear Scan"; } @Override public boolean printingEnabled(OptOptions options, boolean before) { return false; } /** * Perform the linear scan register allocation algorithm.<p> * * See TOPLAS 21(5), Sept 1999, p 895-913 * @param ir the IR */ @Override public void perform(IR ir) { // Create the object that manages spill locations spillManager = new SpillLocationManager(ir); ActiveSet active = createEmptySetOfActiveIntervals(ir); // Intervals sorted by increasing start point for (BasicInterval b : ir.MIRInfo.linearScanState.intervals) { MappedBasicInterval bi = (MappedBasicInterval) b; CompoundInterval ci = bi.container; active.expireOldIntervals(bi); // If the interval does not correspond to a physical register // then we process it. if (!ci.getRegister().isPhysical()) { // Update register allocation based on the new interval. active.allocate(bi, ci); } else { // Mark the physical register as currently allocated. ci.getRegister().allocateRegister(); } active.add(bi); } // update the state. if (active.spilledSomething()) { ir.MIRInfo.linearScanState.spilledSomething = true; } } private ActiveSet createEmptySetOfActiveIntervals(IR ir) { SpillCostEstimator spillCost = determineSpillCostEstimator(ir); ActiveSet active = new ActiveSet(ir, spillManager, spillCost); ir.MIRInfo.linearScanState.active = active; return active; } private SpillCostEstimator determineSpillCostEstimator(IR ir) { SpillCostEstimator spillCost = null; switch (ir.options.REGALLOC_SPILL_COST_ESTIMATE) { case OptOptions.REGALLOC_SIMPLE_SPILL_COST: spillCost = new SimpleSpillCost(ir); break; case OptOptions.REGALLOC_BRAINDEAD_SPILL_COST: spillCost = new BrainDeadSpillCost(ir); break; case OptOptions.REGALLOC_BLOCK_COUNT_SPILL_COST: spillCost = new BlockCountSpillCost(ir); break; default: OptimizingCompilerException.UNREACHABLE("unsupported spill cost"); spillCost = null; } return spillCost; } }