Skip to content

[GR-51104] Catch disallowed objects in object reachable callback. #8168

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 4 commits into from
Jan 16, 2024
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 @@ -552,20 +552,37 @@ public String toString() {
public static class FieldScan extends ScanReason {
final AnalysisField field;

private static ScanReason previous(AnalysisField field) {
Object readBy = field.getReadBy();
if (readBy instanceof BytecodePosition) {
ResolvedJavaMethod readingMethod = ((BytecodePosition) readBy).getMethod();
return new MethodParsing((AnalysisMethod) readingMethod);
} else if (readBy instanceof AnalysisMethod) {
return new MethodParsing((AnalysisMethod) readBy);
private static ScanReason previous(AnalysisField field, JavaConstant receiver) {
/*
* Since there is no previous reason we try to infer one either from the receiver
* constant or from the field read-by reason.
*/
Object reason;
if (receiver instanceof ImageHeapConstant heapConstant) {
AnalysisError.guarantee(heapConstant.isReachable());
reason = heapConstant.getReachableReason();
} else {
return new OtherReason("registered as read because: " + readBy);
reason = field.getReadBy();
}
if (reason instanceof ScanReason scanReason) {
return scanReason;
} else if (reason instanceof BytecodePosition position) {
ResolvedJavaMethod readingMethod = position.getMethod();
return new MethodParsing((AnalysisMethod) readingMethod);
} else if (reason instanceof AnalysisMethod method) {
return new MethodParsing(method);
} else if (reason != null) {
return new OtherReason("registered as read because: " + reason);
}
return null;
}

public FieldScan(AnalysisField field) {
this(field, null, previous(field));
this(field, null, previous(field, null));
}

public FieldScan(AnalysisField field, JavaConstant receiver) {
this(field, receiver, previous(field, receiver));
}

public FieldScan(AnalysisField field, JavaConstant receiver, ScanReason previous) {
Expand Down Expand Up @@ -718,7 +735,7 @@ public AnalysisMethod getMethod() {

@Override
public String toString(BigBang bb) {
return "scanning root " + asString(bb, constant) + " embedded in " + System.lineSeparator() + INDENTATION_AFTER_NEWLINE + asStackTraceElement();
return "scanning root " + asString(bb, constant) + " embedded in" + System.lineSeparator() + INDENTATION_AFTER_NEWLINE + asStackTraceElement();
}

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -122,9 +122,9 @@ public void scanEmbeddedRoot(JavaConstant root, BytecodePosition position) {
public void onFieldRead(AnalysisField field) {
assert field.isRead() : field;
/* Check if the value is available before accessing it. */
FieldScan reason = new FieldScan(field);
AnalysisType declaringClass = field.getDeclaringClass();
if (field.isStatic()) {
FieldScan reason = new FieldScan(field);
if (isValueAvailable(field)) {
JavaConstant fieldValue = readStaticFieldValue(field);
markReachable(fieldValue, reason);
Expand All @@ -134,19 +134,20 @@ public void onFieldRead(AnalysisField field) {
}
} else {
/* Trigger field scanning for the already processed objects. */
postTask(() -> onInstanceFieldRead(field, declaringClass, reason));
postTask(() -> onInstanceFieldRead(field, declaringClass));
}
}

private void onInstanceFieldRead(AnalysisField field, AnalysisType type, FieldScan reason) {
private void onInstanceFieldRead(AnalysisField field, AnalysisType type) {
for (AnalysisType subtype : type.getSubTypes()) {
for (ImageHeapConstant imageHeapConstant : imageHeap.getReachableObjects(subtype)) {
FieldScan reason = new FieldScan(field, imageHeapConstant);
ImageHeapInstance imageHeapInstance = (ImageHeapInstance) imageHeapConstant;
updateInstanceField(field, imageHeapInstance, reason, null);
}
/* Subtypes include this type itself. */
if (!subtype.equals(type)) {
onInstanceFieldRead(field, subtype, reason);
onInstanceFieldRead(field, subtype);
}
}
}
Expand Down Expand Up @@ -517,7 +518,17 @@ protected void onObjectReachable(ImageHeapConstant imageHeapConstant, ScanReason

AnalysisType type = imageHeapConstant.getType(metaAccess);
Object object = bb.getSnippetReflectionProvider().asObject(Object.class, imageHeapConstant);
type.notifyObjectReachable(universe.getConcurrentAnalysisAccess(), object);
/* Simulated constants don't have a backing object and don't need to be processed. */
if (object != null) {
try {
type.notifyObjectReachable(universe.getConcurrentAnalysisAccess(), object);
} catch (UnsupportedFeatureException e) {
/* Enhance the unsupported feature message with the object trace and rethrow. */
StringBuilder backtrace = new StringBuilder();
ObjectScanner.buildObjectBacktrace(bb, reason, backtrace);
throw new UnsupportedFeatureException(e.getMessage() + System.lineSeparator() + backtrace);
}
}

markTypeInstantiated(objectType, reason);
if (imageHeapConstant instanceof ImageHeapObjectArray imageHeapArray) {
Expand Down
Loading