Skip to content

Commit

Permalink
[GR-7429] Generics support for SubstrateVM.
Browse files Browse the repository at this point in the history
PullRequest: graal/782
  • Loading branch information
cstancu committed Dec 19, 2017
2 parents 2fae84a + 4194ce4 commit 45e6fef
Show file tree
Hide file tree
Showing 13 changed files with 350 additions and 22 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -90,4 +90,12 @@ public interface SnippetReflectionProvider {
* if this provider cannot provide a value of the requested type
*/
<T> T getInjectedNodeIntrinsicParameter(Class<T> type);

/**
* Get the original Java class corresponding to a {@link ResolvedJavaType}.
*
* @param type the type for which the original Java class is requested
* @return the original Java class corresponding to the {@code type} parameter
*/
Class<?> originalClass(ResolvedJavaType type);
}
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
*/
package org.graalvm.compiler.hotspot.meta;

import jdk.vm.ci.hotspot.HotSpotResolvedJavaType;
import org.graalvm.compiler.api.replacements.SnippetReflectionProvider;
import org.graalvm.compiler.hotspot.HotSpotGraalRuntimeProvider;
import org.graalvm.compiler.hotspot.GraalHotSpotVMConfig;
Expand Down Expand Up @@ -104,4 +105,9 @@ public <T> T getInjectedNodeIntrinsicParameter(Class<T> type) {
}
return null;
}

@Override
public Class<?> originalClass(ResolvedJavaType type) {
return ((HotSpotResolvedJavaType) type).mirror();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
/*
* Copyright (c) 2012, 2017, 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.pointsto.infrastructure;

import org.graalvm.compiler.api.replacements.SnippetReflectionProvider;

import jdk.vm.ci.meta.ResolvedJavaType;

public interface OriginalClassProvider {

static Class<?> getJavaClass(SnippetReflectionProvider reflectionProvider, ResolvedJavaType javaType) {
if (javaType instanceof OriginalClassProvider) {
return ((OriginalClassProvider) javaType).getJavaClass();
} else {
return reflectionProvider.originalClass(javaType);
}
}

Class<?> getJavaClass();
}
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@
import java.util.concurrent.ConcurrentMap;
import java.util.concurrent.atomic.AtomicReferenceFieldUpdater;

import com.oracle.graal.pointsto.infrastructure.OriginalClassProvider;
import org.graalvm.compiler.graph.Node;
import org.graalvm.word.WordBase;

Expand All @@ -65,7 +66,7 @@
import jdk.vm.ci.meta.ResolvedJavaMethod;
import jdk.vm.ci.meta.ResolvedJavaType;

public class AnalysisType implements WrappedJavaType, Comparable<AnalysisType> {
public class AnalysisType implements WrappedJavaType, OriginalClassProvider, Comparable<AnalysisType> {

@SuppressWarnings("rawtypes")//
private static final AtomicReferenceFieldUpdater<AnalysisType, ConcurrentHashMap> UNSAFE_ACCESS_FIELDS_UPDATER = //
Expand Down Expand Up @@ -645,6 +646,11 @@ public ResolvedJavaType getWrapped() {
return universe.substitutions.resolve(wrapped);
}

@Override
public Class<?> getJavaClass() {
return OriginalClassProvider.getJavaClass(universe.getOriginalSnippetReflection(), wrapped);
}

@Override
public final String getName() {
return wrapped.getName();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -593,4 +593,8 @@ private boolean collectMethodImplementations(AnalysisMethod method, AnalysisType
public SnippetReflectionProvider getSnippetReflection() {
return snippetReflection;
}

public SnippetReflectionProvider getOriginalSnippetReflection() {
return originalSnippetReflection;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@

import com.oracle.svm.core.meta.SubstrateObjectConstant;
import com.oracle.svm.core.snippets.KnownIntrinsics;
import com.oracle.svm.core.util.VMError;

import jdk.vm.ci.meta.JavaConstant;
import jdk.vm.ci.meta.JavaKind;
Expand Down Expand Up @@ -58,4 +59,9 @@ public JavaConstant forBoxed(JavaKind kind, Object value) {
public <T> T getInjectedNodeIntrinsicParameter(Class<T> type) {
return null;
}

@Override
public Class<?> originalClass(ResolvedJavaType type) {
throw VMError.shouldNotReachHere();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -215,14 +215,17 @@ public final class DynamicHub implements JavaKind.FormatWithToString, AnnotatedE

@Platforms(Platform.HOSTED_ONLY.class) private int hostedIdentityHashCode;

private GenericInfo genericInfo;

@Platforms(Platform.HOSTED_ONLY.class)
public DynamicHub(String name, boolean isLocalClass, DynamicHub superHub, DynamicHub componentHub, String sourceFileName) {
public DynamicHub(String name, boolean isLocalClass, DynamicHub superType, DynamicHub componentHub, String sourceFileName) {
/* Class names must be interned strings according to the Java spec. */
this.name = name.intern();
this.isLocalClass = isLocalClass;
this.superHub = superHub;
this.superHub = superType;
this.componentHub = componentHub;
this.sourceFileName = sourceFileName;
this.genericInfo = GenericInfo.forEmpty();
}

@Platforms(Platform.HOSTED_ONLY.class)
Expand Down Expand Up @@ -257,6 +260,11 @@ public void setEnclosingClass(DynamicHub enclosingClass) {
this.enclosingClass = enclosingClass;
}

@Platforms(Platform.HOSTED_ONLY.class)
public void setGenericInfo(GenericInfo genericInfo) {
this.genericInfo = genericInfo;
}

