Skip to content

Commit 52bd5de

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

File tree

6 files changed

+156
-13
lines changed

6 files changed

+156
-13
lines changed

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

Lines changed: 19 additions & 6 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;
@@ -157,10 +159,16 @@ private Error reportHugeObjectError(ImageHeapObject info, String objectTypeMsg,
157159

158160
@Override
159161
public ImageHeapLayoutInfo layout(ImageHeap imageHeap, int pageSize) {
162+
return layout(imageHeap, pageSize, () -> false);
163+
}
164+
165+
@Override
166+
public ImageHeapLayoutInfo layout(ImageHeap imageHeap, int pageSize, ImageHeapLayingOutController controller) {
167+
ImageHeapLayingOutControl control = new ImageHeapLayingOutControl(controller);
160168
int objectAlignment = ConfigurationValues.getObjectLayout().getAlignment();
161169
assert pageSize % objectAlignment == 0 : "Page size does not match object alignment";
162170

163-
ImageHeapLayoutInfo layoutInfo = doLayout(imageHeap, pageSize);
171+
ImageHeapLayoutInfo layoutInfo = doLayout(imageHeap, pageSize, control);
164172

165173
for (ChunkedImageHeapPartition partition : getPartitions()) {
166174
assert partition.getStartOffset() % partition.getStartAlignment() == 0 : partition;
@@ -170,15 +178,16 @@ public ImageHeapLayoutInfo layout(ImageHeap imageHeap, int pageSize) {
170178
return layoutInfo;
171179
}
172180

173-
private ImageHeapLayoutInfo doLayout(ImageHeap imageHeap, int pageSize) {
181+
private ImageHeapLayoutInfo doLayout(ImageHeap imageHeap, int pageSize, ImageHeapLayingOutControl control) {
174182
allocator = new ChunkedImageHeapAllocator(imageHeap, startOffset);
175183
for (ChunkedImageHeapPartition partition : getPartitions()) {
176-
partition.layout(allocator);
184+
control.heartbeat();
185+
partition.layout(allocator, control);
177186
}
178-
return populateInfoObjects(imageHeap.countAndVerifyDynamicHubs(), pageSize);
187+
return populateInfoObjects(imageHeap.countAndVerifyDynamicHubs(), pageSize, control);
179188
}
180189

181-
private ImageHeapLayoutInfo populateInfoObjects(int dynamicHubCount, int pageSize) {
190+
private ImageHeapLayoutInfo populateInfoObjects(int dynamicHubCount, int pageSize, ImageHeapLayingOutControl control) {
182191
// Determine writable start boundary from chunks: a chunk that contains writable objects
183192
// must also have a writable card table
184193
long offsetOfFirstWritableAlignedChunk = -1;
@@ -187,6 +196,7 @@ private ImageHeapLayoutInfo populateInfoObjects(int dynamicHubCount, int pageSiz
187196
offsetOfFirstWritableAlignedChunk = chunk.getBegin();
188197
break; // (chunks are in ascending memory order)
189198
}
199+
control.heartbeat();
190200
}
191201
VMError.guarantee(offsetOfFirstWritableAlignedChunk >= 0 && offsetOfFirstWritableAlignedChunk % pageSize == 0, "Start of the writable part is assumed to be page-aligned");
192202
long offsetOfFirstWritableUnalignedChunk = -1;
@@ -199,6 +209,7 @@ private ImageHeapLayoutInfo populateInfoObjects(int dynamicHubCount, int pageSiz
199209
offsetOfFirstWritableUnalignedChunk = chunk.getBegin();
200210
}
201211
offsetOfLastWritableUnalignedChunk = chunk.getBegin();
212+
control.heartbeat();
202213
}
203214

204215
heapInfo.initialize(getReadOnlyRegular().firstObject, getReadOnlyRegular().lastObject, getReadOnlyRelocatable().firstObject, getReadOnlyRelocatable().lastObject,
@@ -207,6 +218,8 @@ private ImageHeapLayoutInfo populateInfoObjects(int dynamicHubCount, int pageSiz
207218
getReadOnlyHuge().firstObject, getReadOnlyHuge().lastObject, offsetOfFirstWritableAlignedChunk, offsetOfFirstWritableUnalignedChunk, offsetOfLastWritableUnalignedChunk,
208219
dynamicHubCount);
209220

221+
control.heartbeat();
222+
210223
long writableEnd = getWritableHuge().getStartOffset() + getWritableHuge().getSize();
211224
long writableSize = writableEnd - offsetOfFirstWritableAlignedChunk;
212225
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: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,8 @@
2424
*/
2525
package com.oracle.svm.core.image;
2626

27+
import com.oracle.svm.core.util.VMError;
28+
2729
import java.nio.ByteBuffer;
2830

2931
/**
@@ -47,6 +49,16 @@ public interface ImageHeapLayouter {
4749
*/
4850
ImageHeapLayoutInfo layout(ImageHeap imageHeap, int pageSize);
4951

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+
@SuppressWarnings("unused")
58+
default ImageHeapLayoutInfo layout(ImageHeap imageHeap, int pageSize, ImageHeapLayingOutController controller) {
59+
throw VMError.unimplemented("This layouter does not support cancellation");
60+
}
61+
5062
/** Hook to run tasks after heap layout is finished. */
5163
@SuppressWarnings("unused")
5264
default void afterLayout(ImageHeap imageHeap) {

0 commit comments

Comments
 (0)