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 "runtime/internal/atomic"
18 "unsafe"
19 )
20
21
22
23
24
25
26
27 type checkmarksMap [heapArenaBytes / goarch.PtrSize / 8]uint8
28
29
30
31 var useCheckmark = false
32
33
34
35
36 func startCheckmarks() {
37 assertWorldStopped()
38
39
40 for _, ai := range mheap_.allArenas {
41 arena := mheap_.arenas[ai.l1()][ai.l2()]
42 bitmap := arena.checkmarks
43
44 if bitmap == nil {
45
46 bitmap = (*checkmarksMap)(persistentalloc(unsafe.Sizeof(*bitmap), 0, &memstats.gcMiscSys))
47 if bitmap == nil {
48 throw("out of memory allocating checkmarks bitmap")
49 }
50 arena.checkmarks = bitmap
51 } else {
52
53 for i := range bitmap {
54 bitmap[i] = 0
55 }
56 }
57 }
58
59 useCheckmark = true
60 }
61
62
63 func endCheckmarks() {
64 if gcMarkWorkAvailable(nil) {
65 throw("GC work not flushed")
66 }
67 useCheckmark = false
68 }
69
70
71
72
73 func setCheckmark(obj, base, off uintptr, mbits markBits) bool {
74 if !mbits.isMarked() {
75 printlock()
76 print("runtime: checkmarks found unexpected unmarked object obj=", hex(obj), "\n")
77 print("runtime: found obj at *(", hex(base), "+", hex(off), ")\n")
78
79
80 gcDumpObject("base", base, off)
81
82
83 gcDumpObject("obj", obj, ^uintptr(0))
84
85 getg().m.traceback = 2
86 throw("checkmark found unmarked object")
87 }
88
89 ai := arenaIndex(obj)
90 arena := mheap_.arenas[ai.l1()][ai.l2()]
91 arenaWord := (obj / heapArenaBytes / 8) % uintptr(len(arena.checkmarks))
92 mask := byte(1 << ((obj / heapArenaBytes) % 8))
93 bytep := &arena.checkmarks[arenaWord]
94
95 if atomic.Load8(bytep)&mask != 0 {
96
97 return true
98 }
99
100 atomic.Or8(bytep, mask)
101 return false
102 }
103
View as plain text