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.ir; 014 015import java.util.Iterator; 016import java.util.List; 017import java.util.ListIterator; 018import org.jikesrvm.compilers.opt.OptimizingCompilerException; 019import org.jikesrvm.compilers.opt.ir.operand.RegisterOperand; 020import org.jikesrvm.compilers.opt.liveness.LiveSet; 021import org.jikesrvm.compilers.opt.liveness.LiveSetEnumerator; 022import org.jikesrvm.util.LinkedListRVM; 023 024/** 025 * This class holds GC maps for various program points. 026 * This data structure is IR-based. In a later phase, this information 027 * will be used to create the final GC map (see OptMachineCodeMap.java) 028 */ 029public final class GCIRMap implements Iterable<GCIRMapElement> { 030 /** 031 * This is the list of maps. 032 * Each element on the list is an GCIRMapElement, which is a pair 033 * <ol> 034 * <li>an IR instruction (the GC point) 035 * <li>a list of RegSpillListElement, which initially hold symbolic 036 * registers that are references (these are expanded to either 037 * physical regs or spills by the register allocator) 038 * </ol> 039 */ 040 private final LinkedListRVM<GCIRMapElement> list = new LinkedListRVM<GCIRMapElement>(); 041 042 /** 043 * Used for class-wide debugging 044 */ 045 private static final boolean DEBUG = false; 046 047 /** 048 * returns the number of GC points in this map, i.e., the number of 049 * instructions we have maps for. 050 * @return the number of GC points in this map 051 */ 052 public int getNumInstructionMaps() { 053 return list.size(); 054 } 055 056 /** 057 * Calculates the number of spill entries in this GCIRMap 058 * This is the total number of spills for all instructions 059 * in this map. 060 * @return the number of spill entries in this map 061 */ 062 public int countNumSpillElements() { 063 // Since spill locations are not determined until after 064 // register allocation occurs, i.e., after the initial 065 // IR-based maps are created, we actually count the 066 // number of spills. 067 int count = 0; 068 for (GCIRMapElement elem : this) { 069 count += elem.countNumSpillElements(); 070 } 071 return count; 072 } 073 074 /** 075 * TODO What is this method doing in this class ?? RJG 076 * 077 * This method creates a regSpillList from the passed live set. 078 * @param set the set of registers, encoded as a LiveSet object 079 * @return a list corresponding to the set passed 080 */ 081 public List<RegSpillListElement> createDU(LiveSet set) { 082 if (DEBUG) { 083 System.out.println("creating a RegList for " + set); 084 } 085 086 // construct register list 087 List<RegSpillListElement> regList = new LinkedListRVM<RegSpillListElement>(); 088 LiveSetEnumerator lsEnum = set.enumerator(); 089 while (lsEnum.hasMoreElements()) { 090 RegisterOperand regOp = lsEnum.nextElement(); 091 092 // add this register to the regList, if it is a reference 093 // and not a physcial register 094 if (regOp.getType().isReferenceType() && !regOp.getRegister().isPhysical()) { 095 RegSpillListElement elem = new RegSpillListElement(regOp.getRegister()); 096 regList.add(elem); 097 } 098 } 099 return regList; 100 } 101 102 /** 103 * This method inserts a new entry into the GCIRMap 104 * @param inst the IR instruction we care about 105 * @param regList the set of symbolic registers as a list 106 */ 107 public void insert(Instruction inst, List<RegSpillListElement> regList) { 108 109 // make a GCIRMapElement and put it on the big list 110 GCIRMapElement item = new GCIRMapElement(inst, regList); 111 112 if (DEBUG) { 113 System.out.println("Inserting new item: " + item); 114 } 115 116 list.add(item); 117 } 118 119 /** 120 * This method removes an entry in the GCIRMap that is specified 121 * by inst. Only one element of the list will be removed per call. 122 * If the instruction is not found in the GC Map and exeception is thrown. 123 * @param inst the IR instruction we want to remove 124 */ 125 public void delete(Instruction inst) { 126 127 Iterator<GCIRMapElement> iter = list.iterator(); 128 while (iter.hasNext()) { 129 GCIRMapElement ptr = iter.next(); 130 if (ptr.getInstruction() == inst) { 131 iter.remove(); 132 return; 133 } 134 } 135 throw new OptimizingCompilerException("GCIRMap.delete(" + 136 inst + 137 ") did not delete instruction from GC Map "); 138 } 139 140 /** 141 * This method moves an entry in the GCIRMap that is specified 142 * by inst to the end of the list. Only one element of the list will be moved per call. 143 * If the instruction is not found in the GC Map and exception is thrown. 144 * @param inst the IR instruction we want to remove 145 */ 146 public void moveToEnd(Instruction inst) { 147 Iterator<GCIRMapElement> iter = list.iterator(); 148 while (iter.hasNext()) { 149 GCIRMapElement newPtr = iter.next(); 150 if (newPtr.getInstruction() == inst) { 151 iter.remove(); 152 list.add(newPtr); 153 return; 154 } 155 } 156 throw new OptimizingCompilerException("GCIRMap.moveToEnd(" + 157 inst + 158 ") did not delete instruction from GC Map "); 159 } 160 161 /** 162 * This method inserts an entry for a "twin" instruction immediately after the 163 * original entry. 164 * If the instruction is not found in the GC Map an exception is thrown. 165 * @param inst the original IR instruction 166 * @param twin the new twin IR instruction 167 */ 168 public void insertTwin(Instruction inst, Instruction twin) { 169 ListIterator<GCIRMapElement> iter = list.listIterator(); 170 while (iter.hasNext()) { 171 GCIRMapElement newPtr = iter.next(); 172 if (newPtr.getInstruction() == inst) { 173 iter.add(newPtr.createTwin(twin)); 174 return; 175 } 176 } 177 throw new OptimizingCompilerException("GCIRMap.createTwin: " + inst + " not found"); 178 } 179 180 @Override 181 public Iterator<GCIRMapElement> iterator() { 182 return list.iterator(); 183 } 184 185 /** 186 * dumps the map 187 */ 188 public void dump() { 189 System.out.println(toString()); 190 } 191 192 /** 193 * @return string version of this object 194 */ 195 @Override 196 public String toString() { 197 StringBuilder buf = new StringBuilder(); 198 if (list.isEmpty()) { 199 buf.append("empty"); 200 } else { 201 for (GCIRMapElement ptr : list) { 202 buf.append(ptr); 203 } 204 } 205 return buf.toString(); 206 } 207}