Skip to content

[GR-63786] Native Image Judge Integration #10969

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

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
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 @@ -36,6 +36,9 @@

public class PointstoOptions {

@Option(help = "Specify which jar contains the Judge Test classes, whose methods should not be inlined.")//
public static final OptionKey<String> JudgeJarName = new OptionKey<>("");

@Option(help = "Track primitive values using the infrastructure of points-to analysis.")//
public static final OptionKey<Boolean> TrackPrimitiveValues = new OptionKey<>(true);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@
import java.lang.reflect.Executable;
import java.lang.reflect.Modifier;
import java.lang.reflect.Type;
import java.security.ProtectionDomain;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
Expand Down Expand Up @@ -119,6 +120,8 @@ public abstract class AnalysisMethod extends AnalysisElement implements WrappedJ
private static final AtomicReferenceFieldUpdater<AnalysisMethod, Boolean> reachableInCurrentLayerUpdater = AtomicReferenceFieldUpdater
.newUpdater(AnalysisMethod.class, Boolean.class, "reachableInCurrentLayer");

private boolean isJudgeTestMethod;

public record Signature(String name, AnalysisType[] parameterTypes) {
}

Expand Down Expand Up @@ -276,6 +279,20 @@ protected AnalysisMethod(AnalysisUniverse universe, ResolvedJavaMethod wrapped,
parsingContextMaxDepth = PointstoOptions.ParsingContextMaxDepth.getValue(declaringClass.universe.hostVM.options());

this.enableReachableInCurrentLayer = universe.hostVM.enableReachableInCurrentLayer();

var judgeTestJar = PointstoOptions.JudgeJarName.getValue(getUniverse().hostVM.options());
if (judgeTestJar != null && !judgeTestJar.isBlank()) {
ProtectionDomain protectionDomain = getDeclaringClass().getJavaClass().getProtectionDomain();
if (protectionDomain != null) {
var codeSource = protectionDomain.getCodeSource();
if (codeSource != null) {
var location = codeSource.getLocation();
if (location != null && location.toString().contains(judgeTestJar)) {
isJudgeTestMethod = true;
}
}
}
}
}

@SuppressWarnings("this-escape")
Expand Down Expand Up @@ -907,6 +924,10 @@ public Type[] getGenericParameterTypes() {

@Override
public boolean canBeInlined() {
if (isJudgeTestMethod) {
System.out.println("Disallow inlining of " + this);
return false;
}
return !hasNeverInlineDirective();
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@
import java.util.Map;
import java.util.Set;
import java.util.function.Consumer;
import java.util.function.Function;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.stream.Collectors;
Expand Down Expand Up @@ -397,7 +398,7 @@ private static void printMethodNodes(Collection<MethodNode> methods, PrintWriter
}

private static void printInvokeNodes(Map<AnalysisMethod, MethodNode> methodToNode, PrintWriter writer) {
writer.println(convertToCSV("Id", "MethodId", "BytecodeIndexes", "TargetId", "IsDirect"));
writer.println(convertToCSV("Id", "MethodId", "BytecodeIndexes", "TargetId", "IsDirect", "LineNumbers"));
/*
* Methods that act as call targets, but are not reachable (e.g. abstract methods), will not
* have a MethodNode allocated yet. We store them in a separate map, because methodToNode
Expand Down Expand Up @@ -448,23 +449,24 @@ private static List<String> invokeNodeInfo(Map<AnalysisMethod, MethodNode> metho
return Arrays.asList(
String.valueOf(invoke.id),
String.valueOf(method.id),
showBytecodeIndexes(bytecodeIndexes(invoke)),
showIndexes(extractIndexes(invoke, source -> source.bci)),
String.valueOf(targetMethod.id),
String.valueOf(invoke.isDirectInvoke));
String.valueOf(invoke.isDirectInvoke),
showIndexes(extractIndexes(invoke, source -> source.trace.getLineNumber())));
}

private static List<String> callTargetInfo(InvokeNode invoke, Node callee) {
MethodNode node = callee instanceof MethodNodeReference ref ? ref.methodNode : ((MethodNode) callee);
return Arrays.asList(String.valueOf(invoke.id), String.valueOf(node.id));
}

private static List<Integer> bytecodeIndexes(InvokeNode node) {
private static List<Integer> extractIndexes(InvokeNode node, Function<SourceReference, Integer> extractor) {
return Stream.of(node.sourceReferences)
.map(source -> source.bci)
.map(extractor)
.collect(Collectors.toList());
}

private static String showBytecodeIndexes(List<Integer> bytecodeIndexes) {
private static String showIndexes(List<Integer> bytecodeIndexes) {
return bytecodeIndexes.stream()
.map(String::valueOf)
.collect(Collectors.joining("->"));
Expand Down
Loading