/*
* 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.runtime.JavaSizeConstants.BYTES_IN_BYTE;
import static org.jikesrvm.runtime.JavaSizeConstants.BYTES_IN_INT;
import static org.jikesrvm.runtime.UnboxedSizeConstants.BYTES_IN_ADDRESS;
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 an Unboxed Magic type.<p>
*
* Currently, unboxed types are restricted to be values that can fit in a single machines word.
*
* @see RVMType
* @see RVMClass
* @see RVMArray
* @see Primitive
*/
@NonMoving
public final class UnboxedType extends RVMType {
/**
* The pretty (external) name for this Unboxed type.
*/
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 UnboxedType(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;
}
/**
* Create an instance of a {@link UnboxedType}
* @param tr The canonical type reference for this primitive
*
* @return the newly created unboxed type for the type reference
*/
static UnboxedType createUnboxedType(TypeReference tr) {
Atom name;
int stackWords = 1;
int memoryBytes;
Class<?> classForType;
name = tr.getName();
if (tr == TypeReference.Address ||
tr == TypeReference.Word ||
tr == TypeReference.Offset ||
tr == TypeReference.Extent) {
memoryBytes = BYTES_IN_ADDRESS;
} else if (tr == TypeReference.Code) {
memoryBytes = VM.BuildForIA32 ? BYTES_IN_BYTE : BYTES_IN_INT;
} else {
throw new Error("Unknown unboxed type " + tr.getName());
}
try {
classForType = Class.forName(name.classNameFromDescriptor());
} catch (Exception e) {
throw new Error("Error getting java.lang.Class wrapper for type " + name.classNameFromDescriptor(), e);
}
return new UnboxedType(tr, classForType, name, stackWords, memoryBytes);
}
/**
* @return 0 because unboxed types do not extend java.lang.Object
*/
@Override
@Pure
@Uninterruptible
public int getTypeDepth() {
return 0;
}
/**
* @return <code>true</code> because unboxed types cannot contain any references
*/
@Override
@Pure
@Uninterruptible
public boolean isAcyclicReference() {
return true;
}
/**
* @return -1
*/
@Override
@Pure
@Uninterruptible
public int getDimensionality() {
return -1;
}
/**
* @return <code>true</code> because unboxed types are always considered
* resolved"
*/
@Override
@Uninterruptible
public boolean isResolved() {
return true;
}
/**
* @return <code>true</code> because unboxed types are always considered
* "instantiated"
*/
@Override
@Pure
@Uninterruptible
public boolean isInstantiated() {
return true;
}
/**
* @return <code>true</code> because unboxed types are always considered
* "initialized"
*/
@Override
@Pure
@Uninterruptible
public boolean isInitialized() {
return true;
}
@Override
public void markAsBootImageClass() {}
/**
* @return <code>true</code>. All unboxed types are included in the bootimage
* because they are needed for starting Jikes RVM.
*/
@Override
@Pure
@Uninterruptible
public boolean isInBootImage() {
return true;
}
/**
* @return <code>Offset.max()</code>
*/
@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>false</code>
*/
@Override
@Pure
@Uninterruptible
public boolean isPrimitiveType() {
return false;
}
/**
* @return <code>false</code>
*/
@Override
@Pure
@Uninterruptible
public boolean isReferenceType() {
return false;
}
/**
* @return <code>true</code>
*/
@Override
@Pure
@Uninterruptible
public boolean isUnboxedType() {
return true;
}
/**
* 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 unboxed types.
* @see UnboxedType#isResolved()
*/
@Override
@Pure
public void resolve() {}
@Override
public void allBootImageTypesResolved() { }
/**
* Cause instantiation to take place. This is a no-op for unboxed types.
* @see UnboxedType#isInstantiated()
*/
@Override
@Pure
public void instantiate() {}
/**
* Cause initialization to take place. This is a no-op for unboxed types.
* @see UnboxedType#isInitialized()
*/
@Override
@Pure
public void initialize() {}
/**
* {@inheritDoc}
* <p>
* This is a no-op for unboxed types.
*/
@Override
@Pure
public void prepareForFirstUse() { }
/**
* @return false
*/
@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;
}
}