diff --git a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/util/ImageHeapList.java b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/util/ImageHeapList.java
index f42b7b4e7541..0847532ecb84 100644
--- a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/util/ImageHeapList.java
+++ b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/util/ImageHeapList.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2024, 2024, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2024, 2025, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -40,14 +40,19 @@
/**
* A list that is filled at image build time while the static analysis is running, and then read at
* run time.
- *
+ *
* Filling the list at image build time is thread safe. Every object added to the list while the
* static analysis is running is properly added to the shadow heap.
- *
+ *
* The list is immutable at run time. The run-time list can optionally be sorted, to make code at
* run time deterministic regardless of the order in which elements are discovered and added at
* image build time. Sorting happens at image build time, but does not affect the list that users
* are adding to at image build time.
+ *
+ * We support (mostly) append-only semantics. Removing elements is not allowed. Changing the
+ * content of the list via iterator is not supported. Note that we allow updating elements at
+ * existing indexes as this operation is already used. We have deliberately chosen this design to
+ * limit the number of analysis rescans needed.
*/
@Platforms(Platform.HOSTED_ONLY.class) //
public final class ImageHeapList {
@@ -76,6 +81,12 @@ public static final class HostedImageHeapList extends AbstractList {
private final Comparator comparator;
private final List hostedList;
public final RuntimeImageHeapList runtimeList;
+ /**
+ * Used to signal if this list has been modified. If true, the change should be propagated
+ * from the hosted list to the runtime list by calling {@link #update()}. This variable
+ * should always be accessed within a synchronized block guarded by the
+ * object's intrinsic lock.
+ */
private boolean modified;
@SuppressWarnings("unchecked")
@@ -115,9 +126,8 @@ public synchronized void add(int index, E element) {
}
@Override
- public synchronized E remove(int index) {
- modified = true;
- return hostedList.remove(index);
+ public E remove(int index) {
+ throw notSupported();
}
@Override
@@ -138,6 +148,14 @@ public synchronized E set(int index, E element) {
public synchronized int size() {
return hostedList.size();
}
+
+ private static UnsupportedOperationException notSupported() {
+ /*
+ * We have deliberately chosen to only support append-only behavior to limit the number
+ * of analysis rescans needed.
+ */
+ throw new UnsupportedOperationException("ImageHeapList has append-only semantics. Removing elements is forbidden.");
+ }
}
}
diff --git a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/util/ImageHeapMap.java b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/util/ImageHeapMap.java
index da473f28e23e..4f99a91def29 100644
--- a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/util/ImageHeapMap.java
+++ b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/util/ImageHeapMap.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2021, 2021, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2021, 2025, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -26,6 +26,8 @@
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.ConcurrentMap;
+import java.util.function.BiFunction;
import org.graalvm.collections.EconomicMap;
import org.graalvm.collections.EconomicMapWrap;
@@ -51,6 +53,10 @@
*
* This map implementation allows thread-safe collection of data at image build time and storing it
* into a space efficient data structure at run time.
+ *
+ * We support append-only semantics. Once added, the elements should never be removed.
+ * Changing the contents of the map via {key, value, entry} iterators is not supported. We
+ * have deliberately chosen this design to limit the number of analysis rescans needed.
*/
@Platforms(Platform.HOSTED_ONLY.class) //
public final class ImageHeapMap {
@@ -107,6 +113,12 @@ public static final class HostedImageHeapMap extends EconomicMapWrap
private final EconomicMap