001/* 002 * This file is part of the Jikes RVM project (http://jikesrvm.org). 003 * 004 * This file is licensed to You under the Eclipse Public License (EPL); 005 * You may not use this file except in compliance with the License. You 006 * may obtain a copy of the License at 007 * 008 * http://www.opensource.org/licenses/eclipse-1.0.php 009 * 010 * See the COPYRIGHT.txt file distributed with this work for information 011 * regarding copyright ownership. 012 */ 013package org.jikesrvm.compilers.opt.regalloc; 014 015import java.util.HashSet; 016 017import org.jikesrvm.VM; 018import org.jikesrvm.compilers.opt.OptOptions; 019import org.jikesrvm.compilers.opt.driver.CompilerPhase; 020import org.jikesrvm.compilers.opt.ir.GCIRMapElement; 021import org.jikesrvm.compilers.opt.ir.GenericPhysicalRegisterSet; 022import org.jikesrvm.compilers.opt.ir.IR; 023import org.jikesrvm.compilers.opt.ir.Instruction; 024import org.jikesrvm.compilers.opt.ir.RegSpillListElement; 025import org.jikesrvm.compilers.opt.ir.Register; 026 027/** 028 * Update GC Maps again, to account for changes induced by spill code. 029 */ 030final class UpdateGCMaps2 extends CompilerPhase { 031 /** 032 * Return this instance of this phase. This phase contains no 033 * per-compilation instance fields. 034 * @param ir not used 035 * @return this 036 */ 037 @Override 038 public CompilerPhase newExecution(IR ir) { 039 return this; 040 } 041 042 @Override 043 public boolean shouldPerform(OptOptions options) { 044 return true; 045 } 046 047 @Override 048 public String getName() { 049 return "Update GCMaps 2"; 050 } 051 052 @Override 053 public boolean printingEnabled(OptOptions options, boolean before) { 054 return false; 055 } 056 057 /** 058 * @param ir the IR 059 */ 060 @Override 061 public void perform(IR ir) { 062 GenericPhysicalRegisterSet phys = ir.regpool.getPhysicalRegisterSet(); 063 ScratchMap scratchMap = ir.stackManager.getScratchMap(); 064 RegisterAllocatorState regAllocState = ir.MIRInfo.regAllocState; 065 066 if (LinearScan.GC_DEBUG) { 067 System.out.println("SCRATCH MAP:\n" + scratchMap); 068 } 069 if (scratchMap.isEmpty()) return; 070 071 // Walk over each instruction that has a GC point. 072 for (GCIRMapElement GCelement : ir.MIRInfo.gcIRMap) { 073 // new elements to add to the gc map 074 HashSet<RegSpillListElement> newElements = new HashSet<RegSpillListElement>(); 075 076 Instruction GCinst = GCelement.getInstruction(); 077 078 int dfn = regAllocState.getDFN(GCinst); 079 080 if (LinearScan.GC_DEBUG) { 081 VM.sysWrite("GCelement at " + dfn + " , " + GCelement); 082 } 083 084 // a set of elements to delete from the GC Map 085 HashSet<RegSpillListElement> toDelete = new HashSet<RegSpillListElement>(3); 086 087 // For each element in the GC Map ... 088 for (RegSpillListElement elem : GCelement.regSpillList()) { 089 if (LinearScan.GC_DEBUG) { 090 VM.sysWrite("Update " + elem + "\n"); 091 } 092 if (elem.isSpill()) { 093 // check if the spilled value currently is cached in a scratch 094 // register 095 Register r = elem.getSymbolicReg(); 096 Register scratch = scratchMap.getScratch(r, dfn); 097 if (scratch != null) { 098 if (LinearScan.GC_DEBUG) { 099 VM.sysWrite("cached in scratch register " + scratch + "\n"); 100 } 101 // we will add a new element noting that the scratch register 102 // also must be including in the GC map 103 RegSpillListElement newElem = new RegSpillListElement(r); 104 newElem.setRealReg(scratch); 105 newElements.add(newElem); 106 // if the scratch register is dirty, then delete the spill 107 // location from the map, since it doesn't currently hold a 108 // valid value 109 if (scratchMap.isDirty(GCinst, r)) { 110 toDelete.add(elem); 111 } 112 } 113 } else { 114 // check if the physical register is currently spilled. 115 int n = elem.getRealRegNumber(); 116 Register r = phys.get(n); 117 if (scratchMap.isScratch(r, dfn)) { 118 // The regalloc state knows where the physical register r is 119 // spilled. 120 if (LinearScan.GC_DEBUG) { 121 VM.sysWrite("CHANGE to spill location " + regAllocState.getSpill(r) + "\n"); 122 } 123 elem.setSpill(regAllocState.getSpill(r)); 124 } 125 } 126 127 } 128 // delete all obsolete elements 129 for (RegSpillListElement deadElem : toDelete) { 130 GCelement.deleteRegSpillElement(deadElem); 131 } 132 133 // add each new Element to the gc map 134 for (RegSpillListElement newElem : newElements) { 135 GCelement.addRegSpillElement(newElem); 136 } 137 } 138 } 139}