Commit d7d9df8a authored by Austin Clements's avatar Austin Clements

cmd/compile: introduce LivenessMap and LivenessIndex

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: 's avatarKeith Randall <khr@golang.org>
parent 02495da6
......@@ -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
}
......@@ -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
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment