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