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