mirror of
https://github.com/tinygo-org/tinygo.git
synced 2026-08-04 11:07:46 +00:00
runtime (gc_blocks.go): clear full size of allocation
This fixes a bug where runtime.alloc would not clear the padding from rounding the allocation up to a multiple of the block size. The GC still has to scan this, and this could result in permanent false positives (and therefore memory leaks). It also handles overflow in the size calculation.
This commit is contained in:
@@ -42,9 +42,9 @@ func TestBinarySize(t *testing.T) {
|
||||
// This is a small number of very diverse targets that we want to test.
|
||||
tests := []sizeTest{
|
||||
// microcontrollers
|
||||
{"hifive1b", "examples/echo", 3884, 280, 0, 2268},
|
||||
{"microbit", "examples/serial", 2844, 360, 8, 2272},
|
||||
{"wioterminal", "examples/pininterrupt", 7349, 1491, 116, 6912},
|
||||
{"hifive1b", "examples/echo", 3896, 280, 0, 2268},
|
||||
{"microbit", "examples/serial", 2860, 360, 8, 2272},
|
||||
{"wioterminal", "examples/pininterrupt", 7361, 1491, 116, 6912},
|
||||
|
||||
// TODO: also check wasm. Right now this is difficult, because
|
||||
// wasm binaries are run through wasm-opt and therefore the
|
||||
|
||||
@@ -311,22 +311,31 @@ func alloc(size uintptr, layout unsafe.Pointer) unsafe.Pointer {
|
||||
return unsafe.Pointer(&zeroSizedAlloc)
|
||||
}
|
||||
|
||||
if preciseHeap {
|
||||
size += align(unsafe.Sizeof(layout))
|
||||
}
|
||||
|
||||
if interrupt.In() {
|
||||
runtimePanicAt(returnAddress(0), "heap alloc in interrupt")
|
||||
}
|
||||
|
||||
// Round the size up to a multiple of blocks.
|
||||
rawSize := size
|
||||
size += bytesPerBlock - 1
|
||||
if preciseHeap {
|
||||
// Add space for the layout.
|
||||
size += align(unsafe.Sizeof(layout))
|
||||
}
|
||||
if size < rawSize {
|
||||
// The size overflowed.
|
||||
runtimePanicAt(returnAddress(0), "out of memory")
|
||||
}
|
||||
neededBlocks := size / bytesPerBlock
|
||||
size = neededBlocks * bytesPerBlock
|
||||
|
||||
// Make sure there are no concurrent allocations. The heap is not currently
|
||||
// designed for concurrent alloc/GC.
|
||||
gcLock.Lock()
|
||||
|
||||
gcTotalAlloc += uint64(size)
|
||||
// Update the total allocation counters.
|
||||
gcTotalAlloc += uint64(rawSize)
|
||||
gcMallocs++
|
||||
|
||||
neededBlocks := (size + (bytesPerBlock - 1)) / bytesPerBlock
|
||||
gcTotalBlocks += uint64(neededBlocks)
|
||||
|
||||
// Continue looping until a run of free blocks has been found that fits the
|
||||
|
||||
Reference in New Issue
Block a user