Skip to content

Commit 398a5a0

Browse files
committed
Improve trackAcrossLayers
1 parent ca7e8b3 commit 398a5a0

File tree

13 files changed

+148
-182
lines changed

13 files changed

+148
-182
lines changed

substratevm/src/com.oracle.graal.pointsto/src/com/oracle/graal/pointsto/heap/ImageLayerLoader.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -588,8 +588,8 @@ public void initializeBaseLayerMethod(AnalysisMethod analysisMethod) {
588588

589589
/**
590590
* Currently we save analysis parsed graphs for methods considered
591-
* {@link AnalysisMethod#isReachable}. See {@link ImageLayerWriter#persistMethodGraphs} for
592-
* implementation.
591+
* {@link AnalysisMethod#isTrackedAcrossLayers()}. See
592+
* {@link ImageLayerWriter#persistAnalysisParsedGraph} for implementation.
593593
*/
594594
public boolean hasAnalysisParsedGraph(AnalysisMethod analysisMethod) {
595595
return getMethodData(analysisMethod).hasAnalysisGraphLocation();

substratevm/src/com.oracle.graal.pointsto/src/com/oracle/graal/pointsto/heap/ImageLayerSnapshotUtil.java

Lines changed: 20 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,8 @@ public class ImageLayerSnapshotUtil {
6262
public static final int UNDEFINED_CONSTANT_ID = -1;
6363
public static final int UNDEFINED_FIELD_INDEX = -1;
6464

65+
private static final String TRACKED_REASON = "reachable from a graph";
66+
6567
protected final List<Field> externalValueFields;
6668
/** This needs to be initialized after analysis, as some fields are not available before. */
6769
protected Map<Object, Field> externalValues;
@@ -140,10 +142,10 @@ public static class GraphEncoder extends ObjectCopier.Encoder {
140142
public GraphEncoder(Map<Object, Field> externalValues, ImageLayerWriter imageLayerWriter) {
141143
super(externalValues);
142144
addBuiltin(new ImageHeapConstantBuiltIn(imageLayerWriter, null));
143-
addBuiltin(new AnalysisTypeBuiltIn(imageLayerWriter, null));
144-
addBuiltin(new AnalysisMethodBuiltIn(imageLayerWriter, null, null));
145-
addBuiltin(new AnalysisFieldBuiltIn(imageLayerWriter, null));
146-
addBuiltin(new FieldLocationIdentityBuiltIn(imageLayerWriter, null));
145+
addBuiltin(new AnalysisTypeBuiltIn(null));
146+
addBuiltin(new AnalysisMethodBuiltIn(null, null));
147+
addBuiltin(new AnalysisFieldBuiltIn(null));
148+
addBuiltin(new FieldLocationIdentityBuiltIn(null));
147149
}
148150
}
149151

@@ -155,10 +157,10 @@ public GraphDecoder(ClassLoader classLoader, ImageLayerLoader imageLayerLoader,
155157
super(classLoader);
156158
this.imageLayerLoader = imageLayerLoader;
157159
addBuiltin(new ImageHeapConstantBuiltIn(null, imageLayerLoader));
158-
addBuiltin(new AnalysisTypeBuiltIn(null, imageLayerLoader));
159-
addBuiltin(new AnalysisMethodBuiltIn(null, imageLayerLoader, analysisMethod));
160-
addBuiltin(new AnalysisFieldBuiltIn(null, imageLayerLoader));
161-
addBuiltin(new FieldLocationIdentityBuiltIn(null, imageLayerLoader));
160+
addBuiltin(new AnalysisTypeBuiltIn(imageLayerLoader));
161+
addBuiltin(new AnalysisMethodBuiltIn(imageLayerLoader, analysisMethod));
162+
addBuiltin(new AnalysisFieldBuiltIn(imageLayerLoader));
163+
addBuiltin(new FieldLocationIdentityBuiltIn(imageLayerLoader));
162164
}
163165

164166
@Override
@@ -192,19 +194,17 @@ protected Object decode(ObjectCopier.Decoder decoder, Class<?> concreteType, Obj
192194
}
193195

194196
public static class AnalysisTypeBuiltIn extends ObjectCopier.Builtin {
195-
private final ImageLayerWriter imageLayerWriter;
196197
private final ImageLayerLoader imageLayerLoader;
197198

198-
protected AnalysisTypeBuiltIn(ImageLayerWriter imageLayerWriter, ImageLayerLoader imageLayerLoader) {
199+
protected AnalysisTypeBuiltIn(ImageLayerLoader imageLayerLoader) {
199200
super(AnalysisType.class, PointsToAnalysisType.class);
200-
this.imageLayerWriter = imageLayerWriter;
201201
this.imageLayerLoader = imageLayerLoader;
202202
}
203203

204204
@Override
205205
public void encode(ObjectCopier.Encoder encoder, ObjectCopierOutputStream stream, Object obj) throws IOException {
206206
AnalysisType type = (AnalysisType) obj;
207-
imageLayerWriter.ensureTypePersisted(type);
207+
type.registerAsTrackedAcrossLayers(TRACKED_REASON);
208208
stream.writePackedUnsignedInt(type.getId());
209209
}
210210

@@ -216,26 +216,19 @@ protected Object decode(ObjectCopier.Decoder decoder, Class<?> concreteType, Obj
216216
}
217217

218218
public static class AnalysisMethodBuiltIn extends ObjectCopier.Builtin {
219-
private final ImageLayerWriter imageLayerWriter;
220219
private final ImageLayerLoader imageLayerLoader;
221220
private final AnalysisMethod analysisMethod;
222221

223-
protected AnalysisMethodBuiltIn(ImageLayerWriter imageLayerWriter, ImageLayerLoader imageLayerLoader, AnalysisMethod analysisMethod) {
222+
protected AnalysisMethodBuiltIn(ImageLayerLoader imageLayerLoader, AnalysisMethod analysisMethod) {
224223
super(AnalysisMethod.class, PointsToAnalysisMethod.class);
225-
this.imageLayerWriter = imageLayerWriter;
226224
this.imageLayerLoader = imageLayerLoader;
227225
this.analysisMethod = analysisMethod;
228226
}
229227

230228
@Override
231229
public void encode(ObjectCopier.Encoder encoder, ObjectCopierOutputStream stream, Object obj) throws IOException {
232230
AnalysisMethod method = (AnalysisMethod) obj;
233-
AnalysisType declaringClass = method.getDeclaringClass();
234-
imageLayerWriter.ensureMethodPersisted(method);
235-
for (AnalysisType parameter : method.toParameterList()) {
236-
imageLayerWriter.ensureTypePersisted(parameter);
237-
}
238-
imageLayerWriter.ensureTypePersisted(declaringClass);
231+
method.registerAsTrackedAcrossLayers(TRACKED_REASON);
239232
stream.writePackedUnsignedInt(method.getId());
240233
}
241234

@@ -250,19 +243,17 @@ protected Object decode(ObjectCopier.Decoder decoder, Class<?> concreteType, Obj
250243
}
251244

252245
public static class AnalysisFieldBuiltIn extends ObjectCopier.Builtin {
253-
private final ImageLayerWriter imageLayerWriter;
254246
private final ImageLayerLoader imageLayerLoader;
255247

256-
protected AnalysisFieldBuiltIn(ImageLayerWriter imageLayerWriter, ImageLayerLoader imageLayerLoader) {
248+
protected AnalysisFieldBuiltIn(ImageLayerLoader imageLayerLoader) {
257249
super(AnalysisField.class, PointsToAnalysisField.class);
258-
this.imageLayerWriter = imageLayerWriter;
259250
this.imageLayerLoader = imageLayerLoader;
260251
}
261252

262253
@Override
263254
public void encode(ObjectCopier.Encoder encoder, ObjectCopierOutputStream stream, Object obj) throws IOException {
264255
AnalysisField field = (AnalysisField) obj;
265-
int id = encodeField(field, imageLayerWriter);
256+
int id = encodeField(field);
266257
stream.writePackedUnsignedInt(id);
267258
}
268259

@@ -274,20 +265,18 @@ protected Object decode(ObjectCopier.Decoder decoder, Class<?> concreteType, Obj
274265
}
275266

276267
public static class FieldLocationIdentityBuiltIn extends ObjectCopier.Builtin {
277-
private final ImageLayerWriter imageLayerWriter;
278268
private final ImageLayerLoader imageLayerLoader;
279269

280-
protected FieldLocationIdentityBuiltIn(ImageLayerWriter imageLayerWriter, ImageLayerLoader imageLayerLoader) {
270+
protected FieldLocationIdentityBuiltIn(ImageLayerLoader imageLayerLoader) {
281271
super(FieldLocationIdentity.class);
282-
this.imageLayerWriter = imageLayerWriter;
283272
this.imageLayerLoader = imageLayerLoader;
284273
}
285274

286275
@Override
287276
public void encode(ObjectCopier.Encoder encoder, ObjectCopierOutputStream stream, Object obj) throws IOException {
288277
FieldLocationIdentity fieldLocationIdentity = (FieldLocationIdentity) obj;
289278
AnalysisField field = (AnalysisField) fieldLocationIdentity.getField();
290-
int id = encodeField(field, imageLayerWriter);
279+
int id = encodeField(field);
291280
stream.writePackedUnsignedInt(id);
292281
}
293282

@@ -298,8 +287,8 @@ protected Object decode(ObjectCopier.Decoder decoder, Class<?> concreteType, Obj
298287
}
299288
}
300289

301-
private static int encodeField(AnalysisField field, ImageLayerWriter imageLayerWriter) {
302-
imageLayerWriter.ensureFieldPersisted(field);
290+
private static int encodeField(AnalysisField field) {
291+
field.registerAsTrackedAcrossLayers(TRACKED_REASON);
303292
return field.getId();
304293
}
305294

substratevm/src/com.oracle.graal.pointsto/src/com/oracle/graal/pointsto/heap/ImageLayerWriter.java

Lines changed: 30 additions & 71 deletions
Original file line numberDiff line numberDiff line change
@@ -119,38 +119,9 @@ public class ImageLayerWriter {
119119
private final boolean useSharedLayerGraphs;
120120
private final boolean useSharedLayerStrengthenedGraphs;
121121

122-
/*
123-
* Types, members and constants to persist even when they are not considered reachable by the
124-
* analysis, or referenced from the image heap. Typically, these elements would be reachable
125-
* from a persisted graph.
126-
*/
127-
private boolean sealed = false;
128-
private final Set<AnalysisType> typesToPersist = ConcurrentHashMap.newKeySet();
129-
private final Set<AnalysisMethod> methodsToPersist = ConcurrentHashMap.newKeySet();
130-
private final Set<AnalysisField> fieldsToPersist = ConcurrentHashMap.newKeySet();
131122
private final Set<ImageHeapConstant> constantsToPersist = ConcurrentHashMap.newKeySet();
132123

133-
public void ensureTypePersisted(AnalysisType type) {
134-
assert !sealed;
135-
if (typesToPersist.add(type)) {
136-
afterTypeAdded(type);
137-
}
138-
}
139-
140-
public void ensureMethodPersisted(AnalysisMethod method) {
141-
assert !sealed;
142-
if (methodsToPersist.add(method)) {
143-
afterMethodAdded(method);
144-
}
145-
}
146-
147-
public void ensureFieldPersisted(AnalysisField field) {
148-
assert !sealed;
149-
fieldsToPersist.add(field);
150-
}
151-
152124
public void ensureConstantPersisted(ImageHeapConstant constant) {
153-
assert !sealed;
154125
constantsToPersist.add(constant);
155126
afterConstantAdded(constant);
156127
}
@@ -162,7 +133,8 @@ protected record ConstantParent(int constantId, int index) {
162133
private record FileInfo(Path layerFilePath, String fileName, String suffix) {
163134
}
164135

165-
protected record MethodGraphsInfo(String analysisGraphLocation, boolean analysisGraphIsIntrinsic, String strengthenedGraphLocation) {
136+
protected record MethodGraphsInfo(String analysisGraphLocation, boolean analysisGraphIsIntrinsic,
137+
String strengthenedGraphLocation) {
166138

167139
static final MethodGraphsInfo NO_GRAPHS = new MethodGraphsInfo(null, false, null);
168140

@@ -252,6 +224,11 @@ public void setAnalysisUniverse(AnalysisUniverse aUniverse) {
252224
this.aUniverse = aUniverse;
253225
}
254226

227+
@SuppressWarnings("unused")
228+
public void onTrackedAcrossLayer(AnalysisMethod method, Object reason) {
229+
imageLayerWriterHelper.onTrackedAcrossLayer(method, reason);
230+
}
231+
255232
public void dumpFiles() {
256233
graphsOutput.finish();
257234

@@ -291,6 +268,10 @@ public void persistAnalysisInfo() {
291268
snapshotBuilder.setNextFieldId(aUniverse.getNextFieldId());
292269
snapshotBuilder.setNextConstantId(ImageHeapConstant.getCurrentId());
293270

271+
List<AnalysisType> typesToPersist = aUniverse.getTypes().stream().filter(AnalysisType::isTrackedAcrossLayers).toList();
272+
List<AnalysisMethod> methodsToPersist = aUniverse.getMethods().stream().filter(AnalysisMethod::isTrackedAcrossLayers).toList();
273+
List<AnalysisField> fieldsToPersist = aUniverse.getFields().stream().filter(AnalysisField::isTrackedAcrossLayers).toList();
274+
294275
initSortedList(snapshotBuilder::initTypes, typesToPersist, Comparator.comparingInt(AnalysisType::getId), this::persistType);
295276
initSortedList(snapshotBuilder::initMethods, methodsToPersist, Comparator.comparingInt(AnalysisMethod::getId), this::persistMethod);
296277
initSortedList(snapshotBuilder::initFields, fieldsToPersist, Comparator.comparingInt(AnalysisField::getId), this::persistField);
@@ -345,7 +326,7 @@ protected void persistHook() {
345326
}
346327

347328
public boolean isTypePersisted(AnalysisType type) {
348-
return typesToPersist.contains(type);
329+
return type.isTrackedAcrossLayers();
349330
}
350331

351332
private void persistType(AnalysisType type, Supplier<PersistedAnalysisType.Builder> builderSupplier) {
@@ -373,12 +354,6 @@ protected void persistType(AnalysisType type, String typeDescriptor, PersistedAn
373354
if (enclosingType != null) {
374355
builder.setEnclosingTypeId(enclosingType.getId());
375356
}
376-
} catch (AnalysisError.TypeNotFoundError e) {
377-
/*
378-
* GR-59571: The enclosing type is not automatically created when the inner type is
379-
* created. If the enclosing type is missing, it is ignored for now. This try/catch
380-
* block could be removed after the trackAcrossLayers is fully implemented.
381-
*/
382357
} catch (InternalError | TypeNotPresentException | LinkageError e) {
383358
/* Ignore missing type errors. */
384359
}
@@ -399,6 +374,8 @@ protected void persistType(AnalysisType type, String typeDescriptor, PersistedAn
399374
builder.setIsReachable(type.isReachable());
400375

401376
imageLayerWriterHelper.persistType(type, builder);
377+
378+
afterTypeAdded(type);
402379
}
403380

404381
protected static void initInts(IntFunction<PrimitiveList.Int.Builder> builderSupplier, IntStream ids) {
@@ -417,31 +394,17 @@ protected static void initStringList(IntFunction<TextList.Builder> builderSuppli
417394
}
418395
}
419396

397+
@SuppressWarnings("unused")
420398
protected void afterTypeAdded(AnalysisType type) {
421-
/*
422-
* Some persisted types are not reachable. In this case, the super class and interfaces have
423-
* to be persisted manually as well.
424-
*/
425-
if (type.getSuperclass() != null) {
426-
ensureTypePersisted(type.getSuperclass());
427-
}
428-
for (AnalysisType iface : type.getInterfaces()) {
429-
ensureTypePersisted(iface);
430-
}
431-
}
432-
433-
protected void afterMethodAdded(AnalysisMethod method) {
434-
ensureTypePersisted(method.getSignature().getReturnType());
435-
imageLayerWriterHelper.afterMethodAdded(method);
436399
}
437400

438401
private void afterConstantAdded(ImageHeapConstant constant) {
439-
ensureTypePersisted(constant.getType());
402+
constant.getType().registerAsTrackedAcrossLayers(constant);
440403
/* If this is a Class constant persist the corresponding type. */
441404
ConstantReflectionProvider constantReflection = aUniverse.getBigbang().getConstantReflectionProvider();
442405
AnalysisType typeFromClassConstant = (AnalysisType) constantReflection.asJavaType(constant);
443406
if (typeFromClassConstant != null) {
444-
ensureTypePersisted(typeFromClassConstant);
407+
typeFromClassConstant.registerAsTrackedAcrossLayers(constant);
445408
}
446409
}
447410

@@ -535,31 +498,25 @@ public boolean isMethodPersisted(AnalysisMethod method) {
535498
return methodsMap.containsKey(name);
536499
}
537500

538-
public void persistMethodGraphs() {
539-
assert aUniverse.sealed();
540-
541-
aUniverse.getTypes().stream().filter(AnalysisType::isTrackedAcrossLayers)
542-
.forEach(this::ensureTypePersisted);
543-
544-
aUniverse.getMethods().stream().filter(AnalysisMethod::isTrackedAcrossLayers)
545-
.forEach(this::ensureMethodPersisted);
546-
547-
aUniverse.getFields().stream().filter(AnalysisField::isTrackedAcrossLayers)
548-
.forEach(this::ensureFieldPersisted);
549-
501+
public void persistAnalysisParsedGraphs() {
550502
// Persisting graphs discovers additional types, members and constants that need persisting
551503
Set<AnalysisMethod> persistedGraphMethods = new HashSet<>();
504+
boolean modified;
552505
do {
553-
for (AnalysisMethod method : methodsToPersist) {
506+
modified = false;
507+
/*
508+
* GR-60503: It would be better to mark all the elements as trackedAcrossLayers before
509+
* the end of the analysis and only iterate only once over all methods.
510+
*/
511+
for (AnalysisMethod method : aUniverse.getMethods().stream().filter(AnalysisMethod::isTrackedAcrossLayers).toList()) {
554512
if (persistedGraphMethods.add(method)) {
513+
modified = true;
555514
persistAnalysisParsedGraph(method);
556515
}
557516
}
558-
} while (!persistedGraphMethods.equals(methodsToPersist));
517+
} while (modified);
559518

560519
// Note that constants are scanned late so all values are available.
561-
562-
sealed = true;
563520
}
564521

565522
private void persistAnalysisParsedGraph(AnalysisMethod method) {
@@ -647,7 +604,9 @@ protected void persistField(AnalysisField field, PersistedAnalysisField.Builder
647604
protected void persistConstant(ImageHeapConstant imageHeapConstant, ConstantParent parent, PersistedConstant.Builder builder, Set<Integer> constantsToRelink) {
648605
int id = getConstantId(imageHeapConstant);
649606
builder.setId(id);
650-
builder.setTypeId(imageHeapConstant.getType().getId());
607+
AnalysisType type = imageHeapConstant.getType();
608+
AnalysisError.guarantee(type.isTrackedAcrossLayers(), "Type %s from constant %s should have been marked as trackedAcrossLayers, but was not", type, imageHeapConstant);
609+
builder.setTypeId(type.getId());
651610

652611
IdentityHashCodeProvider identityHashCodeProvider = (IdentityHashCodeProvider) aUniverse.getBigbang().getConstantReflectionProvider();
653612
int identityHashCode = identityHashCodeProvider.identityHashCode(imageHeapConstant);

substratevm/src/com.oracle.graal.pointsto/src/com/oracle/graal/pointsto/heap/ImageLayerWriterHelper.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,6 @@ protected void persistMethod(AnalysisMethod method, PersistedAnalysisMethod.Buil
4747
}
4848

4949
@SuppressWarnings("unused")
50-
protected void afterMethodAdded(AnalysisMethod method) {
50+
protected void onTrackedAcrossLayer(AnalysisMethod method, Object reason) {
5151
}
5252
}

0 commit comments

Comments
 (0)