@Platforms(Platform.HOSTED_ONLY.class)
public void setInterfacesEncoding(Object interfacesEncoding) {
this.interfacesEncoding = interfacesEncoding;
Expand Down Expand Up @@ -824,22 +832,18 @@ private native Method privateGetMethodRecursive(@SuppressWarnings("hiding") Stri

@Substitute
@Override
@SuppressWarnings("unchecked")
public TypeVariable<Class<?>>[] getTypeParameters() {
/* We are cheating: assume no generics are used. */
return (TypeVariable<Class<?>>[]) new TypeVariable<?>[0];
public TypeVariable<?>[] getTypeParameters() {
return genericInfo.getTypeParameters();
}

@Substitute
private Type[] getGenericInterfaces() {
/* We are cheating: assume no generics are used. */
return getInterfaces();
public Type[] getGenericInterfaces() {
return genericInfo.hasGenericInterfaces() ? genericInfo.getGenericInterfaces() : getInterfaces();
}

@Substitute
private Type getGenericSuperclass() {
/* We are cheating: assume no generics are used. */
return (Type) getSuperclass();
public Type getGenericSuperclass() {
return genericInfo.hasGenericSuperClass() ? genericInfo.getGenericSuperClass() : getSuperHub();
}

@Substitute
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,126 @@
/*
* Copyright (c) 2017, 2017, 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.svm.core.hub;

//Checkstyle: allow reflection

import java.lang.reflect.Type;
import java.lang.reflect.TypeVariable;
import java.util.Arrays;

import org.graalvm.nativeimage.Platform;
import org.graalvm.nativeimage.Platforms;

public final class GenericInfo {

private static final TypeVariable<?>[] EMPTY_TYPE_VARIABLE_ARRAY = new TypeVariable<?>[0];
private static final Type[] EMPTY_TYPE_ARRAY = new Type[0];
private static final GenericInfo EMPTY_GENERIC_INFO = new GenericInfo(EMPTY_TYPE_VARIABLE_ARRAY, EMPTY_TYPE_ARRAY, null);

@Platforms(Platform.HOSTED_ONLY.class)
static GenericInfo forEmpty() {
return EMPTY_GENERIC_INFO;
}

@Platforms(Platform.HOSTED_ONLY.class)
public static GenericInfo factory(TypeVariable<?>[] typeParameters, Type[] genericInterfaces, Type genericSuperClass) {
boolean hasTypeParameters = typeParameters.length > 0;
boolean hasGenericInterfaces = genericInterfaces.length > 0 && !Arrays.stream(genericInterfaces).allMatch(Class.class::isInstance);
boolean hasGenericSuperClass = genericSuperClass != null && !(genericSuperClass instanceof Class);
if (hasTypeParameters || hasGenericInterfaces || hasGenericSuperClass) {
return new GenericInfo(encodeTypeParameters(typeParameters), encodeGenericInterfaces(hasGenericInterfaces, genericInterfaces),
encodeGenericSuperClass(hasGenericSuperClass, genericSuperClass));
}
return EMPTY_GENERIC_INFO;
}

private static Object encodeTypeParameters(TypeVariable<?>[] typeParameters) {
if (typeParameters.length == 1) {
return typeParameters[0];
}
return typeParameters;
}

private static Object encodeGenericInterfaces(boolean hasGenericInterfaces, Type[] genericInterfaces) {
if (hasGenericInterfaces) {
if (genericInterfaces.length == 1) {
return genericInterfaces[0];
} else {
return genericInterfaces;
}
} else {
return null;
}
}

private static Type encodeGenericSuperClass(boolean hasGenericSuperClass, Type genericSuperClass) {
if (hasGenericSuperClass) {
return genericSuperClass;
}
return null;
}

private final Object typeParametersEncoding;
private final Object genericInterfacesEncoding;
private final Type genericSuperClass;

@Platforms(Platform.HOSTED_ONLY.class)
private GenericInfo(Object typeParameters, Object genericInterfaces, Type genericSuperClass) {
assert typeParameters != null;
this.typeParametersEncoding = typeParameters;
this.genericInterfacesEncoding = genericInterfaces;
this.genericSuperClass = genericSuperClass;
}

TypeVariable<?>[] getTypeParameters() {
if (typeParametersEncoding instanceof Type) {
return new TypeVariable<?>[]{(TypeVariable<?>) typeParametersEncoding};
} else {
/* The caller is allowed to modify the array, so we have to make a copy. */
return ((TypeVariable<?>[]) typeParametersEncoding).clone();
}
}

boolean hasGenericInterfaces() {
return genericInterfacesEncoding != null;
}

Type[] getGenericInterfaces() {
assert hasGenericInterfaces();
if (genericInterfacesEncoding instanceof Type) {
return new Type[]{(Type) genericInterfacesEncoding};
} else {
/* The caller is allowed to modify the array, so we have to make a copy. */
return ((Type[]) genericInterfacesEncoding).clone();
}
}

boolean hasGenericSuperClass() {
return genericSuperClass != null;
}

Type getGenericSuperClass() {
assert hasGenericSuperClass();
return genericSuperClass;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
/*
* Copyright (c) 2017, 2017, 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.svm.core.hub;

//Checkstyle: allow reflection

import java.lang.reflect.GenericDeclaration;

import com.oracle.svm.core.annotate.Alias;
import com.oracle.svm.core.annotate.Substitute;
import com.oracle.svm.core.annotate.TargetClass;

@TargetClass(sun.reflect.generics.reflectiveObjects.TypeVariableImpl.class)
final class Target_sun_reflect_generics_reflectiveObjects_TypeVariableImpl {

@Alias GenericDeclaration genericDeclaration;

/** Reason for substitutions: disable access checks in original method. */
@Substitute
public GenericDeclaration getGenericDeclaration() {
return genericDeclaration;
}

}

public class TypeVariableSubstitutions {
}
Loading

0 comments on commit 45e6fef

Please sign in to comment.