Skip to content

Commit 79efd4d

Browse files
committed
Allow cancellation of image-heap laying out
1 parent 92b2647 commit 79efd4d

File tree

8 files changed

+196
-20
lines changed

8 files changed

+196
-20
lines changed

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

Lines changed: 15 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -39,8 +39,10 @@
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.ImageHeapLayingOutControl;
44+
import com.oracle.svm.core.image.ImageHeapLayingOutController;
45+
import com.oracle.svm.core.image.ImageHeapLayoutInfo;
4446
import com.oracle.svm.core.image.ImageHeapObject;
4547
import com.oracle.svm.core.option.SubstrateOptionsParser;
4648
import com.oracle.svm.core.util.UserError;
@@ -156,11 +158,12 @@ private Error reportHugeObjectError(ImageHeapObject info, String objectTypeMsg,
156158
}
157159

158160
@Override
159-
public ImageHeapLayoutInfo layout(ImageHeap imageHeap, int pageSize) {
161+
public ImageHeapLayoutInfo layout(ImageHeap imageHeap, int pageSize, ImageHeapLayingOutController controller) {
162+
ImageHeapLayingOutControl control = new ImageHeapLayingOutControl(controller);
160163
int objectAlignment = ConfigurationValues.getObjectLayout().getAlignment();
161164
assert pageSize % objectAlignment == 0 : "Page size does not match object alignment";
162165

163-
ImageHeapLayoutInfo layoutInfo = doLayout(imageHeap, pageSize);
166+
ImageHeapLayoutInfo layoutInfo = doLayout(imageHeap, pageSize, control);
164167

165168
for (ChunkedImageHeapPartition partition : getPartitions()) {
166169
assert partition.getStartOffset() % partition.getStartAlignment() == 0 : partition;
@@ -170,15 +173,16 @@ public ImageHeapLayoutInfo layout(ImageHeap imageHeap, int pageSize) {
170173
return layoutInfo;
171174
}
172175

173-
private ImageHeapLayoutInfo doLayout(ImageHeap imageHeap, int pageSize) {
176+
private ImageHeapLayoutInfo doLayout(ImageHeap imageHeap, int pageSize, ImageHeapLayingOutControl control) {
174177
allocator = new ChunkedImageHeapAllocator(imageHeap, startOffset);
175178
for (ChunkedImageHeapPartition partition : getPartitions()) {
176-
partition.layout(allocator);
179+
control.heartbeat();
180+
partition.layout(allocator, control);
177181
}
178-
return populateInfoObjects(imageHeap.countAndVerifyDynamicHubs(), pageSize);
182+
return populateInfoObjects(imageHeap.countAndVerifyDynamicHubs(), pageSize, control);
179183
}
180184

181-
private ImageHeapLayoutInfo populateInfoObjects(int dynamicHubCount, int pageSize) {
185+
private ImageHeapLayoutInfo populateInfoObjects(int dynamicHubCount, int pageSize, ImageHeapLayingOutControl control) {
182186
// Determine writable start boundary from chunks: a chunk that contains writable objects
183187
// must also have a writable card table
184188
long offsetOfFirstWritableAlignedChunk = -1;
@@ -187,6 +191,7 @@ private ImageHeapLayoutInfo populateInfoObjects(int dynamicHubCount, int pageSiz
187191
offsetOfFirstWritableAlignedChunk = chunk.getBegin();
188192
break; // (chunks are in ascending memory order)
189193
}
194+
control.heartbeat();
190195
}
191196
VMError.guarantee(offsetOfFirstWritableAlignedChunk >= 0 && offsetOfFirstWritableAlignedChunk % pageSize == 0, "Start of the writable part is assumed to be page-aligned");
192197
long offsetOfFirstWritableUnalignedChunk = -1;
@@ -199,6 +204,7 @@ private ImageHeapLayoutInfo populateInfoObjects(int dynamicHubCount, int pageSiz
199204
offsetOfFirstWritableUnalignedChunk = chunk.getBegin();
200205
}
201206
offsetOfLastWritableUnalignedChunk = chunk.getBegin();
207+
control.heartbeat();
202208
}
203209

204210
heapInfo.initialize(getReadOnlyRegular().firstObject, getReadOnlyRegular().lastObject, getReadOnlyRelocatable().firstObject, getReadOnlyRelocatable().lastObject,
@@ -207,6 +213,8 @@ private ImageHeapLayoutInfo populateInfoObjects(int dynamicHubCount, int pageSiz
207213
getReadOnlyHuge().firstObject, getReadOnlyHuge().lastObject, offsetOfFirstWritableAlignedChunk, offsetOfFirstWritableUnalignedChunk, offsetOfLastWritableUnalignedChunk,
208214
dynamicHubCount);
209215

216+
control.heartbeat();
217+
210218
long writableEnd = getWritableHuge().getStartOffset() + getWritableHuge().getSize();
211219
long writableSize = writableEnd - offsetOfFirstWritableAlignedChunk;
212220
long imageHeapSize = getReadOnlyHuge().getStartOffset() + getReadOnlyHuge().getSize() - startOffset;

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

Lines changed: 11 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.ImageHeapLayingOutControl;
3536
import com.oracle.svm.core.image.ImageHeapObject;
3637
import com.oracle.svm.core.image.ImageHeapPartition;
3738

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

75-
void layout(ChunkedImageHeapAllocator allocator) {
76+
void layout(ChunkedImageHeapAllocator allocator, ImageHeapLayingOutControl 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, ImageHeapLayingOutControl 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.heartbeat();
9092
}
9193

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

96-
private void layoutInAlignedChunks(ChunkedImageHeapAllocator allocator) {
98+
private void layoutInAlignedChunks(ChunkedImageHeapAllocator allocator, ImageHeapLayingOutControl 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, ImageHeapLayingOutControl control) {
108110
NavigableMap<Long, Queue<ImageHeapObject>> sortedObjects = createSortedObjectsMap();
111+
control.heartbeat();
109112
while (!sortedObjects.isEmpty()) {
110113
ImageHeapObject info = dequeueBestFit(sortedObjects, allocator.getRemainingBytesInAlignedChunk());
111114
if (info == null) {
112115
allocator.startNewAlignedChunk();
113116
} else {
114117
appendAllocatedObject(info, allocator.allocateObjectInAlignedChunk(info, isWritable()));
115118
}
119+
control.heartbeat();
116120
}
117121
}
118122

Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
/*
2+
* Copyright (c) 2025, 2025, Oracle and/or its affiliates. All rights reserved.
3+
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4+
*
5+
* This code is free software; you can redistribute it and/or modify it
6+
* under the terms of the GNU General Public License version 2 only, as
7+
* published by the Free Software Foundation. Oracle designates this
8+
* particular file as subject to the "Classpath" exception as provided
9+
* by Oracle in the LICENSE file that accompanied this code.
10+
*
11+
* This code is distributed in the hope that it will be useful, but WITHOUT
12+
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13+
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14+
* version 2 for more details (a copy is included in the LICENSE file that
15+
* accompanied this code).
16+
*
17+
* You should have received a copy of the GNU General Public License version
18+
* 2 along with this work; if not, write to the Free Software Foundation,
19+
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20+
*
21+
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22+
* or visit www.oracle.com if you need additional information or have any
23+
* questions.
24+
*/
25+
package com.oracle.svm.core.image;
26+
27+
public class ImageHeapLayingOutCancelledException extends RuntimeException {
28+
private static final long serialVersionUID = 1017980175582546348L;
29+
30+
public ImageHeapLayingOutCancelledException() {
31+
}
32+
33+
public ImageHeapLayingOutCancelledException(RuntimeException cause) {
34+
super(cause);
35+
}
36+
}
Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
/*
2+
* Copyright (c) 2025, 2025, Oracle and/or its affiliates. All rights reserved.
3+
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4+
*
5+
* This code is free software; you can redistribute it and/or modify it
6+
* under the terms of the GNU General Public License version 2 only, as
7+
* published by the Free Software Foundation. Oracle designates this
8+
* particular file as subject to the "Classpath" exception as provided
9+
* by Oracle in the LICENSE file that accompanied this code.
10+
*
11+
* This code is distributed in the hope that it will be useful, but WITHOUT
12+
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13+
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14+
* version 2 for more details (a copy is included in the LICENSE file that
15+
* accompanied this code).
16+
*
17+
* You should have received a copy of the GNU General Public License version
18+
* 2 along with this work; if not, write to the Free Software Foundation,
19+
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20+
*
21+
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22+
* or visit www.oracle.com if you need additional information or have any
23+
* questions.
24+
*/
25+
package com.oracle.svm.core.image;
26+
27+
/**
28+
* Facilitates {@link ImageHeapLayouter#layout(ImageHeap, int, ImageHeapLayingOutController)}
29+
* cancellation through an {@link ImageHeapLayingOutController} instance.
30+
*/
31+
public class ImageHeapLayingOutControl {
32+
protected final ImageHeapLayingOutController controller;
33+
34+
public ImageHeapLayingOutControl(ImageHeapLayingOutController controller) {
35+
this.controller = controller;
36+
}
37+
38+
public void heartbeat() throws ImageHeapLayingOutCancelledException {
39+
if (controller.shouldCancel()) {
40+
throw new ImageHeapLayingOutCancelledException();
41+
}
42+
}
43+
}
Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
/*
2+
* Copyright (c) 2025, 2025, Oracle and/or its affiliates. All rights reserved.
3+
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4+
*
5+
* This code is free software; you can redistribute it and/or modify it
6+
* under the terms of the GNU General Public License version 2 only, as
7+
* published by the Free Software Foundation. Oracle designates this
8+
* particular file as subject to the "Classpath" exception as provided
9+
* by Oracle in the LICENSE file that accompanied this code.
10+
*
11+
* This code is distributed in the hope that it will be useful, but WITHOUT
12+
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13+
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14+
* version 2 for more details (a copy is included in the LICENSE file that
15+
* accompanied this code).
16+
*
17+
* You should have received a copy of the GNU General Public License version
18+
* 2 along with this work; if not, write to the Free Software Foundation,
19+
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20+
*
21+
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22+
* or visit www.oracle.com if you need additional information or have any
23+
* questions.
24+
*/
25+
package com.oracle.svm.core.image;
26+
27+
public interface ImageHeapLayingOutController {
28+
29+
/**
30+
* Called periodically by {@link ImageHeapLayingOutControl}.
31+
*
32+
* @return Whether the layout operation should be cancelled.
33+
*/
34+
boolean shouldCancel();
35+
}

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

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,16 @@ public interface ImageHeapLayouter {
4545
/**
4646
* Places all heap partitions and assigns objects their final offsets.
4747
*/
48-
ImageHeapLayoutInfo layout(ImageHeap imageHeap, int pageSize);
48+
default ImageHeapLayoutInfo layout(ImageHeap imageHeap, int pageSize) {
49+
return layout(imageHeap, pageSize, new NonCancellableImageHeapLayingOutController());
50+
}
51+
52+
/**
53+
* Cancellable version of {@link ImageHeapLayouter#layout(ImageHeap, int)}. Cancellation is
54+
* performed via {@link ImageHeapLayingOutController}.. If the layout is cancelled, an instance
55+
* of {@link ImageHeapLayingOutCancelledException} is thrown.
56+
*/
57+
ImageHeapLayoutInfo layout(ImageHeap imageHeap, int pageSize, ImageHeapLayingOutController controller);
4958

5059
/** Hook to run tasks after heap layout is finished. */
5160
@SuppressWarnings("unused")
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
/*
2+
* Copyright (c) 2025, 2025, Oracle and/or its affiliates. All rights reserved.
3+
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4+
*
5+
* This code is free software; you can redistribute it and/or modify it
6+
* under the terms of the GNU General Public License version 2 only, as
7+
* published by the Free Software Foundation. Oracle designates this
8+
* particular file as subject to the "Classpath" exception as provided
9+
* by Oracle in the LICENSE file that accompanied this code.
10+
*
11+
* This code is distributed in the hope that it will be useful, but WITHOUT
12+
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13+
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14+
* version 2 for more details (a copy is included in the LICENSE file that
15+
* accompanied this code).
16+
*
17+
* You should have received a copy of the GNU General Public License version
18+
* 2 along with this work; if not, write to the Free Software Foundation,
19+
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20+
*
21+
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22+
* or visit www.oracle.com if you need additional information or have any
23+
* questions.
24+
*/
25+
package com.oracle.svm.core.image;
26+
27+
/**
28+
* An implementation of {@link ImageHeapLayingOutController} that never cancels the laying out.
29+
*/
30+
public final class NonCancellableImageHeapLayingOutController implements ImageHeapLayingOutController {
31+
@Override
32+
public boolean shouldCancel() {
33+
return false;
34+
}
35+
}

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

Lines changed: 11 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,8 @@
3030

3131
import com.oracle.graal.pointsto.heap.ImageHeapPrimitiveArray;
3232
import com.oracle.svm.core.image.ImageHeap;
33+
import com.oracle.svm.core.image.ImageHeapLayingOutControl;
34+
import com.oracle.svm.core.image.ImageHeapLayingOutController;
3335
import com.oracle.svm.core.image.ImageHeapLayouter;
3436
import com.oracle.svm.core.image.ImageHeapObject;
3537
import com.oracle.svm.core.image.ImageHeapPartition;
@@ -73,33 +75,37 @@ public void assignObjectToPartition(ImageHeapObject info, boolean immutable, boo
7375
}
7476

7577
@Override
76-
public WasmGCImageHeapLayoutInfo layout(ImageHeap imageHeap, int pageSize) {
77-
layoutPseudoPartition();
78-
doLayout();
78+
public WasmGCImageHeapLayoutInfo layout(ImageHeap imageHeap, int pageSize, ImageHeapLayingOutController controller) {
79+
ImageHeapLayingOutControl control = new ImageHeapLayingOutControl(controller);
80+
81+
layoutPseudoPartition(control);
82+
doLayout(control);
7983

8084
long totalSize = StreamSupport.stream(imageHeap.getObjects().spliterator(), false).mapToLong(ImageHeapObject::getSize).sum();
8185
long serializedSize = singlePartition.getStartOffset() + singlePartition.getSize() - startOffset;
8286
return new WasmGCImageHeapLayoutInfo(startOffset, serializedSize, totalSize);
8387
}
8488

85-
private void doLayout() {
89+
private void doLayout(ImageHeapLayingOutControl control) {
8690
int offset = 0;
8791
for (ImageHeapObject info : singlePartition.getObjects()) {
8892
// Only primitive arrays are supposed to be in this partition
8993
ImageHeapPrimitiveArray primitiveArray = (ImageHeapPrimitiveArray) info.getWrapped();
9094
info.setOffsetInPartition(offset);
9195
offset += primitiveArray.getType().getComponentType().getStorageKind().getByteCount() * primitiveArray.getLength();
96+
control.heartbeat();
9297
}
9398

9499
singlePartition.setSize(offset);
95100
}
96101

97-
private void layoutPseudoPartition() {
102+
private void layoutPseudoPartition(ImageHeapLayingOutControl control) {
98103
// Approximate size of the partition (based on the SVM object layout size of the objects)
99104
long pseudoSize = 0;
100105
for (ImageHeapObject info : pseudoPartition.getObjects()) {
101106
info.setOffsetInPartition(0);
102107
pseudoSize = info.getSize();
108+
control.heartbeat();
103109
}
104110

105111
pseudoPartition.setSize(pseudoSize);

0 commit comments

Comments
 (0)