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.classloader; 014 015 import org.jikesrvm.Constants; 016 import org.jikesrvm.VM; 017 import org.jikesrvm.objectmodel.TIB; 018 import org.vmmagic.pragma.NonMoving; 019 import org.vmmagic.pragma.Pure; 020 import org.vmmagic.pragma.Uninterruptible; 021 import org.vmmagic.unboxed.Offset; 022 023 /** 024 * Description of a java "primitive" type (int, float, etc.) 025 * 026 * <p> This description is not read from a ".class" file, but rather 027 * is manufactured by the VM before execution begins. 028 * 029 * <p> Note that instances of primitives are not objects: 030 * <ul> 031 * <li> they are never heap allocated in the virtual machine 032 * <li> they have no virtual methods 033 * <li> they appear only in the virtual machine's stack, in its registers, 034 * or in fields/elements of class/array instances. 035 * </ul> 036 * 037 * @see RVMType 038 * @see RVMClass 039 * @see RVMArray 040 * @see UnboxedType 041 */ 042 @NonMoving 043 public final class Primitive extends RVMType implements Constants, ClassLoaderConstants { 044 /** 045 * The pretty (external) name for this primitive. 046 * For example, for a long the name is 'long' 047 * and the descriptor is 'J' 048 */ 049 private final Atom name; 050 051 /** 052 * How many slots in the Java Expression Stack does it take 053 * to hold a value of this primitive type? 054 */ 055 private final int stackWords; 056 057 /** 058 * How many bytes in memory does it take to hold a value of this 059 * primitive type? 060 */ 061 private final int memoryBytes; 062 063 /** 064 * Name - something like "int". 065 */ 066 @Override 067 @Pure 068 public String toString() { 069 return name.toString(); 070 } 071 072 /** 073 * Constructor 074 * @param tr The canonical type reference for this primitive 075 * @param classForType The java.lang.Class representation 076 * @param name The name for this primitive 077 * @param stackWords The stack slots used by this primitive 078 * @param memoryBytes The bytes in memory used by this primitive 079 */ 080 private Primitive(TypeReference tr, Class<?> classForType, Atom name, int stackWords, int memoryBytes) { 081 super(tr, // type reference 082 classForType, // j.l.Class representation 083 -1, // dimensionality 084 null // runtime visible annotations 085 ); 086 this.name = name; 087 this.stackWords = stackWords; 088 this.memoryBytes = memoryBytes; 089 this.depth = 0; 090 } 091 092 /** 093 * Create an instance of a {@link Primitive} 094 * @param tr The canonical type reference for this primitive 095 */ 096 static Primitive createPrimitive(TypeReference tr) { 097 Atom name; 098 int stackWords; 099 int memoryBytes; 100 Class<?> classForType; 101 switch (tr.getName().parseForTypeCode()) { 102 case VoidTypeCode: 103 stackWords = 0; 104 memoryBytes = 0; 105 name = Atom.findOrCreateAsciiAtom("void"); 106 classForType = Void.TYPE; 107 break; 108 case BooleanTypeCode: 109 stackWords = 1; 110 memoryBytes = BYTES_IN_BOOLEAN; 111 name = Atom.findOrCreateAsciiAtom("boolean"); 112 classForType = Boolean.TYPE; 113 break; 114 case ByteTypeCode: 115 stackWords = 1; 116 memoryBytes = BYTES_IN_BYTE; 117 name = Atom.findOrCreateAsciiAtom("byte"); 118 classForType = Byte.TYPE; 119 break; 120 case CharTypeCode: 121 stackWords = 1; 122 memoryBytes = BYTES_IN_CHAR; 123 name = Atom.findOrCreateAsciiAtom("char"); 124 classForType = Character.TYPE; 125 break; 126 case ShortTypeCode: 127 stackWords = 1; 128 memoryBytes = BYTES_IN_SHORT; 129 name = Atom.findOrCreateAsciiAtom("short"); 130 classForType = Short.TYPE; 131 break; 132 case IntTypeCode: 133 stackWords = 1; 134 memoryBytes = BYTES_IN_INT; 135 name = Atom.findOrCreateAsciiAtom("int"); 136 classForType = Integer.TYPE; 137 break; 138 case LongTypeCode: 139 stackWords = 2; 140 memoryBytes = BYTES_IN_LONG; 141 name = Atom.findOrCreateAsciiAtom("long"); 142 classForType = Long.TYPE; 143 break; 144 case FloatTypeCode: 145 stackWords = 1; 146 memoryBytes = BYTES_IN_FLOAT; 147 name = Atom.findOrCreateAsciiAtom("float"); 148 classForType = Float.TYPE; 149 break; 150 case DoubleTypeCode: 151 stackWords = 2; 152 memoryBytes = BYTES_IN_DOUBLE; 153 name = Atom.findOrCreateAsciiAtom("double"); 154 classForType = Double.TYPE; 155 break; 156 default: 157 throw new Error("Unknown primitive "+tr.getName().classFileNameFromDescriptor()); 158 } 159 return new Primitive(tr, classForType, name, stackWords, memoryBytes); 160 } 161 162 /** 163 * get number of superclasses to Object 164 * @return 0 165 */ 166 @Override 167 @Pure 168 @Uninterruptible 169 public int getTypeDepth() { 170 return 0; 171 } 172 173 /** 174 * @return <code>true</code> 175 */ 176 @Override 177 @Pure 178 @Uninterruptible 179 public boolean isAcyclicReference() { 180 return true; 181 } 182 183 /** 184 * Number of [ in descriptor for arrays; -1 for primitives; 0 for 185 * classes 186 * @return -1; 187 */ 188 @Override 189 @Pure 190 @Uninterruptible 191 public int getDimensionality() { 192 return -1; 193 } 194 195 /** 196 * @return <code>true</code> because primitives are always considered 197 * "resolved" 198 */ 199 @Override 200 @Uninterruptible 201 public boolean isResolved() { 202 return true; 203 } 204 205 /** 206 * @return <code>true</code> because primitives are always considered 207 * "instantiated" 208 */ 209 @Override 210 @Pure 211 @Uninterruptible 212 public boolean isInstantiated() { 213 return true; 214 } 215 216 /** 217 * @return <code>true</code> because primitives are always considered 218 * "initialized" 219 */ 220 @Override 221 @Pure 222 @Uninterruptible 223 public boolean isInitialized() { 224 return true; 225 } 226 227 @Override 228 public void markAsBootImageClass() {} 229 230 /** 231 * @return <code>true</code> because primitives are needed to start 232 * Jikes RVM 233 */ 234 @Override 235 @Pure 236 @Uninterruptible 237 public boolean isInBootImage() { 238 return true; 239 } 240 241 /** 242 * @return Offset.max(); 243 */ 244 @Override 245 @Pure 246 @Uninterruptible 247 public Offset getThinLockOffset() { 248 if (VM.VerifyAssertions) VM._assert(NOT_REACHED); 249 return Offset.max(); 250 } 251 252 /** 253 * @return <code>false</code> 254 */ 255 @Override 256 @Pure 257 @Uninterruptible 258 public boolean isClassType() { 259 return false; 260 } 261 262 /** 263 * @return <code>false</code> 264 */ 265 @Override 266 @Pure 267 @Uninterruptible 268 public boolean isArrayType() { 269 return false; 270 } 271 272 /** 273 * @return <code>true</code> 274 */ 275 @Override 276 @Pure 277 @Uninterruptible 278 public boolean isPrimitiveType() { 279 return true; 280 } 281 282 /** 283 * @return <code>false</code> 284 */ 285 @Override 286 @Pure 287 @Uninterruptible 288 public boolean isReferenceType() { 289 return false; 290 } 291 292 /** 293 * @return <code>false</code> 294 */ 295 @Override 296 @Pure 297 @Uninterruptible 298 public boolean isUnboxedType() { 299 return false; 300 } 301 302 /** 303 * Stack space requirement in words. 304 */ 305 @Override 306 @Pure 307 @Uninterruptible 308 public int getStackWords() { 309 return stackWords; 310 } 311 312 @Override 313 @Pure 314 @Uninterruptible 315 public int getMemoryBytes() { 316 return memoryBytes; 317 } 318 319 /** 320 * Cause resolution to take place. This is a no-op for primitive types. 321 * @see Primitive#isResolved() 322 */ 323 @Override 324 @Pure 325 public void resolve() {} 326 327 @Override 328 public void allBootImageTypesResolved() { } 329 330 /** 331 * Cause instantiation to take place. This is a no-op for primitive types. 332 * @see Primitive#isInstantiated() 333 */ 334 @Override 335 @Pure 336 public void instantiate() {} 337 338 /** 339 * Cause initialization to take place. This is a no-op for primitive types. 340 * @see Primitive#isInitialized() 341 */ 342 @Override 343 @Pure 344 public void initialize() {} 345 346 /** 347 * @return <code>false</code> 348 */ 349 @Override 350 @Pure 351 @Uninterruptible 352 public boolean hasFinalizer() { 353 return false; 354 } 355 356 /* 357 * Primitives are not first class objects - 358 * but the implementation of reflection is cleaner if 359 * we pretend that they are and provide dummy implementations of 360 * the following methods 361 */ 362 363 /** 364 * Static fields of this class/array type. 365 * @return zero length array 366 */ 367 @Override 368 @Pure 369 public RVMField[] getStaticFields() { 370 return emptyVMField; 371 } 372 373 /** 374 * Non-static fields of this class/array type 375 * (composed with supertypes, if any). 376 * @return zero length array 377 */ 378 @Override 379 @Pure 380 public RVMField[] getInstanceFields() { 381 return emptyVMField; 382 } 383 384 /** 385 * Statically dispatched methods of this class/array type. 386 * @return zero length array 387 */ 388 @Override 389 @Pure 390 public RVMMethod[] getStaticMethods() { 391 return emptyVMMethod; 392 } 393 394 /** 395 * Virtually dispatched methods of this class/array type 396 * (composed with supertypes, if any). 397 * @return zero length array 398 */ 399 @Override 400 @Pure 401 public RVMMethod[] getVirtualMethods() { 402 return emptyVMMethod; 403 } 404 405 /** 406 * Runtime type information for this class/array type. 407 */ 408 @Override 409 @Uninterruptible 410 public TIB getTypeInformationBlock() { 411 if (VM.VerifyAssertions) VM._assert(NOT_REACHED); 412 return null; 413 } 414 }