Skip to content

Commit

Permalink
cmd/compile: do not emit a few more basic types from every compilation
Browse files Browse the repository at this point in the history
We already emit types for any and func(error) string in runtime.a
but unlike the other pre-emitted types, we don't then exclude them
from being emitted in other packages. Fix that.

Also add slices of non-func types that we already emit.

Saves 0.3% of .a files in std cmd deps, computed by adding sizes from:

	ls -l $(go list -export -f '{{.Export}}' -deps std cmd

The effect is small and not worth doing on its own.
The real improvement is making “what to write always in runtime”
and “what not to write in other packages” more obviously aligned.

Change-Id: Ie5cb5fd7e5a3025d2776d9b4cece775fdf92d3b6
Reviewed-on: https://go-review.googlesource.com/c/go/+/450135
Reviewed-by: Keith Randall <[email protected]>
Run-TryBot: Russ Cox <[email protected]>
TryBot-Result: Gopher Robot <[email protected]>
Auto-Submit: Russ Cox <[email protected]>
Reviewed-by: Cuong Manh Le <[email protected]>
Reviewed-by: Keith Randall <[email protected]>
  • Loading branch information
rsc authored and gopherbot committed Nov 16, 2022
1 parent c085c6c commit cb5534c
Show file tree
Hide file tree
Showing 2 changed files with 52 additions and 15 deletions.
64 changes: 49 additions & 15 deletions src/cmd/compile/internal/reflectdata/reflect.go
Original file line number Diff line number Diff line change
Expand Up @@ -1395,30 +1395,66 @@ func WriteImportStrings() {
}
}

// writtenByWriteBasicTypes reports whether typ is written by WriteBasicTypes.
// WriteBasicTypes always writes pointer types; any pointer has been stripped off typ already.
func writtenByWriteBasicTypes(typ *types.Type) bool {
if typ.Sym() == nil && typ.Kind() == types.TFUNC {
f := typ.FuncType()
// func(error) string
if f.Receiver.NumFields() == 0 && f.TParams.NumFields() == 0 &&
f.Params.NumFields() == 1 && f.Results.NumFields() == 1 &&
f.Params.FieldType(0) == types.ErrorType &&
f.Results.FieldType(0) == types.Types[types.TSTRING] {
return true
}
}

// Now we have left the basic types plus any and error, plus slices of them.
// Strip the slice.
if typ.Sym() == nil && typ.IsSlice() {
typ = typ.Elem()
}

// Basic types.
sym := typ.Sym()
if sym != nil && (sym.Pkg == types.BuiltinPkg || sym.Pkg == types.UnsafePkg) {
return true
}
// any or error
return (sym == nil && typ.IsEmptyInterface()) || typ == types.ErrorType
}

func WriteBasicTypes() {
// do basic types if compiling package runtime.
// they have to be in at least one package,
// and runtime is always loaded implicitly,
// so this is as good as any.
// another possible choice would be package main,
// but using runtime means fewer copies in object files.
// The code here needs to be in sync with writtenByWriteBasicTypes above.
if base.Ctxt.Pkgpath == "runtime" {
// Note: always write NewPtr(t) because NeedEmit's caller strips the pointer.
var list []*types.Type
for i := types.Kind(1); i <= types.TBOOL; i++ {
writeType(types.NewPtr(types.Types[i]))
list = append(list, types.Types[i])
}
list = append(list,
types.Types[types.TSTRING],
types.Types[types.TUNSAFEPTR],
types.AnyType,
types.ErrorType)
for _, t := range list {
writeType(types.NewPtr(t))
writeType(types.NewPtr(types.NewSlice(t)))
}
writeType(types.NewPtr(types.Types[types.TSTRING]))
writeType(types.NewPtr(types.Types[types.TUNSAFEPTR]))
writeType(types.AnyType)

// emit type structs for error and func(error) string.
// The latter is the type of an auto-generated wrapper.
writeType(types.NewPtr(types.ErrorType))

writeType(types.NewSignature(types.NoPkg, nil, nil, []*types.Field{
// emit type for func(error) string,
// which is the type of an auto-generated wrapper.
writeType(types.NewPtr(types.NewSignature(types.NoPkg, nil, nil, []*types.Field{
types.NewField(base.Pos, nil, types.ErrorType),
}, []*types.Field{
types.NewField(base.Pos, nil, types.Types[types.TSTRING]),
}))
})))

// add paths for runtime and main, which 6l imports implicitly.
dimportpath(ir.Pkgs.Runtime)
Expand Down Expand Up @@ -1759,6 +1795,9 @@ func NeedEmit(typ *types.Type) bool {
// instantiated generic functions too.

switch sym := typ.Sym(); {
case writtenByWriteBasicTypes(typ):
return base.Ctxt.Pkgpath == "runtime"

case sym == nil:
// Anonymous type; possibly never seen before or ever again.
// Need to emit to be safe (however, see TODO above).
Expand All @@ -1768,11 +1807,6 @@ func NeedEmit(typ *types.Type) bool {
// Local defined type; our responsibility.
return true

case base.Ctxt.Pkgpath == "runtime" && (sym.Pkg == types.BuiltinPkg || sym.Pkg == types.UnsafePkg):
// Package runtime is responsible for including code for builtin
// types (predeclared and package unsafe).
return true

case typ.IsFullyInstantiated():
// Instantiated type; possibly instantiated with unique type arguments.
// Need to emit to be safe (however, see TODO above).
Expand Down
3 changes: 3 additions & 0 deletions src/cmd/link/internal/ld/dwarf.go
Original file line number Diff line number Diff line change
Expand Up @@ -539,6 +539,9 @@ func (d *dwctxt) newtype(gotype loader.Sym) *dwarf.DWDie {
sn := d.ldr.SymName(gotype)
name := sn[5:] // could also decode from Type.string
tdata := d.ldr.Data(gotype)
if len(tdata) == 0 {
d.linkctxt.Errorf(gotype, "missing type")
}
kind := decodetypeKind(d.arch, tdata)
bytesize := decodetypeSize(d.arch, tdata)

Expand Down

0 comments on commit cb5534c

Please sign in to comment.