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 @@ -26,20 +26,22 @@

package com.oracle.graal.pointsto.standalone;

import com.oracle.graal.pointsto.api.HostVM;
import com.oracle.graal.pointsto.meta.AnalysisType;
import com.oracle.graal.pointsto.meta.HostedProviders;
import com.oracle.graal.pointsto.standalone.plugins.StandaloneGraphBuilderPhase;
import com.oracle.graal.pointsto.util.AnalysisError;
import jdk.vm.ci.meta.ResolvedJavaType;
import java.util.Comparator;
import java.util.concurrent.ConcurrentHashMap;

import org.graalvm.compiler.java.GraphBuilderPhase;
import org.graalvm.compiler.nodes.graphbuilderconf.GraphBuilderConfiguration;
import org.graalvm.compiler.nodes.graphbuilderconf.IntrinsicContext;
import org.graalvm.compiler.options.OptionValues;
import org.graalvm.compiler.phases.OptimisticOptimizations;

import java.util.Comparator;
import java.util.concurrent.ConcurrentHashMap;
import com.oracle.graal.pointsto.api.HostVM;
import com.oracle.graal.pointsto.meta.AnalysisType;
import com.oracle.graal.pointsto.meta.HostedProviders;
import com.oracle.graal.pointsto.standalone.plugins.StandaloneGraphBuilderPhase;
import com.oracle.graal.pointsto.util.AnalysisError;

import jdk.vm.ci.meta.ResolvedJavaType;

