changeset 16492:8853b9304083

made type resolution require an accessing class context
author Doug Simon <doug.simon@oracle.com>
date Fri, 11 Jul 2014 13:47:47 +0200
parents 4d7a9829315e
children b45bb90c0192
files graal/com.oracle.graal.api.meta/src/com/oracle/graal/api/meta/JavaType.java graal/com.oracle.graal.api.meta/src/com/oracle/graal/api/meta/ProfilingInfo.java graal/com.oracle.graal.api.meta/src/com/oracle/graal/api/meta/ResolvedJavaType.java graal/com.oracle.graal.api.meta/src/com/oracle/graal/api/meta/Signature.java graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotGraalRuntime.java graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/bridge/CompilerToVM.java graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotResolvedObjectType.java graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotResolvedPrimitiveType.java graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotSignature.java graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotUnresolvedJavaType.java graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/stubs/ForeignCallStub.java src/share/vm/graal/graalCompilerToVM.cpp
diffstat 12 files changed, 108 insertions(+), 55 deletions(-) [+]
line wrap: on
line diff
--- 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);
 
--- 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());
     }
 
--- 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;
--- 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);
 
--- 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);
--- 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}
--- 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);
     }
 
     /**
--- 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;
     }
 
--- 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<String> 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;
     }
--- 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);
     }
 
--- 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]);
                 }
--- 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);