mirror of
https://github.com/golang/go
synced 2024-11-18 10:14:45 -07:00
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: Keith Randall <khr@golang.org>
This commit is contained in:
parent
02495da6b6
commit
d7d9df8a5b
@ -120,14 +120,42 @@ type Liveness struct {
|
|||||||
// Indexed sequentially by safe points in Block and Value order.
|
// Indexed sequentially by safe points in Block and Value order.
|
||||||
livevars []bvec
|
livevars []bvec
|
||||||
|
|
||||||
// stackMapIndex maps from safe points (i.e., CALLs) to their
|
// livenessMap maps from safe points (i.e., CALLs) to their
|
||||||
// index within stackMaps.
|
// liveness map indexes.
|
||||||
stackMapIndex map[*ssa.Value]int
|
//
|
||||||
stackMaps []bvec
|
// TODO(austin): Now that we have liveness at almost every PC,
|
||||||
|
// should this be a dense structure?
|
||||||
|
livenessMap LivenessMap
|
||||||
|
stackMaps []bvec
|
||||||
|
|
||||||
cache progeffectscache
|
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 {
|
type progeffectscache struct {
|
||||||
textavarinit []int32
|
textavarinit []int32
|
||||||
retuevar []int32
|
retuevar []int32
|
||||||
@ -817,10 +845,10 @@ func (lv *Liveness) clobber() {
|
|||||||
before = false
|
before = false
|
||||||
}
|
}
|
||||||
if before {
|
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)
|
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.
|
// These will later become PCDATA instructions.
|
||||||
lv.showlive(nil, lv.stackMaps[0])
|
lv.showlive(nil, lv.stackMaps[0])
|
||||||
pos := 1
|
pos := 1
|
||||||
lv.stackMapIndex = make(map[*ssa.Value]int)
|
lv.livenessMap = LivenessMap{make(map[*ssa.Value]LivenessIndex)}
|
||||||
for _, b := range lv.f.Blocks {
|
for _, b := range lv.f.Blocks {
|
||||||
for _, v := range b.Values {
|
for _, v := range b.Values {
|
||||||
if issafepoint(v) {
|
if issafepoint(v) {
|
||||||
lv.showlive(v, lv.stackMaps[remap[pos]])
|
lv.showlive(v, lv.stackMaps[remap[pos]])
|
||||||
lv.stackMapIndex[v] = remap[pos]
|
lv.livenessMap.m[v] = LivenessIndex{remap[pos]}
|
||||||
pos++
|
pos++
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1153,8 +1181,8 @@ func (lv *Liveness) printDebug() {
|
|||||||
for _, v := range b.Values {
|
for _, v := range b.Values {
|
||||||
fmt.Printf("(%s) %v\n", linestr(v.Pos), v.LongString())
|
fmt.Printf("(%s) %v\n", linestr(v.Pos), v.LongString())
|
||||||
|
|
||||||
if pos, ok := lv.stackMapIndex[v]; ok {
|
if pos := lv.livenessMap.Get(v); pos.Valid() {
|
||||||
pcdata = pos
|
pcdata = pos.stackMapIndex
|
||||||
}
|
}
|
||||||
|
|
||||||
pos, effect := lv.valueEffects(v)
|
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
|
// pointer variables in the function and emits a runtime data
|
||||||
// structure read by the garbage collector.
|
// structure read by the garbage collector.
|
||||||
// Returns a map from GC safe points to their corresponding stack map index.
|
// 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.
|
// Construct the global liveness state.
|
||||||
vars, idx := getvariables(e.curfn)
|
vars, idx := getvariables(e.curfn)
|
||||||
lv := newliveness(e.curfn, f, vars, idx, e.stkptrsize)
|
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 {
|
if ls := e.curfn.Func.lsym; ls != nil {
|
||||||
lv.emit(&ls.Func.GCArgs, &ls.Func.GCLocals)
|
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
|
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.
|
// liveness analysis.
|
||||||
stackMapIndex map[*ssa.Value]int
|
livenessMap LivenessMap
|
||||||
|
|
||||||
// lineRunStart records the beginning of the current run of instructions
|
// lineRunStart records the beginning of the current run of instructions
|
||||||
// within a single block sharing the same line number
|
// within a single block sharing the same line number
|
||||||
@ -4772,7 +4772,7 @@ func genssa(f *ssa.Func, pp *Progs) {
|
|||||||
|
|
||||||
e := f.Frontend().(*ssafn)
|
e := f.Frontend().(*ssafn)
|
||||||
|
|
||||||
s.stackMapIndex = liveness(e, f)
|
s.livenessMap = liveness(e, f)
|
||||||
|
|
||||||
// Remember where each block starts.
|
// Remember where each block starts.
|
||||||
s.bstart = make([]*obj.Prog, f.NumBlocks())
|
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,
|
// 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).
|
// since it emits PCDATA for the stack map at the call (calls are safe points).
|
||||||
func (s *SSAGenState) PrepareCall(v *ssa.Value) {
|
func (s *SSAGenState) PrepareCall(v *ssa.Value) {
|
||||||
idx, ok := s.stackMapIndex[v]
|
idx := s.livenessMap.Get(v)
|
||||||
if !ok {
|
if !idx.Valid() {
|
||||||
Fatalf("missing stack map index for %v", v.LongString())
|
Fatalf("missing stack map index for %v", v.LongString())
|
||||||
}
|
}
|
||||||
p := s.Prog(obj.APCDATA)
|
p := s.Prog(obj.APCDATA)
|
||||||
Addrconst(&p.From, objabi.PCDATA_StackMapIndex)
|
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 {
|
if sym, _ := v.Aux.(*obj.LSym); sym == Deferreturn {
|
||||||
// Deferred calls will appear to be returning to
|
// Deferred calls will appear to be returning to
|
||||||
|
Loading…
Reference in New Issue
Block a user