From ed7a0682e2aa8305f2bea9f2a1b6eb4721291a0a Mon Sep 17 00:00:00 2001 From: Austin Clements Date: Tue, 27 Mar 2018 16:11:10 -0400 Subject: [PATCH] cmd/compile: output stack map index everywhere it changes MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Currently, the code generator only considers outputting stack map indexes at CALL instructions. Raise this into the code generator loop itself so that changes in the stack map index at any instruction emit a PCDATA Prog before the actual instruction. We'll optimize this in later CLs: name old time/op new time/op delta Template 190ms ± 2% 191ms ± 2% ~ (p=0.529 n=10+10) Unicode 96.4ms ± 1% 98.5ms ± 3% +2.18% (p=0.001 n=9+10) GoTypes 669ms ± 1% 673ms ± 1% +0.62% (p=0.004 n=9+9) Compiler 3.18s ± 1% 3.22s ± 1% +1.06% (p=0.000 n=10+9) SSA 7.59s ± 1% 7.64s ± 1% +0.66% (p=0.023 n=10+10) Flate 128ms ± 1% 130ms ± 2% +1.07% (p=0.043 n=10+10) GoParser 157ms ± 2% 158ms ± 3% ~ (p=0.123 n=10+10) Reflect 442ms ± 1% 445ms ± 1% +0.73% (p=0.017 n=10+9) Tar 179ms ± 1% 180ms ± 1% +0.58% (p=0.019 n=9+9) XML 229ms ± 1% 232ms ± 2% +1.27% (p=0.009 n=10+10) [Geo mean] 401ms 405ms +0.94% name old exe-bytes new exe-bytes delta HelloSize 1.46M ± 0% 1.47M ± 0% +0.84% (p=0.000 n=10+10) [Geo mean] 1.46M 1.47M +0.84% For #24543. Change-Id: I4bfe45b767c9d9db47308a27763b303fa75bfa54 Reviewed-on: https://go-review.googlesource.com/109350 Run-TryBot: Austin Clements TryBot-Result: Gobot Gobot Reviewed-by: Keith Randall --- src/cmd/compile/internal/gc/gsubr.go | 14 ++++++++++++++ src/cmd/compile/internal/gc/plive.go | 8 +++++++- src/cmd/compile/internal/gc/ssa.go | 9 +++++---- 3 files changed, 26 insertions(+), 5 deletions(-) diff --git a/src/cmd/compile/internal/gc/gsubr.go b/src/cmd/compile/internal/gc/gsubr.go index 55b16792f97..70b5cd3366d 100644 --- a/src/cmd/compile/internal/gc/gsubr.go +++ b/src/cmd/compile/internal/gc/gsubr.go @@ -49,6 +49,9 @@ type Progs struct { curfn *Node // fn these Progs are for progcache []obj.Prog // local progcache cacheidx int // first free element of progcache + + nextLive LivenessIndex // liveness index for the next Prog + prevLive LivenessIndex // last emitted liveness index } // newProgs returns a new Progs for fn. @@ -67,6 +70,8 @@ func newProgs(fn *Node, worker int) *Progs { pp.pos = fn.Pos pp.settext(fn) + pp.nextLive = LivenessInvalid + pp.prevLive = LivenessInvalid return pp } @@ -103,6 +108,15 @@ func (pp *Progs) Free() { // Prog adds a Prog with instruction As to pp. func (pp *Progs) Prog(as obj.As) *obj.Prog { + if pp.nextLive.stackMapIndex != pp.prevLive.stackMapIndex { + // Emit stack map index change. + idx := pp.nextLive.stackMapIndex + pp.prevLive.stackMapIndex = idx + p := pp.Prog(obj.APCDATA) + Addrconst(&p.From, objabi.PCDATA_StackMapIndex) + Addrconst(&p.To, int64(idx)) + } + p := pp.next pp.next = pp.NewProg() pp.clearp(pp.next) diff --git a/src/cmd/compile/internal/gc/plive.go b/src/cmd/compile/internal/gc/plive.go index 456a2f76522..7a953546dcf 100644 --- a/src/cmd/compile/internal/gc/plive.go +++ b/src/cmd/compile/internal/gc/plive.go @@ -153,7 +153,13 @@ type LivenessIndex struct { } // LivenessInvalid indicates an unsafe point. -var LivenessInvalid = LivenessIndex{-1} +// +// We use index -2 because PCDATA tables conventionally start at -1, +// so -1 is used to mean the entry liveness map (which is actually at +// index 0; sigh). TODO(austin): Maybe we should use PCDATA+1 as the +// index into the liveness map so -1 uniquely refers to the entry +// liveness map. +var LivenessInvalid = LivenessIndex{-2} func (idx LivenessIndex) Valid() bool { return idx.stackMapIndex >= 0 diff --git a/src/cmd/compile/internal/gc/ssa.go b/src/cmd/compile/internal/gc/ssa.go index 09d12cba1ef..b280fb73974 100644 --- a/src/cmd/compile/internal/gc/ssa.go +++ b/src/cmd/compile/internal/gc/ssa.go @@ -15,7 +15,6 @@ import ( "cmd/compile/internal/ssa" "cmd/compile/internal/types" "cmd/internal/obj" - "cmd/internal/objabi" "cmd/internal/src" "cmd/internal/sys" ) @@ -4818,12 +4817,17 @@ func genssa(f *ssa.Func, pp *Progs) { // Emit basic blocks for i, b := range f.Blocks { s.bstart[b.ID] = s.pp.next + s.pp.nextLive = LivenessInvalid s.lineRunStart = nil + // Emit values in block thearch.SSAMarkMoves(&s, b) for _, v := range b.Values { x := s.pp.next s.DebugFriendlySetPosFrom(v) + // Attach this safe point to the next + // instruction. + s.pp.nextLive = s.livenessMap.Get(v) switch v.Op { case ssa.OpInitMem: // memory arg needs no code @@ -5279,9 +5283,6 @@ func (s *SSAGenState) PrepareCall(v *ssa.Value) { 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.stackMapIndex)) if sym, _ := v.Aux.(*obj.LSym); sym == Deferreturn { // Deferred calls will appear to be returning to