Skip to content

Commit fdd84a0

Browse files
committed
[GR-24210] Unified continuous image heap layout.
PullRequest: graal/6477
2 parents 96a99da + ad39e05 commit fdd84a0

File tree

19 files changed

+394
-375
lines changed

19 files changed

+394
-375
lines changed

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

Lines changed: 6 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -139,8 +139,6 @@ public void invokeWithoutAllocation(Log log) {
139139
.signed(getHistoryLength()).string(" / ").signed(historyCount)
140140
.indent(true);
141141
ImageHeapInfo imageHeapInfo = HeapImpl.getImageHeapInfo();
142-
Pointer firstRORPointer = Word.objectToUntrackedPointer(imageHeapInfo.firstReadOnlyReferenceObject);
143-
Pointer lastRORPointer = Word.objectToUntrackedPointer(imageHeapInfo.lastReadOnlyReferenceObject);
144142
/*
145143
* Report the history from the next available slot in the ring buffer. The older
146144
* history is more reliable, since I have already used that to visit objects. The
@@ -152,15 +150,14 @@ public void invokeWithoutAllocation(Log log) {
152150
Word objectEntry = objectHistory[index];
153151
log.string(" objectEntry: ").hex(objectEntry);
154152
UnsignedWord headerEntry = headerHistory[index];
155-
UnsignedWord headerHubBits = ObjectHeaderImpl.clearBits(headerEntry);
153+
Pointer headerHub = (Pointer) ObjectHeaderImpl.clearBits(headerEntry);
156154
UnsignedWord headerHeaderBits = ObjectHeaderImpl.getHeaderBitsFromHeaderCarefully(headerEntry);
157-
log.string(" headerEntry: ").hex(headerEntry).string(" = ").hex(headerHubBits).string(" | ").hex(headerHeaderBits).string(" / ");
158-
boolean headerInImageHeap = ((headerHubBits.aboveOrEqual(firstRORPointer)) && headerHubBits.belowOrEqual(lastRORPointer));
155+
log.string(" headerEntry: ").hex(headerEntry).string(" = ").hex(headerHub).string(" | ").hex(headerHeaderBits).string(" / ");
156+
boolean headerInImageHeap = imageHeapInfo.isInReadOnlyReferencePartition(headerHub) ||
157+
imageHeapInfo.isInReadOnlyRelocatablePartition(headerHub);
159158
if (headerInImageHeap) {
160-
Pointer hubBitsAsPointer = (Pointer) headerHubBits;
161-
Object hubBitsAsObject = KnownIntrinsics.convertUnknownValue(hubBitsAsPointer.toObject(), Object.class);
162-
DynamicHub hubBitsAsDynamicHub = (DynamicHub) hubBitsAsObject;
163-
log.string(" class: ").string(hubBitsAsDynamicHub.getName());
159+
DynamicHub hub = (DynamicHub) KnownIntrinsics.convertUnknownValue(headerHub.toObject(), Object.class);
160+
log.string(" class: ").string(hub.getName());
164161
Object entryAsObject = KnownIntrinsics.convertUnknownValue(objectEntry.toObject(), Object.class);
165162
if (LayoutEncoding.isArray(entryAsObject)) {
166163
int length = KnownIntrinsics.readArrayLength(entryAsObject);

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

Lines changed: 18 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -376,24 +376,29 @@ public List<Class<?>> getClassList() {
376376
if (classList == null) {
377377
/* Two threads might race to set classList, but they compute the same result. */
378378
List<Class<?>> list = new ArrayList<>(1024);
379-
Object firstObject = imageHeapInfo.firstReadOnlyReferenceObject;
380-
Object lastObject = imageHeapInfo.lastReadOnlyReferenceObject;
381-
Pointer firstPointer = Word.objectToUntrackedPointer(firstObject);
382-
Pointer lastPointer = Word.objectToUntrackedPointer(lastObject);
383-
Pointer currentPointer = firstPointer;
384-
while (currentPointer.belowOrEqual(lastPointer)) {
385-
Object currentObject = KnownIntrinsics.convertUnknownValue(currentPointer.toObject(), Object.class);
386-
if (currentObject instanceof Class<?>) {
387-
Class<?> asClass = (Class<?>) currentObject;
388-
list.add(asClass);
389-
}
390-
currentPointer = LayoutEncoding.getObjectEnd(currentObject);
391-
}
379+
addClassObjectsInPartition(list, imageHeapInfo.firstReadOnlyReferenceObject, imageHeapInfo.lastReadOnlyReferenceObject);
380+
addClassObjectsInPartition(list, imageHeapInfo.firstReadOnlyRelocatableObject, imageHeapInfo.lastReadOnlyRelocatableObject);
392381
classList = Collections.unmodifiableList(list);
393382
}
394383
return classList;
395384
}
396385

