Skip to content

Commit 74ad263

Browse files
committed
Allow cancellation of image-heap laying out
1 parent 3932a4f commit 74ad263

File tree

7 files changed

+70
-20
lines changed

7 files changed

+70
-20
lines changed

substratevm/src/com.oracle.svm.core.genscavenge/src/com/oracle/svm/core/genscavenge/ChunkedImageHeapLayouter.java

Lines changed: 14 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -39,8 +39,8 @@
3939
import com.oracle.svm.core.genscavenge.remset.RememberedSet;
4040
import com.oracle.svm.core.hub.DynamicHub;
4141
import com.oracle.svm.core.image.ImageHeap;
42-
import com.oracle.svm.core.image.ImageHeapLayoutInfo;
4342
import com.oracle.svm.core.image.ImageHeapLayouter;
43+
import com.oracle.svm.core.image.ImageHeapLayoutInfo;
4444
import com.oracle.svm.core.image.ImageHeapObject;
4545
import com.oracle.svm.core.option.SubstrateOptionsParser;
4646
import com.oracle.svm.core.util.UserError;
@@ -156,11 +156,12 @@ private Error reportHugeObjectError(ImageHeapObject info, String objectTypeMsg,
156156
}
157157

158158
@Override
159-
public ImageHeapLayoutInfo layout(ImageHeap imageHeap, int pageSize) {
159+
public ImageHeapLayoutInfo layout(ImageHeap imageHeap, int pageSize, ImageHeapLayouterCallback callback) {
160+
ImageHeapLayouterControl control = new ImageHeapLayouterControl(callback);
160161
int objectAlignment = ConfigurationValues.getObjectLayout().getAlignment();
161162
assert pageSize % objectAlignment == 0 : "Page size does not match object alignment";
162163

163-
ImageHeapLayoutInfo layoutInfo = doLayout(imageHeap, pageSize);
164+
ImageHeapLayoutInfo layoutInfo = doLayout(imageHeap, pageSize, control);
164165

165166
for (ChunkedImageHeapPartition partition : getPartitions()) {
166167
assert partition.getStartOffset() % partition.getStartAlignment() == 0 : partition;
@@ -170,15 +171,16 @@ public ImageHeapLayoutInfo layout(ImageHeap imageHeap, int pageSize) {
170171
return layoutInfo;
171172
}
172173

173-
private ImageHeapLayoutInfo doLayout(ImageHeap imageHeap, int pageSize) {
174+
private ImageHeapLayoutInfo doLayout(ImageHeap imageHeap, int pageSize, ImageHeapLayouterControl control) {
174175
allocator = new ChunkedImageHeapAllocator(imageHeap, startOffset);
175176
for (ChunkedImageHeapPartition partition : getPartitions()) {
176-
partition.layout(allocator);
177+
control.poll();
178+
partition.layout(allocator, control);
177179
}
178-
return populateInfoObjects(imageHeap.countAndVerifyDynamicHubs(), pageSize);
180+
return populateInfoObjects(imageHeap.countAndVerifyDynamicHubs(), pageSize, control);
179181
}
180182

181-
private ImageHeapLayoutInfo populateInfoObjects(int dynamicHubCount, int pageSize) {
183+
private ImageHeapLayoutInfo populateInfoObjects(int dynamicHubCount, int pageSize, ImageHeapLayouterControl control) {
182184
// Determine writable start boundary from chunks: a chunk that contains writable objects
183185
// must also have a writable card table
184186
long offsetOfFirstWritableAlignedChunk = -1;
@@ -188,6 +190,8 @@ private ImageHeapLayoutInfo populateInfoObjects(int dynamicHubCount, int pageSiz
188190
break; // (chunks are in ascending memory order)
189191
}
190192
}
193+
control.poll();
194+
191195
VMError.guarantee(offsetOfFirstWritableAlignedChunk >= 0 && offsetOfFirstWritableAlignedChunk % pageSize == 0, "Start of the writable part is assumed to be page-aligned");
192196
long offsetOfFirstWritableUnalignedChunk = -1;
193197
long offsetOfLastWritableUnalignedChunk = -1;
@@ -200,13 +204,16 @@ private ImageHeapLayoutInfo populateInfoObjects(int dynamicHubCount, int pageSiz
200204
}
201205
offsetOfLastWritableUnalignedChunk = chunk.getBegin();
202206
}
207+
control.poll();
203208

204209
heapInfo.initialize(getReadOnlyRegular().firstObject, getReadOnlyRegular().lastObject, getReadOnlyRelocatable().firstObject, getReadOnlyRelocatable().lastObject,
205210
getWritablePatched().firstObject, getWritablePatched().lastObject,
206211
getWritableRegular().firstObject, getWritableRegular().lastObject, getWritableHuge().firstObject, getWritableHuge().lastObject,
207212
getReadOnlyHuge().firstObject, getReadOnlyHuge().lastObject, offsetOfFirstWritableAlignedChunk, offsetOfFirstWritableUnalignedChunk, offsetOfLastWritableUnalignedChunk,
208213
dynamicHubCount);
209214

215+
control.poll();
216+
210217
long writableEnd = getWritableHuge().getStartOffset() + getWritableHuge().getSize();
211218
long writableSize = writableEnd - offsetOfFirstWritableAlignedChunk;
212219
long imageHeapSize = getReadOnlyHuge().getStartOffset() + getReadOnlyHuge().getSize() - startOffset;

substratevm/src/com.oracle.svm.core.genscavenge/src/com/oracle/svm/core/genscavenge/ChunkedImageHeapPartition.java

Lines changed: 10 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@
3232
import java.util.TreeMap;
3333

3434
import com.oracle.svm.core.config.ConfigurationValues;
35+
import com.oracle.svm.core.image.ImageHeapLayouter.ImageHeapLayouterControl;
3536
import com.oracle.svm.core.image.ImageHeapObject;
3637
import com.oracle.svm.core.image.ImageHeapPartition;
3738

@@ -72,44 +73,46 @@ void assign(ImageHeapObject obj) {
7273
objects.add(obj);
7374
}
7475

75-
void layout(ChunkedImageHeapAllocator allocator) {
76+
void layout(ChunkedImageHeapAllocator allocator, ImageHeapLayouterControl control) {
7677
if (hugeObjects) {
77-
layoutInUnalignedChunks(allocator);
78+
layoutInUnalignedChunks(allocator, control);
7879
} else {
79-
layoutInAlignedChunks(allocator);
80+
layoutInAlignedChunks(allocator, control);
8081
}
8182
}
8283

83-
private void layoutInUnalignedChunks(ChunkedImageHeapAllocator allocator) {
84+
private void layoutInUnalignedChunks(ChunkedImageHeapAllocator allocator, ImageHeapLayouterControl control) {
8485
allocator.finishAlignedChunk();
8586
allocator.alignBetweenChunks(getStartAlignment());
8687
startOffset = allocator.getPosition();
8788

8889
for (ImageHeapObject info : objects) { // No need to sort by size
8990
appendAllocatedObject(info, allocator.allocateUnalignedChunkForObject(info, isWritable()));
91+
control.poll();
9092
}
9193

9294
allocator.alignBetweenChunks(getEndAlignment());
9395
endOffset = allocator.getPosition();
9496
}
9597

96-
private void layoutInAlignedChunks(ChunkedImageHeapAllocator allocator) {
98+
private void layoutInAlignedChunks(ChunkedImageHeapAllocator allocator, ImageHeapLayouterControl control) {
9799
allocator.maybeStartAlignedChunk();
98100
allocator.alignInAlignedChunk(getStartAlignment());
99101
startOffset = allocator.getPosition();
100102

101-
allocateObjectsInAlignedChunks(allocator);
103+
allocateObjectsInAlignedChunks(allocator, control);
102104

103105
allocator.alignInAlignedChunk(getEndAlignment());
104106
endOffset = allocator.getPosition();
105107
}
106108

107-
private void allocateObjectsInAlignedChunks(ChunkedImageHeapAllocator allocator) {
109+
private void allocateObjectsInAlignedChunks(ChunkedImageHeapAllocator allocator, ImageHeapLayouterControl control) {
108110
NavigableMap<Long, Queue<ImageHeapObject>> sortedObjects = createSortedObjectsMap();
109111
while (!sortedObjects.isEmpty()) {
110112
ImageHeapObject info = dequeueBestFit(sortedObjects, allocator.getRemainingBytesInAlignedChunk());
111113
if (info == null) {
112114
allocator.startNewAlignedChunk();
115+
control.poll();
113116
} else {
114117
appendAllocatedObject(info, allocator.allocateObjectInAlignedChunk(info, isWritable()));
115118
}

substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/image/ImageHeapLayouter.java

Lines changed: 39 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -43,9 +43,11 @@ public interface ImageHeapLayouter {
4343
void assignObjectToPartition(ImageHeapObject info, boolean immutable, boolean references, boolean relocatable, boolean patched);
4444

4545
/**
46-
* Places all heap partitions and assigns objects their final offsets.
46+
* Places all heap partitions and assigns objects their final offsets. The layout operation can
47+
* be cancelled through the {@link ImageHeapLayouterCallback}. If the layout is cancelled, an
48+
* instance of {@link ImageHeapLayoutCancelledException} is thrown.
4749
*/
48-
ImageHeapLayoutInfo layout(ImageHeap imageHeap, int pageSize);
50+
ImageHeapLayoutInfo layout(ImageHeap imageHeap, int pageSize, ImageHeapLayouterCallback callback);
4951

5052
/** Hook to run tasks after heap layout is finished. */
5153
@SuppressWarnings("unused")
@@ -63,4 +65,39 @@ default void afterLayout(ImageHeap imageHeap) {
6365
* same offset in the given buffer, the same offset must be specified to this method.
6466
*/
6567
void writeMetadata(ByteBuffer imageHeapBytes, long imageHeapOffsetInBuffer);
68+
69+
/**
70+
* Facilitates {@link ImageHeapLayouter#layout} cancellation through an
71+
* {@link ImageHeapLayouterCallback} instance.
72+
*/
73+
class ImageHeapLayouterControl {
74+
protected final ImageHeapLayouterCallback callback;
75+
76+
public ImageHeapLayouterControl(ImageHeapLayouterCallback callback) {
77+
this.callback = callback;
78+
}
79+
80+
public void poll() throws ImageHeapLayoutCancelledException {
81+
if (callback.shouldCancel()) {
82+
throw new ImageHeapLayoutCancelledException();
83+
}
84+
}
85+
}
86+
87+
interface ImageHeapLayouterCallback {
88+
89+
ImageHeapLayouterCallback NONE = () -> false;
90+
91+
/**
92+
* Called periodically to determine whether the operation should be canceled.
93+
*/
94+
boolean shouldCancel();
95+
}
96+
97+
class ImageHeapLayoutCancelledException extends RuntimeException {
98+
private static final long serialVersionUID = 1017980175582546348L;
99+
100+
public ImageHeapLayoutCancelledException() {
101+
}
102+
}
66103
}

substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/image/NativeImage.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -94,6 +94,7 @@
9494
import com.oracle.svm.core.graal.nodes.TLABObjectHeaderConstant;
9595
import com.oracle.svm.core.heap.Heap;
9696
import com.oracle.svm.core.image.ImageHeapLayoutInfo;
97+
import com.oracle.svm.core.image.ImageHeapLayouter.ImageHeapLayouterCallback;
9798
import com.oracle.svm.core.image.ImageHeapPartition;
9899
import com.oracle.svm.core.imagelayer.DynamicImageLayerInfo;
99100
import com.oracle.svm.core.imagelayer.ImageLayerBuildingSupport;
@@ -436,7 +437,7 @@ public void build(String imageName, DebugContext debug) {
436437

437438
long roSectionSize = codeCache.getAlignedConstantsSize();
438439
long rwSectionSize = ConfigurationValues.getObjectLayout().alignUp(cGlobals.getSize());
439-
heapLayout = heap.getLayouter().layout(heap, objectFile.getPageSize());
440+
heapLayout = heap.getLayouter().layout(heap, objectFile.getPageSize(), ImageHeapLayouterCallback.NONE);
440441
// after this point, the layout is final and must not be changed anymore
441442
assert !hasDuplicatedObjects(heap.getObjects()) : "heap.getObjects() must not contain any duplicates";
442443

web-image/src/com.oracle.svm.hosted.webimage/src/com/oracle/svm/hosted/webimage/wasm/codegen/WebImageWasmLMCodeGen.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@
3636
import com.oracle.svm.core.c.CGlobalData;
3737
import com.oracle.svm.core.graal.code.CGlobalDataReference;
3838
import com.oracle.svm.core.image.ImageHeapLayoutInfo;
39+
import com.oracle.svm.core.image.ImageHeapLayouter.ImageHeapLayouterCallback;
3940
import com.oracle.svm.core.meta.MethodPointer;
4041
import com.oracle.svm.hosted.image.NativeImageHeap;
4142
import com.oracle.svm.hosted.image.NativeImageHeapWriter;
@@ -90,7 +91,7 @@ public long getImageHeapSize() {
9091
*/
9192
@Override
9293
protected void writeImageHeap() {
93-
ImageHeapLayoutInfo layout = codeCache.nativeImageHeap.getLayouter().layout(codeCache.nativeImageHeap, WasmUtil.PAGE_SIZE);
94+
ImageHeapLayoutInfo layout = codeCache.nativeImageHeap.getLayouter().layout(codeCache.nativeImageHeap, WasmUtil.PAGE_SIZE, ImageHeapLayouterCallback.NONE);
9495
setLayout(layout);
9596

9697
afterHeapLayout();

web-image/src/com.oracle.svm.hosted.webimage/src/com/oracle/svm/hosted/webimage/wasmgc/codegen/WasmGCHeapWriter.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,7 @@
4949
import com.oracle.graal.pointsto.util.AnalysisError;
5050
import com.oracle.svm.core.hub.DynamicHub;
5151
import com.oracle.svm.core.hub.Hybrid;
52+
import com.oracle.svm.core.image.ImageHeapLayouter.ImageHeapLayouterCallback;
5253
import com.oracle.svm.core.meta.MethodPointer;
5354
import com.oracle.svm.core.meta.SubstrateMethodPointerConstant;
5455
import com.oracle.svm.core.util.VMError;
@@ -273,7 +274,7 @@ public WasmGCHeapWriter(WebImageCodeCache codeCache, WebImageWasmGCProviders pro
273274

274275
public WasmGCImageHeapLayoutInfo layout() {
275276
collectObjectData();
276-
return (WasmGCImageHeapLayoutInfo) heap.getLayouter().layout(heap, WasmUtil.PAGE_SIZE);
277+
return (WasmGCImageHeapLayoutInfo) heap.getLayouter().layout(heap, WasmUtil.PAGE_SIZE, ImageHeapLayouterCallback.NONE);
277278
}
278279

279280
public void write(WasmGCImageHeapLayoutInfo layout, WasmModule module) {

web-image/src/com.oracle.svm.hosted.webimage/src/com/oracle/svm/hosted/webimage/wasmgc/image/WasmGCHeapLayouter.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -73,7 +73,7 @@ public void assignObjectToPartition(ImageHeapObject info, boolean immutable, boo
7373
}
7474

7575
@Override
76-
public WasmGCImageHeapLayoutInfo layout(ImageHeap imageHeap, int pageSize) {
76+
public WasmGCImageHeapLayoutInfo layout(ImageHeap imageHeap, int pageSize, ImageHeapLayouterCallback callback) {
7777
layoutPseudoPartition();
7878
doLayout();
7979

0 commit comments

Comments
 (0)