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    public class VariableElement implements OSRConstants {
025    
026      //////////////////////////////////
027      // instance fields
028      //////////////////////////////////
029    
030      /** the kind of this element : LOCAL or STACK */
031      private final boolean kind;
032    
033      /**
034       * the number of element, e.g., with kind we
035       * can know it is L0 or S1.
036       */
037      private final char num;
038    
039      /** type code, can only be INT, FLOAT, LONG, DOUBLE, RET_ADDR, WORD or REF */
040      private final byte tcode;
041    
042      /**
043       * The value of this element.
044       * For type INT, FLOAT, RET_ADDR and WORD (32-bit), the lower 32 bits are valid.
045       * For type LONG and DOUBLE and WORD(64-bit), 64 bits are valid.
046       * For REF type, next field 'ref' is valid.
047       *
048       * For FLOAT, and DOUBLE, use Magic.intBitsAsFloat
049       *                         or Magic.longBitsAsDouble
050       * to convert bits to floating-point value.
051       */
052      private final long value;
053    
054      /** for reference type value */
055      private final Object ref;
056    
057      //////////////////////////////////
058      // class auxiliary methods
059      /////////////////////////////////
060      static boolean isIBitsType(int tcode) {
061        switch (tcode) {
062          case INT:
063          case FLOAT:
064          case RET_ADDR:
065            return true;
066          case WORD:
067            return VM.BuildFor32Addr;
068          default:
069            return false;
070        }
071      }
072    
073      static boolean isLBitsType(int tcode) {
074        switch (tcode) {
075          case LONG:
076          case DOUBLE:
077            return true;
078          case WORD:
079            return VM.BuildFor64Addr;
080          default:
081            return false;
082        }
083      }
084    
085      static boolean isRefType(int tcode) {
086        return tcode == REF;
087      }
088    
089      static boolean isWordType(int tcode) {
090        return tcode == WORD;
091      }
092    
093      //////////////////////////////////////
094      // Initializer
095      /////////////////////////////////////
096    
097      /** Constructor for 32-bit value */
098      public VariableElement(boolean what_kind, int which_num, byte type, int ibits) {
099        if (VM.VerifyAssertions) {
100          VM._assert(isIBitsType(type));
101          VM._assert(which_num < 0xFFFF);
102        }
103    
104        this.kind = what_kind;
105        this.num = (char)which_num;
106        this.tcode = type;
107        this.value = ibits & 0x0FFFFFFFFL;
108        this.ref = null;
109      }
110    
111      /** Constructor for 64-bit value */
112      public VariableElement(boolean what_kind, int which_num, byte type, long lbits) {
113        if (VM.VerifyAssertions) {
114          VM._assert(isLBitsType(type));
115          VM._assert(which_num < 0xFFFF);
116        }
117    
118        this.kind = what_kind;
119        this.num = (char)which_num;
120        this.tcode = type;
121        this.value = lbits;
122        this.ref = null;
123      }
124    
125      /** Constructor for reference type */
126      public VariableElement(boolean what_kind, int which_num, byte type, Object ref) {
127        if (VM.VerifyAssertions) {
128          VM._assert(isRefType(type));
129          VM._assert(which_num < 0xFFFF);
130        }
131    
132        this.kind = what_kind;
133        this.num = (char)which_num;
134        this.tcode = type;
135        this.value = 0;
136        this.ref = ref;
137      }
138    
139      /** Constructor for word type */
140      public VariableElement(boolean what_kind, int which_num, byte type, Word word) {
141        if (VM.VerifyAssertions) {
142          VM._assert(isWordType(type));
143          VM._assert(which_num < 0xFFFF);
144        }
145    
146        this.kind = what_kind;
147        this.num = (char)which_num;
148        this.tcode = type;
149        if (VM.BuildFor32Addr) {
150          this.value = (word.toInt()) & 0x0FFFFFFFFL;
151        } else {
152          this.value = word.toLong();
153        }
154        this.ref = null;
155      }
156    
157      ////////////////////////////////
158      // instance method
159      ////////////////////////////////
160    
161      /** local or stack element */
162      boolean isLocal() {
163        return kind == LOCAL;
164      }
165    
166      /** get type code */
167      byte getTypeCode() {
168        return tcode;
169      }
170    
171      char getNumber() {
172        return num;
173      }
174    
175      /** is reference type */
176      boolean isRefType() {
177        return (this.tcode == REF);
178      }
179    
180      Object getObject() {
181        return ref;
182      }
183    
184      /** is word type */
185      boolean isWordType() {
186        return (this.tcode == WORD);
187      }
188    
189      Word getWord() {
190        return (VM.BuildFor32Addr) ? Word.fromIntSignExtend((int) value) : Word.fromLong(value);
191      }
192    
193      /* for numerical */
194      int getIntBits() {
195        return (int) (value & 0x0FFFFFFFF);
196      }
197    
198      long getLongBits() {
199        return value;
200      }
201    
202      /* to string */
203      @Override
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    }