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 *
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
157 * NOTE: preserves the flags, info and scratchObject. Preserving is
158 * required in all cases as several phases also depend on scratch
159 * and/or scratchObject being copied
160 */
161 public RegisterOperand copyRO() {
162 RegisterOperand temp = new RegisterOperand(getRegister(), type);
163 temp.info = info;
164 temp.flags = flags;
165 temp.flags2 = flags2;
166 temp.scratchObject = scratchObject;
167 if (VM.VerifyAssertions) verifyPreciseType();
168 return temp;
169 }
170
171 /**
172 * Returns a copy of this use register operand as another use reg operand.
173 */
174 public RegisterOperand copyU2U() {
175 return copyRO();
176 }
177
178 /**
179 * Returns a copy of this def register operand as a use.
180 */
181 public RegisterOperand copyD2U() {
182 return copyRO();
183 }
184
185 /**
186 * Returns a copy of this use register operand as a def.
187 */
188 public RegisterOperand copyU2D() {
189 return copyRO();
190 }
191
192 /**
193 * Returns a copy of this def register operand as a def.
194 */
195 public RegisterOperand copyD2D() {
196 return copyRO();
197 }
198
199 /**
200 * Returns whether the given operand is a register operand and has the same
201 * register object.
202 *
203 * @param op operand to compare against
204 */
205 @Override
206 public boolean similar(Operand op) {
207 return (op instanceof RegisterOperand) && (getRegister() == ((RegisterOperand) op).getRegister());
208 }
209
210 /**
211 * Copy type information from the given operand into this one
212 * including flag information on whether this is a precise type or
213 * not
214 * @param rhs the type to copy information from
215 */
216 public void copyType(RegisterOperand rhs) {
217 this.flags = rhs.flags;
218 this.setType(rhs.type); // setting type this way will force checking of precision
219 }
220
221 /**
222 * Does the operand represent a value of an int-like data type?
223 *
224 * @return <code>true</code> if the data type of <code>this</code>
225 * is int-like as defined by {@link TypeReference#isIntLikeType}
226 * or <code>false</code> if it is not.
227 */
228 @Override
229 public boolean isIntLike() {
230 return type.isIntLikeType();
231 }
232
233 /**
234 * Does the operand represent a value of an int data type?
235 *
236 * @return <code>true</code> if the data type of <code>this</code>
237 * is int-like as defined by {@link TypeReference#isIntLikeType}
238 * or <code>false</code> if it is not.
239 */
240 @Override
241 public boolean isInt() {
242 return type.isIntType();
243 }
244
245 /**
246 * Does the operand represent a value of the long data type?
247 *
248 * @return <code>true</code> if the data type of <code>this</code>
249 * is a long as defined by {@link TypeReference#isLongType}
250 * or <code>false</code> if it is not.
251 */
252 @Override
253 public boolean isLong() {
254 return type.isLongType();
255 }
256
257 /**
258 * Does the operand represent a value of the float data type?
259 *
260 * @return <code>true</code> if the data type of <code>this</code>
261 * is a float as defined by {@link TypeReference#isFloatType}
262 * or <code>false</code> if it is not.
263 */
264 @Override
265 public boolean isFloat() {
266 return type.isFloatType();
267 }
268
269 /**
270 * Does the operand represent a value of the double data type?
271 *
272 * @return <code>true</code> if the data type of <code>this</code>
273 * is a double as defined by {@link TypeReference#isDoubleType}
274 * or <code>false</code> if it is not.
275 */
276 @Override
277 public boolean isDouble() {
278 return type.isDoubleType();
279 }
280
281 /**
282 * Does the operand represent a value of the reference data type?
283 *
284 * @return <code>true</code> if the data type of <code>this</code>
285 * is a reference as defined by {@link TypeReference#isReferenceType}
286 * or <code>false</code> if it is not.
287 */
288 @Override
289 public boolean isRef() {
290 return type.isReferenceType();
291 }
292
293 /**
294 * Does the operand represent an address like data type?
295 *
296 * @return <code>true</code> if the data type of <code>this</code>
297 * is an address as defined by {@link TypeReference#isWordLikeType}
298 * or <code>false</code> if it is not.
299 */
300 @Override
301 public boolean isAddress() {
302 return type.isWordLikeType();
303 }
304
305 /**
306 * Does the operand definitely represent <code>null</code>?
307 *
308 * @return <code>true</code> if the operand definitely represents
309 * <code>null</code> or <code>false</code> if it does not.
310 */
311 @Override
312 public boolean isDefinitelyNull() {
313 return type == TypeReference.NULL_TYPE;
314 }
315
316 /** Does this register hold a parameter */
317 public boolean isParameter() { return (flags & PARAMETER) != 0; }
318
319 /** Set this register as being used to hold parameters */
320 public void setParameter() { flags |= PARAMETER; }
321
322 /** Clear this register from being used to hold parameters */
323 public void clearParameter() { flags &= ~PARAMETER; }
324
325 /** Is this a volatile register? */
326 public boolean isNonVolatile() { return (flags & NON_VOLATILE) != 0; }
327
328 /** Set this register as being non-volatile */
329 public void setNonVolatile() { flags |= NON_VOLATILE; }
330
331 /** Set this register as being volatile */
332 public void clearNonVolatile() { flags &= ~NON_VOLATILE; }
333
334 /**
335 * Is this register known to contain either NULL or an object whose class was fully loaded
336 * before the current method was called?
337 * This fact is used to determine whether we can optimize away inline guards
338 * based on pre-existence based inlining.*/
339 public boolean isExtant() { return (flags & EXTANT) != 0; }
340
341 /**
342 * Set this register as holding an extant object (or NULL)
343 * (ie, an object whose class was fully loaded before the current method was called).
344 * This fact is used to determine whether we can optimize away inline guards based on pre-existence
345 * based inlining.
346 */
347 public void setExtant() { flags |= EXTANT; }
348
349 /** Clear this register from holding an extant value */
350 public void clearExtant() { flags &= ~EXTANT; }
351
352 /** Does this register have a declared type? */
353 public boolean isDeclaredType() { return (flags & DECLARED_TYPE) != 0; }
354
355 /** Set this register as having a declared type */
356 public void setDeclaredType() { flags |= DECLARED_TYPE; }
357
358 /** Clear this register from having a declared type */
359 public void clearDeclaredType() { flags &= ~DECLARED_TYPE; }
360
361 private void verifyPreciseType() {
362 if (!VM.VerifyAssertions) {
363 VM._assert(false); // this call should always be guarded
364 } else {
365 if (isPreciseType() && type != null &&
366 type.isClassType() && type.isResolved()) {
367 RVMClass preciseClass = type.resolve().asClass();
368 if(preciseClass.isInterface() || preciseClass.isAbstract()) {
369 VM.sysWriteln("Error processing instruction: ", this.instruction.toString());
370 throw new OptimizingCompilerException("Unable to set type as it would make this interface/abstract class precise " + preciseClass);
371 }
372 }
373 }
374 }
375 /** Do we know the precise type of this register? */
376 public boolean isPreciseType() { return (flags & PRECISE_TYPE) != 0; }
377
378 /** Set this register as having a precise type */
379 public void setPreciseType() {
380 flags |= PRECISE_TYPE;
381 if (VM.VerifyAssertions) verifyPreciseType();
382 }
383
384 /** Clear this register from having a precise type */
385 public void clearPreciseType() { flags &= ~PRECISE_TYPE; }
386
387 /** Is this register a declared or a precise type? */
388 public boolean isDeclaredOrPreciseType() { return (flags & (DECLARED_TYPE | PRECISE_TYPE)) != 0; }
389
390 /** Is this register a positive int? */
391 public boolean isPositiveInt() { return (flags & POSITIVE) != 0; }
392
393 /** Set this register as being a positive int */
394 public void setPositiveInt() { flags |= POSITIVE; }
395
396 /** Return a byte encoding register flags */
397 public byte getFlags() {
398 return flags;
399 }
400
401 /** Clear the flags of a register */
402 public void clearFlags() {
403 flags = 0;
404 }
405
406 /** Merge two sets of register flags */
407 public void addFlags(byte inFlag) {
408 flags |= inFlag;
409 if (VM.VerifyAssertions) verifyPreciseType();
410 }
411
412 /** Currently all flags are inheritable, so copy all flags from src */
413 public void setInheritableFlags(RegisterOperand src) {
414 flags = src.getFlags();
415 if (VM.VerifyAssertions) verifyPreciseType();
416 }
417
418 /** Currently all flags are "meetable", so mask flags together */
419 public void meetInheritableFlags(RegisterOperand other) {
420 flags &= other.flags;
421 }
422
423 /**
424 * Return true if we have any bits set (flag true) that other
425 * doesn't. It's ok for other to have bits set true that we have set
426 * to false.
427 */
428 public boolean hasLessConservativeFlags(RegisterOperand other) {
429 return other.getFlags() != (getFlags() | other.getFlags());
430 }
431
432 /** Is this a guard operand from a taken branch? */
433 public boolean isTaken() { return (flags2 & TAKEN) != 0; }
434
435 /** Set this a guard operand from a taken branch */
436 public void setTaken() { flags2 |= TAKEN; }
437
438 /** Clear this from being a guard operand from a taken branch */
439 public void clearTaken() { flags2 &= ~TAKEN; }
440
441 /** Is this a guard operand from a not taken branch? */
442 public boolean isNotTaken() { return (flags2 & NOT_TAKEN) != 0; }
443
444 /** Set this a guard operand from a not taken branch */
445 public void setNotTaken() { flags2 |= NOT_TAKEN; }
446
447 /** Clear this from being a guard operand from a not taken branch */
448 public void clearNotTaken() { flags2 &= ~NOT_TAKEN; }
449
450 /** Is this a guard operand from a bounds check? */
451 public boolean isBoundsCheck() { return (flags2 & BOUNDS_CHECK) != 0; }
452
453 /** Set this as a guard operand from a bounds check */
454 public void setBoundsCheck() { flags2 |= BOUNDS_CHECK; }
455
456 /** Clear this from being a guard operand from a bounds check */
457 public void clearBoundsCheck() { flags2 &= ~BOUNDS_CHECK; }
458
459 /** Is this a guard operand from a null check? */
460 public boolean isNullCheck() { return (flags2 & NULL_CHECK) != 0; }
461
462 /** Set this as being a guard operand from a null check */
463 public void setNullCheck() { flags2 |= NULL_CHECK; }
464
465 /** Clear this from being a guard operand from a null check */
466 public void clearNullCheck() { flags2 &= ~NULL_CHECK; }
467
468 /** Get info scratch short */
469 public short getInfo() {
470 return info;
471 }
472
473 /** Set info scratch short */
474 public void setInfo(short value) {
475 info = value;
476 }
477
478 /**
479 * Sets scratch object of the register operand to parameter. (sic)
480 * Since there is not multiple inheritance in Java, I am copying the
481 * accessor functions & fields of LinkedListElement. This field
482 * is used to maintain lists of USEs and DEFs
483 */
484 public void setNext(RegisterOperand Next) {
485 scratchObject = Next;
486 }
487
488 /**
489 * Sets scratch object of the register operand to parameter.
490 */
491 public void append(RegisterOperand next) {
492 scratchObject = next;
493 }
494
495 /**
496 * Returns the scratch object of the register operand
497 */
498 public RegisterOperand getNext() {
499 return (RegisterOperand) scratchObject;
500 }
501
502 /**
503 * Returns the string representation of this operand.
504 */
505 @Override
506 public String toString() {
507 String s = getRegister().toString();
508 if (type != null) {
509 if (type != TypeReference.VALIDATION_TYPE) {
510 s = s + "(" + type.getName();
511 if (isExtant()) s += ",x";
512 if (isDeclaredType()) s += ",d";
513 if (isPreciseType()) s += ",p";
514 if (isPositiveInt()) s += ",+";
515 s += ")";
516 } else {
517 s += "(GUARD)";
518 }
519 }
520 return s;
521 }
522
523 /**
524 * Modify the register
525 */
526 public void setRegister(Register register) {
527 this.register = register;
528 }
529
530 /**
531 * @return the register
532 */
533 public Register getRegister() {
534 return register;
535 }
536
537 /**
538 * Set the {@link TypeReference} of the value represented by the operand.
539 *
540 * @param t the inferred data type of the contents of the register
541 */
542 public void setType(TypeReference t) {
543 type = t;
544 if (VM.VerifyAssertions) verifyPreciseType();
545 }
546
547 /**
548 * Set the {@link TypeReference} of the value represented by the operand and
549 * make the type precise.
550 *
551 * @param t the inferred data type of the contents of the register
552 */
553 public void setPreciseType(TypeReference t) {
554 type = t;
555 flags |= PRECISE_TYPE;
556 if (VM.VerifyAssertions) verifyPreciseType();
557 }
558
559 /**
560 * Return the {@link TypeReference} of the value represented by the operand.
561 *
562 * @return the inferred data type of the contents of the register
563 */
564 @Override
565 public TypeReference getType() {
566 return type;
567 }
568
569 /**
570 * Refine the type of the register to t if t is a more precise type than the
571 * register currently holds
572 *
573 * @param t type to try to refine to
574 */
575 public void refine(TypeReference t) {
576 // TODO: see JIRA RVM-137
577 if (!isPreciseType()) {
578 setType(t);
579 }
580 }
581 }