From e7240ed8868f8c1df9e3421711eb8d0a537c3414 Mon Sep 17 00:00:00 2001 From: Matthew Dempsky Date: Mon, 21 Aug 2023 13:51:21 -0700 Subject: [PATCH] cmd/compile/internal/ssagen: share runtime._defer types Rather than constructing a new runtime._defer struct type at each defer statement, we can use a single shared one. Also, by naming it runtime._defer, we avoid emitting new runtime and DWARF type descriptors in every package that contains a "defer" statement. Shaves ~1kB off cmd/go. Change-Id: I0bd819aec9f856546e684abf620e339a7555e73f Reviewed-on: https://go-review.googlesource.com/c/go/+/521676 Reviewed-by: Keith Randall Auto-Submit: Matthew Dempsky TryBot-Result: Gopher Robot Reviewed-by: Keith Randall Run-TryBot: Matthew Dempsky --- src/cmd/compile/internal/ssagen/ssa.go | 39 +++++++++++++++++--------- 1 file changed, 25 insertions(+), 14 deletions(-) diff --git a/src/cmd/compile/internal/ssagen/ssa.go b/src/cmd/compile/internal/ssagen/ssa.go index 864bd4f9d0..1ce00281b7 100644 --- a/src/cmd/compile/internal/ssagen/ssa.go +++ b/src/cmd/compile/internal/ssagen/ssa.go @@ -87,6 +87,7 @@ func InitConfig() { _ = types.NewPtr(types.Types[types.TINT64]) // *int64 _ = types.NewPtr(types.ErrorType) // *error _ = types.NewPtr(reflectdata.MapType()) // *runtime.hmap + _ = types.NewPtr(deferstruct()) // *runtime._defer types.NewPtrCacheEnabled = false ssaConfig = ssa.NewConfig(base.Ctxt.Arch.Name, *types_, base.Ctxt, base.Flag.N == 0, Arch.SoftFloat) ssaConfig.Race = base.Flag.Race @@ -8094,19 +8095,23 @@ func max8(a, b int8) int8 { return b } +// deferStructFnField is the field index of _defer.fn. const deferStructFnField = 4 -// deferstruct makes a runtime._defer structure. +var deferType *types.Type + +// deferstruct returns a type interchangeable with runtime._defer. +// Make sure this stays in sync with runtime/runtime2.go:_defer. func deferstruct() *types.Type { - makefield := func(name string, typ *types.Type) *types.Field { - // Unlike the global makefield function, this one needs to set Pkg - // because these types might be compared (in SSA CSE sorting). - // TODO: unify this makefield and the global one above. - sym := &types.Sym{Name: name, Pkg: types.LocalPkg} - return types.NewField(src.NoXPos, sym, typ) - } - // These fields must match the ones in runtime/runtime2.go:_defer and - // (*state).call above. + if deferType != nil { + return deferType + } + + makefield := func(name string, t *types.Type) *types.Field { + sym := (*types.Pkg)(nil).Lookup(name) + return types.NewField(src.NoXPos, sym, t) + } + fields := []*types.Field{ makefield("heap", types.Types[types.TBOOL]), makefield("rangefunc", types.Types[types.TBOOL]), @@ -8123,11 +8128,17 @@ func deferstruct() *types.Type { base.Fatalf("deferStructFnField is %q, not fn", name) } + n := ir.NewDeclNameAt(src.NoXPos, ir.OTYPE, ir.Pkgs.Runtime.Lookup("_defer")) + typ := types.NewNamed(n) + n.SetType(typ) + n.SetTypecheck(1) + // build struct holding the above fields - s := types.NewStruct(fields) - s.SetNoalg(true) - types.CalcStructSize(s) - return s + typ.SetUnderlying(types.NewStruct(fields)) + types.CalcStructSize(typ) + + deferType = typ + return typ } // SpillSlotAddr uses LocalSlot information to initialize an obj.Addr -- 2.48.1