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