Skip to content

Commit 10affef

Browse files
committed
runtime: reduce typed Boehm allocation overhead
Bypass trivial allocation wrappers and skip typed-array setup for scalar objects.
1 parent 5910bf1 commit 10affef

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

@@ -202,11 +210,8 @@ func SetFinalizer(obj interface{}, finalizer interface{}) {
202210
//export GC_init
203211
func libgc_init()
204212

205-
//export GC_malloc
206-
func libgc_malloc(uintptr) unsafe.Pointer
207-
208-
//export GC_malloc_atomic
209-
func libgc_malloc_atomic(uintptr) unsafe.Pointer
213+
//export GC_malloc_kind
214+
func libgc_malloc_kind(uintptr, int32) unsafe.Pointer
210215

211216
//export GC_malloc_atomic_uncollectable
212217
func libgc_malloc_atomic_uncollectable(uintptr) unsafe.Pointer
@@ -217,6 +222,9 @@ func libgc_make_descriptor(uintptr) uintptr
217222
//export GC_calloc_explicitly_typed
218223
func libgc_calloc_explicitly_typed(uintptr, uintptr, uintptr) unsafe.Pointer
219224

225+
//export GC_malloc_explicitly_typed
226+
func libgc_malloc_explicitly_typed(uintptr, uintptr) unsafe.Pointer
227+
220228
//export GC_free
221229
func libgc_free(unsafe.Pointer)
222230

0 commit comments

Comments
 (0)