Skip to content

Commit 9e3dfbd

Browse files
committed
runtime: reduce typed Boehm allocation overhead
Bypass trivial allocation wrappers and skip typed-array setup for scalar objects.
1 parent 6c2ca45 commit 9e3dfbd

1 file changed

Lines changed: 22 additions & 14 deletions

File tree

src/runtime/gc_boehm.go

Lines changed: 22 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,10 @@ import (
2727
const needsStaticHeap = false
2828

2929
const boehmLayoutSizeBits = 4 + unsafe.Sizeof(uintptr(0))/4
30+
const (
31+
boehmPtrFreeKind = 0
32+
boehmNormalKind = 1
33+
)
3034

3135
var gcLock task.PMutex
3236

@@ -77,35 +81,40 @@ func alloc(size uintptr, layout unsafe.Pointer) unsafe.Pointer {
7781
// This object is entirely pointer free, for example make([]int, ...).
7882
// Make sure the GC knows this so it doesn't scan the object
7983
// unnecessarily to improve performance.
80-
ptr = libgc_malloc_atomic(size)
81-
// Memory returned from libgc_malloc_atomic has not been zeroed so we
82-
// have to do that manually.
84+
ptr = libgc_malloc_kind(size, boehmPtrFreeKind)
8385
needsZero = true
8486
case gclayout.Conservative.AsPtr():
8587
// Stack storage does not have an ordinary repeating Go object layout.
86-
ptr = libgc_malloc(size)
88+
ptr = libgc_malloc_kind(size, boehmNormalKind)
8789
default:
8890
elementWords := boehmLayoutElementWords(layout)
8991
pointerSize := unsafe.Sizeof(uintptr(0))
9092
if elementWords == 0 || elementWords > size/pointerSize {
9193
// This should not happen for compiler-generated Go allocations.
92-
ptr = libgc_malloc(size)
94+
ptr = libgc_malloc_kind(size, boehmNormalKind)
9395
break
9496
}
9597
elementSize := elementWords * pointerSize
9698
if size%elementSize != 0 {
97-
ptr = libgc_malloc(size)
99+
ptr = libgc_malloc_kind(size, boehmNormalKind)
98100
break
99101
}
100102

101103
descriptor := libgc_make_descriptor(uintptr(layout))
102104
if descriptor == 0 {
103105
// Descriptor construction can fail under memory pressure. A
104106
// conservative allocation remains correct in that case.
105-
ptr = libgc_malloc(size)
107+
ptr = libgc_malloc_kind(size, boehmNormalKind)
106108
break
107109
}
108-
ptr = libgc_calloc_explicitly_typed(size/elementSize, elementSize, descriptor)
110+
elementCount := size / elementSize
111+
if elementCount == 1 {
112+
ptr = libgc_malloc_explicitly_typed(size, descriptor)
113+
} else {
114+
ptr = libgc_calloc_explicitly_typed(
115+
elementCount, elementSize, descriptor,
116+
)
117+
}
109118
}
110119
gcResumeWorld()
111120
gcLock.Unlock()
@@ -116,7 +125,6 @@ func alloc(size uintptr, layout unsafe.Pointer) unsafe.Pointer {
116125
if needsZero {
117126
memzero(ptr, size)
118127
}
119-
120128
return ptr
121129
}
122130

@@ -197,11 +205,8 @@ func SetFinalizer(obj interface{}, finalizer interface{}) {
197205
//export GC_init
198206
func libgc_init()
199207

200-
//export GC_malloc
201-
func libgc_malloc(uintptr) unsafe.Pointer
202-
203-
//export GC_malloc_atomic
204-
func libgc_malloc_atomic(uintptr) unsafe.Pointer
208+
//export GC_malloc_kind
209+
func libgc_malloc_kind(uintptr, int32) unsafe.Pointer
205210

206211
//export GC_malloc_atomic_uncollectable
207212
func libgc_malloc_atomic_uncollectable(uintptr) unsafe.Pointer
@@ -212,6 +217,9 @@ func libgc_make_descriptor(uintptr) uintptr
212217
//export GC_calloc_explicitly_typed
213218
func libgc_calloc_explicitly_typed(uintptr, uintptr, uintptr) unsafe.Pointer
214219

220+
//export GC_malloc_explicitly_typed
221+
func libgc_malloc_explicitly_typed(uintptr, uintptr) unsafe.Pointer
222+
215223
//export GC_free
216224
func libgc_free(unsafe.Pointer)
217225

0 commit comments

Comments
 (0)