Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -417,7 +417,7 @@ public boolean apply(GraphBuilderContext b, ResolvedJavaMethod targetMethod, Rec
// Primitive Class case returns null
PiNode klassNonNull = helper.emitNullReturnGuard(klass, nullValue, GraalDirectives.UNLIKELY_PROBABILITY);

// if ((Klass::_access_flags & Modifer.INTERCAE) != 0) return null
// if ((Klass::_access_flags & Modifer.INTERFACE) != 0) return null
ValueNode accessFlags = helper.readKlassAccessFlags(klassNonNull);
LogicNode test = IntegerTestNode.create(accessFlags, ConstantNode.forInt(Modifier.INTERFACE), NodeView.DEFAULT);
helper.emitReturnIfNot(test, nullValue, GraalDirectives.UNLIKELY_PROBABILITY);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -143,6 +143,10 @@ public Field originalField(ResolvedJavaField field) {
Objects.requireNonNull(field);
GraalError.guarantee(field instanceof HotSpotResolvedJavaField, "Unexpected implementation class: %s", field.getClass());

if (field.isInternal()) {
/* internal fields never have a corresponding java.lang.reflect.Field. */
return null;
}
return runtime().getMirror(field);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -25,18 +25,13 @@
package com.oracle.graal.pointsto;

import java.io.PrintWriter;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.function.Function;
import java.util.stream.Stream;

import org.graalvm.nativeimage.hosted.Feature;

import com.oracle.graal.pointsto.ClassInclusionPolicy.LayeredBaseImageInclusionPolicy;
import com.oracle.graal.pointsto.ClassInclusionPolicy.SharedLayerImageInclusionPolicy;
import com.oracle.graal.pointsto.api.HostVM;
import com.oracle.graal.pointsto.api.PointstoOptions;
import com.oracle.graal.pointsto.constraints.UnsupportedFeatures;
Expand Down Expand Up @@ -68,7 +63,9 @@
import jdk.vm.ci.code.BytecodeFrame;
import jdk.vm.ci.code.BytecodePosition;
import jdk.vm.ci.meta.ConstantReflectionProvider;
import jdk.vm.ci.meta.ResolvedJavaField;
import jdk.vm.ci.meta.ResolvedJavaMethod;
import jdk.vm.ci.meta.ResolvedJavaType;

/**
* This abstract class is shared between Reachability and Points-to. It contains generic methods
Expand Down Expand Up @@ -103,6 +100,8 @@ public abstract class AbstractAnalysisEngine implements BigBang {
protected final Timer analysisTimer;
protected final Timer verifyHeapTimer;
protected final ClassInclusionPolicy classInclusionPolicy;
private static final ResolvedJavaMethod[] NO_METHODS = new ResolvedJavaMethod[]{};
private static final ResolvedJavaField[] NO_FIELDS = new ResolvedJavaField[]{};

@SuppressWarnings("this-escape")
public AbstractAnalysisEngine(OptionValues options, AnalysisUniverse universe, HostVM hostVM, AnalysisMetaAccess metaAccess, SnippetReflectionProvider snippetReflectionProvider,
Expand Down Expand Up @@ -208,7 +207,7 @@ private boolean analysisModified() {
* After the analysis reaches a stable state check if the shadow heap contains all
* objects reachable from roots. If this leads to analysis state changes, an additional
* analysis iteration will be run.
*
*
* We reuse the analysis executor, which at this point should be in before-start state:
* the analysis finished and it re-initialized the executor for the next iteration. The
* verifier controls the life cycle of the executor: it starts it and then waits until
Expand Down Expand Up @@ -259,7 +258,7 @@ public void profileConstantObject(AnalysisType type) {
}

public boolean isBaseLayerAnalysisEnabled() {
return classInclusionPolicy instanceof LayeredBaseImageInclusionPolicy;
return classInclusionPolicy instanceof SharedLayerImageInclusionPolicy;
}

@Override
Expand Down Expand Up @@ -352,30 +351,58 @@ public final boolean executorIsStarted() {
}

@Override
public void registerTypeForBaseImage(Class<?> cls) {
if (getOrDefault(cls, classInclusionPolicy::isClassIncluded, false)) {
classInclusionPolicy.includeClass(cls);
Stream.concat(Arrays.stream(getOrDefault(cls, Class::getDeclaredConstructors, new Constructor<?>[0])), Arrays.stream(getOrDefault(cls, Class::getDeclaredMethods, new Method[0])))
.filter(classInclusionPolicy::isMethodIncluded)
.forEach(classInclusionPolicy::includeMethod);
Arrays.stream(getOrDefault(cls, Class::getDeclaredFields, new Field[0]))
.filter(classInclusionPolicy::isFieldIncluded)
.forEach(classInclusionPolicy::includeField);
public void tryRegisterTypeForBaseImage(ResolvedJavaType type) {
if (tryApply(type, classInclusionPolicy::isOriginalTypeIncluded, false)) {
classInclusionPolicy.includeType(type);
ResolvedJavaMethod[] constructors = tryApply(type, t -> t.getDeclaredConstructors(false), NO_METHODS);
ResolvedJavaMethod[] methods = tryApply(type, t -> t.getDeclaredMethods(false), NO_METHODS);
for (ResolvedJavaMethod[] executables : List.of(constructors, methods)) {
for (ResolvedJavaMethod executable : executables) {
if (classInclusionPolicy.isOriginalMethodIncluded(executable)) {
classInclusionPolicy.includeMethod(executable);
}
}
}
ResolvedJavaField[] instanceFields = tryApply(type, t -> t.getInstanceFields(false), NO_FIELDS);
ResolvedJavaField[] staticFields = tryApply(type, ResolvedJavaType::getStaticFields, NO_FIELDS);
for (ResolvedJavaField[] fields : List.of(instanceFields, staticFields)) {
for (ResolvedJavaField field : fields) {
if (classInclusionPolicy.isOriginalFieldIncluded(field)) {
classInclusionPolicy.includeField(field);
}
}
}
}
}

@Override
public void registerMethodForBaseImage(AnalysisMethod method) {
if (classInclusionPolicy.isMethodIncluded(method)) {
public void tryRegisterMethodForBaseImage(AnalysisMethod method) {
if (classInclusionPolicy.isAnalysisMethodIncluded(method)) {
classInclusionPolicy.includeMethod(method);
}
}

public static <T, U> U getOrDefault(T cls, Function<T, U> getMembers, U backup) {
@Override
public void tryRegisterFieldForBaseImage(AnalysisField field) {
if (classInclusionPolicy.isAnalysisFieldIncluded(field)) {
classInclusionPolicy.includeField(field);
}
}

/**
* Applies {@code function} to {@code type} and returns the result or, if
* {@link NoClassDefFoundError} or {@link IncompatibleClassChangeError} thrown when applying the
* function, returns {@code fallback}.
* <p>
* The error handling allows for querying members (fields, methods or constructors) of a class
* where a member signature refers to a type that is unresolvable due to an incomplete class
* path. Such resolution errors need to be ignored when building a shared layer.
*/
private static <U> U tryApply(ResolvedJavaType type, Function<ResolvedJavaType, U> function, U fallback) {
try {
return getMembers.apply(cls);
return function.apply(type);
} catch (NoClassDefFoundError | IncompatibleClassChangeError e) {
return backup;
return fallback;
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@
import jdk.graal.compiler.word.WordTypes;
import jdk.vm.ci.code.BytecodePosition;
import jdk.vm.ci.meta.ConstantReflectionProvider;
import jdk.vm.ci.meta.ResolvedJavaType;

/**
* Central static analysis interface that groups together the functionality of reachability analysis
Expand Down Expand Up @@ -139,12 +140,17 @@ default AnalysisMethod fallbackResolveConcreteMethod(AnalysisType resolvingType,
}

@SuppressWarnings("unused")
default void registerTypeForBaseImage(Class<?> cls) {
default void tryRegisterTypeForBaseImage(ResolvedJavaType type) {

}

@SuppressWarnings("unused")
default void registerMethodForBaseImage(AnalysisMethod method) {
default void tryRegisterMethodForBaseImage(AnalysisMethod method) {

}

@SuppressWarnings("unused")
default void tryRegisterFieldForBaseImage(AnalysisField field) {

}
}
Loading