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