/* * 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.util.HashSet; import org.jikesrvm.VM; import org.jikesrvm.compilers.opt.OptOptions; import org.jikesrvm.compilers.opt.driver.CompilerPhase; import org.jikesrvm.compilers.opt.ir.GCIRMapElement; import org.jikesrvm.compilers.opt.ir.GenericPhysicalRegisterSet; import org.jikesrvm.compilers.opt.ir.IR; import org.jikesrvm.compilers.opt.ir.Instruction; import org.jikesrvm.compilers.opt.ir.RegSpillListElement; import org.jikesrvm.compilers.opt.ir.Register; /** * Update GC Maps again, to account for changes induced by spill code. */ final class UpdateGCMaps2 extends CompilerPhase { /** * Return this instance of this phase. This phase contains no * per-compilation instance fields. * @param ir not used * @return this */ @Override public CompilerPhase newExecution(IR ir) { return this; } @Override public boolean shouldPerform(OptOptions options) { return true; } @Override public String getName() { return "Update GCMaps 2"; } @Override public boolean printingEnabled(OptOptions options, boolean before) { return false; } /** * @param ir the IR */ @Override public void perform(IR ir) { GenericPhysicalRegisterSet phys = ir.regpool.getPhysicalRegisterSet(); ScratchMap scratchMap = ir.stackManager.getScratchMap(); RegisterAllocatorState regAllocState = ir.MIRInfo.regAllocState; if (LinearScan.GC_DEBUG) { System.out.println("SCRATCH MAP:"); System.out.println(); System.out.println(scratchMap); } if (scratchMap.isEmpty()) return; // Walk over each instruction that has a GC point. for (GCIRMapElement GCelement : ir.MIRInfo.gcIRMap) { // new elements to add to the gc map HashSet<RegSpillListElement> newElements = new HashSet<RegSpillListElement>(); Instruction GCinst = GCelement.getInstruction(); int dfn = regAllocState.getDFN(GCinst); if (LinearScan.GC_DEBUG) { VM.sysWrite("GCelement at " + dfn + " , " + GCelement); } // a set of elements to delete from the GC Map HashSet<RegSpillListElement> toDelete = new HashSet<RegSpillListElement>(3); // For each element in the GC Map ... for (RegSpillListElement elem : GCelement.regSpillList()) { if (LinearScan.GC_DEBUG) { VM.sysWriteln("Update " + elem); } if (elem.isSpill()) { // check if the spilled value currently is cached in a scratch // register Register r = elem.getSymbolicReg(); Register scratch = scratchMap.getScratch(r, dfn); if (scratch != null) { if (LinearScan.GC_DEBUG) { VM.sysWriteln("cached in scratch register " + scratch); } // we will add a new element noting that the scratch register // also must be including in the GC map RegSpillListElement newElem = new RegSpillListElement(r); newElem.setRealReg(scratch); newElements.add(newElem); // if the scratch register is dirty, then delete the spill // location from the map, since it doesn't currently hold a // valid value if (scratchMap.isDirty(GCinst, r)) { toDelete.add(elem); } } } else { // check if the physical register is currently spilled. int n = elem.getRealRegNumber(); Register r = phys.get(n); if (scratchMap.isScratch(r, dfn)) { // The regalloc state knows where the physical register r is // spilled. if (LinearScan.GC_DEBUG) { VM.sysWriteln("CHANGE to spill location " + regAllocState.getSpill(r)); } elem.setSpill(regAllocState.getSpill(r)); } } } // delete all obsolete elements for (RegSpillListElement deadElem : toDelete) { GCelement.deleteRegSpillElement(deadElem); } // add each new Element to the gc map for (RegSpillListElement newElem : newElements) { GCelement.addRegSpillElement(newElem); } } } }