Skip to content

Commit 87159e5

Browse files
committed
[GR-59009] [GR-59571] Improve trackAcrossLayers
PullRequest: graal/19429
2 parents 1cdb5aa + 9122983 commit 87159e5

File tree

13 files changed

+170
-191
lines changed

13 files changed

+170
-191
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
@@ -590,8 +590,8 @@ public void initializeBaseLayerMethod(AnalysisMethod analysisMethod) {
590590

591591
/**
592592
* Currently we save analysis parsed graphs for methods considered
593-
* {@link AnalysisMethod#isReachable}. See {@link ImageLayerWriter#persistMethodGraphs} for
594-
* implementation.
593+
* {@link AnalysisMethod#isTrackedAcrossLayers()}. See
594+
* {@link ImageLayerWriter#persistAnalysisParsedGraph} for implementation.
595595
*/
596596
public boolean hasAnalysisParsedGraph(AnalysisMethod analysisMethod) {
597597
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
@@ -121,38 +121,9 @@ public class ImageLayerWriter {
121121
private final boolean useSharedLayerGraphs;
122122
private final boolean useSharedLayerStrengthenedGraphs;
123123

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

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

167-
protected record MethodGraphsInfo(String analysisGraphLocation, boolean analysisGraphIsIntrinsic, String strengthenedGraphLocation) {
138+
protected record MethodGraphsInfo(String analysisGraphLocation, boolean analysisGraphIsIntrinsic,
139+
String strengthenedGraphLocation) {
168140

169141
static final MethodGraphsInfo NO_GRAPHS = new MethodGraphsInfo(null, false, null);
170142

@@ -254,6 +226,11 @@ public void setAnalysisUniverse(AnalysisUniverse aUniverse) {
254226
this.aUniverse = aUniverse;
255227
}
256228

229+
@SuppressWarnings("unused")
230+
public void onTrackedAcrossLayer(AnalysisMethod method, Object reason) {
231+
imageLayerWriterHelper.onTrackedAcrossLayer(method, reason);
232+
}
233+
257234
public void dumpFiles() {
258235
graphsOutput.finish();
259236

@@ -293,6 +270,10 @@ public void persistAnalysisInfo() {
293270
snapshotBuilder.setNextFieldId(aUniverse.getNextFieldId());
294271
snapshotBuilder.setNextConstantId(ImageHeapConstant.getCurrentId());
295272

273+
List<AnalysisType> typesToPersist = aUniverse.getTypes().stream().filter(AnalysisType::isTrackedAcrossLayers).toList();
274+
List<AnalysisMethod> methodsToPersist = aUniverse.getMethods().stream().filter(AnalysisMethod::isTrackedAcrossLayers).toList();
275+
List<AnalysisField> fieldsToPersist = aUniverse.getFields().stream().filter(AnalysisField::isTrackedAcrossLayers).toList();
276+
296277
initSortedList(snapshotBuilder::initTypes, typesToPersist, Comparator.comparingInt(AnalysisType::getId), this::persistType);
297278
initSortedList(snapshotBuilder::initMethods, methodsToPersist, Comparator.comparingInt(AnalysisMethod::getId), this::persistMethod);
298279
initSortedList(snapshotBuilder::initFields, fieldsToPersist, Comparator.comparingInt(AnalysisField::getId), this::persistField);
@@ -347,7 +328,7 @@ protected void persistHook() {
347328
}
348329

349330
public boolean isTypePersisted(AnalysisType type) {
350-
return typesToPersist.contains(type);
331+
return type.isTrackedAcrossLayers();
351332
}
352333

353334
private void persistType(AnalysisType type, Supplier<PersistedAnalysisType.Builder> builderSupplier) {
@@ -375,12 +356,6 @@ protected void persistType(AnalysisType type, String typeDescriptor, PersistedAn
375356
if (enclosingType != null) {
376357
builder.setEnclosingTypeId(enclosingType.getId());
377358
}
378-
} catch (AnalysisError.TypeNotFoundError e) {
379-
/*
380-
* GR-59571: The enclosing type is not automatically created when the inner type is
381-
* created. If the enclosing type is missing, it is ignored for now. This try/catch
382-
* block could be removed after the trackAcrossLayers is fully implemented.
383-
*/
384359
} catch (InternalError | TypeNotPresentException | LinkageError e) {
385360
/* Ignore missing type errors. */
386361
}
@@ -401,6 +376,8 @@ protected void persistType(AnalysisType type, String typeDescriptor, PersistedAn
401376
builder.setIsReachable(type.isReachable());
402377

403378
imageLayerWriterHelper.persistType(type, builder);
379+
380+
afterTypeAdded(type);
404381
}
405382

406383
protected static void initInts(IntFunction<PrimitiveList.Int.Builder> builderSupplier, IntStream ids) {
@@ -419,31 +396,17 @@ protected static void initStringList(IntFunction<TextList.Builder> builderSuppli
419396
}
420397
}
421398

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

440403
private void afterConstantAdded(ImageHeapConstant constant) {
441-
ensureTypePersisted(constant.getType());
404+
constant.getType().registerAsTrackedAcrossLayers(constant);
442405
/* If this is a Class constant persist the corresponding type. */
443406
ConstantReflectionProvider constantReflection = aUniverse.getBigbang().getConstantReflectionProvider();
444407
AnalysisType typeFromClassConstant = (AnalysisType) constantReflection.asJavaType(constant);
445408
if (typeFromClassConstant != null) {
446-
ensureTypePersisted(typeFromClassConstant);
409+
typeFromClassConstant.registerAsTrackedAcrossLayers(constant);
447410
}
448411
}
449412

@@ -537,31 +500,25 @@ public boolean isMethodPersisted(AnalysisMethod method) {
537500
return methodsMap.containsKey(name);
538501
}
539502

540-
public void persistMethodGraphs() {
541-
assert aUniverse.sealed();
542-
543-
aUniverse.getTypes().stream().filter(AnalysisType::isTrackedAcrossLayers)
544-
.forEach(this::ensureTypePersisted);
545-
546-
aUniverse.getMethods().stream().filter(AnalysisMethod::isTrackedAcrossLayers)
547-
.forEach(this::ensureMethodPersisted);
548-
549-
aUniverse.getFields().stream().filter(AnalysisField::isTrackedAcrossLayers)
550-
.forEach(this::ensureFieldPersisted);
551-
503+
public void persistAnalysisParsedGraphs() {
552504
// Persisting graphs discovers additional types, members and constants that need persisting
553505
Set<AnalysisMethod> persistedGraphMethods = new HashSet<>();
506+
boolean modified;
554507
do {
555-
for (AnalysisMethod method : methodsToPersist) {
508+
modified = false;
509+
/*
510+
* GR-60503: It would be better to mark all the elements as trackedAcrossLayers before
511+
* the end of the analysis and only iterate only once over all methods.
512+
*/
513+
for (AnalysisMethod method : aUniverse.getMethods().stream().filter(AnalysisMethod::isTrackedAcrossLayers).toList()) {
556514
if (persistedGraphMethods.add(method)) {
515+
modified = true;
557516
persistAnalysisParsedGraph(method);
558517
}
559518
}
560-
} while (!persistedGraphMethods.equals(methodsToPersist));
519+
} while (modified);
561520

562521
// Note that constants are scanned late so all values are available.
563-
564-
sealed = true;
565522
}
566523

567524
private void persistAnalysisParsedGraph(AnalysisMethod method) {
@@ -649,7 +606,9 @@ protected void persistField(AnalysisField field, PersistedAnalysisField.Builder
649606
protected void persistConstant(ImageHeapConstant imageHeapConstant, ConstantParent parent, PersistedConstant.Builder builder, Set<Integer> constantsToRelink) {
650607
int id = getConstantId(imageHeapConstant);
651608
builder.setId(id);
652-
builder.setTypeId(imageHeapConstant.getType().getId());
609+
AnalysisType type = imageHeapConstant.getType();
610+
AnalysisError.guarantee(type.isTrackedAcrossLayers(), "Type %s from constant %s should have been marked as trackedAcrossLayers, but was not", type, imageHeapConstant);
611+
builder.setTypeId(type.getId());
653612

654613
IdentityHashCodeProvider identityHashCodeProvider = (IdentityHashCodeProvider) aUniverse.getBigbang().getConstantReflectionProvider();
655614
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)