public class StandaloneHost extends HostVM {
private final ConcurrentHashMap<AnalysisType, Class<?>> typeToClass = new ConcurrentHashMap<>();
Expand Down Expand Up @@ -80,10 +82,6 @@ public void onTypeReachable(AnalysisType type) {
*/
}

@Override
public void onTypeInstantiated(AnalysisType newValue) {
}

@Override
public GraphBuilderPhase.Instance createGraphBuilderPhase(HostedProviders builderProviders, GraphBuilderConfiguration graphBuilderConfig, OptimisticOptimizations optimisticOpts,
IntrinsicContext initialIntrinsicContext) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -154,13 +154,6 @@ public void checkType(ResolvedJavaType type, AnalysisUniverse universe) {
*/
public abstract void onTypeReachable(AnalysisType newValue);

/**
* Run initialization tasks for a newly instantiated {@link AnalysisType}.
*
* @param newValue the type to initialize
*/
public abstract void onTypeInstantiated(AnalysisType newValue);

/**
* Check if an {@link AnalysisType} is initialized.
*/
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -692,7 +692,6 @@ public void onFieldAccessed(AnalysisField field) {
}

public void onTypeInstantiated(AnalysisType type, UsageKind usage) {
hostVM.onTypeInstantiated(type);
bb.onTypeInstantiated(type, usage);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -84,7 +84,11 @@ private void parseClass(EconomicMap<String, Object> data) {
}
ConfigurationCondition condition = conditionResult.get();

TypeResult<T> result = delegate.resolveType(condition, className, false);
/*
* Even if primitives cannot be queried through Class.forName, they can be registered to
* allow getDeclaredMethods() and similar bulk queries at run time.
*/
TypeResult<T> result = delegate.resolveType(condition, className, true);
if (!result.isPresent()) {
handleError("Could not resolve class " + className + " for reflection configuration.", result.getException());
return;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -55,8 +55,14 @@ public static void registerClass(Class<?> clazz) {
return; // must be defined at runtime before it can be looked up
}
String name = clazz.getName();
VMError.guarantee(!singleton().knownClasses.containsKey(name) || singleton().knownClasses.get(name) == clazz);
singleton().knownClasses.put(name, clazz);
if (!singleton().knownClasses.containsKey(name) || !(singleton().knownClasses.get(name) instanceof Throwable)) {
/*
* If the class has already been seen as throwing an error, we don't overwrite this
* error
*/
VMError.guarantee(!singleton().knownClasses.containsKey(name) || singleton().knownClasses.get(name) == clazz);
singleton().knownClasses.put(name, clazz);
}
}

@Platforms(Platform.HOSTED_ONLY.class)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -992,41 +992,28 @@ public Field getField(String fieldName) throws NoSuchFieldException, SecurityExc

private void checkField(String fieldName, Field field, boolean publicOnly) throws NoSuchFieldException {
boolean throwMissingErrors = throwMissingRegistrationErrors();
boolean noSuchField = false;
boolean missingRegistration = false;
Class<?> clazz = DynamicHub.toClass(this);
if (field == null) {
if (throwMissingErrors) {
if (isClassFlagSet(ALL_DECLARED_FIELDS_FLAG) || (publicOnly && isClassFlagSet(ALL_FIELDS_FLAG))) {
/*
* If getDeclaredFields (or getFields for a public field) is registered, we know
* for sure that the field does indeed not exist if we don't find it.
*/
noSuchField = true;
} else {
missingRegistration = true;
}
if (throwMissingErrors && !allElementsRegistered(publicOnly, ALL_DECLARED_FIELDS_FLAG, ALL_FIELDS_FLAG)) {
throw MissingReflectionRegistrationUtils.forField(clazz, fieldName);
} else {
noSuchField = true;
/*
* If getDeclaredFields (or getFields for a public field) is registered, we know for
* sure that the field does indeed not exist if we don't find it.
*/
throw new NoSuchFieldException(fieldName);
}
} else {
ReflectionMetadataDecoder decoder = ImageSingletons.lookup(ReflectionMetadataDecoder.class);
int fieldModifiers = field.getModifiers();
if (decoder.isNegative(fieldModifiers)) {
noSuchField = true;
} else if (decoder.isHiding(fieldModifiers)) {
if (throwMissingErrors) {
missingRegistration = true;
} else {
noSuchField = true;
}
boolean negative = decoder.isNegative(fieldModifiers);
boolean hiding = decoder.isHiding(fieldModifiers);
if (throwMissingErrors && hiding) {
throw MissingReflectionRegistrationUtils.forField(clazz, fieldName);
} else if (negative || hiding) {
throw new NoSuchFieldException(fieldName);
}
}
VMError.guarantee(!missingRegistration || !noSuchField, "Either a MissingRegistrationError or a NoSuchFieldException should be thrown, not both");
if (missingRegistration) {
throw MissingReflectionRegistrationUtils.forField(DynamicHub.toClass(this), fieldName);
} else if (noSuchField) {
throw new NoSuchFieldException(fieldName);
}
}

@Substitute
Expand All @@ -1039,41 +1026,32 @@ private Method getMethod(String methodName, Class<?>... parameterTypes) throws N

private void checkMethod(String methodName, Class<?>[] parameterTypes, Executable method, boolean publicOnly) throws NoSuchMethodException {
boolean throwMissingErrors = throwMissingRegistrationErrors();
boolean noSuchMethod = false;
boolean missingRegistration = false;
Class<?> clazz = DynamicHub.toClass(this);
if (method == null) {
if (throwMissingErrors) {
if (isClassFlagSet(ALL_DECLARED_METHODS_FLAG) || (publicOnly && isClassFlagSet(ALL_METHODS_FLAG))) {
/*
* If getDeclaredMethods (or getMethods for a public method) is registered, we
* know for sure that the method does indeed not exist if we don't find it.
*/
noSuchMethod = true;
} else {
missingRegistration = true;
}
if (throwMissingErrors && !allElementsRegistered(publicOnly, ALL_DECLARED_METHODS_FLAG, ALL_METHODS_FLAG)) {
throw MissingReflectionRegistrationUtils.forMethod(clazz, methodName, parameterTypes);
} else {
noSuchMethod = true;
/*
* If getDeclaredMethods (or getMethods for a public method) is registered, we know
* for sure that the method does indeed not exist if we don't find it.
*/
throw new NoSuchMethodException(methodToString(methodName, parameterTypes));
}
} else {
ReflectionMetadataDecoder decoder = ImageSingletons.lookup(ReflectionMetadataDecoder.class);
int methodModifiers = method.getModifiers();
if (decoder.isNegative(methodModifiers)) {
noSuchMethod = true;
} else if (decoder.isHiding(methodModifiers)) {
if (throwMissingErrors) {
missingRegistration = true;
} else {
noSuchMethod = true;
}
boolean negative = decoder.isNegative(methodModifiers);
boolean hiding = decoder.isHiding(methodModifiers);
if (throwMissingErrors && hiding) {
throw MissingReflectionRegistrationUtils.forMethod(clazz, methodName, parameterTypes);
} else if (negative || hiding) {
throw new NoSuchMethodException(methodToString(methodName, parameterTypes));
}
}
VMError.guarantee(!missingRegistration || !noSuchMethod, "Either a MissingRegistrationError or a NoSuchMethodException should be thrown, not both");
if (missingRegistration) {
throw MissingReflectionRegistrationUtils.forMethod(DynamicHub.toClass(this), methodName, parameterTypes);
} else if (noSuchMethod) {
throw new NoSuchMethodException(methodToString(methodName, parameterTypes));
}
}

private boolean allElementsRegistered(boolean publicOnly, int allDeclaredElementsFlag, int allPublicElementsFlag) {
return isClassFlagSet(allDeclaredElementsFlag) || (publicOnly && isClassFlagSet(allPublicElementsFlag));
}

@KeepOriginal
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -70,8 +70,6 @@
import org.graalvm.nativeimage.Platform;
import org.graalvm.nativeimage.Platforms;
import org.graalvm.nativeimage.c.function.RelocatedPointer;
import org.graalvm.nativeimage.impl.ConfigurationCondition;
import org.graalvm.nativeimage.impl.RuntimeReflectionSupport;

import com.oracle.graal.pointsto.BigBang;
import com.oracle.graal.pointsto.PointsToAnalysis;
Expand Down Expand Up @@ -150,7 +148,6 @@ public class SVMHost extends HostVM {
private final LinkAtBuildTimeSupport linkAtBuildTimeSupport;
private final HostedStringDeduplication stringTable;
private final UnsafeAutomaticSubstitutionProcessor automaticSubstitutions;
private final RuntimeReflectionSupport reflectionSupport;

/**
* Optionally keep the Graal graphs alive during analysis. This increases the memory footprint
Expand Down Expand Up @@ -188,7 +185,6 @@ public SVMHost(OptionValues options, ClassLoader classLoader, ClassInitializatio
multiMethodAnalysisPolicy = DEFAULT_MULTIMETHOD_ANALYSIS_POLICY;
}
parsingSupport = ImageSingletons.contains(SVMParsingSupport.class) ? ImageSingletons.lookup(SVMParsingSupport.class) : null;
this.reflectionSupport = ImageSingletons.lookup(RuntimeReflectionSupport.class);
}

private static Map<String, EnumSet<AnalysisType.UsageKind>> setupForbiddenTypes(OptionValues options) {
Expand Down Expand Up @@ -316,14 +312,6 @@ public void onTypeReachable(AnalysisType analysisType) {
automaticSubstitutions.computeSubstitutions(this, GraalAccess.getOriginalProviders().getMetaAccess().lookupJavaType(analysisType.getJavaClass()));
}

@Override
public void onTypeInstantiated(AnalysisType newValue) {
if (newValue.isAnnotation()) {
/* getDeclaredMethods is called in the AnnotationType constructor */
reflectionSupport.registerAllDeclaredMethodsQuery(ConfigurationCondition.alwaysTrue(), true, newValue.getJavaClass());
}
}

@Override
public boolean isInitialized(AnalysisType type) {
boolean shouldInitializeAtRuntime = classInitializationSupport.shouldInitializeAtRuntime(type);
Expand Down Expand Up @@ -647,7 +635,7 @@ public void methodBeforeTypeFlowCreationHook(BigBang bb, AnalysisMethod method,
if (n instanceof StackValueNode) {
containsStackValueNode.put(method, true);
} else if (n instanceof ReachabilityRegistrationNode node) {
bb.postTask(debug -> node.getRegistrationTask().ensureDone());
bb.postTask(debug -> node.getRegistrationTask().ensureDone());
}
checkClassInitializerSideEffect(method, n);
}
Expand Down
Loading