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 &amp; 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    }