Skip to content

Commit c6c921f

Browse files
authored
Fix #21615 - The GC expandArrayUsed has pathological behavior when (#21616)
appending to a large array that could potentially use extend, when the requested array size is within a certain size for a multiple of pages. The calculation had the wrong sign for the large padding (the 2 size_t + 1 byte), which made it end up sending a number very close to size_t.max into the extend function. This affected both appending and setting length performance, though appending also had a grow factor which may have mitigated this somewhat.
1 parent 30c08ca commit c6c921f

1 file changed

Lines changed: 21 additions & 1 deletion

File tree

  • druntime/src/core/internal/gc/impl/conservative

druntime/src/core/internal/gc/impl/conservative/gc.d

Lines changed: 21 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1532,7 +1532,7 @@ class ConservativeGC : GC
15321532
return false;
15331533

15341534
// try extending the block into subsequent pages.
1535-
immutable requiredExtension = newUsed - info.size - LARGEPAD;
1535+
immutable requiredExtension = newUsed - (info.size - LARGEPAD);
15361536
auto extendedSize = extend(info.base, requiredExtension, requiredExtension, null);
15371537
if (extendedSize == 0)
15381538
// could not extend, can't satisfy the request
@@ -5393,6 +5393,26 @@ unittest
53935393
}
53945394
}
53955395

5396+
// https://github.com/dlang/dmd/issues/21615
5397+
debug(SENTINEL) {} else // no additional capacity with SENTINEL
5398+
@safe unittest
5399+
{
5400+
size_t numReallocations = 0;
5401+
ubyte[] buffer = new ubyte[4096];
5402+
auto p = &buffer[0];
5403+
foreach (i; 0 .. 1000) {
5404+
buffer.length += 4096;
5405+
if (p !is &buffer[0])
5406+
{
5407+
++numReallocations;
5408+
p = &buffer[0];
5409+
}
5410+
}
5411+
5412+
// pick a decently small number, it's unclear where this memory will start out.
5413+
assert(numReallocations <= 5);
5414+
}
5415+
53965416
/* ============================ MEMSTOMP =============================== */
53975417

53985418
/// Mark the specified memory region as uninitialized -

0 commit comments

Comments
 (0)