386+
private static void addClassObjectsInPartition(List<Class<?>> list, Object firstObject, Object lastObject) {
387+
if (firstObject == null) {
388+
return;
389+
}
390+
Pointer currentPointer = Word.objectToUntrackedPointer(firstObject);
391+
Pointer lastPointer = Word.objectToUntrackedPointer(lastObject);
392+
while (currentPointer.belowOrEqual(lastPointer)) {
393+
Object currentObject = KnownIntrinsics.convertUnknownValue(currentPointer.toObject(), Object.class);
394+
if (currentObject instanceof Class<?>) {
395+
Class<?> asClass = (Class<?>) currentObject;
396+
list.add(asClass);
397+
}
398+
currentPointer = LayoutEncoding.getObjectEnd(currentObject);
399+
}
400+
}
401+
397402
/*
398403
* Verification.
399404
*/

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

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -210,9 +210,10 @@ private boolean verifyBootImageObjects() {
210210
ImageHeapInfo info = HeapImpl.getImageHeapInfo();
211211
boolean ropResult = verifyBootImageObjects(info.firstReadOnlyPrimitiveObject, info.lastReadOnlyPrimitiveObject);
212212
boolean rorResult = verifyBootImageObjects(info.firstReadOnlyReferenceObject, info.lastReadOnlyReferenceObject);
213+
boolean rolResult = verifyBootImageObjects(info.firstReadOnlyRelocatableObject, info.lastReadOnlyRelocatableObject);
213214
boolean rwpResult = verifyBootImageObjects(info.firstWritablePrimitiveObject, info.lastWritablePrimitiveObject);
214215
boolean rwrResult = verifyBootImageObjects(info.firstWritableReferenceObject, info.lastWritableReferenceObject);
215-
return ropResult && rorResult && rwpResult && rwrResult;
216+
return ropResult && rorResult && rolResult && rwpResult && rwrResult;
216217
}
217218

