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.HashMap; 016 import org.jikesrvm.VM; 017 import org.jikesrvm.classloader.TypeReference; 018 import org.jikesrvm.compilers.opt.ir.operand.Operand; 019 import org.jikesrvm.compilers.opt.ir.operand.RegisterOperand; 020 021 public 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 /** 096 * Remove register from register pool. 097 */ 098 public void removeRegister(Register reg) { 099 registerListremove(reg); 100 } 101 102 /** 103 * Gets a new address register. 104 * 105 * @return the newly created register object 106 */ 107 public Register getAddress() { 108 Register reg = makeNewReg(); 109 reg.setAddress(); 110 return reg; 111 } 112 113 /** 114 * Gets a new integer register. 115 * 116 * @return the newly created register object 117 */ 118 public Register getInteger() { 119 Register reg = makeNewReg(); 120 reg.setInteger(); 121 return reg; 122 } 123 124 /** 125 * Gets a new float register. 126 * 127 * @return the newly created register object 128 */ 129 public Register getFloat() { 130 Register reg = makeNewReg(); 131 reg.setFloat(); 132 return reg; 133 } 134 135 /** 136 * Gets a new double register. 137 * 138 * @return the newly created register object 139 */ 140 public Register getDouble() { 141 Register reg; 142 reg = makeNewReg(); 143 reg.setDouble(); 144 return reg; 145 } 146 147 /** 148 * Gets a new condition register. 149 * 150 * @return the newly created register object 151 */ 152 public Register getCondition() { 153 Register reg = makeNewReg(); 154 reg.setCondition(); 155 return reg; 156 } 157 158 /** 159 * Gets a new long register. 160 * 161 * @return the newly created register object 162 */ 163 public Register getLong() { 164 Register reg; 165 reg = makeNewReg(); 166 reg.setLong(); 167 return reg; 168 } 169 170 /** 171 * Gets a new validation register. 172 * 173 * @return the newly created register object 174 */ 175 public Register getValidation() { 176 Register reg = makeNewReg(); 177 reg.setValidation(); 178 return reg; 179 } 180 181 /** 182 * Get a new register of the same type as the argument register 183 * 184 * @param template the register to get the type from 185 * @return the newly created register object 186 */ 187 public Register getReg(Register template) { 188 switch (template.getType()) { 189 case Register.ADDRESS_TYPE: 190 return getAddress(); 191 case Register.INTEGER_TYPE: 192 return getInteger(); 193 case Register.FLOAT_TYPE: 194 return getFloat(); 195 case Register.DOUBLE_TYPE: 196 return getDouble(); 197 case Register.CONDITION_TYPE: 198 return getCondition(); 199 case Register.LONG_TYPE: 200 return getLong(); 201 case Register.VALIDATION_TYPE: 202 return getValidation(); 203 } 204 if (VM.VerifyAssertions) VM._assert(VM.NOT_REACHED); 205 return null; 206 } 207 208 /** 209 * Get a new register of the same type as the argument RegisterOperand 210 * 211 * @param template the register operand to get the type from 212 * @return the newly created register object 213 */ 214 public Register getReg(RegisterOperand template) { 215 return getReg(template.getRegister()); 216 } 217 218 /** 219 * Get a new register of the appropriate type to hold values of 'type' 220 * 221 * @param type the type of values that the register will hold 222 * @return the newly created register object 223 */ 224 public Register getReg(TypeReference type) { 225 if (type.isLongType()) { 226 return getLong(); 227 } else if (type.isDoubleType()) { 228 return getDouble(); 229 } else if (type.isFloatType()) { 230 return getFloat(); 231 } else if (type == TypeReference.VALIDATION_TYPE) { 232 return getValidation(); 233 } else if (type.isWordLikeType() || type.isReferenceType()) { 234 return getAddress(); 235 } else { 236 return getInteger(); 237 } 238 } 239 240 /** 241 * MIR: Get the other half of the register pair that is 242 * associated with the argument register. 243 * <p> 244 * Note: this isn't incredibly general, but all architectures we're currently 245 * targeting need at most 2 machine registers to hold Java data values, so 246 * for now don't bother implementing a general mechanism. 247 * 248 * @param reg a register that may already be part of a register pair 249 * @return the register that is the other half of the register pair, 250 * if the pairing doesn't already exist then it is created. 251 */ 252 public Register getSecondReg(Register reg) { 253 Register otherHalf = _regPairs.get(reg); 254 if (otherHalf == null) { 255 otherHalf = getReg(reg); 256 _regPairs.put(reg, otherHalf); 257 if (reg.isLocal()) otherHalf.setLocal(); 258 if (reg.isSSA()) otherHalf.setSSA(); 259 } 260 return otherHalf; 261 } 262 263 /** 264 * Make a temporary register operand to hold values of the specified type 265 * (a new register is allocated). 266 * 267 * @param type the type of values to be held in the temp register 268 * @return the new temp 269 */ 270 public RegisterOperand makeTemp(TypeReference type) { 271 return new RegisterOperand(getReg(type), type); 272 } 273 274 /** 275 * Make a temporary register operand that is similar to the argument. 276 * 277 * @param template the register operand to use as a template. 278 * @return the new temp 279 */ 280 public RegisterOperand makeTemp(RegisterOperand template) { 281 RegisterOperand temp = new RegisterOperand(getReg(template), template.getType()); 282 temp.addFlags(template.getFlags()); 283 return temp; 284 } 285 286 /** 287 * Make a temporary register operand that can hold the values 288 * implied by the passed operand. 289 * 290 * @param op the operand to use as a template. 291 * @return the new temp 292 */ 293 public RegisterOperand makeTemp(Operand op) { 294 RegisterOperand result; 295 if (op.isRegister()) { 296 result = makeTemp((RegisterOperand) op); 297 } else { 298 result = makeTemp(op.getType()); 299 } 300 return result; 301 } 302 303 /** 304 * Make a temporary to hold an address (allocating a new register). 305 * 306 * @return the newly created temporary 307 */ 308 public RegisterOperand makeTempAddress() { 309 return new RegisterOperand(getAddress(), TypeReference.Address); 310 } 311 312 /** 313 * Make a temporary to hold an address (allocating a new register). 314 * 315 * @return the newly created temporary 316 */ 317 public RegisterOperand makeTempOffset() { 318 return new RegisterOperand(getAddress(), TypeReference.Offset); 319 } 320 321 /** 322 * Make a temporary to hold an int (allocating a new register). 323 * 324 * @return the newly created temporary 325 */ 326 public RegisterOperand makeTempInt() { 327 return new RegisterOperand(getInteger(), TypeReference.Int); 328 } 329 330 /** 331 * Make a temporary to hold a boolean (allocating a new register). 332 * 333 * @return the newly created temporary 334 */ 335 public RegisterOperand makeTempBoolean() { 336 return new RegisterOperand(getInteger(), TypeReference.Boolean); 337 } 338 339 /** 340 * Make a temporary to hold a float (allocating a new register). 341 * 342 * @return the newly created temporary 343 */ 344 public RegisterOperand makeTempFloat() { 345 return new RegisterOperand(getFloat(), TypeReference.Float); 346 } 347 348 /** 349 * Make a temporary to hold a double (allocating a new register). 350 * 351 * @return the newly created temporary 352 */ 353 public RegisterOperand makeTempDouble() { 354 return new RegisterOperand(getDouble(), TypeReference.Double); 355 } 356 357 /** 358 * Make a temporary to hold a long (allocating a new register). 359 * 360 * @return the newly created temporary 361 */ 362 public RegisterOperand makeTempLong() { 363 return new RegisterOperand(getLong(), TypeReference.Long); 364 } 365 366 /** 367 * Make a temporary to hold a condition code (allocating a new register). 368 * 369 * @return the newly created temporary 370 */ 371 public RegisterOperand makeTempCondition() { 372 Register reg = getCondition(); 373 return new RegisterOperand(reg, TypeReference.Int); 374 } 375 376 /** 377 * Make a temporary to hold a guard (validation) (allocating a new register). 378 * 379 * @return the newly created temporary 380 */ 381 public RegisterOperand makeTempValidation() { 382 Register reg = getValidation(); 383 reg.setValidation(); 384 return new RegisterOperand(reg, TypeReference.VALIDATION_TYPE); 385 } 386 387 }