Mercurial > hg > graal-compiler
diff graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotResolvedObjectType.java @ 7084:9ba90252ce08
HotSpotResolvedJavaType is now the HotSpot implementation of ResolvedJavaType,
Renamed old HotSpotResolvedJavaType to HotSpotResolvedObjectType
Renamed HotSpotTypePrimitive to HotSpotResolvedPrimitiveType
Renamed HotSpotTypeUnresolved to HotSpotUnresolvedJavaType
author | Gilles Duboscq <duboscq@ssw.jku.at> |
---|---|
date | Wed, 28 Nov 2012 14:07:25 +0100 |
parents | graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotResolvedJavaType.java@fa3c8913d674 |
children | 4c0d132dca4d |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotResolvedObjectType.java Wed Nov 28 14:07:25 2012 +0100 @@ -0,0 +1,500 @@ +/* + * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code 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 General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package com.oracle.graal.hotspot.meta; + +import static com.oracle.graal.api.meta.MetaUtil.*; +import static com.oracle.graal.graph.FieldIntrospection.*; +import static com.oracle.graal.hotspot.HotSpotGraalRuntime.*; +import static java.lang.reflect.Modifier.*; + +import java.lang.annotation.*; +import java.lang.reflect.*; +import java.util.*; + +import com.oracle.graal.api.meta.*; +import com.oracle.graal.hotspot.*; + +/** + * Implementation of {@link JavaType} for resolved non-primitive HotSpot classes. + */ +public final class HotSpotResolvedObjectType extends HotSpotResolvedJavaType { + + private static final long serialVersionUID = 3481514353553840471L; + + /** + * Value for the {@code sizeOrSpecies} parameter in {@link HotSpotResolvedObjectType#HotSpotResolvedObjectType} + * denoting that the new type represents an interface class. + */ + public static final int INTERFACE_SPECIES_VALUE = Integer.MIN_VALUE; + + /** + * Value for the {@code sizeOrSpecies} parameter in {@link HotSpotResolvedObjectType#HotSpotResolvedObjectType} + * denoting that the new type represents an array class. + */ + public static final int ARRAY_SPECIES_VALUE = Integer.MAX_VALUE; + + /** + * Reference to the metaspace Klass object. + */ + private final long metaspaceKlass; + + private final Class<?> javaMirror; // this could be read directly from 'metaspaceKlass'... + private final String simpleName; + private final boolean hasFinalizableSubclass; + + /** + * The instance size for an instance type, {@link HotSpotResolvedObjectType#INTERFACE_SPECIES_VALUE} denoting + * an interface type or {@link HotSpotResolvedObjectType#ARRAY_SPECIES_VALUE} denoting an array type. + */ + private final int sizeOrSpecies; + + private HashMap<Long, ResolvedJavaField> fieldCache; + private HashMap<Long, HotSpotResolvedJavaMethod> methodCache; + private HotSpotResolvedJavaField[] instanceFields; + private ResolvedJavaType[] interfaces; + private ConstantPool constantPool; + private boolean isInitialized; + private ResolvedJavaType arrayOfType; + + /** + * Gets the Graal mirror from a HotSpot metaspace Klass native object. + * + * @param metaspaceKlass a metaspace Klass object boxed in a {@link Constant} + * @return the {@link ResolvedJavaType} corresponding to {@code klassConstant} + */ + public static ResolvedJavaType fromMetaspaceKlass(Constant metaspaceKlass) { + assert metaspaceKlass.getKind().isLong(); + return fromMetaspaceKlass(metaspaceKlass.asLong()); + } + + /** + * Gets the Graal mirror from a HotSpot metaspace Klass native object. + * + * @param metaspaceKlass a metaspace Klass object + * @return the {@link ResolvedJavaType} corresponding to {@code metaspaceKlass} + */ + public static ResolvedJavaType fromMetaspaceKlass(long metaspaceKlass) { + assert metaspaceKlass != 0; + Class javaClass = (Class) unsafe.getObject(null, metaspaceKlass + HotSpotGraalRuntime.getInstance().getConfig().classMirrorOffset); + assert javaClass != null; + return fromClass(javaClass); + } + + /** + * Gets the Graal mirror from a {@link Class} object. + * + * @return the {@link HotSpotResolvedObjectType} corresponding to {@code javaClass} + */ + public static ResolvedJavaType fromClass(Class javaClass) { + ResolvedJavaType type = (ResolvedJavaType) unsafe.getObject(javaClass, (long) HotSpotGraalRuntime.getInstance().getConfig().graalMirrorInClassOffset); + if (type == null) { + type = HotSpotGraalRuntime.getInstance().getCompilerToVM().getResolvedType(javaClass); + assert type != null; + } + return type; + } + + /** + * @param hasFinalizableSubclass + * @param sizeOrSpecies the size of an instance of the type, or {@link HotSpotResolvedObjectType#INTERFACE_SPECIES_VALUE} or {@link HotSpotResolvedObjectType#ARRAY_SPECIES_VALUE} + */ + public HotSpotResolvedObjectType(long metaspaceKlass, + String name, + String simpleName, + Class javaMirror, + boolean hasFinalizableSubclass, + int sizeOrSpecies) { + super(name); + this.metaspaceKlass = metaspaceKlass; + this.javaMirror = javaMirror; + this.simpleName = simpleName; + this.hasFinalizableSubclass = hasFinalizableSubclass; + this.sizeOrSpecies = sizeOrSpecies; + assert name.charAt(0) != '[' || sizeOrSpecies == ARRAY_SPECIES_VALUE : name + " " + Long.toHexString(sizeOrSpecies); + assert javaMirror.isArray() == isArray(); + assert javaMirror.isInterface() == isInterface(); + //System.out.println("0x" + Long.toHexString(metaspaceKlass) + ": " + name); + } + + @Override + public int getModifiers() { + return javaMirror.getModifiers(); + } + + public int getAccessFlags() { + HotSpotVMConfig config = HotSpotGraalRuntime.getInstance().getConfig(); + return unsafe.getInt(null, metaspaceKlass + config.klassAccessFlagsOffset); + } + + @Override + public ResolvedJavaType getArrayClass() { + if (arrayOfType == null) { + arrayOfType = fromClass(Array.newInstance(javaMirror, 0).getClass()); + } + return arrayOfType; + } + + @Override + public ResolvedJavaType getComponentType() { + Class javaComponentType = javaMirror.getComponentType(); + return javaComponentType == null ? null : fromClass(javaComponentType); + } + + private static boolean hasSubtype(ResolvedJavaType type) { + assert !type.isArray() : type; + if (type.isPrimitive()) { + return false; + } + HotSpotVMConfig config = HotSpotGraalRuntime.getInstance().getConfig(); + if (unsafeReadWord(((HotSpotResolvedObjectType) type).metaspaceKlass + config.subklassOffset) != 0) { + return true; + } + return false; + } + + @Override + public ResolvedJavaType findUniqueConcreteSubtype() { + HotSpotVMConfig config = HotSpotGraalRuntime.getInstance().getConfig(); + if (isArray()) { + if (hasSubtype(getElementalType(this))) { + return null; + } + return this; + } else { + HotSpotResolvedObjectType type = this; + while (isAbstract(type.getModifiers())) { + long subklass = unsafeReadWord(type.metaspaceKlass + config.subklassOffset); + if (subklass == 0 || unsafeReadWord(subklass + config.nextSiblingOffset) != 0) { + return null; + } + type = (HotSpotResolvedObjectType) fromMetaspaceKlass(subklass); + } + if (unsafeReadWord(type.metaspaceKlass + config.subklassOffset) != 0) { + return null; + } + return type; + } + } + + @Override + public HotSpotResolvedObjectType getSuperclass() { + Class javaSuperclass = javaMirror.getSuperclass(); + return javaSuperclass == null ? null : (HotSpotResolvedObjectType) fromClass(javaSuperclass); + } + + @Override + public ResolvedJavaType[] getInterfaces() { + if (interfaces == null) { + Class[] javaInterfaces = javaMirror.getInterfaces(); + ResolvedJavaType[] result = new ResolvedJavaType[javaInterfaces.length]; + for (int i = 0; i < javaInterfaces.length; i++) { + result[i] = fromClass(javaInterfaces[i]); + } + interfaces = result; + } + return interfaces; + } + + public HotSpotResolvedObjectType getSupertype() { + if (isArray()) { + ResolvedJavaType componentType = getComponentType(); + if (javaMirror == Object[].class || componentType.isPrimitive()) { + return (HotSpotResolvedObjectType) fromClass(Object.class); + } + return (HotSpotResolvedObjectType) ((HotSpotResolvedObjectType) componentType).getSupertype().getArrayClass(); + } + if (isInterface()) { + return (HotSpotResolvedObjectType) fromClass(Object.class); + } + return getSuperclass(); + } + + @Override + public ResolvedJavaType findLeastCommonAncestor(ResolvedJavaType otherType) { + if (otherType.isPrimitive()) { + return null; + } else { + HotSpotResolvedObjectType t1 = this; + HotSpotResolvedObjectType t2 = (HotSpotResolvedObjectType) otherType; + while (true) { + if (t2.isAssignableTo(t1)) { + return t1; + } + if (t1.isAssignableTo(t2)) { + return t2; + } + t1 = t1.getSupertype(); + t2 = t2.getSupertype(); + } + } + } + + @Override + public ResolvedJavaType asExactType() { + if (isArray()) { + return getComponentType().asExactType() != null ? this : null; + } + return Modifier.isFinal(getModifiers()) ? this : null; + } + + @Override + public Constant getEncoding(Representation r) { + switch (r) { + case JavaClass: + return Constant.forObject(javaMirror); + case ObjectHub: + return klass(); + case StaticPrimitiveFields: + case StaticObjectFields: + return Constant.forObject(javaMirror); + default: + assert false : "Should not reach here."; + return null; + } + } + + @Override + public boolean hasFinalizableSubclass() { + return hasFinalizableSubclass; + } + + @Override + public boolean hasFinalizer() { + HotSpotVMConfig config = HotSpotGraalRuntime.getInstance().getConfig(); + return (getAccessFlags() & config.klassHasFinalizerFlag) != 0; + } + + @Override + public boolean isPrimitive() { + return false; + } + + @Override + public boolean isArray() { + return sizeOrSpecies == ARRAY_SPECIES_VALUE; + } + + @Override + public boolean isInitialized() { + if (!isInitialized) { + isInitialized = HotSpotGraalRuntime.getInstance().getCompilerToVM().isTypeInitialized(this); + } + return isInitialized; + } + + @Override + public void initialize() { + if (!isInitialized) { + HotSpotGraalRuntime.getInstance().getCompilerToVM().initializeType(this); + } + isInitialized = true; + } + + @Override + public boolean isInstance(Constant obj) { + if (obj.getKind().isObject() && !obj.isNull()) { + return javaMirror.isInstance(obj.asObject()); + } + return false; + } + + @Override + public boolean isInstanceClass() { + return !isArray() && !isInterface(); + } + + @Override + public boolean isInterface() { + return sizeOrSpecies == INTERFACE_SPECIES_VALUE; + } + + @Override + public boolean isAssignableTo(ResolvedJavaType other) { + if (other instanceof HotSpotResolvedObjectType) { + HotSpotResolvedObjectType otherType = (HotSpotResolvedObjectType) other; + return otherType.javaMirror.isAssignableFrom(javaMirror); + } + return false; + } + + @Override + public Kind getKind() { + return Kind.Object; + } + + @Override + public ResolvedJavaMethod resolveMethod(ResolvedJavaMethod method) { + assert method instanceof HotSpotMethod; + return (ResolvedJavaMethod) HotSpotGraalRuntime.getInstance().getCompilerToVM().resolveMethod(this, method.getName(), ((HotSpotSignature) method.getSignature()).asString()); + } + + @Override + public String toString() { + return "HotSpotType<" + simpleName + ", resolved>"; + } + + public ConstantPool constantPool() { + if (constantPool == null) { + constantPool = new HotSpotConstantPool(this); + } + return constantPool; + } + + /** + * Gets the instance size of this type. If an instance of this type cannot + * be fast path allocated, then the returned value is negative (its absolute + * value gives the size). Must not be called if this is an array or interface type. + */ + public int instanceSize() { + assert !isArray(); + assert !isInterface(); + return sizeOrSpecies; + } + + public synchronized HotSpotResolvedJavaMethod createMethod(long metaspaceMethod) { + HotSpotResolvedJavaMethod method = null; + if (methodCache == null) { + methodCache = new HashMap<>(8); + } else { + method = methodCache.get(metaspaceMethod); + } + if (method == null) { + method = new HotSpotResolvedJavaMethod(this, metaspaceMethod); + methodCache.put(metaspaceMethod, method); + } + return method; + } + + public synchronized ResolvedJavaField createField(String fieldName, JavaType type, int offset, int flags, boolean internal) { + ResolvedJavaField result = null; + + long id = offset + ((long) flags << 32); + + // (thomaswue) Must cache the fields, because the local load elimination only works if the objects from two field lookups are identical. + if (fieldCache == null) { + fieldCache = new HashMap<>(8); + } else { + result = fieldCache.get(id); + } + + if (result == null) { + result = new HotSpotResolvedJavaField(this, fieldName, type, offset, flags, internal); + fieldCache.put(id, result); + } else { + assert result.getName().equals(fieldName); + assert result.getModifiers() == (Modifier.fieldModifiers() & flags); + } + + return result; + } + + @Override + public ResolvedJavaMethod findUniqueConcreteMethod(ResolvedJavaMethod method) { + return ((HotSpotResolvedJavaMethod) method).uniqueConcreteMethod(); + } + + @Override + public ResolvedJavaField[] getInstanceFields(boolean includeSuperclasses) { + if (instanceFields == null) { + if (isArray() || isInterface()) { + instanceFields = new HotSpotResolvedJavaField[0]; + } else { + HotSpotResolvedJavaField[] myFields = HotSpotGraalRuntime.getInstance().getCompilerToVM().getInstanceFields(this); + if (javaMirror != Object.class) { + HotSpotResolvedJavaField[] superFields = (HotSpotResolvedJavaField[]) getSuperclass().getInstanceFields(true); + HotSpotResolvedJavaField[] fields = Arrays.copyOf(superFields, superFields.length + myFields.length); + System.arraycopy(myFields, 0, fields, superFields.length, myFields.length); + instanceFields = fields; + } else { + assert myFields.length == 0 : "java.lang.Object has fields!"; + instanceFields = myFields; + } + } + } + if (!includeSuperclasses) { + int myFieldsStart = 0; + while (myFieldsStart < instanceFields.length && instanceFields[myFieldsStart].getDeclaringClass() != this) { + myFieldsStart++; + } + if (myFieldsStart == 0) { + return instanceFields; + } + if (myFieldsStart == instanceFields.length) { + return new HotSpotResolvedJavaField[0]; + } + return Arrays.copyOfRange(instanceFields, myFieldsStart, instanceFields.length); + } + return instanceFields; + } + + @Override + public Class<?> mirror() { + return javaMirror; + } + + @Override + public boolean isClass(Class c) { + return c == javaMirror; + } + + @Override + public <T extends Annotation> T getAnnotation(Class<T> annotationClass) { + return javaMirror.getAnnotation(annotationClass); + } + + @Override + public ResolvedJavaType resolve(ResolvedJavaType accessingClass) { + return this; + } + + /** + * Gets the address of the C++ Klass object for this type. + */ + public Constant klass() { + return new Constant(HotSpotGraalRuntime.getInstance().getTarget().wordKind, metaspaceKlass, this); + } + + public boolean isPrimaryType() { + return HotSpotGraalRuntime.getInstance().getConfig().secondarySuperCacheOffset != superCheckOffset(); + } + + public int superCheckOffset() { + HotSpotVMConfig config = HotSpotGraalRuntime.getInstance().getConfig(); + return unsafe.getInt(null, metaspaceKlass + config.superCheckOffsetOffset); + } + + public long prototypeMarkWord() { + return HotSpotGraalRuntime.getInstance().getCompilerToVM().getPrototypeMarkWord(this); + } + + @Override + public ResolvedJavaField findInstanceFieldWithOffset(long offset) { + ResolvedJavaField[] declaredFields = getInstanceFields(true); + for (ResolvedJavaField field : declaredFields) { + if (((HotSpotResolvedJavaField) field).offset() == offset) { + return field; + } + } + return null; + } +}