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 for _, ai := range mheap_.allArenas {
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
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.b))
92 mask := byte(1 << ((obj / heapArenaBytes) % 8))
93 bytep := &arena.checkmarks.b[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