Source file
src/runtime/mcheckmark.go
1
2
3
4
5
6
7
8
9
10
11
12
13 package runtime
14
15 import (
16 "internal/goarch"
17 "internal/runtime/atomic"
18 "internal/runtime/sys"
19 "unsafe"
20 )
21
22
23
24
25
26 type checkmarksMap struct {
27 _ sys.NotInHeap
28 b [heapArenaBytes / goarch.PtrSize / 8]uint8
29 }
30
31
32
33 var useCheckmark = false
34
35
36
37
38 func startCheckmarks() {
39 assertWorldStopped()
40
41
42 clearCheckmarks := func(ai arenaIdx) {
43 arena := mheap_.arenas[ai.l1()][ai.l2()]
44 bitmap := arena.checkmarks
45
46 if bitmap == nil {
47
48 bitmap = (*checkmarksMap)(persistentalloc(unsafe.Sizeof(*bitmap), 0, &memstats.gcMiscSys))
49 if bitmap == nil {
50 throw("out of memory allocating checkmarks bitmap")
51 }
52 arena.checkmarks = bitmap
53 } else {
54
55 clear(bitmap.b[:])
56 }
57 }
58 for _, ai := range mheap_.heapArenas {
59 clearCheckmarks(ai)
60 }
61 for _, ai := range mheap_.userArenaArenas {
62 clearCheckmarks(ai)
63 }
64
65
66 useCheckmark = true
67 }
68
69
70 func endCheckmarks() {
71 if gcMarkWorkAvailable(nil) {
72 throw("GC work not flushed")
73 }
74 useCheckmark = false
75 }
76
77
78
79
80 func setCheckmark(obj, base, off uintptr, mbits markBits) bool {
81 if !mbits.isMarked() {
82 printlock()
83 print("runtime: checkmarks found unexpected unmarked object obj=", hex(obj), "\n")
84 print("runtime: found obj at *(", hex(base), "+", hex(off), ")\n")
85
86
87 gcDumpObject("base", base, off)
88
89
90 gcDumpObject("obj", obj, ^uintptr(0))
91
92 getg().m.traceback = 2
93 throw("checkmark found unmarked object")
94 }
95
96 ai := arenaIndex(obj)
97 arena := mheap_.arenas[ai.l1()][ai.l2()]
98 if arena == nil {
99
100 return false
101 }
102 wordIdx := (obj - alignDown(obj, heapArenaBytes)) / goarch.PtrSize
103 arenaWord := wordIdx / 8
104 mask := byte(1 << (wordIdx % 8))
105 bytep := &arena.checkmarks.b[arenaWord]
106
107 if atomic.Load8(bytep)&mask != 0 {
108
109 return true
110 }
111
112 atomic.Or8(bytep, mask)
113 return false
114 }
115
View as plain text