Skip to content

[GR-59845] Improve loading of base layer elements #10100

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

Closed
wants to merge 1 commit into from
Closed
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 @@ -49,6 +49,7 @@
import com.oracle.graal.pointsto.heap.HostedValuesProvider;
import com.oracle.graal.pointsto.heap.ImageHeap;
import com.oracle.graal.pointsto.heap.ImageLayerLoader;
import com.oracle.graal.pointsto.heap.ImageLayerSnapshotUtil;
import com.oracle.graal.pointsto.heap.ImageLayerWriter;
import com.oracle.graal.pointsto.infrastructure.SubstitutionProcessor;
import com.oracle.graal.pointsto.meta.AnalysisMetaAccess;
Expand Down Expand Up @@ -162,14 +163,17 @@ private PointsToAnalyzer(String mainEntryClass, OptionValues options) {
aUniverse.setBigBang(bigbang);
ImageHeap heap = new ImageHeap();
HostedValuesProvider hostedValuesProvider = new HostedValuesProvider(aMetaAccess, aUniverse);
ImageLayerSnapshotUtil imageLayerSnapshotUtil = new ImageLayerSnapshotUtil();
ImageLayerLoader imageLayerLoader = new ImageLayerLoader();
imageLayerLoader.setImageLayerSnapshotUtil(imageLayerSnapshotUtil);
imageLayerLoader.setUniverse(aUniverse);
aUniverse.setImageLayerLoader(imageLayerLoader);
StandaloneImageHeapScanner heapScanner = new StandaloneImageHeapScanner(bigbang, heap, aMetaAccess,
snippetReflection, aConstantReflection, new AnalysisObjectScanningObserver(bigbang), analysisClassLoader, hostedValuesProvider);
aUniverse.setHeapScanner(heapScanner);
imageLayerLoader.executeHeapScannerTasks();
ImageLayerWriter imageLayerWriter = new ImageLayerWriter();
ImageLayerWriter imageLayerWriter = new ImageLayerWriter(true);
imageLayerWriter.setImageLayerSnapshotUtil(imageLayerSnapshotUtil);
imageLayerWriter.setImageHeap(heap);
HeapSnapshotVerifier heapVerifier = new StandaloneHeapSnapshotVerifier(bigbang, heap, heapScanner);
aUniverse.setHeapVerifier(heapVerifier);
Expand Down

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,7 @@ public class ImageLayerSnapshotUtil {
public static final String METHODS_TAG = "methods";
public static final String FIELDS_TAG = "fields";
public static final String IS_INTERNAL_TAG = "is internal";
public static final String IS_STATIC_TAG = "is static";
public static final String FIELD_TYPE_TAG = "field type";
public static final String CLASS_JAVA_NAME_TAG = "class java name";
public static final String CAN_BE_STATICALLY_BOUND_TAG = "can be statically bound";
Expand All @@ -85,6 +86,7 @@ public class ImageLayerSnapshotUtil {
public static final String IS_IMPLEMENTATION_INVOKED = "is implementation invoked";
public static final String IS_INTRINSIC_METHOD = "is intrinsic method";
public static final String ANNOTATIONS_TAG = "annotations";
public static final String ANNOTATION_VALUES_TAG = "annotation values";
public static final String IS_INSTANTIATED = "is instantiated";
public static final String IS_UNSAFE_ALLOCATED = "is unsafe allocated";
public static final String IS_REACHABLE = "is reachable";
Expand All @@ -104,8 +106,11 @@ public class ImageLayerSnapshotUtil {
public static final String GENERATED_SERIALIZATION_TAG = "generated serialization";
public static final String LAMBDA_TYPE_TAG = "lambda type";
public static final String CAPTURING_CLASS_TAG = "capturing class";
public static final String PROXY_TYPE_TAG = "proxy type";
public static final String RAW_DECLARING_CLASS_TAG = "raw declaring class";
public static final String RAW_TARGET_CONSTRUCTOR_CLASS_TAG = "raw target constructor class";
public static final String INSTANCE_FIELDS_TAG = "instance fields";
public static final String INSTANCE_FIELDS_WITH_SUPER_TAG = "instance fields with super";
public static final String CONSTANTS_TAG = "constants";
public static final String CONSTANTS_TO_RELINK_TAG = "constants to relink";
public static final String TID_TAG = "tid";
Expand All @@ -118,8 +123,17 @@ public class ImageLayerSnapshotUtil {
public static final String METHOD_TYPE_PARAMETERS_TAG = "method type parameters";
public static final String METHOD_TYPE_RETURN_TAG = "method type return";
public static final String FACTORY_TAG = "factory";
public static final String C_ENTRY_POINT_CALL_STUB_METHOD_TAG = "CEntryPointCallStubMethod";
public static final String REFLECTION_EXPAND_SIGNATURE_METHOD_TAG = "reflection expand signature method";
public static final String JNI_JAVA_CALL_VARIANT_WRAPPER_METHOD_TAG = "jni java call variant wrapper method";
public static final String OUTLINED_SB_TAG = "outlinedSB";
public static final String ORIGINAL_METHOD_ID_TAG = "original method id";
public static final String NOT_AS_PUBLISHED_TAG = "not as published";
public static final String TARGET_CONSTRUCTOR_TAG = "target constructor";
public static final String INSTANTIATED_TYPE_TAG = "instantiated type";
public static final String WRAPPED_MEMBER_CLASS_TAG = "wrapped member class";
public static final String WRAPPED_MEMBER_NAME_TAG = "wrapped member name";
public static final String WRAPPED_MEMBER_ARGUMENTS_TAG = "wrapped member arguments";
public static final String THROW_ALLOCATED_OBJECT_TAG = "throw allocated object";
public static final String IDENTITY_HASH_CODE_TAG = "identityHashCode";
public static final String PARENT_CONSTANT_ID_TAG = "parent constant id";
Expand All @@ -146,6 +160,7 @@ public class ImageLayerSnapshotUtil {
public static final String ARRAY_TAG = "array";
public static final String PRIMITIVE_ARRAY_TAG = "primitive array";
public static final String RELOCATED_CONSTANT_TAG = "relocation constant";
public static final String FIELD_CHECK_TAG = "field check";
public static final String FIELD_ACCESSED_TAG = "accessed";
public static final String FIELD_READ_TAG = "read";
public static final String FIELD_WRITTEN_TAG = "written";
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,8 @@
import static com.oracle.graal.pointsto.heap.ImageLayerSnapshotUtil.IDENTITY_HASH_CODE_TAG;
import static com.oracle.graal.pointsto.heap.ImageLayerSnapshotUtil.ID_TAG;
import static com.oracle.graal.pointsto.heap.ImageLayerSnapshotUtil.IMAGE_HEAP_SIZE_TAG;
import static com.oracle.graal.pointsto.heap.ImageLayerSnapshotUtil.INSTANCE_FIELDS_TAG;
import static com.oracle.graal.pointsto.heap.ImageLayerSnapshotUtil.INSTANCE_FIELDS_WITH_SUPER_TAG;
import static com.oracle.graal.pointsto.heap.ImageLayerSnapshotUtil.INSTANCE_TAG;
import static com.oracle.graal.pointsto.heap.ImageLayerSnapshotUtil.INTERFACES_TAG;
import static com.oracle.graal.pointsto.heap.ImageLayerSnapshotUtil.INTRINSIC_TAG;
Expand All @@ -66,6 +68,7 @@
import static com.oracle.graal.pointsto.heap.ImageLayerSnapshotUtil.IS_INVOKED;
import static com.oracle.graal.pointsto.heap.ImageLayerSnapshotUtil.IS_LINKED_TAG;
import static com.oracle.graal.pointsto.heap.ImageLayerSnapshotUtil.IS_REACHABLE;
import static com.oracle.graal.pointsto.heap.ImageLayerSnapshotUtil.IS_STATIC_TAG;
import static com.oracle.graal.pointsto.heap.ImageLayerSnapshotUtil.IS_SYNTHETIC_TAG;
import static com.oracle.graal.pointsto.heap.ImageLayerSnapshotUtil.IS_UNSAFE_ALLOCATED;
import static com.oracle.graal.pointsto.heap.ImageLayerSnapshotUtil.IS_VAR_ARGS_TAG;
Expand All @@ -84,8 +87,8 @@
import static com.oracle.graal.pointsto.heap.ImageLayerSnapshotUtil.PARENT_CONSTANT_INDEX_TAG;
import static com.oracle.graal.pointsto.heap.ImageLayerSnapshotUtil.POSITION_TAG;
import static com.oracle.graal.pointsto.heap.ImageLayerSnapshotUtil.PRIMITIVE_ARRAY_TAG;
import static com.oracle.graal.pointsto.heap.ImageLayerSnapshotUtil.RETURN_TYPE_TAG;
import static com.oracle.graal.pointsto.heap.ImageLayerSnapshotUtil.RELOCATED_CONSTANT_TAG;
import static com.oracle.graal.pointsto.heap.ImageLayerSnapshotUtil.RETURN_TYPE_TAG;
import static com.oracle.graal.pointsto.heap.ImageLayerSnapshotUtil.SIMULATED_TAG;
import static com.oracle.graal.pointsto.heap.ImageLayerSnapshotUtil.SOURCE_FILE_NAME_TAG;
import static com.oracle.graal.pointsto.heap.ImageLayerSnapshotUtil.STRENGTHENED_GRAPH_TAG;
Expand All @@ -98,6 +101,8 @@

import java.io.IOException;
import java.io.PrintWriter;
import java.lang.annotation.Annotation;
import java.lang.reflect.AnnotatedElement;
import java.lang.reflect.Executable;
import java.lang.reflect.Field;
import java.nio.ByteBuffer;
Expand Down Expand Up @@ -208,7 +213,6 @@ public ImageLayerWriter() {
this(true);
}

@SuppressWarnings({"this-escape", "unused"})
public ImageLayerWriter(boolean useSharedLayerGraphs) {
this.useSharedLayerGraphs = useSharedLayerGraphs;
this.useSharedLayerStrengthenedGraphs = false;
Expand Down Expand Up @@ -278,12 +282,6 @@ public void persistAnalysisInfo() {
jsonMap.put(NEXT_METHOD_ID_TAG, aUniverse.getNextMethodId());
jsonMap.put(NEXT_FIELD_ID_TAG, aUniverse.getNextFieldId());

/*
* $$TypeSwitch classes should not be instantiated as they are only used as a container for
* a static method, so no constant of those types should be created. This filter can be
* removed after a mechanism for determining which types have to be persisted is added, or
* if a stable name is implemented for them.
*/
for (AnalysisType type : aUniverse.getTypes().stream().filter(AnalysisType::isTrackedAcrossLayers).toList()) {
checkTypeStability(type);
persistType(type);
Expand Down Expand Up @@ -312,6 +310,16 @@ public void persistAnalysisInfo() {
jsonMap.put(CONSTANTS_TO_RELINK_TAG, constantsToRelink);
}

private void persistAnnotations(AnnotatedElement annotatedElement, EconomicMap<String, Object> typeMap) {
Class<? extends Annotation>[] annotationTypes = AnnotationAccess.getAnnotationTypes(annotatedElement);
persistAnnotations(annotatedElement, typeMap, annotationTypes);
}

@SuppressWarnings("unused")
protected void persistAnnotations(AnnotatedElement annotatedElement, EconomicMap<String, Object> typeMap, Class<? extends Annotation>[] annotationTypes) {
typeMap.put(ANNOTATIONS_TAG, Arrays.stream(annotationTypes).map(Class::getName).toList());
}

/**
* A hook used to persist more general information about the base layer not accessible in
* pointsto.
Expand All @@ -338,6 +346,15 @@ protected void persistType(AnalysisType type) {
*/
persistType(superclass);
}

for (AnalysisType interfaceType : type.getInterfaces()) {
/*
* Some persisted types are not reachable. In this case, the interfaces have to be
* persisted manually as well.
*/
persistType(interfaceType);
}

EconomicMap<String, Object> typeMap = EconomicMap.create();

persistType(type, typeMap);
Expand All @@ -364,8 +381,17 @@ protected void persistType(AnalysisType type, EconomicMap<String, Object> typeMa
typeMap.put(IS_INITIALIZED_TAG, type.isInitialized());
typeMap.put(IS_LINKED_TAG, type.isLinked());
typeMap.put(SOURCE_FILE_NAME_TAG, type.getSourceFileName());
if (type.getEnclosingType() != null) {
typeMap.put(ENCLOSING_TYPE_TAG, type.getEnclosingType().getId());
try {
AnalysisType enclosingType = type.getEnclosingType();
if (enclosingType != null) {
typeMap.put(ENCLOSING_TYPE_TAG, enclosingType.getId());
}
} catch (AnalysisError.TypeNotFoundError e) {
/*
* GR-59571: The enclosing type is not automatically created when the inner type is
* created. If the enclosing type is missing, it is ignored for now. This try/catch
* block could be removed after the trackAcrossLayers is fully implemented.
*/
}
if (type.isArray()) {
typeMap.put(COMPONENT_TYPE_TAG, type.getComponentType().getId());
Expand All @@ -374,7 +400,9 @@ protected void persistType(AnalysisType type, EconomicMap<String, Object> typeMa
typeMap.put(SUPER_CLASS_TAG, type.getSuperclass().getId());
}
typeMap.put(INTERFACES_TAG, Arrays.stream(type.getInterfaces()).map(AnalysisType::getId).toList());
typeMap.put(ANNOTATIONS_TAG, Arrays.stream(AnnotationAccess.getAnnotationTypes(type)).map(Class::getName).toList());
typeMap.put(INSTANCE_FIELDS_TAG, Arrays.stream(type.getInstanceFields(false)).map(field -> ((AnalysisField) field).getId()).toList());
typeMap.put(INSTANCE_FIELDS_WITH_SUPER_TAG, Arrays.stream(type.getInstanceFields(true)).map(field -> ((AnalysisField) field).getId()).toList());
persistAnnotations(type, typeMap);

typeMap.put(IS_INSTANTIATED, type.isInstantiated());
typeMap.put(IS_UNSAFE_ALLOCATED, type.isUnsafeAllocated());
Expand Down Expand Up @@ -410,6 +438,9 @@ protected void persistMethod(AnalysisMethod method, EconomicMap<String, Object>
methodMap.put(ARGUMENTS_TAG, Arrays.stream(executable.getParameterTypes()).map(Class::getName).toList());
methodMap.put(CLASS_NAME_TAG, executable.getDeclaringClass().getName());
}

persistType(method.getSignature().getReturnType());

methodMap.put(TID_TAG, method.getDeclaringClass().getId());
methodMap.put(ARGUMENT_IDS_TAG, method.getSignature().toParameterList(null).stream().map(AnalysisType::getId).toList());
methodMap.put(ID_TAG, method.getId());
Expand All @@ -429,7 +460,7 @@ protected void persistMethod(AnalysisMethod method, EconomicMap<String, Object>
if (intrinsicMethod != null) {
methodMap.put(METHOD_HANDLE_INTRINSIC_TAG, intrinsicMethod.name());
}
methodMap.put(ANNOTATIONS_TAG, Arrays.stream(AnnotationAccess.getAnnotationTypes(method)).map(Class::getName).toList());
persistAnnotations(method, methodMap);

methodMap.put(IS_VIRTUAL_ROOT_METHOD, method.isVirtualRootMethod());
methodMap.put(IS_DIRECT_ROOT_METHOD, method.isDirectRootMethod());
Expand Down Expand Up @@ -524,11 +555,13 @@ protected void persistField(AnalysisField field) {
if (originalField != null && !originalField.getDeclaringClass().equals(field.getDeclaringClass().getJavaClass())) {
fieldMap.put(CLASS_NAME_TAG, originalField.getDeclaringClass().getName());
}
fieldMap.put(IS_STATIC_TAG, field.isStatic());
fieldMap.put(IS_INTERNAL_TAG, field.isInternal());
fieldMap.put(IS_SYNTHETIC_TAG, field.isSynthetic());
fieldMap.put(FIELD_TYPE_TAG, field.getType().getId());
fieldMap.put(MODIFIERS_TAG, field.getModifiers());
fieldMap.put(POSITION_TAG, field.getPosition());
fieldMap.put(ANNOTATIONS_TAG, Arrays.stream(AnnotationAccess.getAnnotationTypes(field)).map(Class::getName).toList());
persistAnnotations(field, fieldMap);

String tid = String.valueOf(field.getDeclaringClass().getId());
fieldsMap.computeIfAbsent(tid, key -> new ConcurrentHashMap<>()).put(field.getName(), fieldMap);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -40,18 +40,20 @@
public class BaseLayerField extends BaseLayerElement implements ResolvedJavaField {
private final int id;
private final String name;
private final AnalysisType declaringClass;
private final AnalysisType type;
private final ResolvedJavaType declaringClass;
private final ResolvedJavaType type;
private final boolean isInternal;
private final boolean isSynthetic;
private final int modifiers;

public BaseLayerField(int id, String name, AnalysisType declaringClass, AnalysisType type, boolean isInternal, int modifiers, Annotation[] annotations) {
public BaseLayerField(int id, String name, ResolvedJavaType declaringClass, ResolvedJavaType type, boolean isInternal, boolean isSynthetic, int modifiers, Annotation[] annotations) {
super(annotations);
this.id = id;
this.name = name;
this.declaringClass = declaringClass;
this.type = type;
this.isInternal = isInternal;
this.isSynthetic = isSynthetic;
this.modifiers = modifiers;
}

Expand All @@ -76,7 +78,7 @@ public boolean isInternal() {

@Override
public boolean isSynthetic() {
throw GraalError.unimplemented("This field is incomplete and should not be used.");
return isSynthetic;
}

@Override
Expand All @@ -86,12 +88,12 @@ public String getName() {

@Override
public JavaType getType() {
return type.getWrapped();
return type;
}

@Override
public ResolvedJavaType getDeclaringClass() {
return declaringClass.getWrapped();
return declaringClass;
}

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -166,7 +166,7 @@ public ExceptionHandler[] getExceptionHandlers() {

@Override
public StackTraceElement asStackTraceElement(int bci) {
throw GraalError.unimplemented("This method is incomplete and should not be used.");
return new StackTraceElement(declaringClass.toClassName(), name, declaringClass.getSourceFileName(), -1);
}

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,8 @@ public class BaseLayerType extends BaseLayerElement implements ResolvedJavaType,
private final ResolvedJavaType superClass;
private final ResolvedJavaType[] interfaces;
private final ResolvedJavaType objectType;
private ResolvedJavaField[] instanceFields;
private ResolvedJavaField[] instanceFieldsWithSuper;

public BaseLayerType(String name, int baseLayerId, int modifiers, boolean isInterface, boolean isEnum, boolean isInitialized, boolean initializedAtBuildTime, boolean isLinked,
String sourceFileName, ResolvedJavaType enclosingType, ResolvedJavaType componentType, ResolvedJavaType superClass, ResolvedJavaType[] interfaces, ResolvedJavaType objectType,
Expand All @@ -85,6 +87,14 @@ public BaseLayerType(String name, int baseLayerId, int modifiers, boolean isInte
this.objectType = objectType;
}

public void setInstanceFields(ResolvedJavaField[] instanceFields) {
this.instanceFields = instanceFields;
}

public void setInstanceFieldsWithSuper(ResolvedJavaField[] instanceFieldsWithSuper) {
this.instanceFieldsWithSuper = instanceFieldsWithSuper;
}

@Override
public boolean isArray() {
return name.charAt(0) == '[';
Expand Down Expand Up @@ -244,11 +254,7 @@ public ResolvedJavaMethod[] getDeclaredMethods(boolean forceLink) {

@Override
public ResolvedJavaField[] getInstanceFields(boolean includeSuperclasses) {
/*
* For now, the base layer types have no fields. If they are needed, a BaseLayerField could
* be created and put in an AnalysisField in a similar way to this BaseLayerType.
*/
return new ResolvedJavaField[0];
return includeSuperclasses ? instanceFieldsWithSuper : instanceFields;
}

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -51,10 +51,11 @@ static AnnotationArrayValue extract(ByteBuffer buf, ConstantPool cp, Class<?> co
return skip ? null : new AnnotationArrayValue(elements);
}

AnnotationArrayValue(Class<?> elementType, Object[] values) {
this.elements = new AnnotationMemberValue[values.length];
for (int i = 0; i < values.length; ++i) {
this.elements[i] = AnnotationMemberValue.from(elementType, values[i]);
AnnotationArrayValue(Class<?> elementType, Object values) {
int length = Array.getLength(values);
this.elements = new AnnotationMemberValue[length];
for (int i = 0; i < length; ++i) {
this.elements[i] = AnnotationMemberValue.from(elementType, Array.get(values, i));
}
}

Expand Down
Loading