Skip to content

Commit 2fcff3f

Browse files
committed
Remove excess allocations from chunked layouting
1 parent f8fbbb6 commit 2fcff3f

File tree

4 files changed

+33
-51
lines changed

4 files changed

+33
-51
lines changed

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

+18-48
Original file line numberDiff line numberDiff line change
@@ -26,18 +26,14 @@
2626

2727
import java.util.ArrayDeque;
2828
import java.util.ArrayList;
29-
import java.util.Arrays;
30-
import java.util.Comparator;
3129
import java.util.List;
32-
import java.util.Map;
3330
import java.util.NavigableMap;
3431
import java.util.Queue;
3532
import java.util.TreeMap;
3633

3734
import com.oracle.svm.core.config.ConfigurationValues;
3835
import com.oracle.svm.core.image.ImageHeapObject;
3936
import com.oracle.svm.core.image.ImageHeapPartition;
40-
import com.oracle.svm.core.meta.SubstrateObjectConstant;
4137

4238
import jdk.graal.compiler.debug.Assertions;
4339

@@ -124,63 +120,44 @@ private ImageHeapObject dequeueBestFit(NavigableMap<Long, Queue<ImageHeapObject>
124120
if (nbytes < minimumObjectSize) {
125121
return null;
126122
}
127-
Map.Entry<Long, Queue<ImageHeapObject>> entry = sortedObjects.floorEntry(nbytes);
128-
if (entry == null) {
123+
124+
/**
125+
* Find a floor entry. We are purposefully not calling {@link TreeMap#getFloorEntry(Object)}
126+
* as that method allocates a new entry object. Instead, we fetch the floor key and get the
127+
* value for the returned key.
128+
*/
129+
Long floorKey = sortedObjects.floorKey(nbytes);
130+
if (floorKey == null) {
129131
return null;
130132
}
131-
Queue<ImageHeapObject> queue = entry.getValue();
132-
ImageHeapObject info = queue.remove();
133+
Queue<ImageHeapObject> queue = sortedObjects.get(floorKey);
134+
ImageHeapObject obj = queue.remove();
133135
if (queue.isEmpty()) {
134-
sortedObjects.remove(entry.getKey());
136+
sortedObjects.remove(floorKey);
135137
}
136-
return info;
138+
return obj;
137139
}
138140

139141
private NavigableMap<Long, Queue<ImageHeapObject>> createSortedObjectsMap() {
140-
ImageHeapObject[] sorted = objects.toArray(new ImageHeapObject[0]);
141-
Arrays.sort(sorted, new SizeComparator());
142-
143142
NavigableMap<Long, Queue<ImageHeapObject>> map = new TreeMap<>();
144-
Queue<ImageHeapObject> currentQueue = null;
145-
long currentObjectsSize = -1;
146-
for (ImageHeapObject obj : sorted) {
143+
for (ImageHeapObject obj : objects) {
147144
long objSize = obj.getSize();
148-
if (objSize != currentObjectsSize) {
149-
assert objSize > currentObjectsSize && objSize >= ConfigurationValues.getObjectLayout().getMinImageHeapObjectSize() : Assertions.errorMessage(obj, objSize);
150-
currentObjectsSize = objSize;
151-
currentQueue = new ArrayDeque<>();
152-
map.put(currentObjectsSize, currentQueue);
153-
}
154-
assert currentQueue != null;
155-
currentQueue.add(obj);
145+
assert objSize >= ConfigurationValues.getObjectLayout().getMinImageHeapObjectSize() : Assertions.errorMessage(obj, objSize);
146+
Queue<ImageHeapObject> q = map.computeIfAbsent(objSize, k -> new ArrayDeque<>());
147+
q.add(obj);
156148
}
157149
return map;
158150
}
159151

160152
private void appendAllocatedObject(ImageHeapObject info, long allocationOffset) {
161153
if (firstObject == null) {
162-
firstObject = extractObject(info);
154+
firstObject = info.getObjectOrHostedConstant();
163155
}
164156
assert info.getPartition() == this;
165157
long offsetInPartition = allocationOffset - startOffset;
166158
assert ConfigurationValues.getObjectLayout().isAligned(offsetInPartition) : "start: " + offsetInPartition + " must be aligned.";
167159
info.setOffsetInPartition(offsetInPartition);
168-
lastObject = extractObject(info);
169-
}
170-
171-
private static Object extractObject(ImageHeapObject info) {
172-
if (info.getConstant() instanceof SubstrateObjectConstant) {
173-
return info.getObject();
174-
} else {
175-
/*
176-
* The info wraps an ImageHeapObject, i.e., a build time representation of an object
177-
* that is not backed by a raw hosted object. We set the partition limit to the actual
178-
* constant. The constant reflection provider knows that this is a build time value, and
179-
* it will not wrap it in a JavaConstant when reading it. This case is not different
180-
* from normal objects referencing simulated objects.
181-
*/
182-
return info.getConstant();
183-
}
160+
lastObject = info.getObjectOrHostedConstant();
184161
}
185162

186163
@Override
@@ -229,11 +206,4 @@ public boolean isFiller() {
229206
public String toString() {
230207
return name;
231208
}
232-
233-
private static final class SizeComparator implements Comparator<ImageHeapObject> {
234-
@Override
235-
public int compare(ImageHeapObject o1, ImageHeapObject o2) {
236-
return Long.signum(o1.getSize() - o2.getSize());
237-
}
238-
}
239209
}

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

+1-3
Original file line numberDiff line numberDiff line change
@@ -24,10 +24,8 @@
2424
*/
2525
package com.oracle.svm.core.image;
2626

27-
import java.util.Collection;
28-
2927
public interface ImageHeap {
30-
Collection<? extends ImageHeapObject> getObjects();
28+
Iterable<? extends ImageHeapObject> getObjects();
3129

3230
ImageHeapObject addLateToImageHeap(Object object, Object reason);
3331

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

+2
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,8 @@
2929
public interface ImageHeapObject {
3030
long getSize();
3131

32+
Object getObjectOrHostedConstant();
33+
3234
Object getObject();
3335

3436
Class<?> getObjectClass();

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

+12
Original file line numberDiff line numberDiff line change
@@ -901,6 +901,18 @@ public long getSize() {
901901
return size;
902902
}
903903

904+
@Override
905+
public Object getObjectOrHostedConstant() {
906+
/*
907+
* The info wraps an ImageHeapConstant, i.e., a build time representation of an object
908+
* that is not backed by a raw hosted object. We set the partition limit to the actual
909+
* constant. The constant reflection provider knows that this is a build time value, and
910+
* it will not wrap it in a JavaConstant when reading it. This case is not different
911+
* from normal objects referencing simulated objects.
912+
*/
913+
return getConstant();
914+
}
915+
904916
public int getIdentityHashCode() {
905917
return identityHashCode;
906918
}

0 commit comments

Comments
 (0)