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.osr;
014    
015    import org.jikesrvm.VM;
016    import org.jikesrvm.runtime.Magic;
017    import org.vmmagic.unboxed.Word;
018    
019    /**
020     * An instance of VariableElement represents a byte code variable
021     * (local or stack element).  It is used to generate prologue to
022     * recover the runtime state.  It refers to VM architecture.
023     */
024    
025    public class VariableElement implements OSRConstants {
026    
027      //////////////////////////////////
028      // instance fields
029      //////////////////////////////////
030    
031      /** the kind of this element : LOCAL or STACK */
032      private final boolean kind;
033    
034      /**
035       * the number of element, e.g., with kind we
036       * can know it is L0 or S1.
037       */
038      private final char num;
039    
040      /** type code, can only be INT, FLOAT, LONG, DOUBLE, RET_ADDR, WORD or REF */
041      private final byte tcode;
042    
043      /**
044       * The value of this element.
045       * For type INT, FLOAT, RET_ADDR and WORD (32-bit), the lower 32 bits are valid.
046       * For type LONG and DOUBLE and WORD(64-bit), 64 bits are valid.
047       * For REF type, next field 'ref' is valid.
048       *
049       * For FLOAT, and DOUBLE, use Magic.intBitsAsFloat
050       *                         or Magic.longBitsAsDouble
051       * to convert bits to floating-point value.
052       */
053      private final long value;
054    
055      /** for reference type value */
056      private final Object ref;
057    
058      //////////////////////////////////
059      // class auxiliary methods
060      /////////////////////////////////
061      static boolean isIBitsType(int tcode) {
062        switch (tcode) {
063          case INT:
064          case FLOAT:
065          case RET_ADDR:
066            return true;
067          case WORD:
068            return VM.BuildFor32Addr;
069          default:
070            return false;
071        }
072      }
073    
074      static boolean isLBitsType(int tcode) {
075        switch (tcode) {
076          case LONG:
077          case DOUBLE:
078            return true;
079          case WORD:
080            return VM.BuildFor64Addr;
081          default:
082            return false;
083        }
084      }
085    
086      static boolean isRefType(int tcode) {
087        return tcode == REF;
088      }
089    
090      static boolean isWordType(int tcode) {
091        return tcode == WORD;
092      }
093    
094      //////////////////////////////////////
095      // Initializer
096      /////////////////////////////////////
097    
098      /** Constructor for 32-bit value */
099      public VariableElement(boolean what_kind, int which_num, byte type, int ibits) {
100        if (VM.VerifyAssertions) {
101          VM._assert(isIBitsType(type));
102          VM._assert(which_num < 0xFFFF);
103        }
104    
105        this.kind = what_kind;
106        this.num = (char)which_num;
107        this.tcode = type;
108        this.value = (long) ibits & 0x0FFFFFFFFL;
109        this.ref = null;
110      }
111    
112      /** Constructor for 64-bit value */
113      public VariableElement(boolean what_kind, int which_num, byte type, long lbits) {
114        if (VM.VerifyAssertions) {
115          VM._assert(isLBitsType(type));
116          VM._assert(which_num < 0xFFFF);
117        }
118    
119        this.kind = what_kind;
120        this.num = (char)which_num;
121        this.tcode = type;
122        this.value = lbits;
123        this.ref = null;
124      }
125    
126      /** Constructor for reference type */
127      public VariableElement(boolean what_kind, int which_num, byte type, Object ref) {
128        if (VM.VerifyAssertions) {
129          VM._assert(isRefType(type));
130          VM._assert(which_num < 0xFFFF);
131        }
132    
133        this.kind = what_kind;
134        this.num = (char)which_num;
135        this.tcode = type;
136        this.value = 0;
137        this.ref = ref;
138      }
139    
140      /** Constructor for word type */
141      public VariableElement(boolean what_kind, int which_num, byte type, Word word) {
142        if (VM.VerifyAssertions) {
143          VM._assert(isWordType(type));
144          VM._assert(which_num < 0xFFFF);
145        }
146    
147        this.kind = what_kind;
148        this.num = (char)which_num;
149        this.tcode = type;
150        if (VM.BuildFor32Addr) {
151          this.value = ((long) word.toInt()) & 0x0FFFFFFFFL;
152        } else {
153          this.value = word.toLong();
154        }
155        this.ref = null;
156      }
157    
158      ////////////////////////////////
159      // instance method
160      ////////////////////////////////
161    
162      /** local or stack element */
163      boolean isLocal() {
164        return kind == LOCAL;
165      }
166    
167      /** get type code */
168      byte getTypeCode() {
169        return tcode;
170      }
171    
172      char getNumber() {
173        return num;
174      }
175    
176      /** is reference type */
177      boolean isRefType() {
178        return (this.tcode == REF);
179      }
180    
181      Object getObject() {
182        return ref;
183      }
184    
185      /** is word type */
186      boolean isWordType() {
187        return (this.tcode == WORD);
188      }
189    
190      Word getWord() {
191        return (VM.BuildFor32Addr) ? Word.fromIntSignExtend((int) value) : Word.fromLong(value);
192      }
193    
194      /* for numerical */
195      int getIntBits() {
196        return (int) (value & 0x0FFFFFFFF);
197      }
198    
199      long getLongBits() {
200        return value;
201      }
202    
203      /* to string */
204      public String toString() {
205        StringBuilder buf = new StringBuilder("(");
206    
207        if (kind == LOCAL) {
208          buf.append('L');
209        } else {
210          buf.append('S');
211        }
212        buf.append((int)num);
213        buf.append(",");
214    
215        char t = 'V';
216        switch (tcode) {
217          case INT:
218            t = 'I';
219            break;
220          case FLOAT:
221            t = 'F';
222            break;
223          case LONG:
224            t = 'J';
225            break;
226          case DOUBLE:
227            t = 'D';
228            break;
229          case RET_ADDR:
230            t = 'R';
231            break;
232          case REF:
233            t = 'L';
234            break;
235          case WORD:
236            t = 'W';
237            break;
238        }
239    
240        buf.append(t);
241        buf.append(",");
242    
243        switch (tcode) {
244          case REF:
245            // it is legal to have a null reference.
246            if (ref == null) {
247              buf.append("null");
248            } else {
249              buf.append(VM.addressAsHexString(Magic.objectAsAddress(ref)));
250              buf.append(" ");
251    //      buf.append(ref.toString());
252            }
253            break;
254          case WORD:
255            buf.append("0x");
256            if (VM.BuildFor32Addr) {
257              buf.append(Integer.toHexString((int) (value & 0x0FFFFFFFFL)));
258            } else {
259              buf.append(Long.toHexString(value));
260            }
261            buf.append(" ");
262            break;
263          case FLOAT:
264            buf.append(Magic.intBitsAsFloat((int) (value & 0x0FFFFFFFF)));
265            break;
266          case LONG:
267            buf.append(value);
268            break;
269          case DOUBLE:
270            buf.append(Magic.longBitsAsDouble(value));
271            break;
272          default:
273            buf.append((int) (value & 0x0FFFFFFFF));
274            break;
275        }
276    
277        buf.append(")");
278    
279        return buf.toString();
280      }
281    }