Skip to content

[GR-42250] Class constants should not make types reachable during bytecode parsing. #5438

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Nov 16, 2022
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 @@ -357,6 +357,8 @@ protected boolean ignoreConstant(ConstantNode cn) {
if (((BytecodeExceptionNode) usage).getExceptionKind() != BytecodeExceptionKind.CLASS_CAST) {
return false;
}
} else if (usage instanceof FrameState) {
/* FrameState usages are only for debugging and not necessary for correctness. */
} else {
return false;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -378,6 +378,11 @@ protected ImageHeapConstant createImageHeapObject(JavaConstant constant, ScanRea
return value;
}));
}

AnalysisType typeFromClassConstant = (AnalysisType) constantReflection.asJavaType(constant);
if (typeFromClassConstant != null) {
typeFromClassConstant.registerAsReachable();
}
}

/*
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -314,12 +314,9 @@ public void simplify(Node n, SimplifierTool tool) {

} else if (n instanceof ClassIsAssignableFromNode) {
ClassIsAssignableFromNode node = (ClassIsAssignableFromNode) n;
ValueNode thisClass = node.getThisClass();
if (thisClass.isConstant()) {
AnalysisType thisType = (AnalysisType) tool.getConstantReflection().asJavaType(thisClass.asConstant());
if (!thisType.isReachable()) {
node.replaceAndDelete(LogicConstantNode.contradiction(graph));
}
AnalysisType nonReachableType = asConstantNonReachableType(node.getThisClass(), tool);
if (nonReachableType != null) {
node.replaceAndDelete(LogicConstantNode.contradiction(graph));
}

} else if (n instanceof BytecodeExceptionNode) {
Expand All @@ -330,14 +327,23 @@ public void simplify(Node n, SimplifierTool tool) {
*/
BytecodeExceptionNode node = (BytecodeExceptionNode) n;
if (node.getExceptionKind() == BytecodeExceptionNode.BytecodeExceptionKind.CLASS_CAST) {
ValueNode expectedClass = node.getArguments().get(1);
if (expectedClass.isConstant()) {
AnalysisType expectedType = (AnalysisType) tool.getConstantReflection().asJavaType(expectedClass.asConstant());
if (expectedType != null && !expectedType.isReachable()) {
String expectedName = getTypeName(expectedType);
ConstantNode expectedConstant = ConstantNode.forConstant(tool.getConstantReflection().forString(expectedName), tool.getMetaAccess(), graph);
node.getArguments().set(1, expectedConstant);
}
AnalysisType nonReachableType = asConstantNonReachableType(node.getArguments().get(1), tool);
if (nonReachableType != null) {
node.getArguments().set(1, ConstantNode.forConstant(tool.getConstantReflection().forString(getTypeName(nonReachableType)), tool.getMetaAccess(), graph));
}
}

} else if (n instanceof FrameState) {
/*
* We do not want a type to be reachable only to be used for debugging purposes in a
* FrameState. We could just null out the frame slot, but to leave as much
* information as possible we replace the java.lang.Class with the type name.
*/
FrameState node = (FrameState) n;
for (int i = 0; i < node.values().size(); i++) {
AnalysisType nonReachableType = asConstantNonReachableType(node.values().get(i), tool);
if (nonReachableType != null) {
node.values().set(i, ConstantNode.forConstant(tool.getConstantReflection().forString(getTypeName(nonReachableType)), tool.getMetaAccess(), graph));
}
}

Expand All @@ -352,6 +358,16 @@ public void simplify(Node n, SimplifierTool tool) {
}
}

private AnalysisType asConstantNonReachableType(ValueNode value, CoreProviders providers) {
if (value != null && value.isConstant()) {
AnalysisType expectedType = (AnalysisType) providers.getConstantReflection().asJavaType(value.asConstant());
if (expectedType != null && !expectedType.isReachable()) {
return expectedType;
}
}
return null;
}

private void handleInvoke(Invoke invoke, SimplifierTool tool) {
PointsToAnalysis pta = getAnalysis();
FixedNode node = invoke.asFixedNode();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -37,10 +37,8 @@
import com.oracle.graal.pointsto.heap.value.ValueSupplier;
import com.oracle.graal.pointsto.infrastructure.UniverseMetaAccess;
import com.oracle.graal.pointsto.meta.AnalysisField;
import com.oracle.graal.pointsto.meta.AnalysisType;
import com.oracle.graal.pointsto.meta.AnalysisUniverse;
import com.oracle.graal.pointsto.meta.UninitializedStaticFieldValueReader;
import com.oracle.svm.core.BuildPhaseProvider;
import com.oracle.svm.core.RuntimeAssertionsSupport;
import com.oracle.svm.core.annotate.InjectAccessors;
import com.oracle.svm.core.graal.meta.SharedConstantReflectionProvider;
Expand Down Expand Up @@ -308,16 +306,6 @@ public JavaConstant asJavaClass(ResolvedJavaType type) {
return SubstrateObjectConstant.forObject(getHostVM().dynamicHub(type));
}

protected static void registerAsReachable(SVMHost hostVM, DynamicHub dynamicHub) {
assert dynamicHub != null;
/* Make sure that the DynamicHub of this type ends up in the native image. */
AnalysisType valueType = hostVM.lookupType(dynamicHub);
if (!valueType.isReachable() && BuildPhaseProvider.isAnalysisFinished()) {
throw VMError.shouldNotReachHere("Registering type as reachable after analysis: " + valueType);
}
valueType.registerAsReachable();
}

private SVMHost getHostVM() {
return (SVMHost) universe.hostVM();
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -49,12 +49,8 @@ private Object replace(Object source) {
if (source instanceof Class) {
Class<?> clazz = (Class<?>) source;
DynamicHub dynamicHub = hostVM.dynamicHub(metaAccess.lookupJavaType(clazz));
AnalysisConstantReflectionProvider.registerAsReachable(hostVM, dynamicHub);
return dynamicHub;
}
if (source instanceof DynamicHub) {
AnalysisConstantReflectionProvider.registerAsReachable(hostVM, (DynamicHub) source);
}
return source;
}
}