github.com/rsc/tmp@v0.0.0-20240517235954-6deaab19748b/bootstrap/internal/gc/plive.go (about) 1 // Do not edit. Bootstrap copy of /Users/rsc/g/go/src/cmd/internal/gc/plive.go 2 3 // Copyright 2013 The Go Authors. All rights reserved. 4 // Use of this source code is governed by a BSD-style 5 // license that can be found in the LICENSE file. 6 7 // Garbage collector liveness bitmap generation. 8 9 // The command line flag -live causes this code to print debug information. 10 // The levels are: 11 // 12 // -live (aka -live=1): print liveness lists as code warnings at safe points 13 // -live=2: print an assembly listing with liveness annotations 14 // -live=3: print information during each computation phase (much chattier) 15 // 16 // Each level includes the earlier output as well. 17 18 package gc 19 20 import ( 21 "rsc.io/tmp/bootstrap/internal/obj" 22 "fmt" 23 "sort" 24 ) 25 26 const ( 27 UNVISITED = 0 28 VISITED = 1 29 ) 30 31 // An ordinary basic block. 32 // 33 // Instructions are threaded together in a doubly-linked list. To iterate in 34 // program order follow the link pointer from the first node and stop after the 35 // last node has been visited 36 // 37 // for(p = bb->first;; p = p->link) { 38 // ... 39 // if(p == bb->last) 40 // break; 41 // } 42 // 43 // To iterate in reverse program order by following the opt pointer from the 44 // last node 45 // 46 // for(p = bb->last; p != nil; p = p->opt) { 47 // ... 48 // } 49 type BasicBlock struct { 50 pred []*BasicBlock // predecessors; if none, probably start of CFG 51 succ []*BasicBlock // successors; if none, probably ends in return statement 52 first *obj.Prog // first instruction in block 53 last *obj.Prog // last instruction in block 54 rpo int // reverse post-order number (also index in cfg) 55 mark int // mark bit for traversals 56 lastbitmapindex int // for livenessepilogue 57 58 // Summary sets of block effects. 59 60 // Computed during livenessprologue using only the content of 61 // individual blocks: 62 // 63 // uevar: upward exposed variables (used before set in block) 64 // varkill: killed variables (set in block) 65 // avarinit: addrtaken variables set or used (proof of initialization) 66 uevar Bvec 67 varkill Bvec 68 avarinit Bvec 69 70 // Computed during livenesssolve using control flow information: 71 // 72 // livein: variables live at block entry 73 // liveout: variables live at block exit 74 // avarinitany: addrtaken variables possibly initialized at block exit 75 // (initialized in block or at exit from any predecessor block) 76 // avarinitall: addrtaken variables certainly initialized at block exit 77 // (initialized in block or at exit from all predecessor blocks) 78 livein Bvec 79 liveout Bvec 80 avarinitany Bvec 81 avarinitall Bvec 82 } 83 84 // A collection of global state used by liveness analysis. 85 type Liveness struct { 86 fn *Node 87 ptxt *obj.Prog 88 vars []*Node 89 cfg []*BasicBlock 90 91 // An array with a bit vector for each safe point tracking live pointers 92 // in the arguments and locals area, indexed by bb.rpo. 93 argslivepointers []Bvec 94 livepointers []Bvec 95 } 96 97 func xmalloc(size uint32) interface{} { 98 result := (interface{})(make([]byte, size)) 99 if result == nil { 100 Fatal("malloc failed") 101 } 102 return result 103 } 104 105 // Constructs a new basic block containing a single instruction. 106 func newblock(prog *obj.Prog) *BasicBlock { 107 if prog == nil { 108 Fatal("newblock: prog cannot be nil") 109 } 110 result := new(BasicBlock) 111 result.rpo = -1 112 result.mark = UNVISITED 113 result.first = prog 114 result.last = prog 115 result.pred = make([]*BasicBlock, 0, 2) 116 result.succ = make([]*BasicBlock, 0, 2) 117 return result 118 } 119 120 // Frees a basic block and all of its leaf data structures. 121 func freeblock(bb *BasicBlock) { 122 if bb == nil { 123 Fatal("freeblock: cannot free nil") 124 } 125 } 126 127 // Adds an edge between two basic blocks by making from a predecessor of to and 128 // to a successor of from. 129 func addedge(from *BasicBlock, to *BasicBlock) { 130 if from == nil { 131 Fatal("addedge: from is nil") 132 } 133 if to == nil { 134 Fatal("addedge: to is nil") 135 } 136 from.succ = append(from.succ, to) 137 to.pred = append(to.pred, from) 138 } 139 140 // Inserts prev before curr in the instruction 141 // stream. Any control flow, such as branches or fall throughs, that target the 142 // existing instruction are adjusted to target the new instruction. 143 func splicebefore(lv *Liveness, bb *BasicBlock, prev *obj.Prog, curr *obj.Prog) { 144 // There may be other instructions pointing at curr, 145 // and we want them to now point at prev. Instead of 146 // trying to find all such instructions, swap the contents 147 // so that the problem becomes inserting next after curr. 148 // The "opt" field is the backward link in the linked list. 149 150 // Overwrite curr's data with prev, but keep the list links. 151 tmp := *curr 152 153 *curr = *prev 154 curr.Opt = tmp.Opt 155 curr.Link = tmp.Link 156 157 // Overwrite prev (now next) with curr's old data. 158 next := prev 159 160 *next = tmp 161 next.Opt = nil 162 next.Link = nil 163 164 // Now insert next after curr. 165 next.Link = curr.Link 166 167 next.Opt = curr 168 curr.Link = next 169 if next.Link != nil && next.Link.Opt == curr { 170 next.Link.Opt = next 171 } 172 173 if bb.last == curr { 174 bb.last = next 175 } 176 } 177 178 // A pretty printer for basic blocks. 179 func printblock(bb *BasicBlock) { 180 fmt.Printf("basic block %d\n", bb.rpo) 181 fmt.Printf("\tpred:") 182 for _, pred := range bb.pred { 183 fmt.Printf(" %d", pred.rpo) 184 } 185 fmt.Printf("\n") 186 fmt.Printf("\tsucc:") 187 for _, succ := range bb.succ { 188 fmt.Printf(" %d", succ.rpo) 189 } 190 fmt.Printf("\n") 191 fmt.Printf("\tprog:\n") 192 for prog := bb.first; ; prog = prog.Link { 193 fmt.Printf("\t\t%v\n", prog) 194 if prog == bb.last { 195 break 196 } 197 } 198 } 199 200 // Iterates over a basic block applying a callback to each instruction. There 201 // are two criteria for termination. If the end of basic block is reached a 202 // value of zero is returned. If the callback returns a non-zero value, the 203 // iteration is stopped and the value of the callback is returned. 204 func blockany(bb *BasicBlock, f func(*obj.Prog) bool) bool { 205 for p := bb.last; p != nil; p = p.Opt.(*obj.Prog) { 206 if f(p) { 207 return true 208 } 209 } 210 return false 211 } 212 213 // Collects and returns and array of Node*s for functions arguments and local 214 // variables. 215 func getvariables(fn *Node) []*Node { 216 result := make([]*Node, 0, 0) 217 for ll := fn.Func.Dcl; ll != nil; ll = ll.Next { 218 if ll.N.Op == ONAME { 219 // In order for GODEBUG=gcdead=1 to work, each bitmap needs 220 // to contain information about all variables covered by the bitmap. 221 // For local variables, the bitmap only covers the stkptrsize 222 // bytes in the frame where variables containing pointers live. 223 // For arguments and results, the bitmap covers all variables, 224 // so we must include all the variables, even the ones without 225 // pointers. 226 // 227 // The Node.opt field is available for use by optimization passes. 228 // We use it to hold the index of the node in the variables array, plus 1 229 // (so that 0 means the Node is not in the variables array). 230 // Each pass should clear opt when done, but you never know, 231 // so clear them all ourselves too. 232 // The Node.curfn field is supposed to be set to the current function 233 // already, but for some compiler-introduced names it seems not to be, 234 // so fix that here. 235 // Later, when we want to find the index of a node in the variables list, 236 // we will check that n->curfn == curfn and n->opt > 0. Then n->opt - 1 237 // is the index in the variables list. 238 ll.N.Opt = nil 239 240 // The compiler doesn't emit initializations for zero-width parameters or results. 241 if ll.N.Type.Width == 0 { 242 continue 243 } 244 245 ll.N.Curfn = Curfn 246 switch ll.N.Class { 247 case PAUTO: 248 if haspointers(ll.N.Type) { 249 ll.N.Opt = int32(len(result)) 250 result = append(result, ll.N) 251 } 252 253 case PPARAM, PPARAMOUT: 254 ll.N.Opt = int32(len(result)) 255 result = append(result, ll.N) 256 } 257 } 258 } 259 260 return result 261 } 262 263 // A pretty printer for control flow graphs. Takes an array of BasicBlock*s. 264 func printcfg(cfg []*BasicBlock) { 265 for _, bb := range cfg { 266 printblock(bb) 267 } 268 } 269 270 // Assigns a reverse post order number to each connected basic block using the 271 // standard algorithm. Unconnected blocks will not be affected. 272 func reversepostorder(root *BasicBlock, rpo *int32) { 273 root.mark = VISITED 274 for _, bb := range root.succ { 275 if bb.mark == UNVISITED { 276 reversepostorder(bb, rpo) 277 } 278 } 279 *rpo -= 1 280 root.rpo = int(*rpo) 281 } 282 283 // Comparison predicate used for sorting basic blocks by their rpo in ascending 284 // order. 285 type blockrpocmp []*BasicBlock 286 287 func (x blockrpocmp) Len() int { return len(x) } 288 func (x blockrpocmp) Swap(i, j int) { x[i], x[j] = x[j], x[i] } 289 func (x blockrpocmp) Less(i, j int) bool { return x[i].rpo < x[j].rpo } 290 291 // A pattern matcher for call instructions. Returns true when the instruction 292 // is a call to a specific package qualified function name. 293 func iscall(prog *obj.Prog, name *obj.LSym) bool { 294 if prog == nil { 295 Fatal("iscall: prog is nil") 296 } 297 if name == nil { 298 Fatal("iscall: function name is nil") 299 } 300 if prog.As != obj.ACALL { 301 return false 302 } 303 return name == prog.To.Sym 304 } 305 306 // Returns true for instructions that call a runtime function implementing a 307 // select communication clause. 308 309 var selectNames [4]*obj.LSym 310 311 func isselectcommcasecall(prog *obj.Prog) bool { 312 if selectNames[0] == nil { 313 selectNames[0] = Linksym(Pkglookup("selectsend", Runtimepkg)) 314 selectNames[1] = Linksym(Pkglookup("selectrecv", Runtimepkg)) 315 selectNames[2] = Linksym(Pkglookup("selectrecv2", Runtimepkg)) 316 selectNames[3] = Linksym(Pkglookup("selectdefault", Runtimepkg)) 317 } 318 319 for _, name := range selectNames { 320 if iscall(prog, name) { 321 return true 322 } 323 } 324 return false 325 } 326 327 // Returns true for call instructions that target runtime·newselect. 328 329 var isnewselect_sym *obj.LSym 330 331 func isnewselect(prog *obj.Prog) bool { 332 if isnewselect_sym == nil { 333 isnewselect_sym = Linksym(Pkglookup("newselect", Runtimepkg)) 334 } 335 return iscall(prog, isnewselect_sym) 336 } 337 338 // Returns true for call instructions that target runtime·selectgo. 339 340 var isselectgocall_sym *obj.LSym 341 342 func isselectgocall(prog *obj.Prog) bool { 343 if isselectgocall_sym == nil { 344 isselectgocall_sym = Linksym(Pkglookup("selectgo", Runtimepkg)) 345 } 346 return iscall(prog, isselectgocall_sym) 347 } 348 349 var isdeferreturn_sym *obj.LSym 350 351 func isdeferreturn(prog *obj.Prog) bool { 352 if isdeferreturn_sym == nil { 353 isdeferreturn_sym = Linksym(Pkglookup("deferreturn", Runtimepkg)) 354 } 355 return iscall(prog, isdeferreturn_sym) 356 } 357 358 // Walk backwards from a runtime·selectgo call up to its immediately dominating 359 // runtime·newselect call. Any successor nodes of communication clause nodes 360 // are implicit successors of the runtime·selectgo call node. The goal of this 361 // analysis is to add these missing edges to complete the control flow graph. 362 func addselectgosucc(selectgo *BasicBlock) { 363 var succ *BasicBlock 364 365 pred := selectgo 366 for { 367 if len(pred.pred) == 0 { 368 Fatal("selectgo does not have a newselect") 369 } 370 pred = pred.pred[0] 371 if blockany(pred, isselectcommcasecall) { 372 // A select comm case block should have exactly one 373 // successor. 374 if len(pred.succ) != 1 { 375 Fatal("select comm case has too many successors") 376 } 377 succ = pred.succ[0] 378 379 // Its successor should have exactly two successors. 380 // The drop through should flow to the selectgo block 381 // and the branch should lead to the select case 382 // statements block. 383 if len(succ.succ) != 2 { 384 Fatal("select comm case successor has too many successors") 385 } 386 387 // Add the block as a successor of the selectgo block. 388 addedge(selectgo, succ) 389 } 390 391 if blockany(pred, isnewselect) { 392 // Reached the matching newselect. 393 break 394 } 395 } 396 } 397 398 // The entry point for the missing selectgo control flow algorithm. Takes an 399 // array of BasicBlock*s containing selectgo calls. 400 func fixselectgo(selectgo []*BasicBlock) { 401 for _, bb := range selectgo { 402 addselectgosucc(bb) 403 } 404 } 405 406 // Constructs a control flow graph from a sequence of instructions. This 407 // procedure is complicated by various sources of implicit control flow that are 408 // not accounted for using the standard cfg construction algorithm. Returns an 409 // array of BasicBlock*s in control flow graph form (basic blocks ordered by 410 // their RPO number). 411 func newcfg(firstp *obj.Prog) []*BasicBlock { 412 // Reset the opt field of each prog to nil. In the first and second 413 // passes, instructions that are labels temporarily use the opt field to 414 // point to their basic block. In the third pass, the opt field reset 415 // to point to the predecessor of an instruction in its basic block. 416 for p := firstp; p != nil; p = p.Link { 417 p.Opt = nil 418 } 419 420 // Allocate an array to remember where we have seen selectgo calls. 421 // These blocks will be revisited to add successor control flow edges. 422 selectgo := make([]*BasicBlock, 0, 0) 423 424 // Loop through all instructions identifying branch targets 425 // and fall-throughs and allocate basic blocks. 426 cfg := make([]*BasicBlock, 0, 0) 427 428 bb := newblock(firstp) 429 cfg = append(cfg, bb) 430 for p := firstp; p != nil; p = p.Link { 431 Thearch.Proginfo(p) 432 if p.To.Type == obj.TYPE_BRANCH { 433 if p.To.Val == nil { 434 Fatal("prog branch to nil") 435 } 436 if p.To.Val.(*obj.Prog).Opt == nil { 437 p.To.Val.(*obj.Prog).Opt = newblock(p.To.Val.(*obj.Prog)) 438 cfg = append(cfg, p.To.Val.(*obj.Prog).Opt.(*BasicBlock)) 439 } 440 441 if p.As != obj.AJMP && p.Link != nil && p.Link.Opt == nil { 442 p.Link.Opt = newblock(p.Link) 443 cfg = append(cfg, p.Link.Opt.(*BasicBlock)) 444 } 445 } else if isselectcommcasecall(p) || isselectgocall(p) { 446 // Accommodate implicit selectgo control flow. 447 if p.Link.Opt == nil { 448 p.Link.Opt = newblock(p.Link) 449 cfg = append(cfg, p.Link.Opt.(*BasicBlock)) 450 } 451 } 452 } 453 454 // Loop through all basic blocks maximally growing the list of 455 // contained instructions until a label is reached. Add edges 456 // for branches and fall-through instructions. 457 for _, bb := range cfg { 458 for p := bb.last; p != nil; p = p.Link { 459 if p.Opt != nil && p != bb.last { 460 break 461 } 462 bb.last = p 463 464 // Stop before an unreachable RET, to avoid creating 465 // unreachable control flow nodes. 466 if p.Link != nil && p.Link.As == obj.ARET && p.Link.Mode == 1 { 467 break 468 } 469 470 // Collect basic blocks with selectgo calls. 471 if isselectgocall(p) { 472 selectgo = append(selectgo, bb) 473 } 474 } 475 476 if bb.last.To.Type == obj.TYPE_BRANCH { 477 addedge(bb, bb.last.To.Val.(*obj.Prog).Opt.(*BasicBlock)) 478 } 479 if bb.last.Link != nil { 480 // Add a fall-through when the instruction is 481 // not an unconditional control transfer. 482 if bb.last.As != obj.AJMP && bb.last.As != obj.ARET && bb.last.As != obj.AUNDEF { 483 addedge(bb, bb.last.Link.Opt.(*BasicBlock)) 484 } 485 } 486 } 487 488 // Add back links so the instructions in a basic block can be traversed 489 // backward. This is the final state of the instruction opt field. 490 for _, bb := range cfg { 491 p := bb.first 492 var prev *obj.Prog 493 for { 494 p.Opt = prev 495 if p == bb.last { 496 break 497 } 498 prev = p 499 p = p.Link 500 } 501 } 502 503 // Add missing successor edges to the selectgo blocks. 504 if len(selectgo) != 0 { 505 fixselectgo([]*BasicBlock(selectgo)) 506 } 507 508 // Find a depth-first order and assign a depth-first number to 509 // all basic blocks. 510 for _, bb := range cfg { 511 bb.mark = UNVISITED 512 } 513 bb = cfg[0] 514 rpo := int32(len(cfg)) 515 reversepostorder(bb, &rpo) 516 517 // Sort the basic blocks by their depth first number. The 518 // array is now a depth-first spanning tree with the first 519 // node being the root. 520 sort.Sort(blockrpocmp(cfg)) 521 522 // Unreachable control flow nodes are indicated by a -1 in the rpo 523 // field. If we see these nodes something must have gone wrong in an 524 // upstream compilation phase. 525 bb = cfg[0] 526 if bb.rpo == -1 { 527 fmt.Printf("newcfg: unreachable basic block for %v\n", bb.last) 528 printcfg(cfg) 529 Fatal("newcfg: invalid control flow graph") 530 } 531 532 return cfg 533 } 534 535 // Frees a control flow graph (an array of BasicBlock*s) and all of its leaf 536 // data structures. 537 func freecfg(cfg []*BasicBlock) { 538 if len(cfg) > 0 { 539 bb0 := cfg[0] 540 for p := bb0.first; p != nil; p = p.Link { 541 p.Opt = nil 542 } 543 } 544 } 545 546 // Returns true if the node names a variable that is otherwise uninteresting to 547 // the liveness computation. 548 func isfunny(n *Node) bool { 549 return n.Sym != nil && (n.Sym.Name == ".fp" || n.Sym.Name == ".args") 550 } 551 552 // Computes the effects of an instruction on a set of 553 // variables. The vars argument is an array of Node*s. 554 // 555 // The output vectors give bits for variables: 556 // uevar - used by this instruction 557 // varkill - killed by this instruction 558 // for variables without address taken, means variable was set 559 // for variables with address taken, means variable was marked dead 560 // avarinit - initialized or referred to by this instruction, 561 // only for variables with address taken but not escaping to heap 562 // 563 // The avarinit output serves as a signal that the data has been 564 // initialized, because any use of a variable must come after its 565 // initialization. 566 func progeffects(prog *obj.Prog, vars []*Node, uevar Bvec, varkill Bvec, avarinit Bvec) { 567 bvresetall(uevar) 568 bvresetall(varkill) 569 bvresetall(avarinit) 570 571 if prog.As == obj.ARET { 572 // Return instructions implicitly read all the arguments. For 573 // the sake of correctness, out arguments must be read. For the 574 // sake of backtrace quality, we read in arguments as well. 575 // 576 // A return instruction with a p->to is a tail return, which brings 577 // the stack pointer back up (if it ever went down) and then jumps 578 // to a new function entirely. That form of instruction must read 579 // all the parameters for correctness, and similarly it must not 580 // read the out arguments - they won't be set until the new 581 // function runs. 582 for i, node := range vars { 583 switch node.Class &^ PHEAP { 584 case PPARAM: 585 bvset(uevar, int32(i)) 586 587 // If the result had its address taken, it is being tracked 588 // by the avarinit code, which does not use uevar. 589 // If we added it to uevar too, we'd not see any kill 590 // and decide that the varible was live entry, which it is not. 591 // So only use uevar in the non-addrtaken case. 592 // The p->to.type == thearch.D_NONE limits the bvset to 593 // non-tail-call return instructions; see note above 594 // the for loop for details. 595 case PPARAMOUT: 596 if !node.Addrtaken && prog.To.Type == obj.TYPE_NONE { 597 bvset(uevar, int32(i)) 598 } 599 } 600 } 601 602 return 603 } 604 605 if prog.As == obj.ATEXT { 606 // A text instruction marks the entry point to a function and 607 // the definition point of all in arguments. 608 for i, node := range vars { 609 switch node.Class &^ PHEAP { 610 case PPARAM: 611 if node.Addrtaken { 612 bvset(avarinit, int32(i)) 613 } 614 bvset(varkill, int32(i)) 615 } 616 } 617 618 return 619 } 620 621 if prog.Info.Flags&(LeftRead|LeftWrite|LeftAddr) != 0 { 622 from := &prog.From 623 if from.Node != nil && from.Sym != nil && ((from.Node).(*Node)).Curfn == Curfn { 624 switch ((from.Node).(*Node)).Class &^ PHEAP { 625 case PAUTO, PPARAM, PPARAMOUT: 626 pos, ok := from.Node.(*Node).Opt.(int32) // index in vars 627 if !ok { 628 goto Next 629 } 630 if pos >= int32(len(vars)) || vars[pos] != from.Node { 631 Fatal("bad bookkeeping in liveness %v %d", Nconv(from.Node.(*Node), 0), pos) 632 } 633 if ((from.Node).(*Node)).Addrtaken { 634 bvset(avarinit, pos) 635 } else { 636 if prog.Info.Flags&(LeftRead|LeftAddr) != 0 { 637 bvset(uevar, pos) 638 } 639 if prog.Info.Flags&LeftWrite != 0 { 640 if from.Node != nil && !Isfat(((from.Node).(*Node)).Type) { 641 bvset(varkill, pos) 642 } 643 } 644 } 645 } 646 } 647 } 648 649 Next: 650 if prog.Info.Flags&(RightRead|RightWrite|RightAddr) != 0 { 651 to := &prog.To 652 if to.Node != nil && to.Sym != nil && ((to.Node).(*Node)).Curfn == Curfn { 653 switch ((to.Node).(*Node)).Class &^ PHEAP { 654 case PAUTO, PPARAM, PPARAMOUT: 655 pos, ok := to.Node.(*Node).Opt.(int32) // index in vars 656 if !ok { 657 return 658 } 659 if pos >= int32(len(vars)) || vars[pos] != to.Node { 660 Fatal("bad bookkeeping in liveness %v %d", Nconv(to.Node.(*Node), 0), pos) 661 } 662 if ((to.Node).(*Node)).Addrtaken { 663 if prog.As != obj.AVARKILL { 664 bvset(avarinit, pos) 665 } 666 if prog.As == obj.AVARDEF || prog.As == obj.AVARKILL { 667 bvset(varkill, pos) 668 } 669 } else { 670 // RightRead is a read, obviously. 671 // RightAddr by itself is also implicitly a read. 672 // 673 // RightAddr|RightWrite means that the address is being taken 674 // but only so that the instruction can write to the value. 675 // It is not a read. It is equivalent to RightWrite except that 676 // having the RightAddr bit set keeps the registerizer from 677 // trying to substitute a register for the memory location. 678 if (prog.Info.Flags&RightRead != 0) || prog.Info.Flags&(RightAddr|RightWrite) == RightAddr { 679 bvset(uevar, pos) 680 } 681 if prog.Info.Flags&RightWrite != 0 { 682 if to.Node != nil && (!Isfat(((to.Node).(*Node)).Type) || prog.As == obj.AVARDEF) { 683 bvset(varkill, pos) 684 } 685 } 686 } 687 } 688 } 689 } 690 } 691 692 // Constructs a new liveness structure used to hold the global state of the 693 // liveness computation. The cfg argument is an array of BasicBlock*s and the 694 // vars argument is an array of Node*s. 695 func newliveness(fn *Node, ptxt *obj.Prog, cfg []*BasicBlock, vars []*Node) *Liveness { 696 result := new(Liveness) 697 result.fn = fn 698 result.ptxt = ptxt 699 result.cfg = cfg 700 result.vars = vars 701 702 nblocks := int32(len(cfg)) 703 nvars := int32(len(vars)) 704 bulk := bvbulkalloc(nvars, nblocks*7) 705 for _, bb := range cfg { 706 bb.uevar = bulk.next() 707 bb.varkill = bulk.next() 708 bb.livein = bulk.next() 709 bb.liveout = bulk.next() 710 bb.avarinit = bulk.next() 711 bb.avarinitany = bulk.next() 712 bb.avarinitall = bulk.next() 713 } 714 715 result.livepointers = make([]Bvec, 0, 0) 716 result.argslivepointers = make([]Bvec, 0, 0) 717 return result 718 } 719 720 // Frees the liveness structure and all of its leaf data structures. 721 func freeliveness(lv *Liveness) { 722 if lv == nil { 723 Fatal("freeliveness: cannot free nil") 724 } 725 } 726 727 func printeffects(p *obj.Prog, uevar Bvec, varkill Bvec, avarinit Bvec) { 728 fmt.Printf("effects of %v", p) 729 fmt.Printf("\nuevar: ") 730 bvprint(uevar) 731 fmt.Printf("\nvarkill: ") 732 bvprint(varkill) 733 fmt.Printf("\navarinit: ") 734 bvprint(avarinit) 735 fmt.Printf("\n") 736 } 737 738 // Pretty print a variable node. Uses Pascal like conventions for pointers and 739 // addresses to avoid confusing the C like conventions used in the node variable 740 // names. 741 func printnode(node *Node) { 742 p := "" 743 if haspointers(node.Type) { 744 p = "^" 745 } 746 a := "" 747 if node.Addrtaken { 748 a = "@" 749 } 750 fmt.Printf(" %v%s%s", node, p, a) 751 } 752 753 // Pretty print a list of variables. The vars argument is an array of Node*s. 754 func printvars(name string, bv Bvec, vars []*Node) { 755 fmt.Printf("%s:", name) 756 for i, node := range vars { 757 if bvget(bv, int32(i)) != 0 { 758 printnode(node) 759 } 760 } 761 fmt.Printf("\n") 762 } 763 764 // Prints a basic block annotated with the information computed by liveness 765 // analysis. 766 func livenessprintblock(lv *Liveness, bb *BasicBlock) { 767 fmt.Printf("basic block %d\n", bb.rpo) 768 769 fmt.Printf("\tpred:") 770 for _, pred := range bb.pred { 771 fmt.Printf(" %d", pred.rpo) 772 } 773 fmt.Printf("\n") 774 775 fmt.Printf("\tsucc:") 776 for _, succ := range bb.succ { 777 fmt.Printf(" %d", succ.rpo) 778 } 779 fmt.Printf("\n") 780 781 printvars("\tuevar", bb.uevar, []*Node(lv.vars)) 782 printvars("\tvarkill", bb.varkill, []*Node(lv.vars)) 783 printvars("\tlivein", bb.livein, []*Node(lv.vars)) 784 printvars("\tliveout", bb.liveout, []*Node(lv.vars)) 785 printvars("\tavarinit", bb.avarinit, []*Node(lv.vars)) 786 printvars("\tavarinitany", bb.avarinitany, []*Node(lv.vars)) 787 printvars("\tavarinitall", bb.avarinitall, []*Node(lv.vars)) 788 789 fmt.Printf("\tprog:\n") 790 for prog := bb.first; ; prog = prog.Link { 791 fmt.Printf("\t\t%v", prog) 792 if prog.As == obj.APCDATA && prog.From.Offset == obj.PCDATA_StackMapIndex { 793 pos := int32(prog.To.Offset) 794 live := lv.livepointers[pos] 795 fmt.Printf(" ") 796 bvprint(live) 797 } 798 799 fmt.Printf("\n") 800 if prog == bb.last { 801 break 802 } 803 } 804 } 805 806 // Prints a control flow graph annotated with any information computed by 807 // liveness analysis. 808 func livenessprintcfg(lv *Liveness) { 809 for _, bb := range lv.cfg { 810 livenessprintblock(lv, bb) 811 } 812 } 813 814 func checkauto(fn *Node, p *obj.Prog, n *Node) { 815 for l := fn.Func.Dcl; l != nil; l = l.Next { 816 if l.N.Op == ONAME && l.N.Class == PAUTO && l.N == n { 817 return 818 } 819 } 820 821 if n == nil { 822 fmt.Printf("%v: checkauto %v: nil node in %v\n", p.Line(), Curfn, p) 823 return 824 } 825 826 fmt.Printf("checkauto %v: %v (%p; class=%d) not found in %v\n", Curfn, n, n, n.Class, p) 827 for l := fn.Func.Dcl; l != nil; l = l.Next { 828 fmt.Printf("\t%v (%p; class=%d)\n", l.N, l.N, l.N.Class) 829 } 830 Yyerror("checkauto: invariant lost") 831 } 832 833 func checkparam(fn *Node, p *obj.Prog, n *Node) { 834 if isfunny(n) { 835 return 836 } 837 var a *Node 838 var class uint8 839 for l := fn.Func.Dcl; l != nil; l = l.Next { 840 a = l.N 841 class = a.Class &^ PHEAP 842 if a.Op == ONAME && (class == PPARAM || class == PPARAMOUT) && a == n { 843 return 844 } 845 } 846 847 fmt.Printf("checkparam %v: %v (%p; class=%d) not found in %v\n", Curfn, n, n, n.Class, p) 848 for l := fn.Func.Dcl; l != nil; l = l.Next { 849 fmt.Printf("\t%v (%p; class=%d)\n", l.N, l.N, l.N.Class) 850 } 851 Yyerror("checkparam: invariant lost") 852 } 853 854 func checkprog(fn *Node, p *obj.Prog) { 855 if p.From.Name == obj.NAME_AUTO { 856 checkauto(fn, p, p.From.Node.(*Node)) 857 } 858 if p.From.Name == obj.NAME_PARAM { 859 checkparam(fn, p, p.From.Node.(*Node)) 860 } 861 if p.To.Name == obj.NAME_AUTO { 862 checkauto(fn, p, p.To.Node.(*Node)) 863 } 864 if p.To.Name == obj.NAME_PARAM { 865 checkparam(fn, p, p.To.Node.(*Node)) 866 } 867 } 868 869 // Check instruction invariants. We assume that the nodes corresponding to the 870 // sources and destinations of memory operations will be declared in the 871 // function. This is not strictly true, as is the case for the so-called funny 872 // nodes and there are special cases to skip over that stuff. The analysis will 873 // fail if this invariant blindly changes. 874 func checkptxt(fn *Node, firstp *obj.Prog) { 875 if debuglive == 0 { 876 return 877 } 878 879 for p := firstp; p != nil; p = p.Link { 880 if false { 881 fmt.Printf("analyzing '%v'\n", p) 882 } 883 if p.As != obj.ADATA && p.As != obj.AGLOBL && p.As != obj.ATYPE { 884 checkprog(fn, p) 885 } 886 } 887 } 888 889 // NOTE: The bitmap for a specific type t should be cached in t after the first run 890 // and then simply copied into bv at the correct offset on future calls with 891 // the same type t. On https://rsc.googlecode.com/hg/testdata/slow.go, onebitwalktype1 892 // accounts for 40% of the 6g execution time. 893 func onebitwalktype1(t *Type, xoffset *int64, bv Bvec) { 894 if t.Align > 0 && *xoffset&int64(t.Align-1) != 0 { 895 Fatal("onebitwalktype1: invalid initial alignment, %v", t) 896 } 897 898 switch t.Etype { 899 case TINT8, 900 TUINT8, 901 TINT16, 902 TUINT16, 903 TINT32, 904 TUINT32, 905 TINT64, 906 TUINT64, 907 TINT, 908 TUINT, 909 TUINTPTR, 910 TBOOL, 911 TFLOAT32, 912 TFLOAT64, 913 TCOMPLEX64, 914 TCOMPLEX128: 915 *xoffset += t.Width 916 917 case TPTR32, 918 TPTR64, 919 TUNSAFEPTR, 920 TFUNC, 921 TCHAN, 922 TMAP: 923 if *xoffset&int64(Widthptr-1) != 0 { 924 Fatal("onebitwalktype1: invalid alignment, %v", t) 925 } 926 bvset(bv, int32(*xoffset/int64(Widthptr))) // pointer 927 *xoffset += t.Width 928 929 case TSTRING: 930 // struct { byte *str; intgo len; } 931 if *xoffset&int64(Widthptr-1) != 0 { 932 Fatal("onebitwalktype1: invalid alignment, %v", t) 933 } 934 bvset(bv, int32(*xoffset/int64(Widthptr))) //pointer in first slot 935 *xoffset += t.Width 936 937 case TINTER: 938 // struct { Itab *tab; union { void *ptr, uintptr val } data; } 939 // or, when isnilinter(t)==true: 940 // struct { Type *type; union { void *ptr, uintptr val } data; } 941 if *xoffset&int64(Widthptr-1) != 0 { 942 Fatal("onebitwalktype1: invalid alignment, %v", t) 943 } 944 bvset(bv, int32(*xoffset/int64(Widthptr))) // pointer in first slot 945 bvset(bv, int32(*xoffset/int64(Widthptr)+1)) // pointer in second slot 946 *xoffset += t.Width 947 948 case TARRAY: 949 // The value of t->bound is -1 for slices types and >0 for 950 // for fixed array types. All other values are invalid. 951 if t.Bound < -1 { 952 Fatal("onebitwalktype1: invalid bound, %v", t) 953 } 954 if Isslice(t) { 955 // struct { byte *array; uintgo len; uintgo cap; } 956 if *xoffset&int64(Widthptr-1) != 0 { 957 Fatal("onebitwalktype1: invalid TARRAY alignment, %v", t) 958 } 959 bvset(bv, int32(*xoffset/int64(Widthptr))) // pointer in first slot (BitsPointer) 960 *xoffset += t.Width 961 } else { 962 for i := int64(0); i < t.Bound; i++ { 963 onebitwalktype1(t.Type, xoffset, bv) 964 } 965 } 966 967 case TSTRUCT: 968 o := int64(0) 969 var fieldoffset int64 970 for t1 := t.Type; t1 != nil; t1 = t1.Down { 971 fieldoffset = t1.Width 972 *xoffset += fieldoffset - o 973 onebitwalktype1(t1.Type, xoffset, bv) 974 o = fieldoffset + t1.Type.Width 975 } 976 977 *xoffset += t.Width - o 978 979 default: 980 Fatal("onebitwalktype1: unexpected type, %v", t) 981 } 982 } 983 984 // Returns the number of words of local variables. 985 func localswords() int32 { 986 return int32(stkptrsize / int64(Widthptr)) 987 } 988 989 // Returns the number of words of in and out arguments. 990 func argswords() int32 { 991 return int32(Curfn.Type.Argwid / int64(Widthptr)) 992 } 993 994 // Generates live pointer value maps for arguments and local variables. The 995 // this argument and the in arguments are always assumed live. The vars 996 // argument is an array of Node*s. 997 func onebitlivepointermap(lv *Liveness, liveout Bvec, vars []*Node, args Bvec, locals Bvec) { 998 var node *Node 999 var xoffset int64 1000 1001 for i := int32(0); ; i++ { 1002 i = int32(bvnext(liveout, i)) 1003 if i < 0 { 1004 break 1005 } 1006 node = vars[i] 1007 switch node.Class { 1008 case PAUTO: 1009 xoffset = node.Xoffset + stkptrsize 1010 onebitwalktype1(node.Type, &xoffset, locals) 1011 1012 case PPARAM, PPARAMOUT: 1013 xoffset = node.Xoffset 1014 onebitwalktype1(node.Type, &xoffset, args) 1015 } 1016 } 1017 1018 // The node list only contains declared names. 1019 // If the receiver or arguments are unnamed, they will be omitted 1020 // from the list above. Preserve those values - even though they are unused - 1021 // in order to keep their addresses live for use in stack traces. 1022 thisargtype := getthisx(lv.fn.Type) 1023 1024 if thisargtype != nil { 1025 xoffset = 0 1026 onebitwalktype1(thisargtype, &xoffset, args) 1027 } 1028 1029 inargtype := getinargx(lv.fn.Type) 1030 if inargtype != nil { 1031 xoffset = 0 1032 onebitwalktype1(inargtype, &xoffset, args) 1033 } 1034 } 1035 1036 // Construct a disembodied instruction. 1037 func unlinkedprog(as int) *obj.Prog { 1038 p := Ctxt.NewProg() 1039 Clearp(p) 1040 p.As = int16(as) 1041 return p 1042 } 1043 1044 // Construct a new PCDATA instruction associated with and for the purposes of 1045 // covering an existing instruction. 1046 func newpcdataprog(prog *obj.Prog, index int32) *obj.Prog { 1047 var from Node 1048 var to Node 1049 1050 Nodconst(&from, Types[TINT32], obj.PCDATA_StackMapIndex) 1051 Nodconst(&to, Types[TINT32], int64(index)) 1052 pcdata := unlinkedprog(obj.APCDATA) 1053 pcdata.Lineno = prog.Lineno 1054 Naddr(&pcdata.From, &from) 1055 Naddr(&pcdata.To, &to) 1056 return pcdata 1057 } 1058 1059 // Returns true for instructions that are safe points that must be annotated 1060 // with liveness information. 1061 func issafepoint(prog *obj.Prog) bool { 1062 return prog.As == obj.ATEXT || prog.As == obj.ACALL 1063 } 1064 1065 // Initializes the sets for solving the live variables. Visits all the 1066 // instructions in each basic block to summarizes the information at each basic 1067 // block 1068 func livenessprologue(lv *Liveness) { 1069 nvars := int32(len(lv.vars)) 1070 uevar := bvalloc(nvars) 1071 varkill := bvalloc(nvars) 1072 avarinit := bvalloc(nvars) 1073 for _, bb := range lv.cfg { 1074 // Walk the block instructions backward and update the block 1075 // effects with the each prog effects. 1076 for p := bb.last; p != nil; p = p.Opt.(*obj.Prog) { 1077 progeffects(p, []*Node(lv.vars), uevar, varkill, avarinit) 1078 if debuglive >= 3 { 1079 printeffects(p, uevar, varkill, avarinit) 1080 } 1081 bvor(bb.varkill, bb.varkill, varkill) 1082 bvandnot(bb.uevar, bb.uevar, varkill) 1083 bvor(bb.uevar, bb.uevar, uevar) 1084 } 1085 1086 // Walk the block instructions forward to update avarinit bits. 1087 // avarinit describes the effect at the end of the block, not the beginning. 1088 bvresetall(varkill) 1089 1090 for p := bb.first; ; p = p.Link { 1091 progeffects(p, []*Node(lv.vars), uevar, varkill, avarinit) 1092 if debuglive >= 3 { 1093 printeffects(p, uevar, varkill, avarinit) 1094 } 1095 bvandnot(bb.avarinit, bb.avarinit, varkill) 1096 bvor(bb.avarinit, bb.avarinit, avarinit) 1097 if p == bb.last { 1098 break 1099 } 1100 } 1101 } 1102 } 1103 1104 // Solve the liveness dataflow equations. 1105 func livenesssolve(lv *Liveness) { 1106 // These temporary bitvectors exist to avoid successive allocations and 1107 // frees within the loop. 1108 newlivein := bvalloc(int32(len(lv.vars))) 1109 1110 newliveout := bvalloc(int32(len(lv.vars))) 1111 any := bvalloc(int32(len(lv.vars))) 1112 all := bvalloc(int32(len(lv.vars))) 1113 1114 // Push avarinitall, avarinitany forward. 1115 // avarinitall says the addressed var is initialized along all paths reaching the block exit. 1116 // avarinitany says the addressed var is initialized along some path reaching the block exit. 1117 for i, bb := range lv.cfg { 1118 if i == 0 { 1119 bvcopy(bb.avarinitall, bb.avarinit) 1120 } else { 1121 bvresetall(bb.avarinitall) 1122 bvnot(bb.avarinitall) 1123 } 1124 bvcopy(bb.avarinitany, bb.avarinit) 1125 } 1126 1127 change := int32(1) 1128 for change != 0 { 1129 change = 0 1130 for _, bb := range lv.cfg { 1131 bvresetall(any) 1132 bvresetall(all) 1133 for j, pred := range bb.pred { 1134 if j == 0 { 1135 bvcopy(any, pred.avarinitany) 1136 bvcopy(all, pred.avarinitall) 1137 } else { 1138 bvor(any, any, pred.avarinitany) 1139 bvand(all, all, pred.avarinitall) 1140 } 1141 } 1142 1143 bvandnot(any, any, bb.varkill) 1144 bvandnot(all, all, bb.varkill) 1145 bvor(any, any, bb.avarinit) 1146 bvor(all, all, bb.avarinit) 1147 if bvcmp(any, bb.avarinitany) != 0 { 1148 change = 1 1149 bvcopy(bb.avarinitany, any) 1150 } 1151 1152 if bvcmp(all, bb.avarinitall) != 0 { 1153 change = 1 1154 bvcopy(bb.avarinitall, all) 1155 } 1156 } 1157 } 1158 1159 // Iterate through the blocks in reverse round-robin fashion. A work 1160 // queue might be slightly faster. As is, the number of iterations is 1161 // so low that it hardly seems to be worth the complexity. 1162 change = 1 1163 1164 for change != 0 { 1165 change = 0 1166 1167 // Walk blocks in the general direction of propagation. This 1168 // improves convergence. 1169 for i := len(lv.cfg) - 1; i >= 0; i-- { 1170 bb := lv.cfg[i] 1171 1172 // A variable is live on output from this block 1173 // if it is live on input to some successor. 1174 // 1175 // out[b] = \bigcup_{s \in succ[b]} in[s] 1176 bvresetall(newliveout) 1177 for _, succ := range bb.succ { 1178 bvor(newliveout, newliveout, succ.livein) 1179 } 1180 1181 if bvcmp(bb.liveout, newliveout) != 0 { 1182 change = 1 1183 bvcopy(bb.liveout, newliveout) 1184 } 1185 1186 // A variable is live on input to this block 1187 // if it is live on output from this block and 1188 // not set by the code in this block. 1189 // 1190 // in[b] = uevar[b] \cup (out[b] \setminus varkill[b]) 1191 bvandnot(newlivein, bb.liveout, bb.varkill) 1192 1193 bvor(bb.livein, newlivein, bb.uevar) 1194 } 1195 } 1196 } 1197 1198 // This function is slow but it is only used for generating debug prints. 1199 // Check whether n is marked live in args/locals. 1200 func islive(n *Node, args Bvec, locals Bvec) bool { 1201 switch n.Class { 1202 case PPARAM, PPARAMOUT: 1203 for i := 0; int64(i) < n.Type.Width/int64(Widthptr); i++ { 1204 if bvget(args, int32(n.Xoffset/int64(Widthptr)+int64(i))) != 0 { 1205 return true 1206 } 1207 } 1208 1209 case PAUTO: 1210 for i := 0; int64(i) < n.Type.Width/int64(Widthptr); i++ { 1211 if bvget(locals, int32((n.Xoffset+stkptrsize)/int64(Widthptr)+int64(i))) != 0 { 1212 return true 1213 } 1214 } 1215 } 1216 1217 return false 1218 } 1219 1220 // Visits all instructions in a basic block and computes a bit vector of live 1221 // variables at each safe point locations. 1222 func livenessepilogue(lv *Liveness) { 1223 var pred *BasicBlock 1224 var args Bvec 1225 var locals Bvec 1226 var n *Node 1227 var p *obj.Prog 1228 var j int32 1229 var pos int32 1230 var xoffset int64 1231 1232 nvars := int32(len(lv.vars)) 1233 livein := bvalloc(nvars) 1234 liveout := bvalloc(nvars) 1235 uevar := bvalloc(nvars) 1236 varkill := bvalloc(nvars) 1237 avarinit := bvalloc(nvars) 1238 any := bvalloc(nvars) 1239 all := bvalloc(nvars) 1240 ambig := bvalloc(localswords()) 1241 nmsg := int32(0) 1242 startmsg := int32(0) 1243 1244 for _, bb := range lv.cfg { 1245 // Compute avarinitany and avarinitall for entry to block. 1246 // This duplicates information known during livenesssolve 1247 // but avoids storing two more vectors for each block. 1248 bvresetall(any) 1249 1250 bvresetall(all) 1251 for j = 0; j < int32(len(bb.pred)); j++ { 1252 pred = bb.pred[j] 1253 if j == 0 { 1254 bvcopy(any, pred.avarinitany) 1255 bvcopy(all, pred.avarinitall) 1256 } else { 1257 bvor(any, any, pred.avarinitany) 1258 bvand(all, all, pred.avarinitall) 1259 } 1260 } 1261 1262 // Walk forward through the basic block instructions and 1263 // allocate liveness maps for those instructions that need them. 1264 // Seed the maps with information about the addrtaken variables. 1265 for p = bb.first; ; p = p.Link { 1266 progeffects(p, []*Node(lv.vars), uevar, varkill, avarinit) 1267 bvandnot(any, any, varkill) 1268 bvandnot(all, all, varkill) 1269 bvor(any, any, avarinit) 1270 bvor(all, all, avarinit) 1271 1272 if issafepoint(p) { 1273 // Annotate ambiguously live variables so that they can 1274 // be zeroed at function entry. 1275 // livein and liveout are dead here and used as temporaries. 1276 bvresetall(livein) 1277 1278 bvandnot(liveout, any, all) 1279 if !bvisempty(liveout) { 1280 for pos = 0; pos < liveout.n; pos++ { 1281 if bvget(liveout, pos) == 0 { 1282 continue 1283 } 1284 bvset(all, pos) // silence future warnings in this block 1285 n = lv.vars[pos] 1286 if !n.Needzero { 1287 n.Needzero = true 1288 if debuglive >= 1 { 1289 Warnl(int(p.Lineno), "%v: %v is ambiguously live", Curfn.Nname, Nconv(n, obj.FmtLong)) 1290 } 1291 1292 // Record in 'ambiguous' bitmap. 1293 xoffset = n.Xoffset + stkptrsize 1294 1295 onebitwalktype1(n.Type, &xoffset, ambig) 1296 } 1297 } 1298 } 1299 1300 // Allocate a bit vector for each class and facet of 1301 // value we are tracking. 1302 1303 // Live stuff first. 1304 args = bvalloc(argswords()) 1305 1306 lv.argslivepointers = append(lv.argslivepointers, args) 1307 locals = bvalloc(localswords()) 1308 lv.livepointers = append(lv.livepointers, locals) 1309 1310 if debuglive >= 3 { 1311 fmt.Printf("%v\n", p) 1312 printvars("avarinitany", any, lv.vars) 1313 } 1314 1315 // Record any values with an "address taken" reaching 1316 // this code position as live. Must do now instead of below 1317 // because the any/all calculation requires walking forward 1318 // over the block (as this loop does), while the liveout 1319 // requires walking backward (as the next loop does). 1320 onebitlivepointermap(lv, any, lv.vars, args, locals) 1321 } 1322 1323 if p == bb.last { 1324 break 1325 } 1326 } 1327 1328 bb.lastbitmapindex = len(lv.livepointers) - 1 1329 } 1330 1331 var fmt_ string 1332 var next *obj.Prog 1333 var numlive int32 1334 var msg []string 1335 for _, bb := range lv.cfg { 1336 if debuglive >= 1 && Curfn.Nname.Sym.Name != "init" && Curfn.Nname.Sym.Name[0] != '.' { 1337 nmsg = int32(len(lv.livepointers)) 1338 startmsg = nmsg 1339 msg = make([]string, nmsg) 1340 for j = 0; j < nmsg; j++ { 1341 msg[j] = "" 1342 } 1343 } 1344 1345 // walk backward, emit pcdata and populate the maps 1346 pos = int32(bb.lastbitmapindex) 1347 1348 if pos < 0 { 1349 // the first block we encounter should have the ATEXT so 1350 // at no point should pos ever be less than zero. 1351 Fatal("livenessepilogue") 1352 } 1353 1354 bvcopy(livein, bb.liveout) 1355 for p = bb.last; p != nil; p = next { 1356 next = p.Opt.(*obj.Prog) // splicebefore modifies p->opt 1357 1358 // Propagate liveness information 1359 progeffects(p, lv.vars, uevar, varkill, avarinit) 1360 1361 bvcopy(liveout, livein) 1362 bvandnot(livein, liveout, varkill) 1363 bvor(livein, livein, uevar) 1364 if debuglive >= 3 && issafepoint(p) { 1365 fmt.Printf("%v\n", p) 1366 printvars("uevar", uevar, lv.vars) 1367 printvars("varkill", varkill, lv.vars) 1368 printvars("livein", livein, lv.vars) 1369 printvars("liveout", liveout, lv.vars) 1370 } 1371 1372 if issafepoint(p) { 1373 // Found an interesting instruction, record the 1374 // corresponding liveness information. 1375 1376 // Useful sanity check: on entry to the function, 1377 // the only things that can possibly be live are the 1378 // input parameters. 1379 if p.As == obj.ATEXT { 1380 for j = 0; j < liveout.n; j++ { 1381 if bvget(liveout, j) == 0 { 1382 continue 1383 } 1384 n = lv.vars[j] 1385 if n.Class != PPARAM { 1386 yyerrorl(int(p.Lineno), "internal error: %v %v recorded as live on entry", Curfn.Nname, Nconv(n, obj.FmtLong)) 1387 } 1388 } 1389 } 1390 1391 // Record live pointers. 1392 args = lv.argslivepointers[pos] 1393 1394 locals = lv.livepointers[pos] 1395 onebitlivepointermap(lv, liveout, lv.vars, args, locals) 1396 1397 // Ambiguously live variables are zeroed immediately after 1398 // function entry. Mark them live for all the non-entry bitmaps 1399 // so that GODEBUG=gcdead=1 mode does not poison them. 1400 if p.As == obj.ACALL { 1401 bvor(locals, locals, ambig) 1402 } 1403 1404 // Show live pointer bitmaps. 1405 // We're interpreting the args and locals bitmap instead of liveout so that we 1406 // include the bits added by the avarinit logic in the 1407 // previous loop. 1408 if msg != nil { 1409 fmt_ = "" 1410 fmt_ += fmt.Sprintf("%v: live at ", p.Line()) 1411 if p.As == obj.ACALL && p.To.Node != nil { 1412 fmt_ += fmt.Sprintf("call to %s:", ((p.To.Node).(*Node)).Sym.Name) 1413 } else if p.As == obj.ACALL { 1414 fmt_ += "indirect call:" 1415 } else { 1416 fmt_ += fmt.Sprintf("entry to %s:", ((p.From.Node).(*Node)).Sym.Name) 1417 } 1418 numlive = 0 1419 for j = 0; j < int32(len(lv.vars)); j++ { 1420 n = lv.vars[j] 1421 if islive(n, args, locals) { 1422 fmt_ += fmt.Sprintf(" %v", n) 1423 numlive++ 1424 } 1425 } 1426 1427 fmt_ += "\n" 1428 if numlive == 0 { // squelch message 1429 1430 } else { 1431 startmsg-- 1432 msg[startmsg] = fmt_ 1433 } 1434 } 1435 1436 // Only CALL instructions need a PCDATA annotation. 1437 // The TEXT instruction annotation is implicit. 1438 if p.As == obj.ACALL { 1439 if isdeferreturn(p) { 1440 // runtime.deferreturn modifies its return address to return 1441 // back to the CALL, not to the subsequent instruction. 1442 // Because the return comes back one instruction early, 1443 // the PCDATA must begin one instruction early too. 1444 // The instruction before a call to deferreturn is always a 1445 // no-op, to keep PC-specific data unambiguous. 1446 splicebefore(lv, bb, newpcdataprog(p.Opt.(*obj.Prog), pos), p.Opt.(*obj.Prog)) 1447 } else { 1448 splicebefore(lv, bb, newpcdataprog(p, pos), p) 1449 } 1450 } 1451 1452 pos-- 1453 } 1454 } 1455 1456 if msg != nil { 1457 for j = startmsg; j < nmsg; j++ { 1458 if msg[j] != "" { 1459 fmt.Printf("%s", msg[j]) 1460 } 1461 } 1462 1463 msg = nil 1464 nmsg = 0 1465 startmsg = 0 1466 } 1467 } 1468 1469 Flusherrors() 1470 } 1471 1472 // FNV-1 hash function constants. 1473 const ( 1474 H0 = 2166136261 1475 Hp = 16777619 1476 ) 1477 1478 func hashbitmap(h uint32, bv Bvec) uint32 { 1479 var w uint32 1480 1481 n := int((bv.n + 31) / 32) 1482 for i := 0; i < n; i++ { 1483 w = bv.b[i] 1484 h = (h * Hp) ^ (w & 0xff) 1485 h = (h * Hp) ^ ((w >> 8) & 0xff) 1486 h = (h * Hp) ^ ((w >> 16) & 0xff) 1487 h = (h * Hp) ^ ((w >> 24) & 0xff) 1488 } 1489 1490 return h 1491 } 1492 1493 // Compact liveness information by coalescing identical per-call-site bitmaps. 1494 // The merging only happens for a single function, not across the entire binary. 1495 // 1496 // There are actually two lists of bitmaps, one list for the local variables and one 1497 // list for the function arguments. Both lists are indexed by the same PCDATA 1498 // index, so the corresponding pairs must be considered together when 1499 // merging duplicates. The argument bitmaps change much less often during 1500 // function execution than the local variable bitmaps, so it is possible that 1501 // we could introduce a separate PCDATA index for arguments vs locals and 1502 // then compact the set of argument bitmaps separately from the set of 1503 // local variable bitmaps. As of 2014-04-02, doing this to the godoc binary 1504 // is actually a net loss: we save about 50k of argument bitmaps but the new 1505 // PCDATA tables cost about 100k. So for now we keep using a single index for 1506 // both bitmap lists. 1507 func livenesscompact(lv *Liveness) { 1508 // Linear probing hash table of bitmaps seen so far. 1509 // The hash table has 4n entries to keep the linear 1510 // scan short. An entry of -1 indicates an empty slot. 1511 n := len(lv.livepointers) 1512 1513 tablesize := 4 * n 1514 table := make([]int, tablesize) 1515 for i := range table { 1516 table[i] = -1 1517 } 1518 1519 // remap[i] = the new index of the old bit vector #i. 1520 remap := make([]int, n) 1521 1522 for i := range remap { 1523 remap[i] = -1 1524 } 1525 uniq := 0 // unique tables found so far 1526 1527 // Consider bit vectors in turn. 1528 // If new, assign next number using uniq, 1529 // record in remap, record in lv->livepointers and lv->argslivepointers 1530 // under the new index, and add entry to hash table. 1531 // If already seen, record earlier index in remap and free bitmaps. 1532 var jarg Bvec 1533 var j int 1534 var h uint32 1535 var arg Bvec 1536 var jlocal Bvec 1537 var local Bvec 1538 for i := 0; i < n; i++ { 1539 local = lv.livepointers[i] 1540 arg = lv.argslivepointers[i] 1541 h = hashbitmap(hashbitmap(H0, local), arg) % uint32(tablesize) 1542 1543 for { 1544 j = table[h] 1545 if j < 0 { 1546 break 1547 } 1548 jlocal = lv.livepointers[j] 1549 jarg = lv.argslivepointers[j] 1550 if bvcmp(local, jlocal) == 0 && bvcmp(arg, jarg) == 0 { 1551 remap[i] = j 1552 goto Next 1553 } 1554 1555 h++ 1556 if h == uint32(tablesize) { 1557 h = 0 1558 } 1559 } 1560 1561 table[h] = uniq 1562 remap[i] = uniq 1563 lv.livepointers[uniq] = local 1564 lv.argslivepointers[uniq] = arg 1565 uniq++ 1566 Next: 1567 } 1568 1569 // We've already reordered lv->livepointers[0:uniq] 1570 // and lv->argslivepointers[0:uniq] and freed the bitmaps 1571 // we don't need anymore. Clear the pointers later in the 1572 // array so that we can tell where the coalesced bitmaps stop 1573 // and so that we don't double-free when cleaning up. 1574 for j := uniq; j < n; j++ { 1575 lv.livepointers[j] = Bvec{} 1576 lv.argslivepointers[j] = Bvec{} 1577 } 1578 1579 // Rewrite PCDATA instructions to use new numbering. 1580 var i int 1581 for p := lv.ptxt; p != nil; p = p.Link { 1582 if p.As == obj.APCDATA && p.From.Offset == obj.PCDATA_StackMapIndex { 1583 i = int(p.To.Offset) 1584 if i >= 0 { 1585 p.To.Offset = int64(remap[i]) 1586 } 1587 } 1588 } 1589 } 1590 1591 func printbitset(printed int, name string, vars []*Node, bits Bvec) int { 1592 started := 0 1593 for i, n := range vars { 1594 if bvget(bits, int32(i)) == 0 { 1595 continue 1596 } 1597 if started == 0 { 1598 if printed == 0 { 1599 fmt.Printf("\t") 1600 } else { 1601 fmt.Printf(" ") 1602 } 1603 started = 1 1604 printed = 1 1605 fmt.Printf("%s=", name) 1606 } else { 1607 fmt.Printf(",") 1608 } 1609 1610 fmt.Printf("%s", n.Sym.Name) 1611 } 1612 1613 return printed 1614 } 1615 1616 // Prints the computed liveness information and inputs, for debugging. 1617 // This format synthesizes the information used during the multiple passes 1618 // into a single presentation. 1619 func livenessprintdebug(lv *Liveness) { 1620 var j int 1621 var printed int 1622 var p *obj.Prog 1623 var args Bvec 1624 var locals Bvec 1625 var n *Node 1626 1627 fmt.Printf("liveness: %s\n", Curfn.Nname.Sym.Name) 1628 1629 uevar := bvalloc(int32(len(lv.vars))) 1630 varkill := bvalloc(int32(len(lv.vars))) 1631 avarinit := bvalloc(int32(len(lv.vars))) 1632 1633 pcdata := 0 1634 for i, bb := range lv.cfg { 1635 if i > 0 { 1636 fmt.Printf("\n") 1637 } 1638 1639 // bb#0 pred=1,2 succ=3,4 1640 fmt.Printf("bb#%d pred=", i) 1641 1642 for j = 0; j < len(bb.pred); j++ { 1643 if j > 0 { 1644 fmt.Printf(",") 1645 } 1646 fmt.Printf("%d", (bb.pred[j]).rpo) 1647 } 1648 1649 fmt.Printf(" succ=") 1650 for j = 0; j < len(bb.succ); j++ { 1651 if j > 0 { 1652 fmt.Printf(",") 1653 } 1654 fmt.Printf("%d", (bb.succ[j]).rpo) 1655 } 1656 1657 fmt.Printf("\n") 1658 1659 // initial settings 1660 printed = 0 1661 1662 printed = printbitset(printed, "uevar", lv.vars, bb.uevar) 1663 printed = printbitset(printed, "livein", lv.vars, bb.livein) 1664 if printed != 0 { 1665 fmt.Printf("\n") 1666 } 1667 1668 // program listing, with individual effects listed 1669 for p = bb.first; ; p = p.Link { 1670 fmt.Printf("%v\n", p) 1671 if p.As == obj.APCDATA && p.From.Offset == obj.PCDATA_StackMapIndex { 1672 pcdata = int(p.To.Offset) 1673 } 1674 progeffects(p, lv.vars, uevar, varkill, avarinit) 1675 printed = 0 1676 printed = printbitset(printed, "uevar", lv.vars, uevar) 1677 printed = printbitset(printed, "varkill", lv.vars, varkill) 1678 printed = printbitset(printed, "avarinit", lv.vars, avarinit) 1679 if printed != 0 { 1680 fmt.Printf("\n") 1681 } 1682 if issafepoint(p) { 1683 args = lv.argslivepointers[pcdata] 1684 locals = lv.livepointers[pcdata] 1685 fmt.Printf("\tlive=") 1686 printed = 0 1687 for j = 0; j < len(lv.vars); j++ { 1688 n = lv.vars[j] 1689 if islive(n, args, locals) { 1690 tmp9 := printed 1691 printed++ 1692 if tmp9 != 0 { 1693 fmt.Printf(",") 1694 } 1695 fmt.Printf("%v", n) 1696 } 1697 } 1698 1699 fmt.Printf("\n") 1700 } 1701 1702 if p == bb.last { 1703 break 1704 } 1705 } 1706 1707 // bb bitsets 1708 fmt.Printf("end\n") 1709 1710 printed = printbitset(printed, "varkill", lv.vars, bb.varkill) 1711 printed = printbitset(printed, "liveout", lv.vars, bb.liveout) 1712 printed = printbitset(printed, "avarinit", lv.vars, bb.avarinit) 1713 printed = printbitset(printed, "avarinitany", lv.vars, bb.avarinitany) 1714 printed = printbitset(printed, "avarinitall", lv.vars, bb.avarinitall) 1715 if printed != 0 { 1716 fmt.Printf("\n") 1717 } 1718 } 1719 1720 fmt.Printf("\n") 1721 } 1722 1723 // Dumps an array of bitmaps to a symbol as a sequence of uint32 values. The 1724 // first word dumped is the total number of bitmaps. The second word is the 1725 // length of the bitmaps. All bitmaps are assumed to be of equal length. The 1726 // words that are followed are the raw bitmap words. The arr argument is an 1727 // array of Node*s. 1728 func onebitwritesymbol(arr []Bvec, sym *Sym) { 1729 var i int 1730 var j int 1731 var word uint32 1732 1733 n := len(arr) 1734 off := 0 1735 off += 4 // number of bitmaps, to fill in later 1736 bv := arr[0] 1737 off = duint32(sym, off, uint32(bv.n)) // number of bits in each bitmap 1738 for i = 0; i < n; i++ { 1739 // bitmap words 1740 bv = arr[i] 1741 1742 if bv.b == nil { 1743 break 1744 } 1745 for j = 0; int32(j) < bv.n; j += 32 { 1746 word = bv.b[j/32] 1747 1748 // Runtime reads the bitmaps as byte arrays. Oblige. 1749 off = duint8(sym, off, uint8(word)) 1750 1751 off = duint8(sym, off, uint8(word>>8)) 1752 off = duint8(sym, off, uint8(word>>16)) 1753 off = duint8(sym, off, uint8(word>>24)) 1754 } 1755 } 1756 1757 duint32(sym, 0, uint32(i)) // number of bitmaps 1758 ggloblsym(sym, int32(off), obj.RODATA) 1759 } 1760 1761 func printprog(p *obj.Prog) { 1762 for p != nil { 1763 fmt.Printf("%v\n", p) 1764 p = p.Link 1765 } 1766 } 1767 1768 // Entry pointer for liveness analysis. Constructs a complete CFG, solves for 1769 // the liveness of pointer variables in the function, and emits a runtime data 1770 // structure read by the garbage collector. 1771 func liveness(fn *Node, firstp *obj.Prog, argssym *Sym, livesym *Sym) { 1772 // Change name to dump debugging information only for a specific function. 1773 debugdelta := 0 1774 1775 if Curfn.Nname.Sym.Name == "!" { 1776 debugdelta = 2 1777 } 1778 1779 debuglive += debugdelta 1780 if debuglive >= 3 { 1781 fmt.Printf("liveness: %s\n", Curfn.Nname.Sym.Name) 1782 printprog(firstp) 1783 } 1784 1785 checkptxt(fn, firstp) 1786 1787 // Construct the global liveness state. 1788 cfg := newcfg(firstp) 1789 1790 if debuglive >= 3 { 1791 printcfg([]*BasicBlock(cfg)) 1792 } 1793 vars := getvariables(fn) 1794 lv := newliveness(fn, firstp, cfg, vars) 1795 1796 // Run the dataflow framework. 1797 livenessprologue(lv) 1798 1799 if debuglive >= 3 { 1800 livenessprintcfg(lv) 1801 } 1802 livenesssolve(lv) 1803 if debuglive >= 3 { 1804 livenessprintcfg(lv) 1805 } 1806 livenessepilogue(lv) 1807 if debuglive >= 3 { 1808 livenessprintcfg(lv) 1809 } 1810 livenesscompact(lv) 1811 1812 if debuglive >= 2 { 1813 livenessprintdebug(lv) 1814 } 1815 1816 // Emit the live pointer map data structures 1817 onebitwritesymbol(lv.livepointers, livesym) 1818 1819 onebitwritesymbol(lv.argslivepointers, argssym) 1820 1821 // Free everything. 1822 for l := fn.Func.Dcl; l != nil; l = l.Next { 1823 if l.N != nil { 1824 l.N.Opt = nil 1825 } 1826 } 1827 freeliveness(lv) 1828 1829 freecfg([]*BasicBlock(cfg)) 1830 1831 debuglive -= debugdelta 1832 }