/* * This file is part of the Jikes RVM project (http://jikesrvm.org). * * This file is licensed to You under the Eclipse Public License (EPL); * You may not use this file except in compliance with the License. You * may obtain a copy of the License at * * http://www.opensource.org/licenses/eclipse-1.0.php * * See the COPYRIGHT.txt file distributed with this work for information * regarding copyright ownership. */ package org.jikesrvm.classloader; import static org.jikesrvm.VM.NOT_REACHED; import static org.jikesrvm.classloader.ClassLoaderConstants.BooleanTypeCode; import static org.jikesrvm.classloader.ClassLoaderConstants.ByteTypeCode; import static org.jikesrvm.classloader.ClassLoaderConstants.CharTypeCode; import static org.jikesrvm.classloader.ClassLoaderConstants.DoubleTypeCode; import static org.jikesrvm.classloader.ClassLoaderConstants.FloatTypeCode; import static org.jikesrvm.classloader.ClassLoaderConstants.IntTypeCode; import static org.jikesrvm.classloader.ClassLoaderConstants.LongTypeCode; import static org.jikesrvm.classloader.ClassLoaderConstants.ShortTypeCode; import static org.jikesrvm.classloader.ClassLoaderConstants.VoidTypeCode; import static org.jikesrvm.runtime.JavaSizeConstants.BYTES_IN_BOOLEAN; import static org.jikesrvm.runtime.JavaSizeConstants.BYTES_IN_BYTE; import static org.jikesrvm.runtime.JavaSizeConstants.BYTES_IN_CHAR; import static org.jikesrvm.runtime.JavaSizeConstants.BYTES_IN_DOUBLE; import static org.jikesrvm.runtime.JavaSizeConstants.BYTES_IN_FLOAT; import static org.jikesrvm.runtime.JavaSizeConstants.BYTES_IN_INT; import static org.jikesrvm.runtime.JavaSizeConstants.BYTES_IN_LONG; import static org.jikesrvm.runtime.JavaSizeConstants.BYTES_IN_SHORT; import org.jikesrvm.VM; import org.jikesrvm.objectmodel.TIB; import org.vmmagic.pragma.NonMoving; import org.vmmagic.pragma.Pure; import org.vmmagic.pragma.Uninterruptible; import org.vmmagic.unboxed.Offset; /** * Description of a java "primitive" type (int, float, etc.) * * <p> This description is not read from a ".class" file, but rather * is manufactured by the VM before execution begins. * * <p> Note that instances of primitives are not objects: * <ul> * <li> they are never heap allocated in the virtual machine * <li> they have no virtual methods * <li> they appear only in the virtual machine's stack, in its registers, * or in fields/elements of class/array instances. * </ul> * * @see RVMType * @see RVMClass * @see RVMArray * @see UnboxedType */ @NonMoving public final class Primitive extends RVMType { /** * The pretty (external) name for this primitive. * For example, for a long the name is 'long' * and the descriptor is 'J' */ private final Atom name; /** * How many slots in the Java Expression Stack does it take * to hold a value of this primitive type? */ private final int stackWords; /** * How many bytes in memory does it take to hold a value of this * primitive type? */ private final int memoryBytes; /** * Name - something like "int". */ @Override @Pure public String toString() { return name.toString(); } /** * Constructor * @param tr The canonical type reference for this primitive * @param classForType The java.lang.Class representation * @param name The name for this primitive * @param stackWords The stack slots used by this primitive * @param memoryBytes The bytes in memory used by this primitive */ private Primitive(TypeReference tr, Class<?> classForType, Atom name, int stackWords, int memoryBytes) { super(tr, // type reference classForType, // j.l.Class representation -1, // dimensionality null // runtime visible annotations ); this.name = name; this.stackWords = stackWords; this.memoryBytes = memoryBytes; this.depth = 0; } /** * Creates an instance of a {@link Primitive}. * @param tr The canonical type reference for this primitive * @return a newly created instance of {@link Primitive} */ static Primitive createPrimitive(TypeReference tr) { Atom name; int stackWords; int memoryBytes; Class<?> classForType; switch (tr.getName().parseForTypeCode()) { case VoidTypeCode: stackWords = 0; memoryBytes = 0; name = Atom.findOrCreateAsciiAtom("void"); classForType = Void.TYPE; break; case BooleanTypeCode: stackWords = 1; memoryBytes = BYTES_IN_BOOLEAN; name = Atom.findOrCreateAsciiAtom("boolean"); classForType = Boolean.TYPE; break; case ByteTypeCode: stackWords = 1; memoryBytes = BYTES_IN_BYTE; name = Atom.findOrCreateAsciiAtom("byte"); classForType = Byte.TYPE; break; case CharTypeCode: stackWords = 1; memoryBytes = BYTES_IN_CHAR; name = Atom.findOrCreateAsciiAtom("char"); classForType = Character.TYPE; break; case ShortTypeCode: stackWords = 1; memoryBytes = BYTES_IN_SHORT; name = Atom.findOrCreateAsciiAtom("short"); classForType = Short.TYPE; break; case IntTypeCode: stackWords = 1; memoryBytes = BYTES_IN_INT; name = Atom.findOrCreateAsciiAtom("int"); classForType = Integer.TYPE; break; case LongTypeCode: stackWords = 2; memoryBytes = BYTES_IN_LONG; name = Atom.findOrCreateAsciiAtom("long"); classForType = Long.TYPE; break; case FloatTypeCode: stackWords = 1; memoryBytes = BYTES_IN_FLOAT; name = Atom.findOrCreateAsciiAtom("float"); classForType = Float.TYPE; break; case DoubleTypeCode: stackWords = 2; memoryBytes = BYTES_IN_DOUBLE; name = Atom.findOrCreateAsciiAtom("double"); classForType = Double.TYPE; break; default: throw new Error("Unknown primitive " + tr.getName().classFileNameFromDescriptor()); } return new Primitive(tr, classForType, name, stackWords, memoryBytes); } /** * get number of superclasses to Object * @return 0 */ @Override @Pure @Uninterruptible public int getTypeDepth() { return 0; } /** * @return <code>true</code> */ @Override @Pure @Uninterruptible public boolean isAcyclicReference() { return true; } /** * Number of [ in descriptor for arrays; -1 for primitives; 0 for * classes * @return -1; */ @Override @Pure @Uninterruptible public int getDimensionality() { return -1; } /** * @return <code>true</code> because primitives are always considered * "resolved" */ @Override @Uninterruptible public boolean isResolved() { return true; } /** * @return <code>true</code> because primitives are always considered * "instantiated" */ @Override @Pure @Uninterruptible public boolean isInstantiated() { return true; } /** * @return <code>true</code> because primitives are always considered * "initialized" */ @Override @Pure @Uninterruptible public boolean isInitialized() { return true; } @Override public void markAsBootImageClass() {} /** * @return <code>true</code> because primitives are needed to start * Jikes RVM */ @Override @Pure @Uninterruptible public boolean isInBootImage() { return true; } /** * @return Offset.max(); */ @Override @Pure @Uninterruptible public Offset getThinLockOffset() { if (VM.VerifyAssertions) VM._assert(NOT_REACHED); return Offset.max(); } /** * @return <code>false</code> */ @Override @Pure @Uninterruptible public boolean isClassType() { return false; } /** * @return <code>false</code> */ @Override @Pure @Uninterruptible public boolean isArrayType() { return false; } /** * @return <code>true</code> */ @Override @Pure @Uninterruptible public boolean isPrimitiveType() { return true; } /** * @return <code>false</code> */ @Override @Pure @Uninterruptible public boolean isReferenceType() { return false; } /** * @return <code>false</code> */ @Override @Pure @Uninterruptible public boolean isUnboxedType() { return false; } /** * Stack space requirement in words. */ @Override @Pure @Uninterruptible public int getStackWords() { return stackWords; } @Override @Pure @Uninterruptible public int getMemoryBytes() { return memoryBytes; } /** * Cause resolution to take place. This is a no-op for primitive types. * @see Primitive#isResolved() */ @Override @Pure public void resolve() {} @Override public void allBootImageTypesResolved() { } /** * Cause instantiation to take place. This is a no-op for primitive types. * @see Primitive#isInstantiated() */ @Override @Pure public void instantiate() {} /** * Cause initialization to take place. This is a no-op for primitive types. * @see Primitive#isInitialized() */ @Override @Pure public void initialize() {} /** * {@inheritDoc} * <p> * This is a no-op for primitive types. */ @Override @Pure public void prepareForFirstUse() { } /** * @return <code>false</code> */ @Override @Pure @Uninterruptible public boolean hasFinalizer() { return false; } /* * Primitives are not first class objects - * but the implementation of reflection is cleaner if * we pretend that they are and provide dummy implementations of * the following methods */ /** * Static fields of this class/array type. * @return zero length array */ @Override @Pure public RVMField[] getStaticFields() { return emptyVMField; } /** * Non-static fields of this class/array type * (composed with supertypes, if any). * @return zero length array */ @Override @Pure public RVMField[] getInstanceFields() { return emptyVMField; } /** * Statically dispatched methods of this class/array type. * @return zero length array */ @Override @Pure public RVMMethod[] getStaticMethods() { return emptyVMMethod; } /** * Virtually dispatched methods of this class/array type * (composed with supertypes, if any). * @return zero length array */ @Override @Pure public RVMMethod[] getVirtualMethods() { return emptyVMMethod; } /** * Runtime type information for this class/array type. */ @Override @Uninterruptible public TIB getTypeInformationBlock() { if (VM.VerifyAssertions) VM._assert(NOT_REACHED); return null; } }