# HG changeset patch # User Doug Simon # Date 1405079267 -7200 # Node ID 8853b9304083ad63a03b47e5be3c4943ddba9b5e # Parent 4d7a9829315ef289ac47b6d9efc06296b44ca8e8 made type resolution require an accessing class context diff -r 4d7a9829315e -r 8853b9304083 graal/com.oracle.graal.api.meta/src/com/oracle/graal/api/meta/JavaType.java --- a/graal/com.oracle.graal.api.meta/src/com/oracle/graal/api/meta/JavaType.java Fri Jul 11 00:27:23 2014 +0200 +++ b/graal/com.oracle.graal.api.meta/src/com/oracle/graal/api/meta/JavaType.java Fri Jul 11 13:47:47 2014 +0200 @@ -72,11 +72,12 @@ Kind getKind(); /** - * Resolved this type and returns a {@link ResolvedJavaType}. If this type is already a - * {@link ResolvedJavaType}, it returns this type. + * Resolves this type to a {@link ResolvedJavaType}. * - * @param accessingClass the class that requests resolving this type + * @param accessingClass the context of resolution (must not be null) * @return the resolved Java type + * @throws LinkageError if the resolution failed + * @throws NullPointerException if {@code accessingClass} is {@code null} */ ResolvedJavaType resolve(ResolvedJavaType accessingClass); diff -r 4d7a9829315e -r 8853b9304083 graal/com.oracle.graal.api.meta/src/com/oracle/graal/api/meta/ProfilingInfo.java --- a/graal/com.oracle.graal.api.meta/src/com/oracle/graal/api/meta/ProfilingInfo.java Fri Jul 11 00:27:23 2014 +0200 +++ b/graal/com.oracle.graal.api.meta/src/com/oracle/graal/api/meta/ProfilingInfo.java Fri Jul 11 13:47:47 2014 +0200 @@ -206,7 +206,6 @@ return ""; } String s = buf.toString(); - assert s.endsWith(sep); return s.substring(0, s.length() - sep.length()); } diff -r 4d7a9829315e -r 8853b9304083 graal/com.oracle.graal.api.meta/src/com/oracle/graal/api/meta/ResolvedJavaType.java --- a/graal/com.oracle.graal.api.meta/src/com/oracle/graal/api/meta/ResolvedJavaType.java Fri Jul 11 00:27:23 2014 +0200 +++ b/graal/com.oracle.graal.api.meta/src/com/oracle/graal/api/meta/ResolvedJavaType.java Fri Jul 11 13:47:47 2014 +0200 @@ -144,9 +144,8 @@ * Returns true if this type is exactly the type {@link java.lang.Object}. */ default boolean isJavaLangObject() { - boolean result = getSuperclass() == null && !isInterface() && getKind() == Kind.Object; - assert result == getName().equals("Ljava/lang/Object;") : getName(); - return result; + // Removed assertion due to https://bugs.eclipse.org/bugs/show_bug.cgi?id=434442 + return getSuperclass() == null && !isInterface() && getKind() == Kind.Object; } /** @@ -213,7 +212,7 @@ default ResolvedJavaType getElementalType() { ResolvedJavaType t = this; - while (t.getComponentType() != null) { + while (t.isArray()) { t = t.getComponentType(); } return t; diff -r 4d7a9829315e -r 8853b9304083 graal/com.oracle.graal.api.meta/src/com/oracle/graal/api/meta/Signature.java --- a/graal/com.oracle.graal.api.meta/src/com/oracle/graal/api/meta/Signature.java Fri Jul 11 00:27:23 2014 +0200 +++ b/graal/com.oracle.graal.api.meta/src/com/oracle/graal/api/meta/Signature.java Fri Jul 11 13:47:47 2014 +0200 @@ -39,15 +39,16 @@ int getParameterCount(boolean receiver); /** - * Gets the parameter type at the specified position. This method returns a - * {@linkplain ResolvedJavaType resolved} type if possible but without triggering any class - * loading or resolution. + * Gets the parameter type at the specified position. * * @param index the index into the parameters, with {@code 0} indicating the first parameter - * @param accessingClass the context of the type lookup. If accessing class is provided, its - * class loader is used to retrieve an existing resolved type. This value can be - * {@code null} if the caller does not care for a resolved type. + * @param accessingClass the context of the type lookup. If non-null, its class loader is used + * for resolving the type. If {@code null}, then the type returned is either + * unresolved or a resolved type whose resolution is context free (e.g., a primitive + * type or a type in a java.* package). * @return the {@code index}'th parameter type + * @throws LinkageError if {@code accessingClass != null} and resolution fails + * */ JavaType getParameterType(int index, ResolvedJavaType accessingClass); @@ -61,14 +62,14 @@ Kind getParameterKind(int index); /** - * Gets the return type of this signature. This method will return a - * {@linkplain ResolvedJavaType resolved} type if possible but without triggering any class - * loading or resolution. + * Gets the return type of this signature. * - * @param accessingClass the context of the type lookup. If accessing class is provided, its - * class loader is used to retrieve an existing resolved type. This value can be - * {@code null} if the caller does not care for a resolved type. + * @param accessingClass the context of the type lookup. If non-null, its class loader is used + * for resolving the type. If {@code null}, then the type returned is either + * unresolved or a resolved type whose resolution is context free (e.g., a primitive + * type or a type in a java.* package). * @return the return type + * @throws LinkageError if {@code accessingClass != null} and resolution fails */ JavaType getReturnType(ResolvedJavaType accessingClass); diff -r 4d7a9829315e -r 8853b9304083 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotGraalRuntime.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotGraalRuntime.java Fri Jul 11 00:27:23 2014 +0200 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotGraalRuntime.java Fri Jul 11 13:47:47 2014 +0200 @@ -370,32 +370,32 @@ } /** - * Converts a name to a Java type. + * Converts a name to a Java type. This method attempts to resolve {@code name} to a + * {@link ResolvedJavaType}. * * @param name a well formed Java type in {@linkplain JavaType#getName() internal} format - * @param accessingType the context of resolution (may be null) - * @param resolve force resolution to a {@link ResolvedJavaType}. If true, this method will - * either return a {@link ResolvedJavaType} or throw an exception + * @param accessingType the context of resolution which must be non-null + * @param resolve specifies whether resolution failure results in an unresolved type being + * return or a {@link LinkageError} being thrown * @return a Java type for {@code name} which is guaranteed to be of type * {@link ResolvedJavaType} if {@code resolve == true} * @throws LinkageError if {@code resolve == true} and the resolution failed */ public JavaType lookupType(String name, HotSpotResolvedObjectType accessingType, boolean resolve) { + if (accessingType == null) { + throw new GraalInternalError("cannot resolve " + name + " without an accessing class"); + } // If the name represents a primitive type we can short-circuit the lookup. if (name.length() == 1) { Kind kind = Kind.fromPrimitiveOrVoidTypeChar(name.charAt(0)); return HotSpotResolvedPrimitiveType.fromKind(kind); } - // Handle non-primitive types. - Class accessingClass = null; - if (accessingType != null) { - accessingClass = accessingType.mirror(); - } + // Resolve non-primitive types in the VM. + final long metaspaceKlass = compilerToVm.lookupType(name, accessingType != null ? accessingType.mirror() : null, resolve); - // Resolve the type in the VM. - final long metaspaceKlass = compilerToVm.lookupType(name, accessingClass, resolve); - if (metaspaceKlass == 0) { + if (metaspaceKlass == 0L) { + assert resolve == false; return HotSpotUnresolvedJavaType.create(name); } return HotSpotResolvedObjectType.fromMetaspaceKlass(metaspaceKlass); diff -r 4d7a9829315e -r 8853b9304083 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/bridge/CompilerToVM.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/bridge/CompilerToVM.java Fri Jul 11 00:27:23 2014 +0200 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/bridge/CompilerToVM.java Fri Jul 11 13:47:47 2014 +0200 @@ -109,7 +109,7 @@ * Converts a name to a metaspace klass. * * @param name a well formed Java type in {@linkplain JavaType#getName() internal} format - * @param accessingClass the context of resolution (may be null) + * @param accessingClass the context of resolution (must not be null) * @param resolve force resolution to a {@link ResolvedJavaType}. If true, this method will * either return a {@link ResolvedJavaType} or throw an exception * @return a metaspace klass for {@code name} diff -r 4d7a9829315e -r 8853b9304083 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotResolvedObjectType.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotResolvedObjectType.java Fri Jul 11 00:27:23 2014 +0200 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotResolvedObjectType.java Fri Jul 11 13:47:47 2014 +0200 @@ -24,6 +24,7 @@ import static com.oracle.graal.compiler.common.UnsafeAccess.*; import static com.oracle.graal.hotspot.HotSpotGraalRuntime.*; +import static java.util.Objects.*; import java.lang.annotation.*; import java.lang.reflect.*; @@ -710,9 +711,38 @@ return mirror().getAnnotation(annotationClass); } + /** + * Determines if this type is resolved in the context of a given accessing class. This is a + * conservative check based on this type's class loader being identical to + * {@code accessingClass}'s loader. This type may still be the correct resolved type in the + * context of {@code accessingClass} if its loader is an ancestor of {@code accessingClass}'s + * loader. + */ + public boolean isResolvedWithRespectTo(ResolvedJavaType accessingClass) { + assert accessingClass != null; + ResolvedJavaType elementType = getElementalType(); + if (elementType.isPrimitive()) { + // Primitive type resolution is context free. + return true; + } + if (elementType.getName().startsWith("Ljava/")) { + // Classes in a java.* package can only be defined by the + // boot class loader. This is enforced by ClassLoader.preDefineClass() + assert mirror().getClassLoader() == null; + return true; + } + ClassLoader thisCl = mirror().getClassLoader(); + ClassLoader accessingClassCl = ((HotSpotResolvedObjectType) accessingClass).mirror().getClassLoader(); + return thisCl == accessingClassCl; + } + @Override public ResolvedJavaType resolve(ResolvedJavaType accessingClass) { - return this; + if (isResolvedWithRespectTo(requireNonNull(accessingClass))) { + return this; + } + HotSpotResolvedObjectType accessingType = (HotSpotResolvedObjectType) accessingClass; + return (ResolvedJavaType) runtime().lookupType(getName(), accessingType, true); } /** diff -r 4d7a9829315e -r 8853b9304083 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotResolvedPrimitiveType.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotResolvedPrimitiveType.java Fri Jul 11 00:27:23 2014 +0200 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotResolvedPrimitiveType.java Fri Jul 11 13:47:47 2014 +0200 @@ -22,6 +22,8 @@ */ package com.oracle.graal.hotspot.meta; +import static java.util.Objects.*; + import java.lang.annotation.*; import java.lang.reflect.*; import java.net.*; @@ -77,6 +79,10 @@ return HotSpotResolvedObjectType.fromClass(javaArrayMirror); } + public ResolvedJavaType getElementalType() { + return this; + } + @Override public ResolvedJavaType getComponentType() { return null; @@ -204,6 +210,7 @@ @Override public ResolvedJavaType resolve(ResolvedJavaType accessingClass) { + requireNonNull(accessingClass); return this; } diff -r 4d7a9829315e -r 8853b9304083 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotSignature.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotSignature.java Fri Jul 11 00:27:23 2014 +0200 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotSignature.java Fri Jul 11 13:47:47 2014 +0200 @@ -40,8 +40,8 @@ private final List parameters = new ArrayList<>(); private final String returnType; private final String originalString; - private JavaType[] parameterTypes; - private JavaType returnTypeCache; + private ResolvedJavaType[] parameterTypes; + private ResolvedJavaType returnTypeCache; public HotSpotSignature(String signature) { assert signature.length() > 0; @@ -64,7 +64,7 @@ } } - public HotSpotSignature(JavaType returnType, JavaType... parameterTypes) { + public HotSpotSignature(ResolvedJavaType returnType, ResolvedJavaType... parameterTypes) { this.parameterTypes = parameterTypes.clone(); this.returnTypeCache = returnType; this.returnType = returnType.getName(); @@ -128,30 +128,39 @@ } private static boolean checkValidCache(JavaType type, ResolvedJavaType accessingClass) { + assert accessingClass != null; if (!(type instanceof ResolvedJavaType)) { return false; } if (type instanceof HotSpotResolvedObjectType) { - HotSpotResolvedObjectType resolved = (HotSpotResolvedObjectType) type; - if (accessingClass == null) { - return resolved.mirror().getClassLoader() == null; - } else { - return resolved.mirror().getClassLoader() == ((HotSpotResolvedObjectType) accessingClass).mirror().getClassLoader(); - } + return ((HotSpotResolvedObjectType) type).isResolvedWithRespectTo(accessingClass); } + return true; + } - return true; + private static JavaType getUnresolvedOrPrimitiveType(String name) { + if (name.length() == 1) { + Kind kind = Kind.fromPrimitiveOrVoidTypeChar(name.charAt(0)); + return HotSpotResolvedPrimitiveType.fromKind(kind); + } + return new HotSpotUnresolvedJavaType(name); } @Override public JavaType getParameterType(int index, ResolvedJavaType accessingClass) { - if (parameterTypes == null) { - parameterTypes = new JavaType[parameters.size()]; + if (accessingClass == null) { + // Caller doesn't care about resolution context so return an unresolved + // or primitive type (primitive type resolution is context free) + return getUnresolvedOrPrimitiveType(parameters.get(index)); } - JavaType type = parameterTypes[index]; + if (parameterTypes == null) { + parameterTypes = new ResolvedJavaType[parameters.size()]; + } + + ResolvedJavaType type = parameterTypes[index]; if (!checkValidCache(type, accessingClass)) { - type = runtime().lookupType(parameters.get(index), (HotSpotResolvedObjectType) accessingClass, false); + type = (ResolvedJavaType) runtime().lookupType(parameters.get(index), (HotSpotResolvedObjectType) accessingClass, true); parameterTypes[index] = type; } return type; @@ -170,8 +179,13 @@ @Override public JavaType getReturnType(ResolvedJavaType accessingClass) { + if (accessingClass == null) { + // Caller doesn't care about resolution context so return an unresolved + // or primitive type (primitive type resolution is context free) + return getUnresolvedOrPrimitiveType(returnType); + } if (!checkValidCache(returnTypeCache, accessingClass)) { - returnTypeCache = runtime().lookupType(returnType, (HotSpotResolvedObjectType) accessingClass, false); + returnTypeCache = (ResolvedJavaType) runtime().lookupType(returnType, (HotSpotResolvedObjectType) accessingClass, true); } return returnTypeCache; } diff -r 4d7a9829315e -r 8853b9304083 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotUnresolvedJavaType.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotUnresolvedJavaType.java Fri Jul 11 00:27:23 2014 +0200 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotUnresolvedJavaType.java Fri Jul 11 13:47:47 2014 +0200 @@ -35,13 +35,13 @@ public HotSpotUnresolvedJavaType(String name) { super(name); + assert name.charAt(0) == '[' || name.charAt(name.length() - 1) == ';' : name; } /** * Creates an unresolved type for a valid {@link JavaType#getName() type name}. */ public static HotSpotUnresolvedJavaType create(String name) { - assert name.charAt(name.length() - 1) == ';' : name; return new HotSpotUnresolvedJavaType(name); } diff -r 4d7a9829315e -r 8853b9304083 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/stubs/ForeignCallStub.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/stubs/ForeignCallStub.java Fri Jul 11 00:27:23 2014 +0200 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/stubs/ForeignCallStub.java Fri Jul 11 13:47:47 2014 +0200 @@ -114,7 +114,7 @@ ForeignCallDescriptor d = linkage.getDescriptor(); MetaAccessProvider metaAccess = providers.getMetaAccess(); Class[] arguments = d.getArgumentTypes(); - JavaType[] parameters = new JavaType[arguments.length]; + ResolvedJavaType[] parameters = new ResolvedJavaType[arguments.length]; for (int i = 0; i < arguments.length; i++) { parameters[i] = metaAccess.lookupJavaType(arguments[i]); } diff -r 4d7a9829315e -r 8853b9304083 src/share/vm/graal/graalCompilerToVM.cpp --- a/src/share/vm/graal/graalCompilerToVM.cpp Fri Jul 11 00:27:23 2014 +0200 +++ b/src/share/vm/graal/graalCompilerToVM.cpp Fri Jul 11 13:47:47 2014 +0200 @@ -234,11 +234,13 @@ Klass* resolved_klass = NULL; Handle class_loader; Handle protection_domain; - if (JNIHandles::resolve(accessing_class) != NULL) { - Klass* accessing_klass = java_lang_Class::as_Klass(JNIHandles::resolve(accessing_class)); - class_loader = accessing_klass->class_loader(); - protection_domain = accessing_klass->protection_domain(); + if (JNIHandles::resolve(accessing_class) == NULL) { + THROW_(vmSymbols::java_lang_NullPointerException(), 0L); } + Klass* accessing_klass = java_lang_Class::as_Klass(JNIHandles::resolve(accessing_class)); + class_loader = accessing_klass->class_loader(); + protection_domain = accessing_klass->protection_domain(); + if (resolve) { resolved_klass = SystemDictionary::resolve_or_fail(class_name, class_loader, protection_domain, true, THREAD);