]> Cypherpunks.ru repositories - gostls13.git/blob - src/runtime/mcheckmark.go
cmd/compile/internal/inline: score call sites exposed by inlines
[gostls13.git] / src / runtime / mcheckmark.go
1 // Copyright 2020 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.
4
5 // GC checkmarks
6 //
7 // In a concurrent garbage collector, one worries about failing to mark
8 // a live object due to mutations without write barriers or bugs in the
9 // collector implementation. As a sanity check, the GC has a 'checkmark'
10 // mode that retraverses the object graph with the world stopped, to make
11 // sure that everything that should be marked is marked.
12
13 package runtime
14
15 import (
16         "internal/goarch"
17         "runtime/internal/atomic"
18         "runtime/internal/sys"
19         "unsafe"
20 )
21
22 // A checkmarksMap stores the GC marks in "checkmarks" mode. It is a
23 // per-arena bitmap with a bit for every word in the arena. The mark
24 // is stored on the bit corresponding to the first word of the marked
25 // allocation.
26 type checkmarksMap struct {
27         _ sys.NotInHeap
28         b [heapArenaBytes / goarch.PtrSize / 8]uint8
29 }
30
31 // If useCheckmark is true, marking of an object uses the checkmark
32 // bits instead of the standard mark bits.
33 var useCheckmark = false
34
35 // startCheckmarks prepares for the checkmarks phase.
36 //
37 // The world must be stopped.
38 func startCheckmarks() {
39         assertWorldStopped()
40
41         // Clear all checkmarks.
42         for _, ai := range mheap_.allArenas {
43                 arena := mheap_.arenas[ai.l1()][ai.l2()]
44                 bitmap := arena.checkmarks
45
46                 if bitmap == nil {
47                         // Allocate bitmap on first use.
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                         // Otherwise clear the existing bitmap.
55                         for i := range bitmap.b {
56                                 bitmap.b[i] = 0
57                         }
58                 }
59         }
60         // Enable checkmarking.
61         useCheckmark = true
62 }
63
64 // endCheckmarks ends the checkmarks phase.
65 func endCheckmarks() {
66         if gcMarkWorkAvailable(nil) {
67                 throw("GC work not flushed")
68         }
69         useCheckmark = false
70 }
71
72 // setCheckmark throws if marking object is a checkmarks violation,
73 // and otherwise sets obj's checkmark. It returns true if obj was
74 // already checkmarked.
75 func setCheckmark(obj, base, off uintptr, mbits markBits) bool {
76         if !mbits.isMarked() {
77                 printlock()
78                 print("runtime: checkmarks found unexpected unmarked object obj=", hex(obj), "\n")
79                 print("runtime: found obj at *(", hex(base), "+", hex(off), ")\n")
80
81                 // Dump the source (base) object
82                 gcDumpObject("base", base, off)
83
84                 // Dump the object
85                 gcDumpObject("obj", obj, ^uintptr(0))
86
87                 getg().m.traceback = 2
88                 throw("checkmark found unmarked object")
89         }
90
91         ai := arenaIndex(obj)
92         arena := mheap_.arenas[ai.l1()][ai.l2()]
93         arenaWord := (obj / heapArenaBytes / 8) % uintptr(len(arena.checkmarks.b))
94         mask := byte(1 << ((obj / heapArenaBytes) % 8))
95         bytep := &arena.checkmarks.b[arenaWord]
96
97         if atomic.Load8(bytep)&mask != 0 {
98                 // Already checkmarked.
99                 return true
100         }
101
102         atomic.Or8(bytep, mask)
103         return false
104 }