...
1
2
3
4
5 package gc
6
7 import (
8 "internal/race"
9 "math/rand"
10 "sort"
11 "sync"
12
13 "cmd/compile/internal/base"
14 "cmd/compile/internal/ir"
15 "cmd/compile/internal/liveness"
16 "cmd/compile/internal/objw"
17 "cmd/compile/internal/ssagen"
18 "cmd/compile/internal/staticinit"
19 "cmd/compile/internal/types"
20 "cmd/compile/internal/walk"
21 "cmd/internal/obj"
22 )
23
24
25
26 var (
27 compilequeue []*ir.Func
28 )
29
30 func enqueueFunc(fn *ir.Func) {
31 if ir.CurFunc != nil {
32 base.FatalfAt(fn.Pos(), "enqueueFunc %v inside %v", fn, ir.CurFunc)
33 }
34
35 if ir.FuncName(fn) == "_" {
36
37
38 return
39 }
40
41
42 if fn.IsDeadcodeClosure() {
43 return
44 }
45
46 if clo := fn.OClosure; clo != nil && !ir.IsTrivialClosure(clo) {
47 return
48 }
49
50 if ssagen.CreateWasmImportWrapper(fn) {
51 return
52 }
53
54 if len(fn.Body) == 0 {
55
56 ir.InitLSym(fn, false)
57 types.CalcSize(fn.Type())
58 a := ssagen.AbiForBodylessFuncStackMap(fn)
59 abiInfo := a.ABIAnalyzeFuncType(fn.Type())
60 liveness.WriteFuncMap(fn, abiInfo)
61 if fn.ABI == obj.ABI0 {
62 x := ssagen.EmitArgInfo(fn, abiInfo)
63 objw.Global(x, int32(len(x.P)), obj.RODATA|obj.LOCAL)
64 }
65 return
66 }
67
68 errorsBefore := base.Errors()
69
70 todo := []*ir.Func{fn}
71 for len(todo) > 0 {
72 next := todo[len(todo)-1]
73 todo = todo[:len(todo)-1]
74
75 prepareFunc(next)
76 todo = append(todo, next.Closures...)
77 }
78
79 if base.Errors() > errorsBefore {
80 return
81 }
82
83
84
85 compilequeue = append(compilequeue, fn)
86 }
87
88
89
90 func prepareFunc(fn *ir.Func) {
91
92
93
94 ir.InitLSym(fn, true)
95
96
97
98 if staticinit.MapInitToVar != nil {
99 if _, ok := staticinit.MapInitToVar[fn]; ok {
100 ssagen.RegisterMapInitLsym(fn.Linksym())
101 }
102 }
103
104
105 types.CalcSize(fn.Type())
106
107 ir.CurFunc = fn
108 walk.Walk(fn)
109 ir.CurFunc = nil
110 }
111
112
113
114
115 func compileFunctions() {
116 if race.Enabled {
117
118 tmp := make([]*ir.Func, len(compilequeue))
119 perm := rand.Perm(len(compilequeue))
120 for i, v := range perm {
121 tmp[v] = compilequeue[i]
122 }
123 copy(compilequeue, tmp)
124 } else {
125
126
127
128 sort.Slice(compilequeue, func(i, j int) bool {
129 return len(compilequeue[i].Body) > len(compilequeue[j].Body)
130 })
131 }
132
133
134
135 queue := func(work func(int)) {
136 work(0)
137 }
138
139 if nWorkers := base.Flag.LowerC; nWorkers > 1 {
140
141
142
143 workq := make(chan func(int))
144 done := make(chan int)
145 go func() {
146 ids := make([]int, nWorkers)
147 for i := range ids {
148 ids[i] = i
149 }
150 var pending []func(int)
151 for {
152 select {
153 case work := <-workq:
154 pending = append(pending, work)
155 case id := <-done:
156 ids = append(ids, id)
157 }
158 for len(pending) > 0 && len(ids) > 0 {
159 work := pending[len(pending)-1]
160 id := ids[len(ids)-1]
161 pending = pending[:len(pending)-1]
162 ids = ids[:len(ids)-1]
163 go func() {
164 work(id)
165 done <- id
166 }()
167 }
168 }
169 }()
170 queue = func(work func(int)) {
171 workq <- work
172 }
173 }
174
175 var wg sync.WaitGroup
176 var compile func([]*ir.Func)
177 compile = func(fns []*ir.Func) {
178 wg.Add(len(fns))
179 for _, fn := range fns {
180 fn := fn
181 queue(func(worker int) {
182 ssagen.Compile(fn, worker)
183 compile(fn.Closures)
184 wg.Done()
185 })
186 }
187 }
188
189 types.CalcSizeDisabled = true
190 base.Ctxt.InParallel = true
191
192 compile(compilequeue)
193 compilequeue = nil
194 wg.Wait()
195
196 base.Ctxt.InParallel = false
197 types.CalcSizeDisabled = false
198 }
199
View as plain text