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.operand; 014 015 import org.jikesrvm.VM; 016 import org.jikesrvm.classloader.RVMClass; 017 import org.jikesrvm.classloader.TypeReference; 018 import org.jikesrvm.compilers.opt.ir.Register; 019 import org.jikesrvm.compilers.opt.OptimizingCompilerException; 020 021 /** 022 * A symbolic or physical register. 023 * A wrapper around an Register that may contain program-point specific 024 * information about the value denoted by the Register. 025 * <p> 026 * TODO: This class is due for a refactor into subclasses 027 * to split out the symbolic & physical registers and to create 028 * special behavior for symbolic registers used as phi operands and 029 * as validation (guard) operands. 030 * 031 * @see Operand 032 */ 033 public final class RegisterOperand extends Operand { 034 035 /** 036 * Register object that this operand uses. 037 * TODO: make this field private, it is accessed via generated code 038 */ 039 public Register register; 040 041 /** 042 * Inferred data type of the contents of the register. 043 * TODO: make this field private, it is accessed via generated code 044 */ 045 public TypeReference type; 046 047 /** 048 * Optimizations can use it for different purposes, as long as they 049 * are not used simultaneously 050 */ 051 public Object scratchObject; 052 053 /** 054 * 16bit scratch word that can be used for different optimizations. 055 */ 056 private short info; 057 058 /** 059 * Type of a RegisterOperand can be in one of three states: 060 * 061 * <ol> 062 * <li>a- declared: the type obtained from a 063 * getfield,getstatic,putfield,putstatic,array load</li> 064 * <li>b- precise: obtained from a NEW.</li> 065 * <li>c- computed: (default) computed from propagating types.</li> 066 * </ol> 067 * 068 * If the register is holding an int-like type it can be holding 069 * just positive values. 070 * 071 * For calling conventions registers can be for parameters or 072 * volatile/non-volatile. The value in the register can also be 073 * extant - that is a definite non-null value (e.g. this pointer). 074 */ 075 private byte flags; 076 077 /** 078 * The type has been declared as obtained from a getfield, 079 * getstatic, putfield, putstatic, array load 080 */ 081 private static final int DECLARED_TYPE = 0x01; 082 /** We know precisely the type as it was create by a NEW */ 083 private static final int PRECISE_TYPE = 0x02; 084 /** Is the contents of the int-like register always positive? */ 085 private static final int POSITIVE = 0x04; 086 087 /** the register operand is for a parameter */ 088 private static final byte PARAMETER = 0x10; 089 /** is this a non-volatile physical register? */ 090 private static final byte NON_VOLATILE = 0x20; 091 /** is this an extant object? */ 092 private static final byte EXTANT = 0x40; 093 094 /** 095 * Some bits used to characterize guards. TODO: Maybe declare a 096 * new type GuardOperand extends RegisterOperand, and save 097 * this state there? 098 */ 099 private byte flags2; 100 101 /** guard operand that represents a taken branch */ 102 private static final byte TAKEN = 0x01; 103 /** guard operand that represents a not taken branch */ 104 private static final byte NOT_TAKEN = 0x02; 105 /** Guard operand that originates from a bounds-check */ 106 private static final byte BOUNDS_CHECK = 0x04; 107 /** Guard operand that originates from a null-check */ 108 private static final byte NULL_CHECK = 0x08; 109 110 /** 111 * Constructs a new register operand with the given register and data type. 112 * 113 * @param reg register object 114 * @param typ data type 115 */ 116 public RegisterOperand(Register reg, TypeReference typ) { 117 setRegister(reg); 118 setType(typ); 119 } 120 121 /** 122 * Constructs a new register operand with the given register, data type and flags. 123 * 124 * @param reg register object 125 * @param typ data type 126 * @param inFlags to set for this register 127 * @param isPrecise is this a precise type 128 * @param isDeclared is this a declared type 129 */ 130 public RegisterOperand(Register reg, TypeReference typ, byte inFlags, 131 boolean isPrecise, boolean isDeclared) { 132 setRegister(reg); 133 flags = inFlags; 134 if (isPrecise) { 135 setPreciseType(typ); 136 } else { 137 clearPreciseType(); 138 setType(typ); 139 } 140 if (isDeclared) { 141 setDeclaredType(); 142 } else { 143 clearDeclaredType(); 144 } 145 } 146 147 /** 148 * Returns a copy of this register operand as an operand 149 */ 150 @Override 151 public Operand copy() { 152 return copyRO(); 153 } 154 155 /** 156 * Returns a copy of this register operand as a register operand.<p> 157 * 158 * NOTE: preserves the flags, info and scratchObject. Preserving is 159 * required in all cases as several phases also depend on scratch 160 * and/or scratchObject being copied 161 */ 162 public RegisterOperand copyRO() { 163 RegisterOperand temp = new RegisterOperand(getRegister(), type); 164 temp.info = info; 165 temp.flags = flags; 166 temp.flags2 = flags2; 167 temp.scratchObject = scratchObject; 168 if (VM.VerifyAssertions) verifyPreciseType(); 169 return temp; 170 } 171 172 /** 173 * Returns a copy of this use register operand as another use reg operand. 174 */ 175 public RegisterOperand copyU2U() { 176 return copyRO(); 177 } 178 179 /** 180 * Returns a copy of this def register operand as a use. 181 */ 182 public RegisterOperand copyD2U() { 183 return copyRO(); 184 } 185 186 /** 187 * Returns a copy of this use register operand as a def. 188 */ 189 public RegisterOperand copyU2D() { 190 return copyRO(); 191 } 192 193 /** 194 * Returns a copy of this def register operand as a def. 195 */ 196 public RegisterOperand copyD2D() { 197 return copyRO(); 198 } 199 200 /** 201 * Returns whether the given operand is a register operand and has the same 202 * register object. 203 * 204 * @param op operand to compare against 205 */ 206 @Override 207 public boolean similar(Operand op) { 208 return (op instanceof RegisterOperand) && (getRegister() == ((RegisterOperand) op).getRegister()); 209 } 210 211 /** 212 * Copy type information from the given operand into this one 213 * including flag information on whether this is a precise type or 214 * not 215 * @param rhs the type to copy information from 216 */ 217 public void copyType(RegisterOperand rhs) { 218 this.flags = rhs.flags; 219 this.setType(rhs.type); // setting type this way will force checking of precision 220 } 221 222 @Override 223 public boolean isIntLike() { 224 return type.isIntLikeType(); 225 } 226 227 @Override 228 public boolean isInt() { 229 return type.isIntType(); 230 } 231 232 @Override 233 public boolean isLong() { 234 return type.isLongType(); 235 } 236 237 @Override 238 public boolean isFloat() { 239 return type.isFloatType(); 240 } 241 242 @Override 243 public boolean isDouble() { 244 return type.isDoubleType(); 245 } 246 247 @Override 248 public boolean isRef() { 249 return type.isReferenceType(); 250 } 251 252 @Override 253 public boolean isAddress() { 254 return type.isWordLikeType(); 255 } 256 257 @Override 258 public boolean isDefinitelyNull() { 259 return type == TypeReference.NULL_TYPE; 260 } 261 262 /** Does this register hold a parameter */ 263 public boolean isParameter() { return (flags & PARAMETER) != 0; } 264 265 /** Set this register as being used to hold parameters */ 266 public void setParameter() { flags |= PARAMETER; } 267 268 /** Clear this register from being used to hold parameters */ 269 public void clearParameter() { flags &= ~PARAMETER; } 270 271 /** Is this a volatile register? */ 272 public boolean isNonVolatile() { return (flags & NON_VOLATILE) != 0; } 273 274 /** Set this register as being non-volatile */ 275 public void setNonVolatile() { flags |= NON_VOLATILE; } 276 277 /** Set this register as being volatile */ 278 public void clearNonVolatile() { flags &= ~NON_VOLATILE; } 279 280 /** 281 * Is this register known to contain either NULL or an object whose class was fully loaded 282 * before the current method was called? 283 * This fact is used to determine whether we can optimize away inline guards 284 * based on pre-existence based inlining.*/ 285 public boolean isExtant() { return (flags & EXTANT) != 0; } 286 287 /** 288 * Set this register as holding an extant object (or NULL) 289 * (ie, an object whose class was fully loaded before the current method was called). 290 * This fact is used to determine whether we can optimize away inline guards based on pre-existence 291 * based inlining. 292 */ 293 public void setExtant() { flags |= EXTANT; } 294 295 /** Clear this register from holding an extant value */ 296 public void clearExtant() { flags &= ~EXTANT; } 297 298 /** Does this register have a declared type? */ 299 public boolean isDeclaredType() { return (flags & DECLARED_TYPE) != 0; } 300 301 /** Set this register as having a declared type */ 302 public void setDeclaredType() { flags |= DECLARED_TYPE; } 303 304 /** Clear this register from having a declared type */ 305 public void clearDeclaredType() { flags &= ~DECLARED_TYPE; } 306 307 private void verifyPreciseType() { 308 if (!VM.VerifyAssertions) { 309 VM.sysFail("Calls to verifyPreciseType must always be guarded by if \"(VM.VerifyAssertions)\"!"); 310 } else { 311 if (isPreciseType() && type != null && 312 type.isClassType() && type.isResolved()) { 313 RVMClass preciseClass = type.resolve().asClass(); 314 if(preciseClass.isInterface() || preciseClass.isAbstract()) { 315 VM.sysWriteln("Error processing instruction: ", this.instruction.toString()); 316 throw new OptimizingCompilerException("Unable to set type as it would make this interface/abstract class precise " + preciseClass); 317 } 318 } 319 } 320 } 321 /** Do we know the precise type of this register? */ 322 public boolean isPreciseType() { return (flags & PRECISE_TYPE) != 0; } 323 324 /** Set this register as having a precise type */ 325 public void setPreciseType() { 326 flags |= PRECISE_TYPE; 327 if (VM.VerifyAssertions) verifyPreciseType(); 328 } 329 330 /** Clear this register from having a precise type */ 331 public void clearPreciseType() { flags &= ~PRECISE_TYPE; } 332 333 /** Is this register a declared or a precise type? */ 334 public boolean isDeclaredOrPreciseType() { return (flags & (DECLARED_TYPE | PRECISE_TYPE)) != 0; } 335 336 /** Is this register a positive int? */ 337 public boolean isPositiveInt() { return (flags & POSITIVE) != 0; } 338 339 /** Set this register as being a positive int */ 340 public void setPositiveInt() { flags |= POSITIVE; } 341 342 /** Return a byte encoding register flags */ 343 public byte getFlags() { 344 return flags; 345 } 346 347 /** Clear the flags of a register */ 348 public void clearFlags() { 349 flags = 0; 350 } 351 352 /** Merge two sets of register flags */ 353 public void addFlags(byte inFlag) { 354 flags |= inFlag; 355 if (VM.VerifyAssertions) verifyPreciseType(); 356 } 357 358 /** Currently all flags are inheritable, so copy all flags from src */ 359 public void setInheritableFlags(RegisterOperand src) { 360 flags = src.getFlags(); 361 if (VM.VerifyAssertions) verifyPreciseType(); 362 } 363 364 /** Currently all flags are "meetable", so mask flags together */ 365 public void meetInheritableFlags(RegisterOperand other) { 366 flags &= other.flags; 367 } 368 369 /** 370 * Return true if we have any bits set (flag true) that other 371 * doesn't. It's ok for other to have bits set true that we have set 372 * to false. 373 */ 374 public boolean hasLessConservativeFlags(RegisterOperand other) { 375 return other.getFlags() != (getFlags() | other.getFlags()); 376 } 377 378 /** Is this a guard operand from a taken branch? */ 379 public boolean isTaken() { return (flags2 & TAKEN) != 0; } 380 381 /** Set this a guard operand from a taken branch */ 382 public void setTaken() { flags2 |= TAKEN; } 383 384 /** Clear this from being a guard operand from a taken branch */ 385 public void clearTaken() { flags2 &= ~TAKEN; } 386 387 /** Is this a guard operand from a not taken branch? */ 388 public boolean isNotTaken() { return (flags2 & NOT_TAKEN) != 0; } 389 390 /** Set this a guard operand from a not taken branch */ 391 public void setNotTaken() { flags2 |= NOT_TAKEN; } 392 393 /** Clear this from being a guard operand from a not taken branch */ 394 public void clearNotTaken() { flags2 &= ~NOT_TAKEN; } 395 396 /** Is this a guard operand from a bounds check? */ 397 public boolean isBoundsCheck() { return (flags2 & BOUNDS_CHECK) != 0; } 398 399 /** Set this as a guard operand from a bounds check */ 400 public void setBoundsCheck() { flags2 |= BOUNDS_CHECK; } 401 402 /** Clear this from being a guard operand from a bounds check */ 403 public void clearBoundsCheck() { flags2 &= ~BOUNDS_CHECK; } 404 405 /** Is this a guard operand from a null check? */ 406 public boolean isNullCheck() { return (flags2 & NULL_CHECK) != 0; } 407 408 /** Set this as being a guard operand from a null check */ 409 public void setNullCheck() { flags2 |= NULL_CHECK; } 410 411 /** Clear this from being a guard operand from a null check */ 412 public void clearNullCheck() { flags2 &= ~NULL_CHECK; } 413 414 /** Get info scratch short */ 415 public short getInfo() { 416 return info; 417 } 418 419 /** Set info scratch short */ 420 public void setInfo(short value) { 421 info = value; 422 } 423 424 /** 425 * Sets scratch object of the register operand to parameter. (sic) 426 * Since there is not multiple inheritance in Java, I am copying the 427 * accessor functions & fields of LinkedListElement. This field 428 * is used to maintain lists of USEs and DEFs 429 */ 430 public void setNext(RegisterOperand Next) { 431 scratchObject = Next; 432 } 433 434 /** 435 * Sets scratch object of the register operand to parameter. 436 */ 437 public void append(RegisterOperand next) { 438 scratchObject = next; 439 } 440 441 /** 442 * Returns the scratch object of the register operand 443 */ 444 public RegisterOperand getNext() { 445 return (RegisterOperand) scratchObject; 446 } 447 448 /** 449 * Returns the string representation of this operand. 450 */ 451 @Override 452 public String toString() { 453 String s = getRegister().toString(); 454 if (type != null) { 455 if (type != TypeReference.VALIDATION_TYPE) { 456 s = s + "(" + type.getName(); 457 if (isExtant()) s += ",x"; 458 if (isDeclaredType()) s += ",d"; 459 if (isPreciseType()) s += ",p"; 460 if (isPositiveInt()) s += ",+"; 461 s += ")"; 462 } else { 463 s += "(GUARD)"; 464 } 465 } 466 return s; 467 } 468 469 /** 470 * Modify the register 471 */ 472 public void setRegister(Register register) { 473 this.register = register; 474 } 475 476 /** 477 * @return the register 478 */ 479 public Register getRegister() { 480 return register; 481 } 482 483 /** 484 * Set the {@link TypeReference} of the value represented by the operand. 485 * 486 * @param t the inferred data type of the contents of the register 487 */ 488 public void setType(TypeReference t) { 489 type = t; 490 if (VM.VerifyAssertions) verifyPreciseType(); 491 } 492 493 /** 494 * Set the {@link TypeReference} of the value represented by the operand and 495 * make the type precise. 496 * 497 * @param t the inferred data type of the contents of the register 498 */ 499 public void setPreciseType(TypeReference t) { 500 type = t; 501 flags |= PRECISE_TYPE; 502 if (VM.VerifyAssertions) verifyPreciseType(); 503 } 504 505 /** 506 * Return the {@link TypeReference} of the value represented by the operand. 507 * 508 * @return the inferred data type of the contents of the register 509 */ 510 @Override 511 public TypeReference getType() { 512 return type; 513 } 514 515 /** 516 * Refine the type of the register to t if t is a more precise type than the 517 * register currently holds 518 * 519 * @param t type to try to refine to 520 */ 521 public void refine(TypeReference t) { 522 // TODO: see JIRA RVM-137 523 if (!isPreciseType()) { 524 setType(t); 525 } 526 } 527 }