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 }