1 // Copyright 2016 The Go Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style
3 // license that can be found in the LICENSE file.
5 // gccgo-specific support for GC.
14 // For gccgo, use go:linkname to export compiler-called functions.
16 //go:linkname gcWriteBarrier
18 // gcRoot is a single GC root: a variable plus a ptrmask.
21 decl unsafe
.Pointer
// Pointer to variable.
22 size
uintptr // Size of variable.
23 ptrdata
uintptr // Length of gcdata.
24 gcdata
*uint8 // Pointer mask.
27 // gcRootList is the set of GC roots for a package.
28 // The next field is used to put this all into a linked list.
29 // count gives the real length of the array.
30 type gcRootList
struct {
36 // roots is the list of GC roots for the program.
37 // The compiler keeps this variable itself off the list.
38 var gcRoots
*gcRootList
40 // Slice containing pointers to all reachable gcRoot's sorted by
41 // starting address (generated at init time from 'gcRoots').
42 // The compiler also keeps this variable itself off the list.
43 // The storage backing this slice is allocated via persistentalloc(), the
44 // idea being that we don't want to treat the slice itself as a global
45 // variable, since it points to things that don't need to be scanned
47 var gcRootsIndex
[]*gcRoot
49 // rootradixsort performs an in-place radix sort of the 'arr' rootptr slice.
50 // Note: not a stable sort, however we expect it to be called only on slices
51 // with no duplicate entries, so this should not matter.
52 func rootradixsort(arr
[]*gcRoot
, lo
, hi
int, bit
uint) {
53 // Partition the array into two bins based on the values at the
54 // specified bit position: 0's bin (grown from the left) and and
55 // 1's bin (grown from the right). We keep two boundary markers,
56 // the 0's boundary "zbb" (which grows to the right) and the 1's
57 // boundary "obb" (which grows to the left). At each step we
58 // examine the bit for the right-of-ZBB element: if it is zero, we
59 // leave it in place and move the ZBB to the right. If the bit is
60 // not zero, then we swap the ZBB and OBB elements and move the
61 // OBB to the left. When this is done, the two partitions are then
62 // sorted using the next lower bit.
64 // 0's bin boundary, initially set to before the first element
66 // 1's bin boundary, set to just beyond the last element
68 // mask to pick up bit of interest
69 bmask
:= uintptr(1) << bit
72 zbbval
:= uintptr(arr
[zbb
+1].decl
) & bmask
74 // Move zbb one to the right
77 // Move obb one to the left and swap
78 arr
[obb
-1], arr
[zbb
+1] = arr
[zbb
+1], arr
[obb
-1]
84 // NB: in most cases there is just a single partition to visit
85 // so if we wanted to reduce stack space we could check for this
86 // and insert a goto back up to the top.
88 rootradixsort(arr
, lo
, zbb
, bit
-1)
91 rootradixsort(arr
, obb
, hi
, bit
-1)
97 func createGcRootsIndex() {
106 // Construct the gcRootsIndex slice. Use non-heap storage for the array
107 // backing the slice.
108 sp
:= (*notInHeapSlice
)(unsafe
.Pointer(&gcRootsIndex
))
109 sp
.array
= (*notInHeap
)(persistentalloc1(goarch
.PtrSize
*uintptr(nroots
), goarch
.PtrSize
, &memstats
.other_sys
))
111 throw("runtime: cannot allocate memory")
116 // Populate the roots index slice
120 for i
:= 0; i
< gcr
.count
; i
++ {
121 gcRootsIndex
[k
] = &gcr
.roots
[i
]
127 // Sort it by starting address.
128 rootradixsort(gcRootsIndex
, 0, nroots
-1, goarch
.PtrSize
*8-1)
131 // registerGCRoots is called by compiler-generated code.
132 //go:linkname registerGCRoots
134 // registerGCRoots is called by init functions to register the GC
135 // roots for a package. The init functions are run sequentially at
136 // the start of the program, so no locking is needed.
137 func registerGCRoots(r
*gcRootList
) {
142 // checkPreempt is called when the preempt field in the running G is true.
143 // It preempts the goroutine if it is safe to do so.
144 // If preemptscan is true, this scans the stack for the garbage collector
146 func checkPreempt() {
148 if !gp
.preempt || gp
!= gp
.m
.curg ||
!canPreemptM(gp
.m
) {
156 // Act like goroutine called runtime.Gosched.
160 // gcWriteBarrier implements a write barrier. This is implemented in
161 // assembly in the gc library, but there is no special advantage to
162 // doing so with gccgo.
165 func gcWriteBarrier(dst
*uintptr, src
uintptr) {
166 buf
:= &getg().m
.p
.ptr().wbBuf
167 if !buf
.putFast(src
, *dst
) {