Skip to content

Commit 089e691

Browse files
Refactorings to improve the encapsulation of TlabSupport.
1 parent 771739e commit 089e691

File tree

2 files changed

+52
-57
lines changed

2 files changed

+52
-57
lines changed

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

Lines changed: 1 addition & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,6 @@
2929
import static com.oracle.svm.core.graal.snippets.SubstrateAllocationSnippets.TLAB_START_IDENTITY;
3030
import static com.oracle.svm.core.graal.snippets.SubstrateAllocationSnippets.TLAB_TOP_IDENTITY;
3131

32-
import org.graalvm.nativeimage.CurrentIsolate;
3332
import org.graalvm.nativeimage.IsolateThread;
3433
import org.graalvm.nativeimage.Platform;
3534
import org.graalvm.nativeimage.Platforms;
@@ -39,7 +38,6 @@
3938
import org.graalvm.nativeimage.c.struct.RawStructure;
4039
import org.graalvm.nativeimage.c.struct.SizeOf;
4140
import org.graalvm.nativeimage.c.struct.UniqueLocationIdentity;
42-
import org.graalvm.nativeimage.c.type.WordPointer;
4341
import org.graalvm.word.LocationIdentity;
4442
import org.graalvm.word.Pointer;
4543
import org.graalvm.word.PointerBase;
@@ -359,57 +357,13 @@ private static Object allocateArraySlow(DynamicHub hub, int length, UnsignedWord
359357
@BasedOnJDKFile("https://github.com/openjdk/jdk/blob/jdk-23-ga/src/hotspot/share/gc/shared/memAllocator.cpp#L333-L341")
360358
@Uninterruptible(reason = "Holds uninitialized memory.")
361359
private static Pointer allocateRawMemory(UnsignedWord size, BooleanPointer allocatedOutsideTlab) {
362-
Pointer memory = allocateRawMemoryInTlabSlow(size);
360+
Pointer memory = TlabSupport.allocateRawMemoryInTlabSlow(size);
363361
if (memory.isNonNull()) {
364362
return memory;
365363
}
366364
return allocateRawMemoryOutsideTlab(size, allocatedOutsideTlab);
367365
}
368366

369-
// TEMP (chaeubl): move this to TlabSupport and make most TlabSupport methods private
370-
@BasedOnJDKFile("https://github.com/openjdk/jdk/blob/jdk-25+25/src/hotspot/share/gc/shared/memAllocator.cpp#L257-L329")
371-
@Uninterruptible(reason = "Holds uninitialized memory.")
372-
private static Pointer allocateRawMemoryInTlabSlow(UnsignedWord size) {
373-
ThreadLocalAllocation.Descriptor tlab = getTlab();
374-
375-
/*
376-
* Retain tlab and allocate object as an heap allocation if the amount free in the tlab is
377-
* too large to discard.
378-
*/
379-
if (TlabSupport.shouldRetainTlab(tlab)) {
380-
TlabSupport.recordSlowAllocation();
381-
return Word.nullPointer();
382-
}
383-
384-
/* Discard tlab and allocate a new one. */
385-
386-
TlabSupport.recordRefillWaste();
387-
TlabSupport.retireTlab(CurrentIsolate.getCurrentThread(), false);
388-
389-
/* To minimize fragmentation, the last tlab may be smaller than the rest. */
390-
UnsignedWord newTlabSize = TlabSupport.computeSizeOfNewTlab(size);
391-
if (newTlabSize.equal(0)) {
392-
return Word.nullPointer();
393-
}
394-
395-
/*
396-
* Allocate a new TLAB requesting newTlabSize. Any size between minimal and newTlabSize is
397-
* accepted.
398-
*/
399-
UnsignedWord computedMinSize = TlabSupport.computeMinSizeOfNewTlab(size);
400-
401-
WordPointer allocatedTlabSize = StackValue.get(WordPointer.class);
402-
Pointer memory = YoungGeneration.getHeapAllocation().allocateNewTlab(computedMinSize, newTlabSize, allocatedTlabSize);
403-
if (memory.isNull()) {
404-
assert Word.unsigned(0).equal(allocatedTlabSize.read()) : "Allocation failed, but actual size was updated.";
405-
return Word.nullPointer();
406-
}
407-
assert Word.unsigned(0).notEqual(allocatedTlabSize.read()) : "Allocation succeeded but actual size not updated.";
408-
409-
TlabSupport.fillTlab(memory, memory.add(size), allocatedTlabSize);
410-
return memory;
411-
}
412-
413367
@BasedOnJDKFile("https://github.com/openjdk/jdk/blob/jdk-25+25/src/hotspot/share/gc/shared/memAllocator.cpp#L239-L251")
414368
@Uninterruptible(reason = "Holds uninitialized memory.")
415369
private static Pointer allocateRawMemoryOutsideTlab(UnsignedWord size, BooleanPointer allocatedOutsideTlab) {

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

Lines changed: 51 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@
3434

3535
import org.graalvm.nativeimage.CurrentIsolate;
3636
import org.graalvm.nativeimage.IsolateThread;
37+
import org.graalvm.nativeimage.StackValue;
3738
import org.graalvm.nativeimage.c.struct.SizeOf;
3839
import org.graalvm.nativeimage.c.type.WordPointer;
3940
import org.graalvm.word.Pointer;
@@ -158,10 +159,52 @@ public static void initialize(IsolateThread thread) {
158159
resetStatistics(thread);
159160
}
160161

162+
@BasedOnJDKFile("https://github.com/openjdk/jdk/blob/jdk-25+25/src/hotspot/share/gc/shared/memAllocator.cpp#L257-L329")
163+
@Uninterruptible(reason = "Holds uninitialized memory.")
164+
static Pointer allocateRawMemoryInTlabSlow(UnsignedWord size) {
165+
ThreadLocalAllocation.Descriptor tlab = getTlab();
166+
167+
/*
168+
* Retain tlab and allocate object as an heap allocation if the amount free in the tlab is
169+
* too large to discard.
170+
*/
171+
if (shouldRetainTlab(tlab)) {
172+
recordSlowAllocation();
173+
return Word.nullPointer();
174+
}
175+
176+
/* Discard tlab and allocate a new one. */
177+
recordRefillWaste();
178+
retireTlab(CurrentIsolate.getCurrentThread(), false);
179+
180+
/* To minimize fragmentation, the last tlab may be smaller than the rest. */
181+
UnsignedWord newTlabSize = computeSizeOfNewTlab(size);
182+
if (newTlabSize.equal(0)) {
183+
return Word.nullPointer();
184+
}
185+
186+
/*
187+
* Allocate a new TLAB requesting newTlabSize. Any size between minimal and newTlabSize is
188+
* accepted.
189+
*/
190+
UnsignedWord computedMinSize = computeMinSizeOfNewTlab(size);
191+
192+
WordPointer allocatedTlabSize = StackValue.get(WordPointer.class);
193+
Pointer memory = YoungGeneration.getHeapAllocation().allocateNewTlab(computedMinSize, newTlabSize, allocatedTlabSize);
194+
if (memory.isNull()) {
195+
assert Word.unsigned(0).equal(allocatedTlabSize.read()) : "Allocation failed, but actual size was updated.";
196+
return Word.nullPointer();
197+
}
198+
assert Word.unsigned(0).notEqual(allocatedTlabSize.read()) : "Allocation succeeded but actual size not updated.";
199+
200+
fillTlab(memory, memory.add(size), allocatedTlabSize);
201+
return memory;
202+
}
203+
161204
@BasedOnJDKFile("https://github.com/openjdk/jdk/blob/jdk-25+25/src/hotspot/share/runtime/thread.cpp#L168-L174")
162205
@BasedOnJDKFile("https://github.com/openjdk/jdk/blob/jdk-23-ga/src/hotspot/share/gc/shared/threadLocalAllocBuffer.cpp#L183-L195")
163206
@Uninterruptible(reason = "Accesses TLAB")
164-
static void fillTlab(Pointer start, Pointer top, WordPointer newSize) {
207+
private static void fillTlab(Pointer start, Pointer top, WordPointer newSize) {
165208
/* Fill the TLAB. */
166209
numberOfRefills.set(numberOfRefills.get() + 1);
167210

@@ -178,15 +221,15 @@ static void fillTlab(Pointer start, Pointer top, WordPointer newSize) {
178221

179222
@BasedOnJDKFile("https://github.com/openjdk/jdk/blob/jdk-25+25/src/hotspot/share/gc/shared/threadLocalAllocBuffer.cpp#L143-L145")
180223
@Uninterruptible(reason = "Accesses TLAB")
181-
static void recordRefillWaste() {
224+
private static void recordRefillWaste() {
182225
long availableTlabMemory = availableTlabMemory(getTlab()).rawValue();
183226
refillWaste.set(refillWaste.get() + UninterruptibleUtils.NumUtil.safeToInt(availableTlabMemory));
184227
}
185228

186229
@BasedOnJDKFile("https://github.com/openjdk/jdk/blob/jdk-25+25/src/hotspot/share/runtime/thread.cpp#L157-L166")
187230
@BasedOnJDKFile("https://github.com/openjdk/jdk/blob/jdk-25+25/src/hotspot/share/gc/shared/threadLocalAllocBuffer.cpp#L131-L141")
188231
@Uninterruptible(reason = "Accesses TLAB")
189-
static void retireTlab(IsolateThread thread, boolean calculateStats) {
232+
private static void retireTlab(IsolateThread thread, boolean calculateStats) {
190233
/* Sampling and serviceability support. */
191234
ThreadLocalAllocation.Descriptor tlab = getTlab(thread);
192235
if (tlab.getAllocationEnd(TLAB_END_IDENTITY).isNonNull()) {
@@ -284,7 +327,7 @@ private static void retireTlabToEden(IsolateThread thread) {
284327
}
285328

286329
@Uninterruptible(reason = "Accesses TLAB")
287-
static UnsignedWord availableTlabMemory(Descriptor tlab) {
330+
private static UnsignedWord availableTlabMemory(Descriptor tlab) {
288331
Pointer top = tlab.getAllocationTop(TLAB_TOP_IDENTITY);
289332
Pointer end = tlab.getAllocationEnd(TLAB_END_IDENTITY);
290333
assert top.belowOrEqual(end);
@@ -322,7 +365,6 @@ private static void insertFiller(ThreadLocalAllocation.Descriptor tlab) {
322365
if (top.belowThan(hardEnd)) {
323366
FillerObjectUtil.writeFillerObjectAt(top, size);
324367
}
325-
326368
}
327369

328370
@BasedOnJDKFile("https://github.com/openjdk/jdk/blob/jdk-23-ga/src/hotspot/share/gc/shared/threadLocalAllocBuffer.cpp#L175-L181")
@@ -384,7 +426,7 @@ private static UnsignedWord initialRefillWasteLimit() {
384426

385427
@BasedOnJDKFile("https://github.com/openjdk/jdk/blob/jdk-25+8/src/hotspot/share/gc/shared/threadLocalAllocBuffer.inline.hpp#L54-L71")
386428
@Uninterruptible(reason = CALLED_FROM_UNINTERRUPTIBLE_CODE, mayBeInlined = true)
387-
static UnsignedWord computeSizeOfNewTlab(UnsignedWord allocationSize) {
429+
private static UnsignedWord computeSizeOfNewTlab(UnsignedWord allocationSize) {
388430
assert UnsignedUtils.isAMultiple(allocationSize, Word.unsigned(ConfigurationValues.getObjectLayout().getAlignment()));
389431

390432
/*
@@ -403,7 +445,7 @@ static UnsignedWord computeSizeOfNewTlab(UnsignedWord allocationSize) {
403445

404446
@BasedOnJDKFile("https://github.com/openjdk/jdk/blob/jdk-23-ga/src/hotspot/share/gc/shared/threadLocalAllocBuffer.inline.hpp#L73-L77")
405447
@Uninterruptible(reason = CALLED_FROM_UNINTERRUPTIBLE_CODE, mayBeInlined = true)
406-
static UnsignedWord computeMinSizeOfNewTlab(UnsignedWord allocationSize) {
448+
private static UnsignedWord computeMinSizeOfNewTlab(UnsignedWord allocationSize) {
407449
UnsignedWord alignedSize = Word.unsigned(ConfigurationValues.getObjectLayout().alignUp(allocationSize.rawValue()));
408450
UnsignedWord sizeWithReserve = alignedSize.add(getFillerObjectSize());
409451
long minTlabSize = TlabOptionCache.singleton().getMinTlabSize();
@@ -412,13 +454,13 @@ static UnsignedWord computeMinSizeOfNewTlab(UnsignedWord allocationSize) {
412454
}
413455

414456
@Uninterruptible(reason = CALLED_FROM_UNINTERRUPTIBLE_CODE, mayBeInlined = true)
415-
static boolean shouldRetainTlab(Descriptor tlab) {
457+
private static boolean shouldRetainTlab(Descriptor tlab) {
416458
return availableTlabMemory(tlab).aboveThan(refillWasteLimit.get());
417459
}
418460

419461
@BasedOnJDKFile("https://github.com/openjdk/jdk/blob/jdk-25+11/src/hotspot/share/gc/shared/threadLocalAllocBuffer.inline.hpp#L79-L94")
420462
@Uninterruptible(reason = CALLED_FROM_UNINTERRUPTIBLE_CODE, mayBeInlined = true)
421-
static void recordSlowAllocation() {
463+
private static void recordSlowAllocation() {
422464
/*
423465
* Raise size required to bypass TLAB next time. Else there's a risk that a thread that
424466
* repeatedly allocates objects of one size will get stuck on this slow path.
@@ -469,7 +511,6 @@ static void logTlabChunks(Log log, IsolateThread thread, String shortSpaceName)
469511
ThreadLocalAllocation.Descriptor tlab = getTlabUnsafe(thread);
470512

471513
// Aligned chunks are handled in HeapAllocation.
472-
473514
UnalignedHeapChunk.UnalignedHeader uChunk = tlab.getUnalignedChunk();
474515
HeapChunkLogging.logChunks(log, uChunk, shortSpaceName, false);
475516
}

0 commit comments

Comments
 (0)