/*
* $Id$
*
* Copyright (C) 2003-2014 JNode.org
*
* This library is free software; you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as published
* by the Free Software Foundation; either version 2.1 of the License, or
* (at your option) any later version.
*
* This library is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
* License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this library; If not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
package org.jnode.vm.classmgr;
import gnu.java.lang.VMClassHelper;
import java.io.Serializable;
import java.io.Writer;
import java.lang.reflect.InvocationTargetException;
import java.security.ProtectionDomain;
import java.util.Arrays;
import java.util.Comparator;
import java.util.HashSet;
import org.jnode.annotation.Inline;
import org.jnode.annotation.KernelSpace;
import org.jnode.annotation.LoadStatics;
import org.jnode.annotation.MagicPermission;
import org.jnode.annotation.NoInline;
import org.jnode.annotation.SharedStatics;
import org.jnode.annotation.Uninterruptible;
import org.jnode.assembler.NativeStream;
import org.jnode.permission.JNodePermission;
import org.jnode.vm.InternString;
import org.jnode.vm.JvmType;
import org.jnode.vm.LoadCompileService;
import org.jnode.vm.Unsafe;
import org.jnode.vm.VmMagic;
import org.jnode.vm.VmReflection;
import org.jnode.vm.VmSystemClassLoader;
import org.jnode.vm.compiler.CompileError;
import org.jnode.vm.compiler.CompiledIMT;
import org.jnode.vm.compiler.NativeCodeCompiler;
import org.jnode.vm.facade.VmUtils;
import org.jnode.vm.isolate.VmIsolateLocal;
import org.vmmagic.unboxed.Address;
import org.vmmagic.unboxed.ObjectReference;
@SharedStatics
@Uninterruptible
@MagicPermission
public abstract class VmType<T> extends VmAnnotatedElement implements
VmSharedStaticsEntry, VmIsolatedStaticsEntry {
/**
* The parent of this class. Normally VmClass instance, during loading
* String instance
*/
private VmNormalClass<? super T> superClass;
/**
* The classname of the parent of this class.
*/
private final String superClassName;
/**
* The number of super classes until (and including) Object
*/
private int superClassDepth;
/**
* The name of this class
*/
private String name;
/**
* The the source file name of this class
*/
private String sourceFile;
/**
* The the source file name of this class
*/
private String signature;
/**
* All methods and constructors declared in this class
*/
private VmMethod[] methodTable;
/**
* All fields declared in this class
*/
private VmField[] fieldTable;
/**
* My modifiers
*/
private int modifiers = -1;
/**
* Pragma flags, see {@link TypePragmaFlags}
*/
private char pragmaFlags;
/**
* State of this type see {@link VmTypeState}.
*/
private char state;
/**
* The constant pool
*/
private VmCP cp;
/**
* Interface implemented by this class
*/
private VmImplementedInterface[] interfaceTable;
/**
* All interface implemented by this class and its superclasses
*/
private VmInterfaceClass[] allInterfaceTable;
/**
* Loaded of this class
*/
private final VmClassLoader loader;
/**
* Holder for isolate specific Class instance
*/
private VmIsolateLocal<Class<T>> javaClassHolder;
/**
* Have the references in the constant pool been resolved?
*/
private boolean resolvedCpRefs;
/**
* Size of instances of this class in bytes (1..8)
*/
private final byte typeSize;
/**
* Name of the array class with this class as component type
*/
private String arrayClassName;
/**
* The array class with this class as component type
*/
private VmArrayClass<T[]> arrayClass;
/**
* Array containing all super classes and all implemented interfaces
*/
private VmType[] superClassesArray;
/**
* The finalize method of this class
*/
private VmMethod finalizeMethod;
/**
* The mangled name (cache)
*/
private String mangledName;
/**
* Error message during linkage
*/
private String errorMsg;
/**
* Index of this type in the statics index
*/
private final int staticsIndex;
/**
* Index of this type in the isolated statics index
*/
private final int isolatedStaticsIndex;
/**
* The protection domain of this class
*/
private final ProtectionDomain protectionDomain;
/**
* Type information managed and required by the memory manager
*/
private Object mmType;
private static VmNormalClass<Object> ObjectClass;
private static VmInterfaceClass<Cloneable> CloneableClass;
private static VmInterfaceClass<Serializable> SerializableClass;
private static VmNormalClass BooleanClass;
private static VmNormalClass ByteClass;
private static VmNormalClass CharClass;
private static VmNormalClass ShortClass;
private static VmNormalClass IntClass;
private static VmNormalClass FloatClass;
private static VmNormalClass LongClass;
private static VmNormalClass DoubleClass;
private static VmNormalClass VoidClass;
private static VmNormalClass ClassClass;
private static VmArrayClass<boolean[]> BooleanArrayClass;
private static VmArrayClass<byte[]> ByteArrayClass;
private static VmArrayClass<char[]> CharArrayClass;
private static VmArrayClass<short[]> ShortArrayClass;
private static VmArrayClass<int[]> IntArrayClass;
private static VmArrayClass<float[]> FloatArrayClass;
private static VmArrayClass<long[]> LongArrayClass;
private static VmArrayClass<double[]> DoubleArrayClass;
private static VmArrayClass<Object[]> ObjectArrayClass;
/**
* Construct a new VmClass
*
* @param name
* @param superClassName
* @param loader
* @param accessFlags
* @param protectionDomain the protection domain of this type.
*/
protected VmType(String name, String superClassName, VmClassLoader loader,
int accessFlags, ProtectionDomain protectionDomain) {
this(name, null, superClassName, loader, accessFlags, -1,
protectionDomain);
}
/**
* Construct a new VmClass with a given name and superclass
*
* @param name
* @param superClass
* @param loader
* @param typeSize
* @param protectionDomain the protection domain of this type.
*/
VmType(String name, VmNormalClass<? super T> superClass,
VmClassLoader loader, int typeSize,
ProtectionDomain protectionDomain) {
this(name, superClass, superClass.getName(), loader,
Modifier.ACC_PUBLIC, typeSize, protectionDomain);
}
/**
* Construct a new VmClass with a given name and superclass
*
* @param name
* @param superClass
* @param superClassName
* @param loader
* @param modifiers
* @param typeSize
* @param protectionDomain the protection domain of this type.
*/
private VmType(String name, VmNormalClass<? super T> superClass,
String superClassName, VmClassLoader loader, int modifiers,
int typeSize, ProtectionDomain protectionDomain) {
if (superClassName == null) {
if (!name.equals("java.lang.Object")) {
throw new IllegalArgumentException(
"superClassName cannot be null in class " + name);
}
} else if (superClassName.indexOf('/') >= 0) {
throw new IllegalArgumentException("superClassName contains '/'");
}
if (name.indexOf('/') >= 0) {
throw new IllegalArgumentException("name contains '/'");
}
final String pkg = VMClassHelper.getPackagePortion(name);
if (pkg.equals("org.vmmagic.unboxed") || pkg.equals("org.jnode.vm")) {
final String cname = VMClassHelper.getClassNamePortion(name);
if (cname.equals("Address") || cname.equals("AddressArray")
|| cname.equals("Extent") || cname.equals("ExtentArray")
|| cname.equals("ObjectReference")
|| cname.equals("ObjectReferenceArray")
|| cname.equals("Offset") || cname.equals("OffsetArray")
|| cname.equals("Word") || cname.equals("WordArray")
| cname.equals("VmMagic")) {
modifiers |= Modifier.ACC_MAGIC;
}
}
this.name = InternString.internString(name);
this.superClass = superClass;
this.superClassName = (superClassName == null) ? null : InternString.internString(superClassName);
this.modifiers = modifiers;
this.state = VmTypeState.ST_LOADED;
this.loader = loader;
this.protectionDomain = protectionDomain;
this.staticsIndex = loader.getSharedStatics().allocClass(this);
this.isolatedStaticsIndex = loader.getIsolatedStatics().allocIntField();
if (name.charAt(0) == '[') {
this.interfaceTable = new VmImplementedInterface[]{
new VmImplementedInterface(CloneableClass),
new VmImplementedInterface(SerializableClass)};
this.typeSize = (byte) loader.getArchitecture().getReferenceSize();
} else if (typeSize >= 0) {
this.typeSize = (byte) typeSize;
} else {
this.typeSize = (byte) loader.getArchitecture().getReferenceSize();
}
}
/**
* Load the system classes during our bootstrap process.
*
* @param clc
* @return the VmType objects for the system classes
* @throws ClassNotFoundException
*/
@SuppressWarnings("unchecked")
public static VmType[] initializeForBootImage(VmSystemClassLoader clc)
throws ClassNotFoundException {
ObjectClass = (VmNormalClass) clc.loadClass("java.lang.Object", false);
ClassClass = (VmNormalClass) clc.loadClass("java.lang.Class", false);
CloneableClass = (VmInterfaceClass) clc.loadClass(
"java.lang.Cloneable", false);
SerializableClass = (VmInterfaceClass) clc.loadClass(
"java.io.Serializable", false);
ObjectClass.link();
ClassClass.link();
CloneableClass.link();
SerializableClass.link();
final ProtectionDomain protectionDomain = null;
BooleanClass = new VmPrimitiveClass("boolean", ObjectClass, clc,
JvmType.BOOLEAN, 1, false, protectionDomain);
ByteClass = new VmPrimitiveClass("byte", ObjectClass, clc,
JvmType.BYTE, 1, false, protectionDomain);
CharClass = new VmPrimitiveClass("char", ObjectClass, clc,
JvmType.CHAR, 2, false, protectionDomain);
ShortClass = new VmPrimitiveClass("short", ObjectClass, clc,
JvmType.SHORT, 2, false, protectionDomain);
IntClass = new VmPrimitiveClass("int", ObjectClass, clc, JvmType.INT,
4, false, protectionDomain);
FloatClass = new VmPrimitiveClass("float", ObjectClass, clc,
JvmType.FLOAT, 4, true, protectionDomain);
LongClass = new VmPrimitiveClass("long", ObjectClass, clc,
JvmType.LONG, 8, false, protectionDomain);
DoubleClass = new VmPrimitiveClass("double", ObjectClass, clc,
JvmType.DOUBLE, 8, true, protectionDomain);
VoidClass = new VmPrimitiveClass("void", ObjectClass, clc,
JvmType.VOID, 0, false, protectionDomain);
BooleanClass.link();
ByteClass.link();
CharClass.link();
ShortClass.link();
IntClass.link();
FloatClass.link();
LongClass.link();
DoubleClass.link();
VoidClass.link();
BooleanArrayClass = BooleanClass.getArrayClass("[Z");
ByteArrayClass = ByteClass.getArrayClass("[B");
CharArrayClass = CharClass.getArrayClass("[C");
ShortArrayClass = ShortClass.getArrayClass("[S");
IntArrayClass = IntClass.getArrayClass("[I");
FloatArrayClass = FloatClass.getArrayClass("[F");
LongArrayClass = LongClass.getArrayClass("[J");
DoubleArrayClass = DoubleClass.getArrayClass("[D");
ObjectArrayClass = ObjectClass.getArrayClass();
BooleanArrayClass.link();
ByteArrayClass.link();
CharArrayClass.link();
ShortArrayClass.link();
IntArrayClass.link();
FloatArrayClass.link();
LongArrayClass.link();
DoubleArrayClass.link();
ObjectArrayClass.link();
return new VmType[]{ObjectClass, ClassClass, CloneableClass, SerializableClass,
BooleanClass, ByteClass, CharClass, ShortClass, IntClass,
FloatClass, LongClass, DoubleClass, VoidClass,
BooleanArrayClass, ByteArrayClass, CharArrayClass,
ShortArrayClass, IntArrayClass, FloatArrayClass,
LongArrayClass, DoubleArrayClass, ObjectArrayClass};
}
/**
* Load the system classes from an array of system classes. This method is
* called during the boot of the system.
*
* @param bootClasses
*/
@SuppressWarnings("unchecked")
@LoadStatics
protected static void loadFromBootClassArray(VmType[] bootClasses) {
Unsafe.debug("[loadFromBootClassArray:");
final int count = bootClasses.length;
for (int i = 0; i < count; i++) {
final VmType<?> vmClass = bootClasses[i];
final String name = vmClass.name;
if (vmClass.isPrimitive()) {
if (name.equals("boolean")) {
BooleanClass = (VmNormalClass) vmClass;
} else if (name.equals("byte")) {
ByteClass = (VmNormalClass) vmClass;
} else if (name.equals("char")) {
CharClass = (VmNormalClass) vmClass;
} else if (name.equals("short")) {
ShortClass = (VmNormalClass) vmClass;
} else if (name.equals("int")) {
IntClass = (VmNormalClass) vmClass;
} else if (name.equals("float")) {
FloatClass = (VmNormalClass) vmClass;
} else if (name.equals("long")) {
LongClass = (VmNormalClass) vmClass;
} else if (name.equals("double")) {
DoubleClass = (VmNormalClass) vmClass;
} else if (name.equals("void")) {
VoidClass = (VmNormalClass) vmClass;
}
} else if (vmClass.isArray()) {
if (name.equals("[Z")) {
BooleanArrayClass = (VmArrayClass) vmClass;
} else if (name.equals("[B")) {
ByteArrayClass = (VmArrayClass) vmClass;
} else if (name.equals("[C")) {
CharArrayClass = (VmArrayClass) vmClass;
} else if (name.equals("[S")) {
ShortArrayClass = (VmArrayClass) vmClass;
} else if (name.equals("[I")) {
IntArrayClass = (VmArrayClass) vmClass;
} else if (name.equals("[F")) {
FloatArrayClass = (VmArrayClass) vmClass;
} else if (name.equals("[J")) {
LongArrayClass = (VmArrayClass) vmClass;
} else if (name.equals("[D")) {
DoubleArrayClass = (VmArrayClass) vmClass;
}
} else {
if (name.equals("java.lang.Object")) {
ObjectClass = (VmNormalClass) vmClass;
} else if (name.equals("java.lang.Class")) {
ClassClass = (VmNormalClass) vmClass;
} else if (name.equals("java.lang.Cloneable")) {
CloneableClass = (VmInterfaceClass) vmClass;
} else if (name.equals("java.io.Serializable")) {
SerializableClass = (VmInterfaceClass) vmClass;
}
}
}
Unsafe.debug("]\n");
}
/**
* Create an array classname with a this class as component type.
*
* @return char[]
*/
public final String getArrayClassName() {
if (arrayClassName == null) {
char[] result;
int count = name.length();
if (isPrimitive() || isArray()) {
result = new char[count + 1];
result[0] = '[';
for (int i = 0; i < count; i++) {
result[i + 1] = name.charAt(i);
}
} else {
result = new char[count + 3];
result[0] = '[';
result[1] = 'L';
result[count + 2] = ';';
for (int i = 0; i < count; i++) {
result[i + 2] = name.charAt(i);
}
}
arrayClassName = InternString.internString(new String(result));
}
return arrayClassName;
}
/**
* Gets the array class with this class as its component type
*
* @param arrayClassName
* @return The array class
*/
final VmArrayClass<T[]> getArrayClass(String arrayClassName) {
if (arrayClass == null) {
arrayClass = createArrayClass(true, arrayClassName);
} else {
arrayClass.link();
}
return arrayClass;
}
/**
* Gets the array class with this class as its component type
*
* @return The array class
*/
public final VmArrayClass getArrayClass() {
return getArrayClass(null);
}
/**
* Gets the array class with this class as its component type
*
* @param link
* @return The array class
*/
final VmArrayClass getArrayClass(boolean link) {
if (arrayClass == null) {
arrayClass = createArrayClass(link, null);
}
return arrayClass;
}
/**
* Create an array class with a given component type.
*
* @param link True if the new class should be linked, false otherwise
* @param arrayClassName
* @return VmClass
*/
private final VmArrayClass<T[]> createArrayClass(boolean link,
String arrayClassName) {
final String name;
if (arrayClassName != null) {
name = arrayClassName;
} else {
name = getArrayClassName();
}
final VmArrayClass<T[]> arrayClass = new VmArrayClass<T[]>(name, this
.getLoader(), this, -1, protectionDomain);
if (link) {
arrayClass.link();
}
return arrayClass;
}
/**
* Gets the VmClass of java.lang.Object.
*
* @return The class
*/
public static VmNormalClass<Object> getObjectClass() {
if (ObjectClass == null) {
Unsafe.die("ObjectClass == null");
}
return ObjectClass;
}
/**
* Gets the primitive class corresponding to the given signature type.
*
* @param type
* @return VmClass
*/
public static VmNormalClass<?> getPrimitiveClass(char type) {
switch (type) {
case 'Z':
return BooleanClass;
case 'B':
return ByteClass;
case 'C':
return CharClass;
case 'S':
return ShortClass;
case 'I':
return IntClass;
case 'F':
return FloatClass;
case 'J':
return LongClass;
case 'D':
return DoubleClass;
case 'V':
return VoidClass;
default:
throw new IllegalArgumentException("Unknown type " + type);
}
}
/**
* Gets the primitive arrayclass corresponding to the given signature type.
*
* @param type
* @return VmClass
*/
public static VmType getPrimitiveArrayClass(char type) {
switch (type) {
case 'Z':
return BooleanArrayClass;
case 'B':
return ByteArrayClass;
case 'C':
return CharArrayClass;
case 'S':
return ShortArrayClass;
case 'I':
return IntArrayClass;
case 'F':
return FloatArrayClass;
case 'J':
return LongArrayClass;
case 'D':
return DoubleArrayClass;
default:
throw new IllegalArgumentException("Unknown type " + type);
}
}
/**
* Gets the primitive array class corresponding to the given (newarray)
* type.
*
* @param type
* @return VmClass
*/
public static VmArrayClass getPrimitiveArrayClass(int type) {
switch (type) {
case 4:
return BooleanArrayClass;
case 8:
return ByteArrayClass;
case 5:
return CharArrayClass;
case 9:
return ShortArrayClass;
case 10:
return IntArrayClass;
case 6:
return FloatArrayClass;
case 11:
return LongArrayClass;
case 7:
return DoubleArrayClass;
default:
throw new IllegalArgumentException("Unknown type " + type);
}
}
/**
* Gets the size in bytes of instances of this object on the stack.
*
* @return 0..8
*/
public final int getTypeSize() {
return typeSize;
}
/**
* Return the corresponding java.lang.Class for this VmClass. During build
* environment the Class will be loaded by Class.forName
*
* @return The class
*/
public final Class<T> asClass() {
return asClass(false);
}
/**
* Return the corresponding java.lang.Class for this VmClass. During build
* environment the Class will be loaded by Class.forName
*
* @return The class
*/
public final Class<T> asClassDuringBootstrap() {
return asClass(true);
}
/**
* Return the corresponding java.lang.Class for this VmClass. During build
* environment the Class will be loaded by Class.forName
*
* @param isBuildEnv
* @return The class
*/
@SuppressWarnings("unchecked")
private final Class<T> asClass(boolean isBuildEnv) {
if (javaClassHolder == null) {
javaClassHolder = new VmIsolateLocal<Class<T>>();
}
final Class<T> javaClass = javaClassHolder.get();
if (javaClass == null) {
if (isBuildEnv) {
try {
javaClassHolder.set((Class<T>) Class.forName(getName()));
} catch (ClassNotFoundException ex) { /* ignore */
throw new NoClassDefFoundError(getName());
}
} else {
// javaClassHolder.set(new Class(this));
javaClassHolder.set(newClass());
}
return javaClassHolder.get();
} else {
return javaClass;
}
}
/**
* Return the super class of this class or return null for java.lang.Object
*
* @return The class
*/
public final VmNormalClass<? super T> getSuperClass() {
if (superClass != null) {
return superClass;
} else if (superClassName == null) {
// java.lang.Object
return null;
} else {
throw new RuntimeException(
"getSuperClass called too early in class " + name);
}
}
/**
* Return the name of this class
*
* @return The name of this class
*/
@KernelSpace
public final String getName() {
return name;
}
/**
* Convert myself into a String representation
*
* @return The mangled name
*/
public final String getMangledName() {
if (mangledName == null) {
mangledName = Mangler.mangleClassName(name);
}
return mangledName;
}
/**
* Returns the second character of the name of this class
*
* @return char
*/
public char getSecondNameChar() {
return name.charAt(1);
}
/**
* Is my name equal to the given array of characters?
*
* @param otherName
* @return boolean
*/
public boolean nameEquals(char[] otherName) {
return name.equals(otherName);
}
/**
* Is my name equal to the given String?
*
* @param otherName
* @return boolean
*/
public boolean nameEquals(String otherName) {
return name.equals(otherName);
}
/**
* Is my name equal to the given array of characters?
*
* @param classRef
* @return boolean
*/
public boolean nameEquals(VmConstClass classRef) {
return name.equals(classRef.getClassName());
}
public final String toString() {
return "_CL_" + Mangler.mangleClassName(getName());
}
/**
* Return the number of fields declared in this class
*
* @return int
*/
public final int getNoDeclaredFields() {
return (fieldTable == null) ? 0 : fieldTable.length;
}
/**
* Return the declared field with a given index (0..getNoFields()-1)
*
* @param index
* @return The field
*/
public final VmField getDeclaredField(int index) {
return fieldTable[index];
}
/**
* Determines if the class or interface represented by this Class object is
* either the same as, or is a superclass or superinterface of, the class or
* interface represented by the specified Class parameter. It returns true
* if so; otherwise it returns false. If this Class object represents a
* primitive type, this method returns true if the specified Class parameter
* is exactly this Class object; otherwise it returns false. Specifically,
* this method tests whether the type represented by the specified Class
* parameter can be converted to the type represented by this Class object
* via an identity conversion or via a widening reference conversion. See
* The Java Language Specification, sections 5.1.1 and 5.1.4, for details.
*
* @param S
* @return boolean
*/
public boolean isAssignableFrom(VmType S) {
final VmType[] superClassesArray = S.superClassesArray;
final int length = superClassesArray.length;
for (int i = 0; i < length; i++) {
if (superClassesArray[i] == this) {
return true;
}
}
return false;
}
/**
* Is this type public.
*
* @return boolean
*/
public final boolean isPublic() {
return Modifier.isPublic(modifiers);
}
/**
* Is this type public.
*
* @return boolean
*/
public final boolean isProtected() {
return Modifier.isProtected(modifiers);
}
/**
* Is this type public.
*
* @return boolean
*/
public final boolean isPrivate() {
return Modifier.isPrivate(modifiers);
}
/**
* Is this type public.
*
* @return boolean
*/
public final boolean isStatic() {
return Modifier.isStatic(modifiers);
}
/**
* Does this type have shared statics.
*
* @return boolean
*/
public final boolean isSharedStatics() {
return ((pragmaFlags & TypePragmaFlags.SHAREDSTATICS) != 0);
}
/**
* Does this type have magic permission.
*
* @return boolean
*/
public final boolean isMagicPermissionGranted() {
return ((pragmaFlags & TypePragmaFlags.MAGIC_PERMISSION) != 0);
}
/**
* Is this type public.
*
* @return boolean
*/
public final boolean isFinal() {
return Modifier.isFinal(modifiers);
}
/**
* Is this type an enum class.
*
* @return boolean
*/
public final boolean isEnum() {
return Modifier.isEnum(modifiers);
}
/**
* Is this type an annotation class.
*
* @return boolean
*/
public final boolean isAnnotation() {
return Modifier.isAnnotation(modifiers);
}
/**
* Is this type a synthetic class.
*
* @return boolean
*/
public final boolean isSynthetic() {
return Modifier.isSynthetic(modifiers);
}
/**
* Is this type an interface.
*
* @return boolean
*/
public final boolean isInterface() {
return Modifier.isInterface(modifiers);
}
/**
* Is this type abstract.
*
* @return boolean
*/
public final boolean isAbstract() {
return Modifier.isAbstract(modifiers);
}
/**
* Is this type a magic type.
*
* @return boolean
*/
public final boolean isMagicType() {
return Modifier.isMagic(modifiers);
}
/**
* Is this type loaded.
*
* @return boolean
*/
@Inline
final boolean isLoaded() {
return ((state & VmTypeState.ST_LOADED) != 0);
}
/**
* Is this type invalid.
*
* @return boolean
*/
@Inline
public final boolean isInvalid() {
return ((state & VmTypeState.ST_INVALID) != 0);
}
/**
* Is this type verifying.
*
* @return boolean
*/
public final boolean isVerifying() {
return ((state & VmTypeState.ST_VERIFYING) != 0);
}
/**
* Is this type verified.
*
* @return boolean
*/
@Inline
public final boolean isVerified() {
return ((state & VmTypeState.ST_VERIFIED) != 0);
}
/**
* Is this type preparing.
*
* @return boolean
*/
private final boolean isPreparing() {
return ((state & VmTypeState.ST_PREPARING) != 0);
}
/**
* Is this type prepared.
*
* @return boolean
*/
@Inline
final boolean isPrepared() {
return ((state & VmTypeState.ST_PREPARED) != 0);
}
/**
* Is this type compiling.
*
* @return boolean
*/
final boolean isCompiling() {
return ((state & VmTypeState.ST_COMPILING) != 0);
}
/**
* Is this type compiled.
*
* @return boolean
*/
@Inline
public final boolean isCompiled() {
return ((state & VmTypeState.ST_COMPILED) != 0);
}
/**
* Gets the isolated state of this type.
*/
@Inline
private final int getIsolatedState() {
if (VmMagic.isRunningJNode()) {
return VmMagic.getIsolatedStaticFieldAddress(isolatedStaticsIndex)
.loadInt();
} else {
return loader.getIsolatedStatics().getInt(isolatedStaticsIndex);
}
}
/**
* Add a bit to the isolated state of this type.
*/
@Inline
private final void addIsolatedState(int value) {
if (VmMagic.isRunningJNode()) {
final Address ptr = VmMagic
.getIsolatedStaticFieldAddress(isolatedStaticsIndex);
ptr.store(ptr.loadInt() | value);
} else {
final VmIsolatedStatics statics;
final int index = isolatedStaticsIndex;
statics = loader.getIsolatedStatics();
statics.setInt(index, statics.getInt(index) | value);
}
}
/**
* Is this type initializing.
*
* @return boolean
*/
@Inline
final boolean isInitializing() {
if (isSharedStatics()) {
return ((state & VmTypeState.SST_INITIALIZING) != 0);
} else {
return ((getIsolatedState() & VmTypeState.IST_INITIALIZING) != 0);
}
}
/**
* Is this type initialized.
*
* @return boolean
*/
@Inline
public final boolean isInitialized() {
return ((state & (VmTypeState.ST_ALWAYS_INITIALIZED | VmTypeState.SST_INITIALIZED)) != 0)
|| ((getIsolatedState() & VmTypeState.IST_INITIALIZED) != 0);
}
/**
* Is this type always initialized in every isolate.
*
* @return boolean
*/
@Inline
public final boolean isAlwaysInitialized() {
return ((state & (VmTypeState.ST_ALWAYS_INITIALIZED)) != 0);
}
/**
* Mark this type always initialized.
* Can only be called during bootstrapping.
*/
public final void setAlwaysInitialized() {
VmUtils._assert(!VmUtils.isRunningVm());
state |= VmTypeState.ST_ALWAYS_INITIALIZED;
}
/**
* Is this type linked.
*
* @return boolean
*/
@Inline
final boolean isLinked() {
return ((state & VmTypeState.ST_LINKED) != 0);
}
/**
* Is this type an array.
*
* @return boolean
*/
public boolean isArray() {
return false;
}
/**
* Is this class an array of primitive types
*
* @return boolean
*/
public boolean isPrimitiveArray() {
return false;
}
/**
* Does this class have a finalize method other then in java.lang.Object.
*
* @return boolean
*/
public final boolean hasFinalizer() {
return ((modifiers & Modifier.ACC_FINALIZER) != 0);
}
/**
* Gets the finalize method of this class.
*/
public final VmMethod getFinalizeMethod() {
return finalizeMethod;
}
/**
* Get the number of interfaces implemented by this class, or its
* super-classes.
*
* @return int
*/
public final int getNoInterfaces() {
return (allInterfaceTable == null) ? 0 : allInterfaceTable.length;
}
/**
* Get on of the list of interfaces implemented by this class, or its
* super-classes.
*
* @param index
* @return class
*/
public final VmInterfaceClass<?> getInterface(int index) {
return allInterfaceTable[index];
}
/**
* Get the number of implementing interfaces declared in this class
*
* @return int
*/
public final int getNoDeclaredInterfaces() {
return (interfaceTable == null) ? 0 : interfaceTable.length;
}
/**
* Get the number of methods declared in this class
*
* @return int
*/
public final int getNoDeclaredMethods() {
return (methodTable == null) ? 0 : methodTable.length;
}
/**
* Return the declared method with a given index (0..getNoMethods()-1)
*
* @param index
* @return The method
*/
public final VmMethod getDeclaredMethod(int index) {
return methodTable[index];
}
/**
* Gets the index of the given method within this class.
*
* @param method
* @return The index of the given method within this class or -1 if not
* found.
*/
public final int indexOf(VmMethod method) {
final int max = getNoDeclaredMethods();
for (int i = 0; i < max; i++) {
if (methodTable[i] == method) {
return i;
}
}
return -1;
}
/**
* Return the constants pool of this class
*
* @return The constant pool
*/
public final VmCP getCP() {
return cp;
}
/**
* Return the loader of this class
*
* @return The loader
*/
public final VmClassLoader getLoader() {
return loader;
}
/**
* Return the accessflags of this class
*
* @return The modifiers
*/
public final int getAccessFlags() {
return modifiers;
}
/**
* Find the field within the given class that has the given name and
* signature.
*
* @param name
* @param signature
* @return The field
*/
public final VmField getDeclaredField(String name, String signature) {
if (fieldTable != null) {
int count = fieldTable.length;
for (int i = 0; i < count; i++) {
VmField fs = fieldTable[i];
if (fs.nameEquals(name)) {
if ((signature == null) || fs.signatureEquals(signature)) {
return fs;
}
}
}
}
return null;
}
/**
* Find the field within the given class that has the given name and
* signature.
*
* @param name
* @return The field
*/
public final VmField getDeclaredField(String name) {
return getDeclaredField(name, null);
}
/**
* Find the field within the given class (or super-classes) that has the
* given name and signature.
*
* @param name
* @param signature
* @return The field
*/
public final VmField getField(String name, String signature) {
VmField f = getDeclaredField(name, signature);
if (f != null) {
return f;
}
if (superClass != null) {
f = superClass.getField(name, signature);
if (f != null) {
return f;
}
}
final int cnt = getNoInterfaces();
for (int i = 0; i < cnt; i++) {
f = allInterfaceTable[i].getField(name, signature);
if (f != null) {
return f;
}
}
return null;
}
/**
* Find the field within the given class (or super-classes) that has the
* given name.
*
* @param name
* @return The field
*/
public final VmField getField(String name) {
return getField(name, null);
}
/**
* Find the field within the given class (or super-classes) that matches the
* given fieldRef.
*
* @param fieldRef
* @return The field
*/
public final VmField getField(VmConstFieldRef fieldRef) {
return getField(fieldRef.getName(), fieldRef.getSignature());
}
/**
* Find the method within the given class (or super-classes) that has the
* given name and signature.
*
* @param name
* @param signature
* @param onlyThisClass
* @param searchInterfaces
* @param hashCode
* @return The method
*/
final VmMethod getMethod(String name, String signature,
boolean onlyThisClass, boolean searchInterfaces, int hashCode) {
/* Search in my own method table */
final VmMethod[] mt = this.methodTable;
if (mt != null) {
final int count = mt.length;
for (int i = 0; i < count; i++) {
final VmMethod mts = mt[i];
/**
* Use the hascode as first match, to make this as fast as
* possible
*/
int mtsHashCode = mts.getMemberHashCode();
if (mtsHashCode == hashCode) {
if (mts.nameEquals(name) && mts.signatureEquals(signature)) {
return mts;
}
} else if (mtsHashCode > hashCode) {
/**
* The methods are sorted on hashcode, so we can stop
* searching here
*/
break;
}
}
}
// Is it a synthetic abstract method?
if (isAbstract()) {
final VmMethod method = getSyntheticAbstractMethod(name, signature,
hashCode);
if (method != null) {
return method;
}
}
// Look in the superclass
if ((superClass != null) && (!onlyThisClass)) {
final VmMethod method = superClass.getMethod(name, signature,
false, false, hashCode);
if (method != null) {
return method;
}
}
// Look in the super interfaces
if (isInterface() || searchInterfaces) {
final VmInterfaceClass[] ait = allInterfaceTable;
if (ait != null) {
final int count = ait.length;
for (int i = 0; i < count; i++) {
final VmInterfaceClass intf = ait[i];
final VmMethod method = intf.getMethod(name, signature,
true, false, hashCode);
if (method != null) {
return method;
}
}
}
}
// Not found
return null;
}
/**
* Search for an synthetic abstract class, that is not in this class, but is
* a method of one of the implemented interfaces. Synthetic abstract methods
* are added when the VMT is created.
*
* @param name
* @param signature
* @param hashCode
* @return The method
*/
protected abstract VmMethod getSyntheticAbstractMethod(String name,
String signature, int hashCode);
final VmMethod getNativeMethodReplacement(String name, String signature) {
signature = signature.substring(0, signature.indexOf(')'));
/* Search only in my own method table */
final VmMethod[] mt = this.methodTable;
if (mt != null) {
final int count = mt.length;
for (int i = 0; i < count; i++) {
final VmMethod mts = mt[i];
if (mts.nameEquals(name)) {
String sig2 = mts.getSignature();
if (signature.equals(sig2.substring(0, sig2.indexOf(')')))) {
return mts;
}
}
}
}
return null;
}
/**
* Find the method within the given class (or super-classes) that has the
* given name and list of argument types.
*
* @param name
* @param argTypes
* @param declaredOnly
* @return The method
*/
final VmMethod getMethod(String name, VmType[] argTypes,
boolean declaredOnly) {
VmType other = this;
while (true) {
/* Search in my own method table */
final VmMethod[] mt = other.methodTable;
if (mt != null) {
final int count = mt.length;
for (int i = 0; i < count; i++) {
final VmMethod mts = mt[i];
if (mts.nameEquals(name)) {
if (mts.matchArgumentTypes(argTypes)) {
return mts;
}
}
}
}
if (other.isInterface() && (!declaredOnly)) {
// Look in the super interfaces
final VmImplementedInterface[] it = other.interfaceTable;
if (it != null) {
int count = it.length;
for (int i = 0; i < count; i++) {
VmImplementedInterface intf = it[i];
VmMethod method = intf.getResolvedVmClass().getMethod(name,
argTypes, false);
if (method != null) {
return method;
}
}
}
}
if ((other.superClass != null) && (!declaredOnly)) {
// Look in the superclass
declaredOnly = false;
other = other.superClass;
continue;
}
// Not found
return null;
}
}
/**
* Find the method within the given class that has the given name and list
* of argument types.
*
* @param name
* @param argTypes
* @return The method
*/
public final VmMethod getDeclaredMethod(String name, VmType[] argTypes) {
return getMethod(name, argTypes, true);
}
/**
* Find the method within the given class and its super-classes that has the
* given name and list of argument types.
*
* @param name
* @param argTypes
* @return The method
*/
public final VmMethod getMethod(String name, VmType[] argTypes) {
return getMethod(name, argTypes, false);
}
/**
* Find the method within the given class (or super-classes) that has the
* given name and signature.
*
* @param name
* @param signature
* @param onlyThisClass
* @param searchInterfaces
* @return The method
*/
private final VmMethod getMethod(String name, String signature,
boolean onlyThisClass, boolean searchInterfaces) {
return getMethod(name, signature, onlyThisClass, searchInterfaces,
VmMember.calcHashCode(name, signature));
}
/**
* Find the method within this class that has the given name and signature.
*
* @param name
* @param signature
* @return The method
*/
public final VmMethod getDeclaredMethod(String name, String signature) {
return getMethod(name, signature, true, false, VmMember.calcHashCode(
name, signature));
}
/**
* Find the method within the given class (or super-classes) that has the
* given name and signature.
*
* @param name
* @param signature
* @return The method
*/
public final VmMethod getMethod(String name, String signature) {
return getMethod(name, signature, false, true, VmMember.calcHashCode(
name, signature));
}
/**
* Find the method within the given class (or super-classes) that matches
* the given methodRef.
*
* @param methodRef
* @return The method
*/
public final VmMethod getMethod(VmConstMethodRef methodRef) {
return getMethod(methodRef.getName(), methodRef.getSignature(), false,
true, methodRef.getMemberHashCode());
}
/**
* Do in the following order: Verification, Preparation, Resolution
*
* @return VmClass This class
*/
public final VmType link() {
if (!isLinked()) {
prepare();
verify();
compile();
if (isInvalid()) {
if (errorMsg != null) {
throw new LinkageError(errorMsg);
} else {
throw new LinkageError("Class invalid");
}
}
if (arrayClass != null) {
// arrayClass.link();
}
if (mmType == null) {
VmUtils.notifyClassResolved(this);
}
this.state |= VmTypeState.ST_LINKED;
}
return this;
}
/**
* Prepare this class. This method is not synchronized since it is called
* frequently. A simple test is done to see if the class has already been
* prepared, if not a synchronized helper method is called to do the actual
* prepare.
*/
void prepare() {
if (!isPrepared()) {
doPrepare();
}
}
/**
* Compile this class. This method is not synchronized since it is called
* frequently. A simple test is done to see if the class has already been
* compiled, if not a synchronized helper method is called to do the actual
* compile.
*/
void compile() {
if (!isCompiled()) {
doCompile();
}
}
/**
* Verify this class. This method is not synchronized since it is called
* frequently. A simple test is done to see if the class has already been
* verfied, if not a synchronized helper method is called to do the actual
* verify.
*/
void verify() {
if (!isVerified()) {
doVerify();
}
}
/**
* Prepare this class. The following steps will be taken.
* <ul>
* <li>Load the super class (if any)
* <li>Load the implemented interface classes (if any)
* <li>Calculate the object size
* <li>Fix the offset for all declared non-static fields
* <li>Create the VMT
* </ul>
*/
private synchronized void doPrepare() {
if (isPrepared()) {
return;
}
if (isPreparing()) {
throw new Error("Recursive prepare in " + getName());
}
state |= VmTypeState.ST_PREPARING;
try {
// Step 1a: Load the super class
if ((superClass == null) && (superClassName != null)) {
setSuperClass((VmNormalClass<? super T>) loader.loadClass(
superClassName, false));
}
// Step 1b: Resolve the super class
if (superClass != null) {
superClass.prepare();
superClassDepth = superClass.getSuperClassDepth() + 1;
addPragmaFlags(superClass.getPragmaFlags()
& TypePragmaFlags.INHERITABLE_FLAGS_MASK);
}
/**
* Step 2a: Load the implemented interface classes (if any)
*/
final int cnt = getNoDeclaredInterfaces();
for (int i = 0; i < cnt; i++) {
final VmImplementedInterface intf = interfaceTable[i];
intf.resolve(loader);
}
// Now we're at the DEFINED state
state |= VmTypeState.ST_DEFINED;
} catch (ClassNotFoundException ex) {
state |= VmTypeState.ST_INVALID;
state &= ~VmTypeState.ST_PREPARING;
errorMsg = ex.toString();
throw new NoClassDefFoundError(ex.getMessage() + " in " + getName());
}
// Step 3: Calculate the object size
// Step 4a: Fix the offset for all declared non-static fields
// Step 4b: Create the referenceOffsets field
prepareForInstantiation();
/* Build the allInterfaceTable */
final HashSet<VmInterfaceClass<?>> all = new HashSet<VmInterfaceClass<?>>();
getAllInterfaces(all, this);
this.allInterfaceTable = new VmInterfaceClass[all.size()];
all.toArray(allInterfaceTable);
// Step 5: Create the TIB
final Object[] tib = prepareTIB(all);
/* Build the interface method table */
if (all.size() > 0) {
final IMTBuilder imtBuilder = prepareIMT(all);
if (imtBuilder != null) {
tib[TIBLayout.IMT_INDEX] = imtBuilder.getImt();
tib[TIBLayout.IMTCOLLISIONS_INDEX] = imtBuilder
.getImtCollisions();
final CompiledIMT cimt = loader.compileIMT(imtBuilder);
tib[TIBLayout.COMPILED_IMT_INDEX] = cimt.getIMTAddress();
}
}
// Process uninterruptible
if ((pragmaFlags & TypePragmaFlags.UNINTERRUPTIBLE) != 0) {
final int mCount = getNoDeclaredMethods();
for (int m = 0; m < mCount; m++) {
getDeclaredMethod(m).setUninterruptible();
}
}
/* Build the super classes array */
this.superClassesArray = createSuperClassesArray(all);
if (tib != null) {
tib[TIBLayout.SUPERCLASSES_INDEX] = superClassesArray;
}
/* Is there a finalizer method other then in java.lang.Object? */
if (superClass != null) {
// superClass != null, so we're not in java.lang.Object
finalizeMethod = getMethod("finalize", "()V", true, false);
if (finalizeMethod == null) {
finalizeMethod = superClass.getFinalizeMethod();
}
if (finalizeMethod != null) {
modifiers |= Modifier.ACC_FINALIZER;
}
}
/* If there is no static initializer, this class is initialized */
if (getMethod("<clinit>", "()V", true, false) == null) {
state |= VmTypeState.ST_ALWAYS_INITIALIZED;
}
// Now we're in the PREPARED state
state |= VmTypeState.ST_PREPARED;
state &= ~VmTypeState.ST_PREPARING;
// Notify all threads that are waiting for me
notifyAll();
}
/**
* Compile this type.
*/
private synchronized void doCompile() {
if (isCompiled()) {
return;
}
if (!isCompiling()) {
if (loader.isCompileRequired()) {
state |= VmTypeState.ST_COMPILING;
// BootLogInstance.get().debug("Compiling " + getName());
// Compile the superclass (if any)
if (superClass != null) {
superClass.compile();
}
// Compile the methods with the least optimizing compiler
final int count;
try {
count = doCompileRuntime(0, false);
} catch (Throwable ex) {
state |= VmTypeState.ST_INVALID;
state &= ~VmTypeState.ST_COMPILING;
errorMsg = ex.toString();
final LinkageError le = new LinkageError(
"Failed to compile " + name);
le.initCause(ex);
throw le;
}
final int declared = getNoDeclaredMethods();
if (count != declared) {
errorMsg = "Compiled skipped some methods ("
+ (declared - count);
throw new LinkageError(errorMsg);
}
state &= ~VmTypeState.ST_COMPILING;
notifyAll();
}
}
}
/**
* Verify this type.
*/
private synchronized void doVerify() {
if (isVerified()) {
return;
}
if (isVerifying()) {
throw new Error("Recursive verify in " + getName());
}
state |= VmTypeState.ST_VERIFYING;
// Verify the superclass (if any)
if (superClass != null) {
superClass.verify();
}
// TODO implement verification
state |= VmTypeState.ST_VERIFIED;
state &= ~VmTypeState.ST_VERIFYING;
notifyAll();
}
/**
* Do the prepare action required to instantiate this object
*/
protected abstract void prepareForInstantiation();
/**
* Prepare the virtual method table
*
* @param allInterfaces
* @return The tib
*/
protected abstract Object[] prepareTIB(
HashSet<VmInterfaceClass<?>> allInterfaces);
/**
* Prepare the interface method table
*
* @param allInterfaces
* @return The imt builder
*/
protected abstract IMTBuilder prepareIMT(
HashSet<VmInterfaceClass<?>> allInterfaces);
/**
* Create the super classes array for this type.
*
* @param allInterfaces All interfaces directly or indirectly implemented by this
* class
* @return The super classes array
*/
protected VmType<?>[] createSuperClassesArray(
HashSet<VmInterfaceClass<?>> allInterfaces) {
final int length = superClassDepth + 1 + allInterfaces.size();
final VmType[] array = new VmType[length];
// array[0] = this;
VmType<? super T> superPtr = superClass;
for (int i = 0; i < superClassDepth; i++) {
array[superClassDepth - i - 1] = superPtr;
superPtr = superPtr.getSuperClass();
}
array[superClassDepth] = this;
int index = superClassDepth + 1;
for (VmInterfaceClass intfClass : allInterfaces) {
array[index++] = intfClass;
}
if (false) {
System.out.println("SuperClassesArray for " + getName());
for (int i = 0; i < length; i++) {
System.out.println("[" + i + "]\t" + array[i].getName());
}
}
return array;
}
/**
* Fill the given hashset with all interface implemented by the given type
* C.
*
* @param all A HashSet of VmInterfaceClass instances.
* @param C
*/
private void getAllInterfaces(HashSet<VmInterfaceClass<?>> all,
VmType<?> C) {
while (C != null) {
final VmImplementedInterface[] it = C.interfaceTable;
if (it != null) {
int count = it.length;
for (int i = 0; i < count; i++) {
final VmInterfaceClass ic = it[i].getResolvedVmClass();
if (!all.contains(ic)) {
all.add(ic);
getAllInterfaces(all, ic);
}
}
}
C = C.getSuperClass();
}
}
/**
* Resolve all constant references in the constants pool
*/
public final void resolveCpRefs() {
if (!resolvedCpRefs) {
prepare();
if (superClass != null) {
superClass.resolveCpRefs();
}
/**
* Step 2b: Load the classes of my fields
*/
final int fcnt = getNoDeclaredFields();
for (int i = 0; i < fcnt; i++) {
final VmField fs = fieldTable[i];
fs.resolve();
}
/**
* Step 2c: Load the classes of my methods
*/
final int mcnt = getNoDeclaredMethods();
for (int i = 0; i < mcnt; i++) {
final VmMethod mts = methodTable[i];
mts.resolve();
}
VmCP cp = this.cp;
if (cp != null) {
for (int i = 0; i < cp.getLength(); i++) {
final Object obj = cp.getAny(i);
if (obj instanceof VmResolvableConstObject) {
((VmResolvableConstObject) obj).resolve(loader);
}
}
}
resolvedCpRefs = true;
}
}
public boolean isCpRefsResolved() {
return resolvedCpRefs;
}
/**
* Compile all the methods in this class during bootstrapping.
*
* @param compiler
* @param os
* @param optLevel The optimization level
* @return The number of compiled methods
*/
public final int compileBootstrap(NativeCodeCompiler compiler,
NativeStream os, int optLevel) {
if (!isPrepared()) {
throw new IllegalStateException("VmType must have been prepared");
}
int rc = 0;
if (!isCompiled()) {
final VmMethod[] mt = methodTable;
if (mt != null) {
final int count = mt.length;
for (int i = 0; i < count; i++) {
final VmMethod method = mt[i];
try {
// if (optLevel > method.getNativeCodeOptLevel()) {
compiler.compileBootstrap(method, os, optLevel);
rc++;
// method.setModifier(true, Modifier.ACC_COMPILED);
// }
} catch (Throwable ex) {
throw new CompileError("Compile of " + method
+ " failed", ex);
}
}
}
state |= VmTypeState.ST_COMPILED;
}
if (arrayClass != null) {
arrayClass.link();
rc += arrayClass.compileBootstrap(compiler, os, optLevel);
}
return rc;
}
/**
* Compile all the methods in this class during runtime.
*
* @param optLevel The optimization level
* @return The number of compiled methods
*/
public final int compileRuntime(int optLevel, boolean enableTestCompilers) {
if (!isPrepared()) {
throw new IllegalStateException("VmType must have been prepared");
}
return doCompileRuntime(optLevel, enableTestCompilers);
}
/**
* Compile all the methods in this class during runtime.
*
* @param optLevel The optimization level
* @return The number of compiled methods
*/
private final int doCompileRuntime(int optLevel, boolean enableTestCompilers) {
final VmMethod[] mt = this.methodTable;
int compileCount = 0;
if (mt != null) {
final int count = mt.length;
int level = optLevel;
if (enableTestCompilers) {
//should match the strategy in LoadCompileService.doCompile()
level += LoadCompileService.getHighestOptimizationLevel(false) + 1;
}
for (int i = 0; i < count; i++) {
final VmMethod method = mt[i];
if (level > method.getNativeCodeOptLevel()) {
LoadCompileService.compile(method, optLevel, enableTestCompilers);
// method.setModifier(true, Modifier.ACC_COMPILED);
compileCount++;
}
}
}
this.state |= VmTypeState.ST_COMPILED;
return compileCount;
}
public final int disassemble(String methodName, int optLevel,
boolean enableTestCompilers, Writer writer) {
if (!isPrepared()) {
throw new IllegalStateException("VmType must have been prepared");
}
return doDisassemble(methodName, optLevel, enableTestCompilers, writer);
}
private final int doDisassemble(String methodName, int optLevel,
boolean enableTestCompilers, Writer writer) {
final VmMethod[] mt = this.methodTable;
int disasmCount = 0;
if (mt != null) {
final int count = mt.length;
for (int i = 0; i < count; i++) {
final VmMethod method = mt[i];
if (methodName == null || methodName.trim().isEmpty()) {
loader.disassemble(method, optLevel, enableTestCompilers,
writer);
disasmCount++;
} else if (method.getName().equals(methodName)) {
loader.disassemble(method, optLevel, enableTestCompilers,
writer);
disasmCount++;
}
}
}
return disasmCount;
}
/**
* Sets the superClass.
*
* @param superClass The superClass to set
*/
protected void setSuperClass(VmNormalClass<? super T> superClass) {
if (superClass == null) {
throw new IllegalArgumentException("superClass cannot be null");
}
if (this.superClass == null) {
this.superClass = superClass;
} else {
throw new IllegalArgumentException("Cannot overwrite superClass");
}
}
/**
* Sets the mTable.
*
* @param methodTable The method table to set
*/
protected final void setMethodTable(VmMethod[] methodTable) {
if (this.methodTable == null) {
this.methodTable = methodTable;
Arrays.sort(methodTable, new MethodComparator());
} else {
throw new IllegalArgumentException("Cannot overwrite method table");
}
}
/**
* Sets the fieldTable.
*
* @param fieldTable The fieldTable to set
*/
protected void setFieldTable(VmField[] fieldTable) {
if (this.fieldTable == null) {
this.fieldTable = fieldTable;
} else {
throw new IllegalArgumentException("Cannot overwrite field table");
}
}
/**
* Sets the interfaceTable.
*
* @param interfaceTable The interfaceTable to set
*/
protected final void setInterfaceTable(
VmImplementedInterface[] interfaceTable) {
if (this.interfaceTable == null) {
this.interfaceTable = interfaceTable;
} else {
throw new IllegalArgumentException(
"Cannot overwrite interface table");
}
}
/**
* Sets the cp.
*
* @param cp The cp to set
*/
protected void setCp(VmCP cp) {
if (this.cp == null) {
this.cp = cp;
} else {
throw new IllegalArgumentException("Cannot overwrite constant pool");
}
}
/**
* Is this class a primitive type?
*
* @return boolean
*/
public boolean isPrimitive() {
return false;
}
/**
* Is this class a reference type. A reference type is an array of a
* non-primitive class.
*
* @return boolean
*/
public final boolean isReferenceType() {
return (!isPrimitive() || isArray());
}
/**
* Verify this object before it is written into the bootimage by the
* bootimage builder.
*
* @see org.jnode.vm.objects.VmSystemObject#verifyBeforeEmit()
*/
public void verifyBeforeEmit() {
super.verifyBeforeEmit();
VmMethod clinit = getInitializerMethod();
if (clinit == null) {
state |= VmTypeState.ST_ALWAYS_INITIALIZED;
}
}
/**
* Invoke the static initializer of this class. This method is not
* synchronized since it is called frequently. A simple test is done to see
* if the class has already been initialized, if not a synchronized helper
* method is called to do the actual initialization.
*/
@Inline
public final void initialize() {
if (!isInitialized() && !isInitializing()) {
linkAndInitialize();
}
}
/**
* Link and initialize this type. This is a seperate method in order to
* control the inlining path of the native code compiler.
*/
@NoInline
private final void linkAndInitialize() {
link();
if ((superClass != null) && !isArray()) {
/* The direct super-class must be initialized first $2.17.4 */
superClass.initialize();
}
doInitialize();
}
/**
* Invoke the static initializer of this class.
*/
private synchronized void doInitialize() {
if (!isInitialized()) {
if (!isInitializing()) {
final boolean sharedStatics = isSharedStatics();
if (sharedStatics) {
state |= VmTypeState.SST_INITIALIZING;
} else {
addIsolatedState(VmTypeState.IST_INITIALIZING);
}
/*
* Screen.debug("initialize("); Screen.debug(name);
*/
final VmMethod initMethod = getInitializerMethod();
if (initMethod != null) {
try {
VmReflection.invokeStatic(initMethod);
} catch (InvocationTargetException ex) {
final Throwable targetEx = ex.getTargetException();
if (targetEx != null) {
ex.getTargetException().printStackTrace();
// Unsafe.die("VmType.doInitialize");
throw new ExceptionInInitializerError(ex
.getTargetException());
} else {
throw new ExceptionInInitializerError(
"targetEx == null");
}
}
}
if (sharedStatics) {
state |= VmTypeState.SST_INITIALIZED;
} else {
addIsolatedState(VmTypeState.IST_INITIALIZED);
}
}
}
}
/**
* Gets the <clinit>method or null if no <clinit>method was found in this
* class.
*
* @return VmMethod
*/
private VmMethod getInitializerMethod() {
final VmMethod[] mt = this.methodTable;
if (mt != null) {
int count = mt.length;
for (int i = 0; i < count; i++) {
VmMethod m = mt[i];
if (m.isInitializer()) {
return m;
}
}
}
return null;
}
/**
* @return String
* @see org.jnode.vm.objects.VmSystemObject#getExtraInfo()
*/
public String getExtraInfo() {
return "Modifiers: " + Modifier.toString(modifiers);
}
public static class MethodComparator implements Comparator<VmMethod> {
/**
* @param o1
* @param o2
* @return int
* @see java.util.Comparator#compare(java.lang.Object, java.lang.Object)
*/
public int compare(VmMethod o1, VmMethod o2) {
final int m1 = o1.getMemberHashCode();
final int m2 = o2.getMemberHashCode();
if (m1 < m2) {
return -1;
} else if (m1 > m2) {
return 1;
} else {
return 0;
}
}
/**
* @param obj
* @return boolean
* @see java.lang.Object#equals(java.lang.Object)
*/
public boolean equals(Object obj) {
return (obj instanceof MethodComparator);
}
}
/**
* Gets the number of super classes until (and including) Object. E.g. this
* is 0 for Object and 1 for an interface.
*
* @return int
*/
public final int getSuperClassDepth() {
return superClassDepth;
}
/**
* Gets the super classes array of this type
*
* @return The super classes array
*/
protected final VmType[] getSuperClassesArray() {
return superClassesArray;
}
/**
* Gets the index of this type in the shared statics table.
*
* @return Returns the staticsIndex.
*/
public final int getSharedStaticsIndex() {
return this.staticsIndex;
}
/**
* Gets the protection domain of this type.
*
* @return the protection domain of this type.
*/
public final ProtectionDomain getProtectionDomain() {
return protectionDomain;
}
/**
* Gets the {@link JvmType} value for this type.
*
* @return the {@link JvmType} value (integer).
*/
public int getJvmType() {
return JvmType.REFERENCE;
}
/**
* Gets the type information required and managed by the memory manager.
*
* @return Returns the mmType.
*/
public final Object getMmType() {
return mmType;
}
/**
* Sets the type information required and managed by the memory manager.
*
* @param mmType The mmType to set.
*/
public final void setMmType(Object mmType) {
if (this.mmType != null) {
Unsafe.debug("Cannot override mmType\n");
} else {
this.mmType = mmType;
}
}
/**
* @see org.jnode.vm.classmgr.VmAnnotatedElement#getSuperElement()
*/
@Override
protected final VmAnnotatedElement getSuperElement() {
return superClass;
}
/**
* Add the given pragma flags to my flags.
*/
final void addPragmaFlags(int flags) {
this.pragmaFlags |= flags;
}
/**
* Gets the pragma flags of this type.
*/
final char getPragmaFlags() {
return this.pragmaFlags;
}
public String getSourceFile() {
return sourceFile;
}
public void setSourceFile(String sourceFile) {
this.sourceFile = sourceFile;
}
public String getSignature() {
return signature;
}
public void setSignature(String signature) {
this.signature = signature;
}
/**
* Index of the isolated type state. This refers to an int entry.
*
* @see org.jnode.vm.classmgr.VmIsolatedStaticsEntry#getIsolatedStaticsIndex()
*/
public final int getIsolatedStaticsIndex() {
return isolatedStaticsIndex;
}
/**
* Permission used in {@link #fromClass(Class)}
*/
private static final JNodePermission GETVMCLASS = new JNodePermission("getVmClass");
private static int FIELD_OFFSET = -1;
public static <V> VmType<V> fromClass(Class<V> clazz) {
if (FIELD_OFFSET == -1) {
FIELD_OFFSET = ((VmInstanceField) ClassClass.getDeclaredField("vmClass")).getOffset();
}
// final SecurityManager sm = System.getSecurityManager();
// if (sm != null) { //todo: misplaced securty check -> stack overflow in gnu.testlet.
// //todo: TestSecurityManager.checkPermission
//todo secure this method
// sm.checkPermission(GETVMCLASS);
// }
return (VmType<V>) ObjectReference.fromObject(clazz).toAddress().add(FIELD_OFFSET).
loadObjectReference().toObject();
}
public Class newClass() {
return new Class(this);
}
}