github.com/bir3/gocompiler@v0.3.205/src/cmd/compile/internal/liveness/plive.go (about) 1 // Copyright 2013 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 // Garbage collector liveness bitmap generation. 6 7 // The command line flag -live causes this code to print debug information. 8 // The levels are: 9 // 10 // -live (aka -live=1): print liveness lists as code warnings at safe points 11 // -live=2: print an assembly listing with liveness annotations 12 // 13 // Each level includes the earlier output as well. 14 15 package liveness 16 17 import ( 18 "fmt" 19 "os" 20 "sort" 21 "strings" 22 23 "github.com/bir3/gocompiler/src/cmd/compile/internal/abi" 24 "github.com/bir3/gocompiler/src/cmd/compile/internal/base" 25 "github.com/bir3/gocompiler/src/cmd/compile/internal/bitvec" 26 "github.com/bir3/gocompiler/src/cmd/compile/internal/ir" 27 "github.com/bir3/gocompiler/src/cmd/compile/internal/objw" 28 "github.com/bir3/gocompiler/src/cmd/compile/internal/reflectdata" 29 "github.com/bir3/gocompiler/src/cmd/compile/internal/ssa" 30 "github.com/bir3/gocompiler/src/cmd/compile/internal/typebits" 31 "github.com/bir3/gocompiler/src/cmd/compile/internal/types" 32 "github.com/bir3/gocompiler/src/cmd/internal/notsha256" 33 "github.com/bir3/gocompiler/src/cmd/internal/obj" 34 "github.com/bir3/gocompiler/src/cmd/internal/objabi" 35 "github.com/bir3/gocompiler/src/cmd/internal/src" 36 ) 37 38 // OpVarDef is an annotation for the liveness analysis, marking a place 39 // where a complete initialization (definition) of a variable begins. 40 // Since the liveness analysis can see initialization of single-word 41 // variables quite easy, OpVarDef is only needed for multi-word 42 // variables satisfying isfat(n.Type). For simplicity though, buildssa 43 // emits OpVarDef regardless of variable width. 44 // 45 // An 'OpVarDef x' annotation in the instruction stream tells the liveness 46 // analysis to behave as though the variable x is being initialized at that 47 // point in the instruction stream. The OpVarDef must appear before the 48 // actual (multi-instruction) initialization, and it must also appear after 49 // any uses of the previous value, if any. For example, if compiling: 50 // 51 // x = x[1:] 52 // 53 // it is important to generate code like: 54 // 55 // base, len, cap = pieces of x[1:] 56 // OpVarDef x 57 // x = {base, len, cap} 58 // 59 // If instead the generated code looked like: 60 // 61 // OpVarDef x 62 // base, len, cap = pieces of x[1:] 63 // x = {base, len, cap} 64 // 65 // then the liveness analysis would decide the previous value of x was 66 // unnecessary even though it is about to be used by the x[1:] computation. 67 // Similarly, if the generated code looked like: 68 // 69 // base, len, cap = pieces of x[1:] 70 // x = {base, len, cap} 71 // OpVarDef x 72 // 73 // then the liveness analysis will not preserve the new value of x, because 74 // the OpVarDef appears to have "overwritten" it. 75 // 76 // OpVarDef is a bit of a kludge to work around the fact that the instruction 77 // stream is working on single-word values but the liveness analysis 78 // wants to work on individual variables, which might be multi-word 79 // aggregates. It might make sense at some point to look into letting 80 // the liveness analysis work on single-word values as well, although 81 // there are complications around interface values, slices, and strings, 82 // all of which cannot be treated as individual words. 83 84 // blockEffects summarizes the liveness effects on an SSA block. 85 type blockEffects struct { 86 // Computed during Liveness.prologue using only the content of 87 // individual blocks: 88 // 89 // uevar: upward exposed variables (used before set in block) 90 // varkill: killed variables (set in block) 91 uevar bitvec.BitVec 92 varkill bitvec.BitVec 93 94 // Computed during Liveness.solve using control flow information: 95 // 96 // livein: variables live at block entry 97 // liveout: variables live at block exit 98 livein bitvec.BitVec 99 liveout bitvec.BitVec 100 } 101 102 // A collection of global state used by liveness analysis. 103 type liveness struct { 104 fn *ir.Func 105 f *ssa.Func 106 vars []*ir.Name 107 idx map[*ir.Name]int32 108 stkptrsize int64 109 110 be []blockEffects 111 112 // allUnsafe indicates that all points in this function are 113 // unsafe-points. 114 allUnsafe bool 115 // unsafePoints bit i is set if Value ID i is an unsafe-point 116 // (preemption is not allowed). Only valid if !allUnsafe. 117 unsafePoints bitvec.BitVec 118 119 // An array with a bit vector for each safe point in the 120 // current Block during liveness.epilogue. Indexed in Value 121 // order for that block. Additionally, for the entry block 122 // livevars[0] is the entry bitmap. liveness.compact moves 123 // these to stackMaps. 124 livevars []bitvec.BitVec 125 126 // livenessMap maps from safe points (i.e., CALLs) to their 127 // liveness map indexes. 128 livenessMap Map 129 stackMapSet bvecSet 130 stackMaps []bitvec.BitVec 131 132 cache progeffectscache 133 134 // partLiveArgs includes input arguments (PPARAM) that may 135 // be partially live. That is, it is considered live because 136 // a part of it is used, but we may not initialize all parts. 137 partLiveArgs map[*ir.Name]bool 138 139 doClobber bool // Whether to clobber dead stack slots in this function. 140 noClobberArgs bool // Do not clobber function arguments 141 } 142 143 // Map maps from *ssa.Value to LivenessIndex. 144 type Map struct { 145 Vals map[ssa.ID]objw.LivenessIndex 146 // The set of live, pointer-containing variables at the DeferReturn 147 // call (only set when open-coded defers are used). 148 DeferReturn objw.LivenessIndex 149 } 150 151 func (m *Map) reset() { 152 if m.Vals == nil { 153 m.Vals = make(map[ssa.ID]objw.LivenessIndex) 154 } else { 155 for k := range m.Vals { 156 delete(m.Vals, k) 157 } 158 } 159 m.DeferReturn = objw.LivenessDontCare 160 } 161 162 func (m *Map) set(v *ssa.Value, i objw.LivenessIndex) { 163 m.Vals[v.ID] = i 164 } 165 166 func (m Map) Get(v *ssa.Value) objw.LivenessIndex { 167 // If v isn't in the map, then it's a "don't care" and not an 168 // unsafe-point. 169 if idx, ok := m.Vals[v.ID]; ok { 170 return idx 171 } 172 return objw.LivenessIndex{StackMapIndex: objw.StackMapDontCare, IsUnsafePoint: false} 173 } 174 175 type progeffectscache struct { 176 retuevar []int32 177 tailuevar []int32 178 initialized bool 179 } 180 181 // shouldTrack reports whether the liveness analysis 182 // should track the variable n. 183 // We don't care about variables that have no pointers, 184 // nor do we care about non-local variables, 185 // nor do we care about empty structs (handled by the pointer check), 186 // nor do we care about the fake PAUTOHEAP variables. 187 func shouldTrack(n *ir.Name) bool { 188 return (n.Class == ir.PAUTO && n.Esc() != ir.EscHeap || n.Class == ir.PPARAM || n.Class == ir.PPARAMOUT) && n.Type().HasPointers() 189 } 190 191 // getvariables returns the list of on-stack variables that we need to track 192 // and a map for looking up indices by *Node. 193 func getvariables(fn *ir.Func) ([]*ir.Name, map[*ir.Name]int32) { 194 var vars []*ir.Name 195 for _, n := range fn.Dcl { 196 if shouldTrack(n) { 197 vars = append(vars, n) 198 } 199 } 200 idx := make(map[*ir.Name]int32, len(vars)) 201 for i, n := range vars { 202 idx[n] = int32(i) 203 } 204 return vars, idx 205 } 206 207 func (lv *liveness) initcache() { 208 if lv.cache.initialized { 209 base.Fatalf("liveness cache initialized twice") 210 return 211 } 212 lv.cache.initialized = true 213 214 for i, node := range lv.vars { 215 switch node.Class { 216 case ir.PPARAM: 217 // A return instruction with a p.to is a tail return, which brings 218 // the stack pointer back up (if it ever went down) and then jumps 219 // to a new function entirely. That form of instruction must read 220 // all the parameters for correctness, and similarly it must not 221 // read the out arguments - they won't be set until the new 222 // function runs. 223 lv.cache.tailuevar = append(lv.cache.tailuevar, int32(i)) 224 225 case ir.PPARAMOUT: 226 // All results are live at every return point. 227 // Note that this point is after escaping return values 228 // are copied back to the stack using their PAUTOHEAP references. 229 lv.cache.retuevar = append(lv.cache.retuevar, int32(i)) 230 } 231 } 232 } 233 234 // A liveEffect is a set of flags that describe an instruction's 235 // liveness effects on a variable. 236 // 237 // The possible flags are: 238 // 239 // uevar - used by the instruction 240 // varkill - killed by the instruction (set) 241 // 242 // A kill happens after the use (for an instruction that updates a value, for example). 243 type liveEffect int 244 245 const ( 246 uevar liveEffect = 1 << iota 247 varkill 248 ) 249 250 // valueEffects returns the index of a variable in lv.vars and the 251 // liveness effects v has on that variable. 252 // If v does not affect any tracked variables, it returns -1, 0. 253 func (lv *liveness) valueEffects(v *ssa.Value) (int32, liveEffect) { 254 n, e := affectedVar(v) 255 if e == 0 || n == nil { // cheapest checks first 256 return -1, 0 257 } 258 // AllocFrame has dropped unused variables from 259 // lv.fn.Func.Dcl, but they might still be referenced by 260 // OpVarFoo pseudo-ops. Ignore them to prevent "lost track of 261 // variable" ICEs (issue 19632). 262 switch v.Op { 263 case ssa.OpVarDef, ssa.OpVarLive, ssa.OpKeepAlive: 264 if !n.Used() { 265 return -1, 0 266 } 267 } 268 269 if n.Class == ir.PPARAM && !n.Addrtaken() && n.Type().Size() > int64(types.PtrSize) { 270 // Only aggregate-typed arguments that are not address-taken can be 271 // partially live. 272 lv.partLiveArgs[n] = true 273 } 274 275 var effect liveEffect 276 // Read is a read, obviously. 277 // 278 // Addr is a read also, as any subsequent holder of the pointer must be able 279 // to see all the values (including initialization) written so far. 280 // This also prevents a variable from "coming back from the dead" and presenting 281 // stale pointers to the garbage collector. See issue 28445. 282 if e&(ssa.SymRead|ssa.SymAddr) != 0 { 283 effect |= uevar 284 } 285 if e&ssa.SymWrite != 0 && (!isfat(n.Type()) || v.Op == ssa.OpVarDef) { 286 effect |= varkill 287 } 288 289 if effect == 0 { 290 return -1, 0 291 } 292 293 if pos, ok := lv.idx[n]; ok { 294 return pos, effect 295 } 296 return -1, 0 297 } 298 299 // affectedVar returns the *ir.Name node affected by v. 300 func affectedVar(v *ssa.Value) (*ir.Name, ssa.SymEffect) { 301 // Special cases. 302 switch v.Op { 303 case ssa.OpLoadReg: 304 n, _ := ssa.AutoVar(v.Args[0]) 305 return n, ssa.SymRead 306 case ssa.OpStoreReg: 307 n, _ := ssa.AutoVar(v) 308 return n, ssa.SymWrite 309 310 case ssa.OpArgIntReg: 311 // This forces the spill slot for the register to be live at function entry. 312 // one of the following holds for a function F with pointer-valued register arg X: 313 // 0. No GC (so an uninitialized spill slot is okay) 314 // 1. GC at entry of F. GC is precise, but the spills around morestack initialize X's spill slot 315 // 2. Stack growth at entry of F. Same as GC. 316 // 3. GC occurs within F itself. This has to be from preemption, and thus GC is conservative. 317 // a. X is in a register -- then X is seen, and the spill slot is also scanned conservatively. 318 // b. X is spilled -- the spill slot is initialized, and scanned conservatively 319 // c. X is not live -- the spill slot is scanned conservatively, and it may contain X from an earlier spill. 320 // 4. GC within G, transitively called from F 321 // a. X is live at call site, therefore is spilled, to its spill slot (which is live because of subsequent LoadReg). 322 // b. X is not live at call site -- but neither is its spill slot. 323 n, _ := ssa.AutoVar(v) 324 return n, ssa.SymRead 325 326 case ssa.OpVarLive: 327 return v.Aux.(*ir.Name), ssa.SymRead 328 case ssa.OpVarDef: 329 return v.Aux.(*ir.Name), ssa.SymWrite 330 case ssa.OpKeepAlive: 331 n, _ := ssa.AutoVar(v.Args[0]) 332 return n, ssa.SymRead 333 } 334 335 e := v.Op.SymEffect() 336 if e == 0 { 337 return nil, 0 338 } 339 340 switch a := v.Aux.(type) { 341 case nil, *obj.LSym: 342 // ok, but no node 343 return nil, e 344 case *ir.Name: 345 return a, e 346 default: 347 base.Fatalf("weird aux: %s", v.LongString()) 348 return nil, e 349 } 350 } 351 352 type livenessFuncCache struct { 353 be []blockEffects 354 livenessMap Map 355 } 356 357 // Constructs a new liveness structure used to hold the global state of the 358 // liveness computation. The cfg argument is a slice of *BasicBlocks and the 359 // vars argument is a slice of *Nodes. 360 func newliveness(fn *ir.Func, f *ssa.Func, vars []*ir.Name, idx map[*ir.Name]int32, stkptrsize int64) *liveness { 361 lv := &liveness{ 362 fn: fn, 363 f: f, 364 vars: vars, 365 idx: idx, 366 stkptrsize: stkptrsize, 367 } 368 369 // Significant sources of allocation are kept in the ssa.Cache 370 // and reused. Surprisingly, the bit vectors themselves aren't 371 // a major source of allocation, but the liveness maps are. 372 if lc, _ := f.Cache.Liveness.(*livenessFuncCache); lc == nil { 373 // Prep the cache so liveness can fill it later. 374 f.Cache.Liveness = new(livenessFuncCache) 375 } else { 376 if cap(lc.be) >= f.NumBlocks() { 377 lv.be = lc.be[:f.NumBlocks()] 378 } 379 lv.livenessMap = Map{Vals: lc.livenessMap.Vals, DeferReturn: objw.LivenessDontCare} 380 lc.livenessMap.Vals = nil 381 } 382 if lv.be == nil { 383 lv.be = make([]blockEffects, f.NumBlocks()) 384 } 385 386 nblocks := int32(len(f.Blocks)) 387 nvars := int32(len(vars)) 388 bulk := bitvec.NewBulk(nvars, nblocks*7) 389 for _, b := range f.Blocks { 390 be := lv.blockEffects(b) 391 392 be.uevar = bulk.Next() 393 be.varkill = bulk.Next() 394 be.livein = bulk.Next() 395 be.liveout = bulk.Next() 396 } 397 lv.livenessMap.reset() 398 399 lv.markUnsafePoints() 400 401 lv.partLiveArgs = make(map[*ir.Name]bool) 402 403 lv.enableClobber() 404 405 return lv 406 } 407 408 func (lv *liveness) blockEffects(b *ssa.Block) *blockEffects { 409 return &lv.be[b.ID] 410 } 411 412 // Generates live pointer value maps for arguments and local variables. The 413 // this argument and the in arguments are always assumed live. The vars 414 // argument is a slice of *Nodes. 415 func (lv *liveness) pointerMap(liveout bitvec.BitVec, vars []*ir.Name, args, locals bitvec.BitVec) { 416 for i := int32(0); ; i++ { 417 i = liveout.Next(i) 418 if i < 0 { 419 break 420 } 421 node := vars[i] 422 switch node.Class { 423 case ir.PPARAM, ir.PPARAMOUT: 424 if !node.IsOutputParamInRegisters() { 425 if node.FrameOffset() < 0 { 426 lv.f.Fatalf("Node %v has frameoffset %d\n", node.Sym().Name, node.FrameOffset()) 427 } 428 typebits.SetNoCheck(node.Type(), node.FrameOffset(), args) 429 break 430 } 431 fallthrough // PPARAMOUT in registers acts memory-allocates like an AUTO 432 case ir.PAUTO: 433 typebits.Set(node.Type(), node.FrameOffset()+lv.stkptrsize, locals) 434 } 435 } 436 } 437 438 // IsUnsafe indicates that all points in this function are 439 // unsafe-points. 440 func IsUnsafe(f *ssa.Func) bool { 441 // The runtime assumes the only safe-points are function 442 // prologues (because that's how it used to be). We could and 443 // should improve that, but for now keep consider all points 444 // in the runtime unsafe. obj will add prologues and their 445 // safe-points. 446 // 447 // go:nosplit functions are similar. Since safe points used to 448 // be coupled with stack checks, go:nosplit often actually 449 // means "no safe points in this function". 450 return base.Flag.CompilingRuntime || f.NoSplit 451 } 452 453 // markUnsafePoints finds unsafe points and computes lv.unsafePoints. 454 func (lv *liveness) markUnsafePoints() { 455 if IsUnsafe(lv.f) { 456 // No complex analysis necessary. 457 lv.allUnsafe = true 458 return 459 } 460 461 lv.unsafePoints = bitvec.New(int32(lv.f.NumValues())) 462 463 // Mark architecture-specific unsafe points. 464 for _, b := range lv.f.Blocks { 465 for _, v := range b.Values { 466 if v.Op.UnsafePoint() { 467 lv.unsafePoints.Set(int32(v.ID)) 468 } 469 } 470 } 471 472 // Mark write barrier unsafe points. 473 for _, wbBlock := range lv.f.WBLoads { 474 if wbBlock.Kind == ssa.BlockPlain && len(wbBlock.Values) == 0 { 475 // The write barrier block was optimized away 476 // but we haven't done dead block elimination. 477 // (This can happen in -N mode.) 478 continue 479 } 480 // Check that we have the expected diamond shape. 481 if len(wbBlock.Succs) != 2 { 482 lv.f.Fatalf("expected branch at write barrier block %v", wbBlock) 483 } 484 s0, s1 := wbBlock.Succs[0].Block(), wbBlock.Succs[1].Block() 485 if s0 == s1 { 486 // There's no difference between write barrier on and off. 487 // Thus there's no unsafe locations. See issue 26024. 488 continue 489 } 490 if s0.Kind != ssa.BlockPlain || s1.Kind != ssa.BlockPlain { 491 lv.f.Fatalf("expected successors of write barrier block %v to be plain", wbBlock) 492 } 493 if s0.Succs[0].Block() != s1.Succs[0].Block() { 494 lv.f.Fatalf("expected successors of write barrier block %v to converge", wbBlock) 495 } 496 497 // Flow backwards from the control value to find the 498 // flag load. We don't know what lowered ops we're 499 // looking for, but all current arches produce a 500 // single op that does the memory load from the flag 501 // address, so we look for that. 502 var load *ssa.Value 503 v := wbBlock.Controls[0] 504 for { 505 if sym, ok := v.Aux.(*obj.LSym); ok && sym == ir.Syms.WriteBarrier { 506 load = v 507 break 508 } 509 switch v.Op { 510 case ssa.Op386TESTL: 511 // 386 lowers Neq32 to (TESTL cond cond), 512 if v.Args[0] == v.Args[1] { 513 v = v.Args[0] 514 continue 515 } 516 case ssa.Op386MOVLload, ssa.OpARM64MOVWUload, ssa.OpPPC64MOVWZload, ssa.OpWasmI64Load32U: 517 // Args[0] is the address of the write 518 // barrier control. Ignore Args[1], 519 // which is the mem operand. 520 // TODO: Just ignore mem operands? 521 v = v.Args[0] 522 continue 523 } 524 // Common case: just flow backwards. 525 if len(v.Args) != 1 { 526 v.Fatalf("write barrier control value has more than one argument: %s", v.LongString()) 527 } 528 v = v.Args[0] 529 } 530 531 // Mark everything after the load unsafe. 532 found := false 533 for _, v := range wbBlock.Values { 534 found = found || v == load 535 if found { 536 lv.unsafePoints.Set(int32(v.ID)) 537 } 538 } 539 540 // Mark the two successor blocks unsafe. These come 541 // back together immediately after the direct write in 542 // one successor and the last write barrier call in 543 // the other, so there's no need to be more precise. 544 for _, succ := range wbBlock.Succs { 545 for _, v := range succ.Block().Values { 546 lv.unsafePoints.Set(int32(v.ID)) 547 } 548 } 549 } 550 551 // Find uintptr -> unsafe.Pointer conversions and flood 552 // unsafeness back to a call (which is always a safe point). 553 // 554 // Looking for the uintptr -> unsafe.Pointer conversion has a 555 // few advantages over looking for unsafe.Pointer -> uintptr 556 // conversions: 557 // 558 // 1. We avoid needlessly blocking safe-points for 559 // unsafe.Pointer -> uintptr conversions that never go back to 560 // a Pointer. 561 // 562 // 2. We don't have to detect calls to reflect.Value.Pointer, 563 // reflect.Value.UnsafeAddr, and reflect.Value.InterfaceData, 564 // which are implicit unsafe.Pointer -> uintptr conversions. 565 // We can't even reliably detect this if there's an indirect 566 // call to one of these methods. 567 // 568 // TODO: For trivial unsafe.Pointer arithmetic, it would be 569 // nice to only flood as far as the unsafe.Pointer -> uintptr 570 // conversion, but it's hard to know which argument of an Add 571 // or Sub to follow. 572 var flooded bitvec.BitVec 573 var flood func(b *ssa.Block, vi int) 574 flood = func(b *ssa.Block, vi int) { 575 if flooded.N == 0 { 576 flooded = bitvec.New(int32(lv.f.NumBlocks())) 577 } 578 if flooded.Get(int32(b.ID)) { 579 return 580 } 581 for i := vi - 1; i >= 0; i-- { 582 v := b.Values[i] 583 if v.Op.IsCall() { 584 // Uintptrs must not contain live 585 // pointers across calls, so stop 586 // flooding. 587 return 588 } 589 lv.unsafePoints.Set(int32(v.ID)) 590 } 591 if vi == len(b.Values) { 592 // We marked all values in this block, so no 593 // need to flood this block again. 594 flooded.Set(int32(b.ID)) 595 } 596 for _, pred := range b.Preds { 597 flood(pred.Block(), len(pred.Block().Values)) 598 } 599 } 600 for _, b := range lv.f.Blocks { 601 for i, v := range b.Values { 602 if !(v.Op == ssa.OpConvert && v.Type.IsPtrShaped()) { 603 continue 604 } 605 // Flood the unsafe-ness of this backwards 606 // until we hit a call. 607 flood(b, i+1) 608 } 609 } 610 } 611 612 // Returns true for instructions that must have a stack map. 613 // 614 // This does not necessarily mean the instruction is a safe-point. In 615 // particular, call Values can have a stack map in case the callee 616 // grows the stack, but not themselves be a safe-point. 617 func (lv *liveness) hasStackMap(v *ssa.Value) bool { 618 if !v.Op.IsCall() { 619 return false 620 } 621 // typedmemclr and typedmemmove are write barriers and 622 // deeply non-preemptible. They are unsafe points and 623 // hence should not have liveness maps. 624 if sym, ok := v.Aux.(*ssa.AuxCall); ok && (sym.Fn == ir.Syms.Typedmemclr || sym.Fn == ir.Syms.Typedmemmove) { 625 return false 626 } 627 return true 628 } 629 630 // Initializes the sets for solving the live variables. Visits all the 631 // instructions in each basic block to summarizes the information at each basic 632 // block 633 func (lv *liveness) prologue() { 634 lv.initcache() 635 636 for _, b := range lv.f.Blocks { 637 be := lv.blockEffects(b) 638 639 // Walk the block instructions backward and update the block 640 // effects with the each prog effects. 641 for j := len(b.Values) - 1; j >= 0; j-- { 642 pos, e := lv.valueEffects(b.Values[j]) 643 if e&varkill != 0 { 644 be.varkill.Set(pos) 645 be.uevar.Unset(pos) 646 } 647 if e&uevar != 0 { 648 be.uevar.Set(pos) 649 } 650 } 651 } 652 } 653 654 // Solve the liveness dataflow equations. 655 func (lv *liveness) solve() { 656 // These temporary bitvectors exist to avoid successive allocations and 657 // frees within the loop. 658 nvars := int32(len(lv.vars)) 659 newlivein := bitvec.New(nvars) 660 newliveout := bitvec.New(nvars) 661 662 // Walk blocks in postorder ordering. This improves convergence. 663 po := lv.f.Postorder() 664 665 // Iterate through the blocks in reverse round-robin fashion. A work 666 // queue might be slightly faster. As is, the number of iterations is 667 // so low that it hardly seems to be worth the complexity. 668 669 for change := true; change; { 670 change = false 671 for _, b := range po { 672 be := lv.blockEffects(b) 673 674 newliveout.Clear() 675 switch b.Kind { 676 case ssa.BlockRet: 677 for _, pos := range lv.cache.retuevar { 678 newliveout.Set(pos) 679 } 680 case ssa.BlockRetJmp: 681 for _, pos := range lv.cache.tailuevar { 682 newliveout.Set(pos) 683 } 684 case ssa.BlockExit: 685 // panic exit - nothing to do 686 default: 687 // A variable is live on output from this block 688 // if it is live on input to some successor. 689 // 690 // out[b] = \bigcup_{s \in succ[b]} in[s] 691 newliveout.Copy(lv.blockEffects(b.Succs[0].Block()).livein) 692 for _, succ := range b.Succs[1:] { 693 newliveout.Or(newliveout, lv.blockEffects(succ.Block()).livein) 694 } 695 } 696 697 if !be.liveout.Eq(newliveout) { 698 change = true 699 be.liveout.Copy(newliveout) 700 } 701 702 // A variable is live on input to this block 703 // if it is used by this block, or live on output from this block and 704 // not set by the code in this block. 705 // 706 // in[b] = uevar[b] \cup (out[b] \setminus varkill[b]) 707 newlivein.AndNot(be.liveout, be.varkill) 708 be.livein.Or(newlivein, be.uevar) 709 } 710 } 711 } 712 713 // Visits all instructions in a basic block and computes a bit vector of live 714 // variables at each safe point locations. 715 func (lv *liveness) epilogue() { 716 nvars := int32(len(lv.vars)) 717 liveout := bitvec.New(nvars) 718 livedefer := bitvec.New(nvars) // always-live variables 719 720 // If there is a defer (that could recover), then all output 721 // parameters are live all the time. In addition, any locals 722 // that are pointers to heap-allocated output parameters are 723 // also always live (post-deferreturn code needs these 724 // pointers to copy values back to the stack). 725 // TODO: if the output parameter is heap-allocated, then we 726 // don't need to keep the stack copy live? 727 if lv.fn.HasDefer() { 728 for i, n := range lv.vars { 729 if n.Class == ir.PPARAMOUT { 730 if n.IsOutputParamHeapAddr() { 731 // Just to be paranoid. Heap addresses are PAUTOs. 732 base.Fatalf("variable %v both output param and heap output param", n) 733 } 734 if n.Heapaddr != nil { 735 // If this variable moved to the heap, then 736 // its stack copy is not live. 737 continue 738 } 739 // Note: zeroing is handled by zeroResults in walk.go. 740 livedefer.Set(int32(i)) 741 } 742 if n.IsOutputParamHeapAddr() { 743 // This variable will be overwritten early in the function 744 // prologue (from the result of a mallocgc) but we need to 745 // zero it in case that malloc causes a stack scan. 746 n.SetNeedzero(true) 747 livedefer.Set(int32(i)) 748 } 749 if n.OpenDeferSlot() { 750 // Open-coded defer args slots must be live 751 // everywhere in a function, since a panic can 752 // occur (almost) anywhere. Because it is live 753 // everywhere, it must be zeroed on entry. 754 livedefer.Set(int32(i)) 755 // It was already marked as Needzero when created. 756 if !n.Needzero() { 757 base.Fatalf("all pointer-containing defer arg slots should have Needzero set") 758 } 759 } 760 } 761 } 762 763 // We must analyze the entry block first. The runtime assumes 764 // the function entry map is index 0. Conveniently, layout 765 // already ensured that the entry block is first. 766 if lv.f.Entry != lv.f.Blocks[0] { 767 lv.f.Fatalf("entry block must be first") 768 } 769 770 { 771 // Reserve an entry for function entry. 772 live := bitvec.New(nvars) 773 lv.livevars = append(lv.livevars, live) 774 } 775 776 for _, b := range lv.f.Blocks { 777 be := lv.blockEffects(b) 778 779 // Walk forward through the basic block instructions and 780 // allocate liveness maps for those instructions that need them. 781 for _, v := range b.Values { 782 if !lv.hasStackMap(v) { 783 continue 784 } 785 786 live := bitvec.New(nvars) 787 lv.livevars = append(lv.livevars, live) 788 } 789 790 // walk backward, construct maps at each safe point 791 index := int32(len(lv.livevars) - 1) 792 793 liveout.Copy(be.liveout) 794 for i := len(b.Values) - 1; i >= 0; i-- { 795 v := b.Values[i] 796 797 if lv.hasStackMap(v) { 798 // Found an interesting instruction, record the 799 // corresponding liveness information. 800 801 live := &lv.livevars[index] 802 live.Or(*live, liveout) 803 live.Or(*live, livedefer) // only for non-entry safe points 804 index-- 805 } 806 807 // Update liveness information. 808 pos, e := lv.valueEffects(v) 809 if e&varkill != 0 { 810 liveout.Unset(pos) 811 } 812 if e&uevar != 0 { 813 liveout.Set(pos) 814 } 815 } 816 817 if b == lv.f.Entry { 818 if index != 0 { 819 base.Fatalf("bad index for entry point: %v", index) 820 } 821 822 // Check to make sure only input variables are live. 823 for i, n := range lv.vars { 824 if !liveout.Get(int32(i)) { 825 continue 826 } 827 if n.Class == ir.PPARAM { 828 continue // ok 829 } 830 base.FatalfAt(n.Pos(), "bad live variable at entry of %v: %L", lv.fn.Nname, n) 831 } 832 833 // Record live variables. 834 live := &lv.livevars[index] 835 live.Or(*live, liveout) 836 } 837 838 if lv.doClobber { 839 lv.clobber(b) 840 } 841 842 // The liveness maps for this block are now complete. Compact them. 843 lv.compact(b) 844 } 845 846 // If we have an open-coded deferreturn call, make a liveness map for it. 847 if lv.fn.OpenCodedDeferDisallowed() { 848 lv.livenessMap.DeferReturn = objw.LivenessDontCare 849 } else { 850 idx, _ := lv.stackMapSet.add(livedefer) 851 lv.livenessMap.DeferReturn = objw.LivenessIndex{ 852 StackMapIndex: idx, 853 IsUnsafePoint: false, 854 } 855 } 856 857 // Done compacting. Throw out the stack map set. 858 lv.stackMaps = lv.stackMapSet.extractUnique() 859 lv.stackMapSet = bvecSet{} 860 861 // Useful sanity check: on entry to the function, 862 // the only things that can possibly be live are the 863 // input parameters. 864 for j, n := range lv.vars { 865 if n.Class != ir.PPARAM && lv.stackMaps[0].Get(int32(j)) { 866 lv.f.Fatalf("%v %L recorded as live on entry", lv.fn.Nname, n) 867 } 868 } 869 } 870 871 // Compact coalesces identical bitmaps from lv.livevars into the sets 872 // lv.stackMapSet. 873 // 874 // Compact clears lv.livevars. 875 // 876 // There are actually two lists of bitmaps, one list for the local variables and one 877 // list for the function arguments. Both lists are indexed by the same PCDATA 878 // index, so the corresponding pairs must be considered together when 879 // merging duplicates. The argument bitmaps change much less often during 880 // function execution than the local variable bitmaps, so it is possible that 881 // we could introduce a separate PCDATA index for arguments vs locals and 882 // then compact the set of argument bitmaps separately from the set of 883 // local variable bitmaps. As of 2014-04-02, doing this to the godoc binary 884 // is actually a net loss: we save about 50k of argument bitmaps but the new 885 // PCDATA tables cost about 100k. So for now we keep using a single index for 886 // both bitmap lists. 887 func (lv *liveness) compact(b *ssa.Block) { 888 pos := 0 889 if b == lv.f.Entry { 890 // Handle entry stack map. 891 lv.stackMapSet.add(lv.livevars[0]) 892 pos++ 893 } 894 for _, v := range b.Values { 895 hasStackMap := lv.hasStackMap(v) 896 isUnsafePoint := lv.allUnsafe || v.Op != ssa.OpClobber && lv.unsafePoints.Get(int32(v.ID)) 897 idx := objw.LivenessIndex{StackMapIndex: objw.StackMapDontCare, IsUnsafePoint: isUnsafePoint} 898 if hasStackMap { 899 idx.StackMapIndex, _ = lv.stackMapSet.add(lv.livevars[pos]) 900 pos++ 901 } 902 if hasStackMap || isUnsafePoint { 903 lv.livenessMap.set(v, idx) 904 } 905 } 906 907 // Reset livevars. 908 lv.livevars = lv.livevars[:0] 909 } 910 911 func (lv *liveness) enableClobber() { 912 // The clobberdead experiment inserts code to clobber pointer slots in all 913 // the dead variables (locals and args) at every synchronous safepoint. 914 if !base.Flag.ClobberDead { 915 return 916 } 917 if lv.fn.Pragma&ir.CgoUnsafeArgs != 0 { 918 // C or assembly code uses the exact frame layout. Don't clobber. 919 return 920 } 921 if len(lv.vars) > 10000 || len(lv.f.Blocks) > 10000 { 922 // Be careful to avoid doing too much work. 923 // Bail if >10000 variables or >10000 blocks. 924 // Otherwise, giant functions make this experiment generate too much code. 925 return 926 } 927 if lv.f.Name == "forkAndExecInChild" { 928 // forkAndExecInChild calls vfork on some platforms. 929 // The code we add here clobbers parts of the stack in the child. 930 // When the parent resumes, it is using the same stack frame. But the 931 // child has clobbered stack variables that the parent needs. Boom! 932 // In particular, the sys argument gets clobbered. 933 return 934 } 935 if lv.f.Name == "wbBufFlush" || 936 ((lv.f.Name == "callReflect" || lv.f.Name == "callMethod") && lv.fn.ABIWrapper()) { 937 // runtime.wbBufFlush must not modify its arguments. See the comments 938 // in runtime/mwbbuf.go:wbBufFlush. 939 // 940 // reflect.callReflect and reflect.callMethod are called from special 941 // functions makeFuncStub and methodValueCall. The runtime expects 942 // that it can find the first argument (ctxt) at 0(SP) in makeFuncStub 943 // and methodValueCall's frame (see runtime/traceback.go:getArgInfo). 944 // Normally callReflect and callMethod already do not modify the 945 // argument, and keep it alive. But the compiler-generated ABI wrappers 946 // don't do that. Special case the wrappers to not clobber its arguments. 947 lv.noClobberArgs = true 948 } 949 if h := os.Getenv("GOCLOBBERDEADHASH"); h != "" { 950 // Clobber only functions where the hash of the function name matches a pattern. 951 // Useful for binary searching for a miscompiled function. 952 hstr := "" 953 for _, b := range notsha256.Sum256([]byte(lv.f.Name)) { 954 hstr += fmt.Sprintf("%08b", b) 955 } 956 if !strings.HasSuffix(hstr, h) { 957 return 958 } 959 fmt.Printf("\t\t\tCLOBBERDEAD %s\n", lv.f.Name) 960 } 961 lv.doClobber = true 962 } 963 964 // Inserts code to clobber pointer slots in all the dead variables (locals and args) 965 // at every synchronous safepoint in b. 966 func (lv *liveness) clobber(b *ssa.Block) { 967 // Copy block's values to a temporary. 968 oldSched := append([]*ssa.Value{}, b.Values...) 969 b.Values = b.Values[:0] 970 idx := 0 971 972 // Clobber pointer slots in all dead variables at entry. 973 if b == lv.f.Entry { 974 for len(oldSched) > 0 && len(oldSched[0].Args) == 0 { 975 // Skip argless ops. We need to skip at least 976 // the lowered ClosurePtr op, because it 977 // really wants to be first. This will also 978 // skip ops like InitMem and SP, which are ok. 979 b.Values = append(b.Values, oldSched[0]) 980 oldSched = oldSched[1:] 981 } 982 clobber(lv, b, lv.livevars[0]) 983 idx++ 984 } 985 986 // Copy values into schedule, adding clobbering around safepoints. 987 for _, v := range oldSched { 988 if !lv.hasStackMap(v) { 989 b.Values = append(b.Values, v) 990 continue 991 } 992 clobber(lv, b, lv.livevars[idx]) 993 b.Values = append(b.Values, v) 994 idx++ 995 } 996 } 997 998 // clobber generates code to clobber pointer slots in all dead variables 999 // (those not marked in live). Clobbering instructions are added to the end 1000 // of b.Values. 1001 func clobber(lv *liveness, b *ssa.Block, live bitvec.BitVec) { 1002 for i, n := range lv.vars { 1003 if !live.Get(int32(i)) && !n.Addrtaken() && !n.OpenDeferSlot() && !n.IsOutputParamHeapAddr() { 1004 // Don't clobber stack objects (address-taken). They are 1005 // tracked dynamically. 1006 // Also don't clobber slots that are live for defers (see 1007 // the code setting livedefer in epilogue). 1008 if lv.noClobberArgs && n.Class == ir.PPARAM { 1009 continue 1010 } 1011 clobberVar(b, n) 1012 } 1013 } 1014 } 1015 1016 // clobberVar generates code to trash the pointers in v. 1017 // Clobbering instructions are added to the end of b.Values. 1018 func clobberVar(b *ssa.Block, v *ir.Name) { 1019 clobberWalk(b, v, 0, v.Type()) 1020 } 1021 1022 // b = block to which we append instructions 1023 // v = variable 1024 // offset = offset of (sub-portion of) variable to clobber (in bytes) 1025 // t = type of sub-portion of v. 1026 func clobberWalk(b *ssa.Block, v *ir.Name, offset int64, t *types.Type) { 1027 if !t.HasPointers() { 1028 return 1029 } 1030 switch t.Kind() { 1031 case types.TPTR, 1032 types.TUNSAFEPTR, 1033 types.TFUNC, 1034 types.TCHAN, 1035 types.TMAP: 1036 clobberPtr(b, v, offset) 1037 1038 case types.TSTRING: 1039 // struct { byte *str; int len; } 1040 clobberPtr(b, v, offset) 1041 1042 case types.TINTER: 1043 // struct { Itab *tab; void *data; } 1044 // or, when isnilinter(t)==true: 1045 // struct { Type *type; void *data; } 1046 clobberPtr(b, v, offset) 1047 clobberPtr(b, v, offset+int64(types.PtrSize)) 1048 1049 case types.TSLICE: 1050 // struct { byte *array; int len; int cap; } 1051 clobberPtr(b, v, offset) 1052 1053 case types.TARRAY: 1054 for i := int64(0); i < t.NumElem(); i++ { 1055 clobberWalk(b, v, offset+i*t.Elem().Size(), t.Elem()) 1056 } 1057 1058 case types.TSTRUCT: 1059 for _, t1 := range t.Fields().Slice() { 1060 clobberWalk(b, v, offset+t1.Offset, t1.Type) 1061 } 1062 1063 default: 1064 base.Fatalf("clobberWalk: unexpected type, %v", t) 1065 } 1066 } 1067 1068 // clobberPtr generates a clobber of the pointer at offset offset in v. 1069 // The clobber instruction is added at the end of b. 1070 func clobberPtr(b *ssa.Block, v *ir.Name, offset int64) { 1071 b.NewValue0IA(src.NoXPos, ssa.OpClobber, types.TypeVoid, offset, v) 1072 } 1073 1074 func (lv *liveness) showlive(v *ssa.Value, live bitvec.BitVec) { 1075 if base.Flag.Live == 0 || ir.FuncName(lv.fn) == "init" || strings.HasPrefix(ir.FuncName(lv.fn), ".") { 1076 return 1077 } 1078 if lv.fn.Wrapper() || lv.fn.Dupok() { 1079 // Skip reporting liveness information for compiler-generated wrappers. 1080 return 1081 } 1082 if !(v == nil || v.Op.IsCall()) { 1083 // Historically we only printed this information at 1084 // calls. Keep doing so. 1085 return 1086 } 1087 if live.IsEmpty() { 1088 return 1089 } 1090 1091 pos := lv.fn.Nname.Pos() 1092 if v != nil { 1093 pos = v.Pos 1094 } 1095 1096 s := "live at " 1097 if v == nil { 1098 s += fmt.Sprintf("entry to %s:", ir.FuncName(lv.fn)) 1099 } else if sym, ok := v.Aux.(*ssa.AuxCall); ok && sym.Fn != nil { 1100 fn := sym.Fn.Name 1101 if pos := strings.Index(fn, "."); pos >= 0 { 1102 fn = fn[pos+1:] 1103 } 1104 s += fmt.Sprintf("call to %s:", fn) 1105 } else { 1106 s += "indirect call:" 1107 } 1108 1109 for j, n := range lv.vars { 1110 if live.Get(int32(j)) { 1111 s += fmt.Sprintf(" %v", n) 1112 } 1113 } 1114 1115 base.WarnfAt(pos, s) 1116 } 1117 1118 func (lv *liveness) printbvec(printed bool, name string, live bitvec.BitVec) bool { 1119 if live.IsEmpty() { 1120 return printed 1121 } 1122 1123 if !printed { 1124 fmt.Printf("\t") 1125 } else { 1126 fmt.Printf(" ") 1127 } 1128 fmt.Printf("%s=", name) 1129 1130 comma := "" 1131 for i, n := range lv.vars { 1132 if !live.Get(int32(i)) { 1133 continue 1134 } 1135 fmt.Printf("%s%s", comma, n.Sym().Name) 1136 comma = "," 1137 } 1138 return true 1139 } 1140 1141 // printeffect is like printbvec, but for valueEffects. 1142 func (lv *liveness) printeffect(printed bool, name string, pos int32, x bool) bool { 1143 if !x { 1144 return printed 1145 } 1146 if !printed { 1147 fmt.Printf("\t") 1148 } else { 1149 fmt.Printf(" ") 1150 } 1151 fmt.Printf("%s=", name) 1152 if x { 1153 fmt.Printf("%s", lv.vars[pos].Sym().Name) 1154 } 1155 1156 return true 1157 } 1158 1159 // Prints the computed liveness information and inputs, for debugging. 1160 // This format synthesizes the information used during the multiple passes 1161 // into a single presentation. 1162 func (lv *liveness) printDebug() { 1163 fmt.Printf("liveness: %s\n", ir.FuncName(lv.fn)) 1164 1165 for i, b := range lv.f.Blocks { 1166 if i > 0 { 1167 fmt.Printf("\n") 1168 } 1169 1170 // bb#0 pred=1,2 succ=3,4 1171 fmt.Printf("bb#%d pred=", b.ID) 1172 for j, pred := range b.Preds { 1173 if j > 0 { 1174 fmt.Printf(",") 1175 } 1176 fmt.Printf("%d", pred.Block().ID) 1177 } 1178 fmt.Printf(" succ=") 1179 for j, succ := range b.Succs { 1180 if j > 0 { 1181 fmt.Printf(",") 1182 } 1183 fmt.Printf("%d", succ.Block().ID) 1184 } 1185 fmt.Printf("\n") 1186 1187 be := lv.blockEffects(b) 1188 1189 // initial settings 1190 printed := false 1191 printed = lv.printbvec(printed, "uevar", be.uevar) 1192 printed = lv.printbvec(printed, "livein", be.livein) 1193 if printed { 1194 fmt.Printf("\n") 1195 } 1196 1197 // program listing, with individual effects listed 1198 1199 if b == lv.f.Entry { 1200 live := lv.stackMaps[0] 1201 fmt.Printf("(%s) function entry\n", base.FmtPos(lv.fn.Nname.Pos())) 1202 fmt.Printf("\tlive=") 1203 printed = false 1204 for j, n := range lv.vars { 1205 if !live.Get(int32(j)) { 1206 continue 1207 } 1208 if printed { 1209 fmt.Printf(",") 1210 } 1211 fmt.Printf("%v", n) 1212 printed = true 1213 } 1214 fmt.Printf("\n") 1215 } 1216 1217 for _, v := range b.Values { 1218 fmt.Printf("(%s) %v\n", base.FmtPos(v.Pos), v.LongString()) 1219 1220 pcdata := lv.livenessMap.Get(v) 1221 1222 pos, effect := lv.valueEffects(v) 1223 printed = false 1224 printed = lv.printeffect(printed, "uevar", pos, effect&uevar != 0) 1225 printed = lv.printeffect(printed, "varkill", pos, effect&varkill != 0) 1226 if printed { 1227 fmt.Printf("\n") 1228 } 1229 1230 if pcdata.StackMapValid() { 1231 fmt.Printf("\tlive=") 1232 printed = false 1233 if pcdata.StackMapValid() { 1234 live := lv.stackMaps[pcdata.StackMapIndex] 1235 for j, n := range lv.vars { 1236 if !live.Get(int32(j)) { 1237 continue 1238 } 1239 if printed { 1240 fmt.Printf(",") 1241 } 1242 fmt.Printf("%v", n) 1243 printed = true 1244 } 1245 } 1246 fmt.Printf("\n") 1247 } 1248 1249 if pcdata.IsUnsafePoint { 1250 fmt.Printf("\tunsafe-point\n") 1251 } 1252 } 1253 1254 // bb bitsets 1255 fmt.Printf("end\n") 1256 printed = false 1257 printed = lv.printbvec(printed, "varkill", be.varkill) 1258 printed = lv.printbvec(printed, "liveout", be.liveout) 1259 if printed { 1260 fmt.Printf("\n") 1261 } 1262 } 1263 1264 fmt.Printf("\n") 1265 } 1266 1267 // Dumps a slice of bitmaps to a symbol as a sequence of uint32 values. The 1268 // first word dumped is the total number of bitmaps. The second word is the 1269 // length of the bitmaps. All bitmaps are assumed to be of equal length. The 1270 // remaining bytes are the raw bitmaps. 1271 func (lv *liveness) emit() (argsSym, liveSym *obj.LSym) { 1272 // Size args bitmaps to be just large enough to hold the largest pointer. 1273 // First, find the largest Xoffset node we care about. 1274 // (Nodes without pointers aren't in lv.vars; see ShouldTrack.) 1275 var maxArgNode *ir.Name 1276 for _, n := range lv.vars { 1277 switch n.Class { 1278 case ir.PPARAM, ir.PPARAMOUT: 1279 if !n.IsOutputParamInRegisters() { 1280 if maxArgNode == nil || n.FrameOffset() > maxArgNode.FrameOffset() { 1281 maxArgNode = n 1282 } 1283 } 1284 } 1285 } 1286 // Next, find the offset of the largest pointer in the largest node. 1287 var maxArgs int64 1288 if maxArgNode != nil { 1289 maxArgs = maxArgNode.FrameOffset() + types.PtrDataSize(maxArgNode.Type()) 1290 } 1291 1292 // Size locals bitmaps to be stkptrsize sized. 1293 // We cannot shrink them to only hold the largest pointer, 1294 // because their size is used to calculate the beginning 1295 // of the local variables frame. 1296 // Further discussion in https://golang.org/cl/104175. 1297 // TODO: consider trimming leading zeros. 1298 // This would require shifting all bitmaps. 1299 maxLocals := lv.stkptrsize 1300 1301 // Temporary symbols for encoding bitmaps. 1302 var argsSymTmp, liveSymTmp obj.LSym 1303 1304 args := bitvec.New(int32(maxArgs / int64(types.PtrSize))) 1305 aoff := objw.Uint32(&argsSymTmp, 0, uint32(len(lv.stackMaps))) // number of bitmaps 1306 aoff = objw.Uint32(&argsSymTmp, aoff, uint32(args.N)) // number of bits in each bitmap 1307 1308 locals := bitvec.New(int32(maxLocals / int64(types.PtrSize))) 1309 loff := objw.Uint32(&liveSymTmp, 0, uint32(len(lv.stackMaps))) // number of bitmaps 1310 loff = objw.Uint32(&liveSymTmp, loff, uint32(locals.N)) // number of bits in each bitmap 1311 1312 for _, live := range lv.stackMaps { 1313 args.Clear() 1314 locals.Clear() 1315 1316 lv.pointerMap(live, lv.vars, args, locals) 1317 1318 aoff = objw.BitVec(&argsSymTmp, aoff, args) 1319 loff = objw.BitVec(&liveSymTmp, loff, locals) 1320 } 1321 1322 // These symbols will be added to Ctxt.Data by addGCLocals 1323 // after parallel compilation is done. 1324 return base.Ctxt.GCLocalsSym(argsSymTmp.P), base.Ctxt.GCLocalsSym(liveSymTmp.P) 1325 } 1326 1327 // Entry pointer for Compute analysis. Solves for the Compute of 1328 // pointer variables in the function and emits a runtime data 1329 // structure read by the garbage collector. 1330 // Returns a map from GC safe points to their corresponding stack map index, 1331 // and a map that contains all input parameters that may be partially live. 1332 func Compute(curfn *ir.Func, f *ssa.Func, stkptrsize int64, pp *objw.Progs) (Map, map[*ir.Name]bool) { 1333 // Construct the global liveness state. 1334 vars, idx := getvariables(curfn) 1335 lv := newliveness(curfn, f, vars, idx, stkptrsize) 1336 1337 // Run the dataflow framework. 1338 lv.prologue() 1339 lv.solve() 1340 lv.epilogue() 1341 if base.Flag.Live > 0 { 1342 lv.showlive(nil, lv.stackMaps[0]) 1343 for _, b := range f.Blocks { 1344 for _, val := range b.Values { 1345 if idx := lv.livenessMap.Get(val); idx.StackMapValid() { 1346 lv.showlive(val, lv.stackMaps[idx.StackMapIndex]) 1347 } 1348 } 1349 } 1350 } 1351 if base.Flag.Live >= 2 { 1352 lv.printDebug() 1353 } 1354 1355 // Update the function cache. 1356 { 1357 cache := f.Cache.Liveness.(*livenessFuncCache) 1358 if cap(lv.be) < 2000 { // Threshold from ssa.Cache slices. 1359 for i := range lv.be { 1360 lv.be[i] = blockEffects{} 1361 } 1362 cache.be = lv.be 1363 } 1364 if len(lv.livenessMap.Vals) < 2000 { 1365 cache.livenessMap = lv.livenessMap 1366 } 1367 } 1368 1369 // Emit the live pointer map data structures 1370 ls := curfn.LSym 1371 fninfo := ls.Func() 1372 fninfo.GCArgs, fninfo.GCLocals = lv.emit() 1373 1374 p := pp.Prog(obj.AFUNCDATA) 1375 p.From.SetConst(objabi.FUNCDATA_ArgsPointerMaps) 1376 p.To.Type = obj.TYPE_MEM 1377 p.To.Name = obj.NAME_EXTERN 1378 p.To.Sym = fninfo.GCArgs 1379 1380 p = pp.Prog(obj.AFUNCDATA) 1381 p.From.SetConst(objabi.FUNCDATA_LocalsPointerMaps) 1382 p.To.Type = obj.TYPE_MEM 1383 p.To.Name = obj.NAME_EXTERN 1384 p.To.Sym = fninfo.GCLocals 1385 1386 if x := lv.emitStackObjects(); x != nil { 1387 p := pp.Prog(obj.AFUNCDATA) 1388 p.From.SetConst(objabi.FUNCDATA_StackObjects) 1389 p.To.Type = obj.TYPE_MEM 1390 p.To.Name = obj.NAME_EXTERN 1391 p.To.Sym = x 1392 } 1393 1394 return lv.livenessMap, lv.partLiveArgs 1395 } 1396 1397 func (lv *liveness) emitStackObjects() *obj.LSym { 1398 var vars []*ir.Name 1399 for _, n := range lv.fn.Dcl { 1400 if shouldTrack(n) && n.Addrtaken() && n.Esc() != ir.EscHeap { 1401 vars = append(vars, n) 1402 } 1403 } 1404 if len(vars) == 0 { 1405 return nil 1406 } 1407 1408 // Sort variables from lowest to highest address. 1409 sort.Slice(vars, func(i, j int) bool { return vars[i].FrameOffset() < vars[j].FrameOffset() }) 1410 1411 // Populate the stack object data. 1412 // Format must match runtime/stack.go:stackObjectRecord. 1413 x := base.Ctxt.Lookup(lv.fn.LSym.Name + ".stkobj") 1414 x.Set(obj.AttrContentAddressable, true) 1415 lv.fn.LSym.Func().StackObjects = x 1416 off := 0 1417 off = objw.Uintptr(x, off, uint64(len(vars))) 1418 for _, v := range vars { 1419 // Note: arguments and return values have non-negative Xoffset, 1420 // in which case the offset is relative to argp. 1421 // Locals have a negative Xoffset, in which case the offset is relative to varp. 1422 // We already limit the frame size, so the offset and the object size 1423 // should not be too big. 1424 frameOffset := v.FrameOffset() 1425 if frameOffset != int64(int32(frameOffset)) { 1426 base.Fatalf("frame offset too big: %v %d", v, frameOffset) 1427 } 1428 off = objw.Uint32(x, off, uint32(frameOffset)) 1429 1430 t := v.Type() 1431 sz := t.Size() 1432 if sz != int64(int32(sz)) { 1433 base.Fatalf("stack object too big: %v of type %v, size %d", v, t, sz) 1434 } 1435 lsym, useGCProg, ptrdata := reflectdata.GCSym(t) 1436 if useGCProg { 1437 ptrdata = -ptrdata 1438 } 1439 off = objw.Uint32(x, off, uint32(sz)) 1440 off = objw.Uint32(x, off, uint32(ptrdata)) 1441 off = objw.SymPtrOff(x, off, lsym) 1442 } 1443 1444 if base.Flag.Live != 0 { 1445 for _, v := range vars { 1446 base.WarnfAt(v.Pos(), "stack object %v %v", v, v.Type()) 1447 } 1448 } 1449 1450 return x 1451 } 1452 1453 // isfat reports whether a variable of type t needs multiple assignments to initialize. 1454 // For example: 1455 // 1456 // type T struct { x, y int } 1457 // x := T{x: 0, y: 1} 1458 // 1459 // Then we need: 1460 // 1461 // var t T 1462 // t.x = 0 1463 // t.y = 1 1464 // 1465 // to fully initialize t. 1466 func isfat(t *types.Type) bool { 1467 if t != nil { 1468 switch t.Kind() { 1469 case types.TSLICE, types.TSTRING, 1470 types.TINTER: // maybe remove later 1471 return true 1472 case types.TARRAY: 1473 // Array of 1 element, check if element is fat 1474 if t.NumElem() == 1 { 1475 return isfat(t.Elem()) 1476 } 1477 return true 1478 case types.TSTRUCT: 1479 // Struct with 1 field, check if field is fat 1480 if t.NumFields() == 1 { 1481 return isfat(t.Field(0).Type) 1482 } 1483 return true 1484 } 1485 } 1486 1487 return false 1488 } 1489 1490 // WriteFuncMap writes the pointer bitmaps for bodyless function fn's 1491 // inputs and outputs as the value of symbol <fn>.args_stackmap. 1492 // If fn has outputs, two bitmaps are written, otherwise just one. 1493 func WriteFuncMap(fn *ir.Func, abiInfo *abi.ABIParamResultInfo) { 1494 if ir.FuncName(fn) == "_" || fn.Sym().Linkname != "" { 1495 return 1496 } 1497 nptr := int(abiInfo.ArgWidth() / int64(types.PtrSize)) 1498 bv := bitvec.New(int32(nptr) * 2) 1499 1500 for _, p := range abiInfo.InParams() { 1501 typebits.SetNoCheck(p.Type, p.FrameOffset(abiInfo), bv) 1502 } 1503 1504 nbitmap := 1 1505 if fn.Type().NumResults() > 0 { 1506 nbitmap = 2 1507 } 1508 lsym := base.Ctxt.Lookup(fn.LSym.Name + ".args_stackmap") 1509 off := objw.Uint32(lsym, 0, uint32(nbitmap)) 1510 off = objw.Uint32(lsym, off, uint32(bv.N)) 1511 off = objw.BitVec(lsym, off, bv) 1512 1513 if fn.Type().NumResults() > 0 { 1514 for _, p := range abiInfo.OutParams() { 1515 if len(p.Registers) == 0 { 1516 typebits.SetNoCheck(p.Type, p.FrameOffset(abiInfo), bv) 1517 } 1518 } 1519 off = objw.BitVec(lsym, off, bv) 1520 } 1521 1522 objw.Global(lsym, int32(off), obj.RODATA|obj.LOCAL) 1523 }