]> Cypherpunks repositories - gostls13.git/commitdiff
cmd/compile: introduce LivenessMap and LivenessIndex
authorAustin Clements <austin@google.com>
Thu, 22 Mar 2018 16:04:51 +0000 (12:04 -0400)
committerAustin Clements <austin@google.com>
Tue, 22 May 2018 14:43:36 +0000 (14:43 +0000)
Currently liveness only produces a stack map index at each safe point,
so the information is summarized in a map[*ssa.Value]int. We're about
to have both a stack map index and a register map index, so replace
the int with a LivenessIndex type we can extend, and replace the map
with a LivenessMap that we can also change more easily in the future.

This also gives us an easy hook for defining the value that means "not
a safe point".

Passes toolstash -cmp.

For #24543.

Change-Id: Ic4c069839635efed4fd0f603899b80f8be3b56ec
Reviewed-on: https://go-review.googlesource.com/109347
Run-TryBot: Austin Clements <austin@google.com>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Keith Randall <khr@golang.org>
src/cmd/compile/internal/gc/plive.go
src/cmd/compile/internal/gc/ssa.go

index edb205bfb4846f3dc3028abb0810ad8119a0da78..5eca80718c1ba490d00d3e6612ce82ae29036f6c 100644 (file)
@@ -120,14 +120,42 @@ type Liveness struct {
        // Indexed sequentially by safe points in Block and Value order.
        livevars []bvec
 
-       // stackMapIndex maps from safe points (i.e., CALLs) to their
-       // index within stackMaps.
-       stackMapIndex map[*ssa.Value]int
-       stackMaps     []bvec
+       // livenessMap maps from safe points (i.e., CALLs) to their
+       // liveness map indexes.
+       //
+       // TODO(austin): Now that we have liveness at almost every PC,
+       // should this be a dense structure?
+       livenessMap LivenessMap
+       stackMaps   []bvec
 
        cache progeffectscache
 }
 
+// LivenessMap maps from *ssa.Value to LivenessIndex.
+type LivenessMap struct {
+       m map[*ssa.Value]LivenessIndex
+}
+
+func (m LivenessMap) Get(v *ssa.Value) LivenessIndex {
+       if i, ok := m.m[v]; ok {
+               return i
+       }
+       // Not a safe point.
+       return LivenessInvalid
+}
+
+// LivenessIndex stores the liveness map index for a safe-point.
+type LivenessIndex struct {
+       stackMapIndex int
+}
+
+// LivenessInvalid indicates an unsafe point.
+var LivenessInvalid = LivenessIndex{-1}
+
+func (idx LivenessIndex) Valid() bool {
+       return idx.stackMapIndex >= 0
+}
+
 type progeffectscache struct {
        textavarinit []int32
        retuevar     []int32
@@ -817,10 +845,10 @@ func (lv *Liveness) clobber() {
                                before = false
                        }
                        if before {
-                               clobber(lv, b, lv.stackMaps[lv.stackMapIndex[v]])
+                               clobber(lv, b, lv.stackMaps[lv.livenessMap.Get(v).stackMapIndex])
                        }
                        b.Values = append(b.Values, v)
-                       clobber(lv, b, lv.stackMaps[lv.stackMapIndex[v]])
+                       clobber(lv, b, lv.stackMaps[lv.livenessMap.Get(v).stackMapIndex])
                }
        }
 }
@@ -1006,12 +1034,12 @@ Outer:
        // These will later become PCDATA instructions.
        lv.showlive(nil, lv.stackMaps[0])
        pos := 1
-       lv.stackMapIndex = make(map[*ssa.Value]int)
+       lv.livenessMap = LivenessMap{make(map[*ssa.Value]LivenessIndex)}
        for _, b := range lv.f.Blocks {
                for _, v := range b.Values {
                        if issafepoint(v) {
                                lv.showlive(v, lv.stackMaps[remap[pos]])
-                               lv.stackMapIndex[v] = remap[pos]
+                               lv.livenessMap.m[v] = LivenessIndex{remap[pos]}
                                pos++
                        }
                }
@@ -1153,8 +1181,8 @@ func (lv *Liveness) printDebug() {
                for _, v := range b.Values {
                        fmt.Printf("(%s) %v\n", linestr(v.Pos), v.LongString())
 
-                       if pos, ok := lv.stackMapIndex[v]; ok {
-                               pcdata = pos
+                       if pos := lv.livenessMap.Get(v); pos.Valid() {
+                               pcdata = pos.stackMapIndex
                        }
 
                        pos, effect := lv.valueEffects(v)
@@ -1265,7 +1293,7 @@ func (lv *Liveness) emit(argssym, livesym *obj.LSym) {
 // pointer variables in the function and emits a runtime data
 // structure read by the garbage collector.
 // Returns a map from GC safe points to their corresponding stack map index.
-func liveness(e *ssafn, f *ssa.Func) map[*ssa.Value]int {
+func liveness(e *ssafn, f *ssa.Func) LivenessMap {
        // Construct the global liveness state.
        vars, idx := getvariables(e.curfn)
        lv := newliveness(e.curfn, f, vars, idx, e.stkptrsize)
@@ -1284,5 +1312,5 @@ func liveness(e *ssafn, f *ssa.Func) map[*ssa.Value]int {
        if ls := e.curfn.Func.lsym; ls != nil {
                lv.emit(&ls.Func.GCArgs, &ls.Func.GCLocals)
        }
-       return lv.stackMapIndex
+       return lv.livenessMap
 }
index 761066ee5424df76f30068217991f89cc3fca4df..038886c3ff076b3602882a58aaa4eda6a368db8e 100644 (file)
@@ -4694,9 +4694,9 @@ type SSAGenState struct {
 
        maxarg int64 // largest frame size for arguments to calls made by the function
 
-       // Map from GC safe points to stack map index, generated by
+       // Map from GC safe points to liveness index, generated by
        // liveness analysis.
-       stackMapIndex map[*ssa.Value]int
+       livenessMap LivenessMap
 
        // lineRunStart records the beginning of the current run of instructions
        // within a single block sharing the same line number
@@ -4772,7 +4772,7 @@ func genssa(f *ssa.Func, pp *Progs) {
 
        e := f.Frontend().(*ssafn)
 
-       s.stackMapIndex = liveness(e, f)
+       s.livenessMap = liveness(e, f)
 
        // Remember where each block starts.
        s.bstart = make([]*obj.Prog, f.NumBlocks())
@@ -5270,13 +5270,13 @@ func (s *SSAGenState) Call(v *ssa.Value) *obj.Prog {
 // It must be called immediately before emitting the actual CALL instruction,
 // since it emits PCDATA for the stack map at the call (calls are safe points).
 func (s *SSAGenState) PrepareCall(v *ssa.Value) {
-       idx, ok := s.stackMapIndex[v]
-       if !ok {
+       idx := s.livenessMap.Get(v)
+       if !idx.Valid() {
                Fatalf("missing stack map index for %v", v.LongString())
        }
        p := s.Prog(obj.APCDATA)
        Addrconst(&p.From, objabi.PCDATA_StackMapIndex)
-       Addrconst(&p.To, int64(idx))
+       Addrconst(&p.To, int64(idx.stackMapIndex))
 
        if sym, _ := v.Aux.(*obj.LSym); sym == Deferreturn {
                // Deferred calls will appear to be returning to