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.HashMap; 016import org.jikesrvm.VM; 017import org.jikesrvm.classloader.TypeReference; 018import org.jikesrvm.compilers.opt.ir.operand.Operand; 019import org.jikesrvm.compilers.opt.ir.operand.RegisterOperand; 020 021public abstract class AbstractRegisterPool { 022 023 /* inlined behavior of DoublyLinkedList */ 024 private Register start, end; 025 026 /** 027 * When 2 registers are necessary to encode a result, such as with a long on 028 * 32bit architectures, this hash map remembers the pairing of registers. It's 029 * key is the 1st register and the value is the 2nd register. 030 */ 031 private final HashMap<Register, Register> _regPairs = new HashMap<Register, Register>(); 032 033 /** 034 * All registers are assigned unique numbers; currentNum is the counter 035 * containing the next available register number. 036 */ 037 protected int currentNum; 038 039 /** 040 * @return the first symbolic register in this pool. 041 */ 042 public Register getFirstSymbolicRegister() { 043 return start; 044 } 045 046 private void registerListappend(Register reg) { 047 if (start == null) { 048 start = end = reg; 049 } else { 050 end.append(reg); 051 end = reg; 052 } 053 } 054 055 private void registerListremove(Register e) { 056 if (e == start) { 057 if (e == end) { 058 start = end = null; 059 } else { 060 Register next = e.next; 061 start = next; 062 next.prev = null; 063 } 064 } else if (e == end) { 065 Register prev = e.prev; 066 end = prev; 067 prev.next = null; 068 } else { 069 e.remove(); 070 } 071 } 072 /* end of inlined behavior */ 073 074 private Register makeNewReg() { 075 Register reg = new Register(currentNum); 076 currentNum++; 077 registerListappend(reg); 078 return reg; 079 } 080 081 /** 082 * Release a now unused register.<p> 083 * NOTE: It is the CALLERS responsibility to ensure that the register is no 084 * longer used!!!! 085 * @param r the register to release 086 */ 087 public void release(RegisterOperand r) { 088 Register reg = r.getRegister(); 089 if (reg.number == currentNum - 1) { 090 currentNum--; 091 registerListremove(end); 092 } 093 } 094 095 public void removeRegister(Register reg) { 096 registerListremove(reg); 097 } 098 099 /** 100 * Gets a new address register. 101 * 102 * @return the newly created register object 103 */ 104 public Register getAddress() { 105 Register reg = makeNewReg(); 106 reg.setAddress(); 107 return reg; 108 } 109 110 /** 111 * Gets a new integer register. 112 * 113 * @return the newly created register object 114 */ 115 public Register getInteger() { 116 Register reg = makeNewReg(); 117 reg.setInteger(); 118 return reg; 119 } 120 121 /** 122 * Gets a new float register. 123 * 124 * @return the newly created register object 125 */ 126 public Register getFloat() { 127 Register reg = makeNewReg(); 128 reg.setFloat(); 129 return reg; 130 } 131 132 /** 133 * Gets a new double register. 134 * 135 * @return the newly created register object 136 */ 137 public Register getDouble() { 138 Register reg; 139 reg = makeNewReg(); 140 reg.setDouble(); 141 return reg; 142 } 143 144 /** 145 * Gets a new condition register. 146 * 147 * @return the newly created register object 148 */ 149 public Register getCondition() { 150 Register reg = makeNewReg(); 151 reg.setCondition(); 152 return reg; 153 } 154 155 /** 156 * Gets a new long register. 157 * 158 * @return the newly created register object 159 */ 160 public Register getLong() { 161 Register reg; 162 reg = makeNewReg(); 163 reg.setLong(); 164 return reg; 165 } 166 167 /** 168 * Gets a new validation register. 169 * 170 * @return the newly created register object 171 */ 172 public Register getValidation() { 173 Register reg = makeNewReg(); 174 reg.setValidation(); 175 return reg; 176 } 177 178 /** 179 * Get a new register of the same type as the argument register 180 * 181 * @param template the register to get the type from 182 * @return the newly created register object 183 */ 184 public Register getReg(Register template) { 185 switch (template.getType()) { 186 case Register.ADDRESS_TYPE: 187 return getAddress(); 188 case Register.INTEGER_TYPE: 189 return getInteger(); 190 case Register.FLOAT_TYPE: 191 return getFloat(); 192 case Register.DOUBLE_TYPE: 193 return getDouble(); 194 case Register.CONDITION_TYPE: 195 return getCondition(); 196 case Register.LONG_TYPE: 197 return getLong(); 198 case Register.VALIDATION_TYPE: 199 return getValidation(); 200 } 201 if (VM.VerifyAssertions) VM._assert(VM.NOT_REACHED); 202 return null; 203 } 204 205 /** 206 * Get a new register of the same type as the argument RegisterOperand 207 * 208 * @param template the register operand to get the type from 209 * @return the newly created register object 210 */ 211 public Register getReg(RegisterOperand template) { 212 return getReg(template.getRegister()); 213 } 214 215 /** 216 * Get a new register of the appropriate type to hold values of 'type' 217 * 218 * @param type the type of values that the register will hold 219 * @return the newly created register object 220 */ 221 public Register getReg(TypeReference type) { 222 if (type.isLongType()) { 223 return getLong(); 224 } else if (type.isDoubleType()) { 225 return getDouble(); 226 } else if (type.isFloatType()) { 227 return getFloat(); 228 } else if (type == TypeReference.VALIDATION_TYPE) { 229 return getValidation(); 230 } else if (type.isWordLikeType() || type.isReferenceType()) { 231 return getAddress(); 232 } else { 233 return getInteger(); 234 } 235 } 236 237 /** 238 * MIR: Get the other half of the register pair that is 239 * associated with the argument register. 240 * <p> 241 * Note: this isn't incredibly general, but all architectures we're currently 242 * targeting need at most 2 machine registers to hold Java data values, so 243 * for now don't bother implementing a general mechanism. 244 * 245 * @param reg a register that may already be part of a register pair 246 * @return the register that is the other half of the register pair, 247 * if the pairing doesn't already exist then it is created. 248 */ 249 public Register getSecondReg(Register reg) { 250 Register otherHalf = _regPairs.get(reg); 251 if (otherHalf == null) { 252 otherHalf = getReg(reg); 253 _regPairs.put(reg, otherHalf); 254 if (reg.isLocal()) otherHalf.setLocal(); 255 if (reg.isSSA()) otherHalf.setSSA(); 256 } 257 return otherHalf; 258 } 259 260 /** 261 * Make a temporary register operand to hold values of the specified type 262 * (a new register is allocated). 263 * 264 * @param type the type of values to be held in the temp register 265 * @return the new temp 266 */ 267 public RegisterOperand makeTemp(TypeReference type) { 268 return new RegisterOperand(getReg(type), type); 269 } 270 271 /** 272 * Make a temporary register operand that is similar to the argument. 273 * 274 * @param template the register operand to use as a template. 275 * @return the new temp 276 */ 277 public RegisterOperand makeTemp(RegisterOperand template) { 278 RegisterOperand temp = new RegisterOperand(getReg(template), template.getType()); 279 temp.addFlags(template.getFlags()); 280 return temp; 281 } 282 283 /** 284 * Make a temporary register operand that can hold the values 285 * implied by the passed operand. 286 * 287 * @param op the operand to use as a template. 288 * @return the new temp 289 */ 290 public RegisterOperand makeTemp(Operand op) { 291 RegisterOperand result; 292 if (op.isRegister()) { 293 result = makeTemp((RegisterOperand) op); 294 } else { 295 result = makeTemp(op.getType()); 296 } 297 return result; 298 } 299 300 /** 301 * Make a temporary to hold an address (allocating a new register). 302 * 303 * @return the newly created temporary 304 */ 305 public RegisterOperand makeTempAddress() { 306 return new RegisterOperand(getAddress(), TypeReference.Address); 307 } 308 309 /** 310 * Make a temporary to hold an address (allocating a new register). 311 * 312 * @return the newly created temporary 313 */ 314 public RegisterOperand makeTempOffset() { 315 return new RegisterOperand(getAddress(), TypeReference.Offset); 316 } 317 318 /** 319 * Make a temporary to hold an int (allocating a new register). 320 * 321 * @return the newly created temporary 322 */ 323 public RegisterOperand makeTempInt() { 324 return new RegisterOperand(getInteger(), TypeReference.Int); 325 } 326 327 /** 328 * Make a temporary to hold a boolean (allocating a new register). 329 * 330 * @return the newly created temporary 331 */ 332 public RegisterOperand makeTempBoolean() { 333 return new RegisterOperand(getInteger(), TypeReference.Boolean); 334 } 335 336 /** 337 * Make a temporary to hold a float (allocating a new register). 338 * 339 * @return the newly created temporary 340 */ 341 public RegisterOperand makeTempFloat() { 342 return new RegisterOperand(getFloat(), TypeReference.Float); 343 } 344 345 /** 346 * Make a temporary to hold a double (allocating a new register). 347 * 348 * @return the newly created temporary 349 */ 350 public RegisterOperand makeTempDouble() { 351 return new RegisterOperand(getDouble(), TypeReference.Double); 352 } 353 354 /** 355 * Make a temporary to hold a long (allocating a new register). 356 * 357 * @return the newly created temporary 358 */ 359 public RegisterOperand makeTempLong() { 360 return new RegisterOperand(getLong(), TypeReference.Long); 361 } 362 363 /** 364 * Make a temporary to hold a condition code (allocating a new register). 365 * 366 * @return the newly created temporary 367 */ 368 public RegisterOperand makeTempCondition() { 369 Register reg = getCondition(); 370 return new RegisterOperand(reg, TypeReference.Int); 371 } 372 373 /** 374 * Make a temporary to hold a guard (validation) (allocating a new register). 375 * 376 * @return the newly created temporary 377 */ 378 public RegisterOperand makeTempValidation() { 379 Register reg = getValidation(); 380 reg.setValidation(); 381 return new RegisterOperand(reg, TypeReference.VALIDATION_TYPE); 382 } 383 384}