@@ -27,6 +27,10 @@ import (
2727const needsStaticHeap = false
2828
2929const boehmLayoutSizeBits = 4 + unsafe .Sizeof (uintptr (0 ))/ 4
30+ const (
31+ boehmPtrFreeKind = 0
32+ boehmNormalKind = 1
33+ )
3034
3135var gcLock task.PMutex
3236
@@ -77,35 +81,43 @@ 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 )
89+ case gclayout .Pointer .AsPtr (), gclayout .PointerPair .AsPtr ():
90+ // Conservative scanning is exact when every word is a pointer.
91+ ptr = libgc_malloc_kind (size , boehmNormalKind )
8792 default :
8893 elementWords := boehmLayoutElementWords (layout )
89- pointerSize := unsafe .Sizeof (uintptr (0 ))
90- if elementWords == 0 || elementWords > size / pointerSize {
94+ pointerAlign := unsafe .Alignof (uintptr (0 ))
95+ if elementWords == 0 || elementWords > size / pointerAlign {
9196 // This should not happen for compiler-generated Go allocations.
92- ptr = libgc_malloc (size )
97+ ptr = libgc_malloc_kind (size , boehmNormalKind )
9398 break
9499 }
95- elementSize := elementWords * pointerSize
100+ elementSize := elementWords * pointerAlign
96101 if size % elementSize != 0 {
97- ptr = libgc_malloc (size )
102+ ptr = libgc_malloc_kind (size , boehmNormalKind )
98103 break
99104 }
100105
101106 descriptor := libgc_make_descriptor (uintptr (layout ))
102107 if descriptor == 0 {
103- // Descriptor construction can fail under memory pressure. A
104- // conservative allocation remains correct in that case .
105- ptr = libgc_malloc (size )
108+ // The bridge returns zero if its cache or bitmap allocation fails.
109+ // It also rejects the no-pointer descriptor, which is handled above .
110+ ptr = libgc_malloc_kind (size , boehmNormalKind )
106111 break
107112 }
108- ptr = libgc_calloc_explicitly_typed (size / elementSize , elementSize , descriptor )
113+ elementCount := size / elementSize
114+ if elementCount == 1 {
115+ ptr = libgc_malloc_explicitly_typed (size , descriptor )
116+ } else {
117+ ptr = libgc_calloc_explicitly_typed (
118+ elementCount , elementSize , descriptor ,
119+ )
120+ }
109121 }
110122 gcResumeWorld ()
111123 gcLock .Unlock ()
@@ -116,7 +128,6 @@ func alloc(size uintptr, layout unsafe.Pointer) unsafe.Pointer {
116128 if needsZero {
117129 memzero (ptr , size )
118130 }
119-
120131 return ptr
121132}
122133
@@ -202,11 +213,8 @@ func SetFinalizer(obj interface{}, finalizer interface{}) {
202213//export GC_init
203214func libgc_init ()
204215
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
216+ //export GC_malloc_kind
217+ func libgc_malloc_kind (uintptr , int32 ) unsafe.Pointer
210218
211219//export GC_malloc_atomic_uncollectable
212220func libgc_malloc_atomic_uncollectable (uintptr ) unsafe.Pointer
@@ -217,6 +225,9 @@ func libgc_make_descriptor(uintptr) uintptr
217225//export GC_calloc_explicitly_typed
218226func libgc_calloc_explicitly_typed (uintptr , uintptr , uintptr ) unsafe.Pointer
219227
228+ //export GC_malloc_explicitly_typed
229+ func libgc_malloc_explicitly_typed (uintptr , uintptr ) unsafe.Pointer
230+
220231//export GC_free
221232func libgc_free (unsafe.Pointer )
222233
0 commit comments