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