// 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
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])
}
}
}
// 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++
}
}
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)
// 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)
if ls := e.curfn.Func.lsym; ls != nil {
lv.emit(&ls.Func.GCArgs, &ls.Func.GCLocals)
}
- return lv.stackMapIndex
+ return lv.livenessMap
}
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
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())
// 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