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 }