Skip to content

Commit 63c39af

Browse files
committed
wasm: fix C realloc and optimize it a bit
- Do not use make([]byte, ...) to allocate, instead call the allocator directly with a nil (undefined) layout. This makes sure the precise GC will scan the contents of the allocation, since C could very well put pointers in there. - Simplify the map to use the pointer as the key and the size as the value, instead of storing the slices directly in the map.
1 parent b611cbc commit 63c39af

File tree

1 file changed

+15
-12
lines changed

1 file changed

+15
-12
lines changed

src/runtime/arch_tinygowasm_malloc.go

Lines changed: 15 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -8,16 +8,17 @@ import "unsafe"
88
// code linked from other languages can allocate memory without colliding with
99
// our GC allocations.
1010

11-
var allocs = make(map[uintptr][]byte)
11+
// Map of allocations, where the key is the allocated pointer and the value is
12+
// the size of the allocation.
13+
var allocs = make(map[unsafe.Pointer]uintptr)
1214

1315
//export malloc
1416
func libc_malloc(size uintptr) unsafe.Pointer {
1517
if size == 0 {
1618
return nil
1719
}
18-
buf := make([]byte, size)
19-
ptr := unsafe.Pointer(&buf[0])
20-
allocs[uintptr(ptr)] = buf
20+
ptr := alloc(size, nil)
21+
allocs[ptr] = size
2122
return ptr
2223
}
2324

@@ -26,8 +27,8 @@ func libc_free(ptr unsafe.Pointer) {
2627
if ptr == nil {
2728
return
2829
}
29-
if _, ok := allocs[uintptr(ptr)]; ok {
30-
delete(allocs, uintptr(ptr))
30+
if _, ok := allocs[ptr]; ok {
31+
delete(allocs, ptr)
3132
} else {
3233
panic("free: invalid pointer")
3334
}
@@ -48,18 +49,20 @@ func libc_realloc(oldPtr unsafe.Pointer, size uintptr) unsafe.Pointer {
4849

4950
// It's hard to optimize this to expand the current buffer with our GC, but
5051
// it is theoretically possible. For now, just always allocate fresh.
51-
buf := make([]byte, size)
52+
// TODO: we could skip this if the new allocation is smaller than the old.
53+
ptr := alloc(size, nil)
5254

5355
if oldPtr != nil {
54-
if oldBuf, ok := allocs[uintptr(oldPtr)]; ok {
55-
copy(buf, oldBuf)
56-
delete(allocs, uintptr(oldPtr))
56+
if oldSize, ok := allocs[oldPtr]; ok {
57+
oldBuf := unsafe.Slice((*byte)(oldPtr), oldSize)
58+
newBuf := unsafe.Slice((*byte)(ptr), size)
59+
copy(newBuf, oldBuf)
60+
delete(allocs, oldPtr)
5761
} else {
5862
panic("realloc: invalid pointer")
5963
}
6064
}
6165

62-
ptr := unsafe.Pointer(&buf[0])
63-
allocs[uintptr(ptr)] = buf
66+
allocs[ptr] = size
6467
return ptr
6568
}

0 commit comments

Comments
 (0)