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 */
013 package org.jikesrvm.compilers.opt.ir;
014
015 import java.util.Iterator;
016 import java.util.List;
017 import java.util.ListIterator;
018 import org.jikesrvm.compilers.opt.OptimizingCompilerException;
019 import org.jikesrvm.compilers.opt.ir.operand.RegisterOperand;
020 import org.jikesrvm.compilers.opt.liveness.LiveSet;
021 import org.jikesrvm.compilers.opt.liveness.LiveSetEnumerator;
022 import org.jikesrvm.util.LinkedListRVM;
023
024 /**
025 *
026 * This class holds GC maps for various program points.
027 * This data structure is IR-based. In a later phase, this information
028 * will be used to create the final GC map (see OptMachineCodeMap.java)
029 */
030 public final class GCIRMap implements Iterable<GCIRMapElement> {
031 /**
032 * This is the list of maps
033 * Each element on the list is an GCIRMapElement, which is a pair
034 * - an IR instruction (the GC point)
035 * - a list of RegSpillListElement, which initially hold symbolic
036 * registers that are references
037 * (these are expanded to either physical regs or spills
038 * by the register allocator)
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 exeception 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 exeception is thrown.
165 * @param inst the orignal 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 public Iterator<GCIRMapElement> iterator() {
181 return list.iterator();
182 }
183
184 /**
185 * dumps the map
186 */
187 public void dump() {
188 System.out.println(toString());
189 }
190
191 /**
192 * @return string version of this object
193 */
194 public String toString() {
195 StringBuilder buf = new StringBuilder("");
196 if (list.isEmpty()) {
197 buf.append("empty");
198 } else {
199 for (GCIRMapElement ptr : list) {
200 buf.append(ptr);
201 }
202 }
203 return buf.toString();
204 }
205 }