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 }