218219
private boolean verifyBootImageObjects(Object firstObject, Object lastObject) {

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

Lines changed: 21 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,6 @@
2727
import org.graalvm.compiler.word.Word;
2828
import org.graalvm.word.Pointer;
2929

30-
import com.oracle.svm.core.SubstrateOptions;
3130
import com.oracle.svm.core.annotate.Uninterruptible;
3231
import com.oracle.svm.core.annotate.UnknownObjectField;
3332

@@ -42,18 +41,15 @@ public final class ImageHeapInfo {
4241
@UnknownObjectField(types = Object.class) public Object firstReadOnlyReferenceObject;
4342
@UnknownObjectField(types = Object.class) public Object lastReadOnlyReferenceObject;
4443

44+
@UnknownObjectField(types = Object.class) public Object firstReadOnlyRelocatableObject;
45+
@UnknownObjectField(types = Object.class) public Object lastReadOnlyRelocatableObject;
46+
4547
@UnknownObjectField(types = Object.class) public Object firstWritablePrimitiveObject;
4648
@UnknownObjectField(types = Object.class) public Object lastWritablePrimitiveObject;
4749

4850
@UnknownObjectField(types = Object.class) public Object firstWritableReferenceObject;
4951
@UnknownObjectField(types = Object.class) public Object lastWritableReferenceObject;
5052

51-
@UnknownObjectField(types = Object.class) public Object firstReadOnlyObject;
52-
@UnknownObjectField(types = Object.class) public Object lastReadOnlyObject;
53-
54-
@UnknownObjectField(types = Object.class) public Object firstWritableObject;
55-
@UnknownObjectField(types = Object.class) public Object lastWritableObject;
56-
5753
@UnknownObjectField(types = Object.class) public Object firstObject;
5854
@UnknownObjectField(types = Object.class) public Object lastObject;
5955

@@ -62,21 +58,26 @@ public ImageHeapInfo() {
6258

6359
@SuppressWarnings("hiding")
6460
public void initialize(Object firstReadOnlyPrimitiveObject, Object lastReadOnlyPrimitiveObject, Object firstReadOnlyReferenceObject, Object lastReadOnlyReferenceObject,
65-
Object firstWritablePrimitiveObject, Object lastWritablePrimitiveObject, Object firstWritableReferenceObject, Object lastWritableReferenceObject) {
61+
Object firstReadOnlyRelocatableObject, Object lastReadOnlyRelocatableObject, Object firstWritablePrimitiveObject, Object lastWritablePrimitiveObject,
62+
Object firstWritableReferenceObject, Object lastWritableReferenceObject) {
6663
this.firstReadOnlyPrimitiveObject = firstReadOnlyPrimitiveObject;
6764
this.lastReadOnlyPrimitiveObject = lastReadOnlyPrimitiveObject;
6865
this.firstReadOnlyReferenceObject = firstReadOnlyReferenceObject;
6966
this.lastReadOnlyReferenceObject = lastReadOnlyReferenceObject;
67+
this.firstReadOnlyRelocatableObject = firstReadOnlyRelocatableObject;
68+
this.lastReadOnlyRelocatableObject = lastReadOnlyRelocatableObject;
7069
this.firstWritablePrimitiveObject = firstWritablePrimitiveObject;
7170
this.lastWritablePrimitiveObject = lastWritablePrimitiveObject;
7271
this.firstWritableReferenceObject = firstWritableReferenceObject;
7372
this.lastWritableReferenceObject = lastWritableReferenceObject;
7473

7574
// Compute boundaries for checks considering partitions can be empty (first == last == null)
76-
this.firstReadOnlyObject = (firstReadOnlyPrimitiveObject != null) ? firstReadOnlyPrimitiveObject : firstReadOnlyReferenceObject;
77-
this.lastReadOnlyObject = (lastReadOnlyReferenceObject != null) ? lastReadOnlyReferenceObject : lastReadOnlyPrimitiveObject;
78-
this.firstWritableObject = (firstWritablePrimitiveObject != null) ? firstWritablePrimitiveObject : firstWritableReferenceObject;
79-
this.lastWritableObject = (lastWritableReferenceObject != null) ? lastWritableReferenceObject : lastWritablePrimitiveObject;
75+
Object firstReadOnlyObject = (firstReadOnlyPrimitiveObject != null) ? firstReadOnlyPrimitiveObject
76+
: ((firstReadOnlyReferenceObject != null) ? firstReadOnlyReferenceObject : firstReadOnlyRelocatableObject);
77+
Object lastReadOnlyObject = (lastReadOnlyRelocatableObject != null) ? lastReadOnlyRelocatableObject
78+
: ((lastReadOnlyReferenceObject != null) ? lastReadOnlyReferenceObject : lastReadOnlyPrimitiveObject);
79+
Object firstWritableObject = (firstWritablePrimitiveObject != null) ? firstWritablePrimitiveObject : firstWritableReferenceObject;
80+
Object lastWritableObject = (lastWritableReferenceObject != null) ? lastWritableReferenceObject : lastWritablePrimitiveObject;
8081
this.firstObject = (firstReadOnlyObject != null) ? firstReadOnlyObject : firstWritableObject;
8182
this.lastObject = (lastWritableObject != null) ? lastWritableObject : lastReadOnlyObject;
8283
}
@@ -107,6 +108,12 @@ public boolean isInReadOnlyReferencePartition(Pointer ptr) {
107108
return Word.objectToUntrackedPointer(firstReadOnlyReferenceObject).belowOrEqual(ptr) && ptr.belowOrEqual(Word.objectToUntrackedPointer(lastReadOnlyReferenceObject));
108109
}
109110

111+
@Uninterruptible(reason = "Called from uninterruptible code.", mayBeInlined = true)
112+
public boolean isInReadOnlyRelocatablePartition(Pointer ptr) {
113+
assert ptr.isNonNull();
114+
return Word.objectToUntrackedPointer(firstReadOnlyRelocatableObject).belowOrEqual(ptr) && ptr.belowOrEqual(Word.objectToUntrackedPointer(lastReadOnlyRelocatableObject));
115+
}
116+
110117
@Uninterruptible(reason = "Called from uninterruptible code.", mayBeInlined = true)
111118
public boolean isInWritableReferencePartition(Pointer ptr) {
112119
assert ptr.isNonNull();
@@ -123,15 +130,9 @@ public boolean isInImageHeap(Pointer objectPointer) {
123130
boolean result;
124131
if (objectPointer.isNull()) {
125132
result = false;
126-
} else if (SubstrateOptions.SpawnIsolates.getValue()) {
127-
result = objectPointer.aboveOrEqual(Word.objectToUntrackedPointer(firstObject)) && objectPointer.belowOrEqual(Word.objectToUntrackedPointer(lastObject));
128133
} else {
129-
result = objectPointer.aboveOrEqual(Word.objectToUntrackedPointer(firstReadOnlyObject)) &&
130-
objectPointer.belowOrEqual(Word.objectToUntrackedPointer(lastReadOnlyObject)) ||
131-
objectPointer.aboveOrEqual(Word.objectToUntrackedPointer(firstWritableObject)) &&
132-
objectPointer.belowOrEqual(Word.objectToUntrackedPointer(lastWritableObject));
134+
result = objectPointer.aboveOrEqual(Word.objectToUntrackedPointer(firstObject)) && objectPointer.belowOrEqual(Word.objectToUntrackedPointer(lastObject));
133135
}
134-
135136
assert result == isInImageHeapSlow(objectPointer);
136137
return result;
137138
}
@@ -142,6 +143,7 @@ public boolean isInImageHeapSlow(Pointer objectPointer) {
142143
if (objectPointer.isNonNull()) {
143144
result |= isInReadOnlyPrimitivePartition(objectPointer);
144145
result |= isInReadOnlyReferencePartition(objectPointer);
146+
result |= isInReadOnlyRelocatablePartition(objectPointer);
145147
result |= isInWritablePrimitivePartition(objectPointer);
146148
result |= isInWritableReferencePartition(objectPointer);
147149
}

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

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@
3939
public final class ImageHeapWalker {
4040
private static final MemoryWalker.NativeImageHeapRegionAccess<ImageHeapInfo> READ_ONLY_PRIMITIVE_WALKER = new ReadOnlyPrimitiveMemoryWalkerAccess();
4141
private static final MemoryWalker.NativeImageHeapRegionAccess<ImageHeapInfo> READ_ONLY_REFERENCE_WALKER = new ReadOnlyReferenceMemoryWalkerAccess();
42+
private static final MemoryWalker.NativeImageHeapRegionAccess<ImageHeapInfo> READ_ONLY_RELOCATABLE_WALKER = new ReadOnlyRelocatableMemoryWalkerAccess();
4243
private static final MemoryWalker.NativeImageHeapRegionAccess<ImageHeapInfo> WRITABLE_PRIMITIVE_WALKER = new WritablePrimitiveMemoryWalkerAccess();
4344
private static final MemoryWalker.NativeImageHeapRegionAccess<ImageHeapInfo> WRITABLE_REFERENCE_WALKER = new WritableReferenceMemoryWalkerAccess();
4445

@@ -48,13 +49,15 @@ private ImageHeapWalker() {
4849
public static boolean walkRegions(ImageHeapInfo heapInfo, MemoryWalker.Visitor visitor) {
4950
return visitor.visitNativeImageHeapRegion(heapInfo, READ_ONLY_PRIMITIVE_WALKER) &&
5051
visitor.visitNativeImageHeapRegion(heapInfo, READ_ONLY_REFERENCE_WALKER) &&
52+
visitor.visitNativeImageHeapRegion(heapInfo, READ_ONLY_RELOCATABLE_WALKER) &&
5153
visitor.visitNativeImageHeapRegion(heapInfo, WRITABLE_PRIMITIVE_WALKER) &&
5254
visitor.visitNativeImageHeapRegion(heapInfo, WRITABLE_REFERENCE_WALKER);
5355
}
5456

5557
public static boolean walkImageHeapObjects(ImageHeapInfo heapInfo, ObjectVisitor visitor) {
5658
return walkPartition(heapInfo.firstReadOnlyPrimitiveObject, heapInfo.lastReadOnlyPrimitiveObject, visitor) &&
5759
walkPartition(heapInfo.firstReadOnlyReferenceObject, heapInfo.lastReadOnlyReferenceObject, visitor) &&
60+
walkPartition(heapInfo.firstReadOnlyRelocatableObject, heapInfo.lastReadOnlyRelocatableObject, visitor) &&
5861
walkPartition(heapInfo.firstWritablePrimitiveObject, heapInfo.lastWritablePrimitiveObject, visitor) &&
5962
walkPartition(heapInfo.firstWritableReferenceObject, heapInfo.lastWritableReferenceObject, visitor);
6063
}
@@ -82,6 +85,8 @@ static void logPartitionBoundaries(Log log, ImageHeapInfo imageHeapInfo) {
8285
Word.objectToUntrackedPointer(imageHeapInfo.lastReadOnlyPrimitiveObject)).newline();
8386
log.string("ReadOnly References: ").hex(Word.objectToUntrackedPointer(imageHeapInfo.firstReadOnlyReferenceObject)).string(" .. ").hex(
8487
Word.objectToUntrackedPointer(imageHeapInfo.lastReadOnlyReferenceObject)).newline();
88+
log.string("ReadOnly Relocatables: ").hex(Word.objectToUntrackedPointer(imageHeapInfo.firstReadOnlyRelocatableObject)).string(" .. ").hex(
89+
Word.objectToUntrackedPointer(imageHeapInfo.lastReadOnlyRelocatableObject)).newline();
8590
log.string("Writable Primitives: ").hex(Word.objectToUntrackedPointer(imageHeapInfo.firstWritablePrimitiveObject)).string(" .. ").hex(
8691
Word.objectToUntrackedPointer(imageHeapInfo.lastWritablePrimitiveObject)).newline();
8792
log.string("Writable References: ").hex(Word.objectToUntrackedPointer(imageHeapInfo.firstWritableReferenceObject)).string(" .. ").hex(
@@ -167,6 +172,23 @@ public Object getLastObject(ImageHeapInfo info) {
167172
}
168173
}
169174

175+
final class ReadOnlyRelocatableMemoryWalkerAccess extends MemoryWalkerAccessBase {
176+
@Platforms(Platform.HOSTED_ONLY.class)
177+
ReadOnlyRelocatableMemoryWalkerAccess() {
178+
super("read-only relocatables", true, false);
179+
}
180+
181+
@Override
182+
public Object getFirstObject(ImageHeapInfo info) {
183+
return info.firstReadOnlyRelocatableObject;
184+
}
185+
186+
@Override
187+
public Object getLastObject(ImageHeapInfo info) {
188+
return info.lastReadOnlyRelocatableObject;
189+
}
190+
}
191+
170192
final class WritablePrimitiveMemoryWalkerAccess extends MemoryWalkerAccessBase {
171193
@Platforms(Platform.HOSTED_ONLY.class)
172194
WritablePrimitiveMemoryWalkerAccess() {
Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
/*
2+
* Copyright (c) 2020, 2020, 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.genscavenge;
26+
27+
public class LinearImageHeapAllocator {
28+
private long position;
29+
30+
public LinearImageHeapAllocator(long position) {
31+
this.position = position;
32+
}
33+
34+
public long getPosition() {
35+
return position;
36+
}
37+
38+
public long allocate(long size) {
39+
long begin = position;
40+
position += size;
41+
return begin;
42+
}
43+
44+
public void align(int multiple) {
45+
allocate(computePadding(position, multiple));
46+
}
47+
48+
static long computePadding(long offset, int alignment) {
49+
long remainder = offset % alignment;
50+
return remainder == 0 ? 0 : alignment - remainder;
51+
}
52+
}

0 commit comments

Comments
 (0)