Skip to content

Commit

Permalink
[GR-28150] Make CAP output deterministic.
Browse files Browse the repository at this point in the history
PullRequest: graal/7909
  • Loading branch information
cstancu committed Dec 19, 2020
2 parents 753b9b6 + 3c81d0a commit b773acb
Show file tree
Hide file tree
Showing 3 changed files with 58 additions and 6 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@
import java.util.List;
import java.util.Optional;
import java.util.stream.Collectors;

import org.graalvm.nativeimage.c.CContext;
import org.graalvm.nativeimage.c.function.CFunctionPointer;
import org.graalvm.nativeimage.c.function.InvokeCFunctionPointer;
Expand Down Expand Up @@ -101,7 +102,7 @@ public interface JThrowable extends JObject {
* } jvalue;
* </pre>
*/
@CContext(JNIHeaderDirectives.class)
@CContext(LibGraalJNIHeaderDirectives.class)
@CStruct("jvalue")
public interface JValue extends PointerBase {
// @formatter:off
Expand Down Expand Up @@ -132,14 +133,14 @@ public interface JValue extends PointerBase {
JValue addressOf(int index);
}

@CContext(JNIHeaderDirectives.class)
@CContext(LibGraalJNIHeaderDirectives.class)
@CStruct(value = "JNIEnv_", addStructKeyword = true)
public interface JNIEnv extends PointerBase {
@CField("functions")
JNINativeInterface getFunctions();
}

@CContext(JNIHeaderDirectives.class)
@CContext(LibGraalJNIHeaderDirectives.class)
@CStruct(value = "JNINativeInterface_", addStructKeyword = true)
public interface JNINativeInterface extends PointerBase {

Expand Down Expand Up @@ -512,9 +513,14 @@ public interface SetStaticBooleanField extends CFunctionPointer {
void call(JNIEnv env, JClass clazz, JFieldID fieldID, boolean value);
}

static class JNIHeaderDirectives implements CContext.Directives {
static class LibGraalJNIHeaderDirectives implements CContext.Directives {
private static final String[] INCLUDES = {"jni.h", "jni_md.h"};

@Override
public boolean isInConfiguration() {
return jdk.vm.ci.services.Services.IS_BUILDING_NATIVE_IMAGE;
}

@Override
public List<String> getOptions() {
return Arrays.stream(findJNIHeaders()).map((p) -> "-I" + p.getParent()).collect(Collectors.toList());
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,23 @@ public void mergeChildrenAndDelete(ElementInfo target) {
}

/**
* Returns a unique identifier string for this element.
* Returns a unique identifier string for this element <i>iif</i> this element is a leaf node.
* <p>
* </p>
* Note: This identifier is not unique for intermediate nodes. For example the following enum
* infos:
* <ul>
* <li>{@code NativeCodeInfo:PosixDirectives:EnumInfo:int:EnumConstantInfo:SIGPOLL}</li>
* <li>{@code NativeCodeInfo:PosixDirectives:EnumInfo:int:EnumConstantInfo:SIGABRT}</li>
* </ul>
*
* each have an ancestor with the "unique" ID {@code NativeCodeInfo:PosixDirectives:EnumInfo}
* which actually refers to a different {@link EnumInfo} object, originating from different
* annotated classes:
* <ul>
* <li>{@code com.oracle.svm.core.posix.headers.Signal.LinuxSignalEnum}</li>
* <li>{@code com.oracle.svm.core.posix.headers.Signal.SignalEnum}</li>
* </ul>
*/
public final String getUniqueID() {
StringBuilder result = new StringBuilder();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,12 +24,42 @@
*/
package com.oracle.svm.hosted.c.info;

import java.util.ArrayList;
import java.util.Comparator;
import java.util.List;

import com.oracle.svm.core.util.UserError;

public abstract class InfoTreeVisitor {

/**
* Compares the the Class name, the name and the result of
* {@link ElementInfo#getAnnotatedElement()} to get a stable order for sorting the children of
* an {@link ElementInfo} node.
*
* Note: We cannot use the {@link ElementInfo#getUniqueID()} method because it only looks at the
* parent path, without looking at any children, so for intermediate nodes in the tree there may
* be ID conflicts. This is not a problem when storing the tree as the children are stored as an
* {@link ArrayList}. It is also not a problem when writing the tree out as only the leaf nodes
* are written. However, to get a stable processing order we need extra information.
*/
static final Comparator<ElementInfo> elementInfoComparator;
static {
/* Defining the comparator chain on multiple lines requires less type annotations. */
Comparator<ElementInfo> classNameComparator = Comparator.comparing(e -> e.getClass().getName());
Comparator<ElementInfo> nameComparator = classNameComparator.thenComparing(e -> e.getName());
elementInfoComparator = nameComparator.thenComparing(e -> e.getAnnotatedElement().toString());
}

protected final void processChildren(ElementInfo info) {
for (ElementInfo child : info.getChildren()) {
List<ElementInfo> children = info.getChildren();
/*
* Sort the children before processing. Although storing the children already sorted is
* possible, that is not necessary. Sorting them in the visitor is enough to get a stable
* processing order.
*/
children.sort(elementInfoComparator);
for (ElementInfo child : children) {
try {
child.accept(this);
} catch (NumberFormatException e) {
Expand Down

0 comments on commit b773acb

Please sign in to comment.