mirror of
https://github.com/golang/go
synced 2024-11-07 06:16:19 -07:00
[dev.link] cmd/link: assign special indices for builtin functions
Compiler-generated function references (e.g. call to runtime.newobject) appear frequently. We assign special indices for them, so they don't need to be referenced by name. Change-Id: I2072594cbc56c9e1037a26e4aae12e68c2436e9f Reviewed-on: https://go-review.googlesource.com/c/go/+/202085 Run-TryBot: Cherry Zhang <cherryyz@google.com> TryBot-Result: Gobot Gobot <gobot@golang.org> Reviewed-by: Jeremy Faller <jeremy@golang.org>
This commit is contained in:
parent
df01b7968b
commit
fb06609817
@ -49,7 +49,8 @@ func (r *objReader) readNew() {
|
||||
case goobj2.PkgIdxNone:
|
||||
i = int(s.SymIdx) + rr.NSym()
|
||||
case goobj2.PkgIdxBuiltin:
|
||||
panic("PkgIdxBuiltin is unused")
|
||||
name, abi := goobj2.BuiltinName(int(s.SymIdx))
|
||||
return SymID{name, int64(abi)}
|
||||
case goobj2.PkgIdxSelf:
|
||||
i = int(s.SymIdx)
|
||||
default:
|
||||
|
45
src/cmd/internal/goobj2/builtin.go
Normal file
45
src/cmd/internal/goobj2/builtin.go
Normal file
@ -0,0 +1,45 @@
|
||||
// Copyright 2019 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package goobj2
|
||||
|
||||
// Builtin (compiler-generated) function references appear
|
||||
// frequently. We assign special indices for them, so they
|
||||
// don't need to be referenced by name.
|
||||
|
||||
// NBuiltin returns the number of listed builtin
|
||||
// symbols.
|
||||
func NBuiltin() int {
|
||||
return len(builtins)
|
||||
}
|
||||
|
||||
// BuiltinName returns the name and ABI of the i-th
|
||||
// builtin symbol.
|
||||
func BuiltinName(i int) (string, int) {
|
||||
return builtins[i].name, builtins[i].abi
|
||||
}
|
||||
|
||||
// BuiltinIdx returns the index of the builtin with the
|
||||
// given name and abi, or -1 if it is not a builtin.
|
||||
func BuiltinIdx(name string, abi int) int {
|
||||
i, ok := builtinMap[name]
|
||||
if !ok {
|
||||
return -1
|
||||
}
|
||||
if builtins[i].abi != abi {
|
||||
return -1
|
||||
}
|
||||
return i
|
||||
}
|
||||
|
||||
//go:generate go run mkbuiltin.go
|
||||
|
||||
var builtinMap map[string]int
|
||||
|
||||
func init() {
|
||||
builtinMap = make(map[string]int, len(builtins))
|
||||
for i, b := range builtins {
|
||||
builtinMap[b.name] = i
|
||||
}
|
||||
}
|
194
src/cmd/internal/goobj2/builtinlist.go
Normal file
194
src/cmd/internal/goobj2/builtinlist.go
Normal file
@ -0,0 +1,194 @@
|
||||
// Code generated by mkbuiltin.go. DO NOT EDIT.
|
||||
|
||||
package goobj2
|
||||
|
||||
var builtins = [...]struct {
|
||||
name string
|
||||
abi int
|
||||
}{
|
||||
{"runtime.newobject", 1},
|
||||
{"runtime.panicdivide", 1},
|
||||
{"runtime.panicshift", 1},
|
||||
{"runtime.panicmakeslicelen", 1},
|
||||
{"runtime.throwinit", 1},
|
||||
{"runtime.panicwrap", 1},
|
||||
{"runtime.gopanic", 1},
|
||||
{"runtime.gorecover", 1},
|
||||
{"runtime.goschedguarded", 1},
|
||||
{"runtime.goPanicIndex", 1},
|
||||
{"runtime.goPanicIndexU", 1},
|
||||
{"runtime.goPanicSliceAlen", 1},
|
||||
{"runtime.goPanicSliceAlenU", 1},
|
||||
{"runtime.goPanicSliceAcap", 1},
|
||||
{"runtime.goPanicSliceAcapU", 1},
|
||||
{"runtime.goPanicSliceB", 1},
|
||||
{"runtime.goPanicSliceBU", 1},
|
||||
{"runtime.goPanicSlice3Alen", 1},
|
||||
{"runtime.goPanicSlice3AlenU", 1},
|
||||
{"runtime.goPanicSlice3Acap", 1},
|
||||
{"runtime.goPanicSlice3AcapU", 1},
|
||||
{"runtime.goPanicSlice3B", 1},
|
||||
{"runtime.goPanicSlice3BU", 1},
|
||||
{"runtime.goPanicSlice3C", 1},
|
||||
{"runtime.goPanicSlice3CU", 1},
|
||||
{"runtime.printbool", 1},
|
||||
{"runtime.printfloat", 1},
|
||||
{"runtime.printint", 1},
|
||||
{"runtime.printhex", 1},
|
||||
{"runtime.printuint", 1},
|
||||
{"runtime.printcomplex", 1},
|
||||
{"runtime.printstring", 1},
|
||||
{"runtime.printpointer", 1},
|
||||
{"runtime.printiface", 1},
|
||||
{"runtime.printeface", 1},
|
||||
{"runtime.printslice", 1},
|
||||
{"runtime.printnl", 1},
|
||||
{"runtime.printsp", 1},
|
||||
{"runtime.printlock", 1},
|
||||
{"runtime.printunlock", 1},
|
||||
{"runtime.concatstring2", 1},
|
||||
{"runtime.concatstring3", 1},
|
||||
{"runtime.concatstring4", 1},
|
||||
{"runtime.concatstring5", 1},
|
||||
{"runtime.concatstrings", 1},
|
||||
{"runtime.cmpstring", 1},
|
||||
{"runtime.intstring", 1},
|
||||
{"runtime.slicebytetostring", 1},
|
||||
{"runtime.slicebytetostringtmp", 1},
|
||||
{"runtime.slicerunetostring", 1},
|
||||
{"runtime.stringtoslicebyte", 1},
|
||||
{"runtime.stringtoslicerune", 1},
|
||||
{"runtime.slicecopy", 1},
|
||||
{"runtime.slicestringcopy", 1},
|
||||
{"runtime.decoderune", 1},
|
||||
{"runtime.countrunes", 1},
|
||||
{"runtime.convI2I", 1},
|
||||
{"runtime.convT16", 1},
|
||||
{"runtime.convT32", 1},
|
||||
{"runtime.convT64", 1},
|
||||
{"runtime.convTstring", 1},
|
||||
{"runtime.convTslice", 1},
|
||||
{"runtime.convT2E", 1},
|
||||
{"runtime.convT2Enoptr", 1},
|
||||
{"runtime.convT2I", 1},
|
||||
{"runtime.convT2Inoptr", 1},
|
||||
{"runtime.assertE2I", 1},
|
||||
{"runtime.assertE2I2", 1},
|
||||
{"runtime.assertI2I", 1},
|
||||
{"runtime.assertI2I2", 1},
|
||||
{"runtime.panicdottypeE", 1},
|
||||
{"runtime.panicdottypeI", 1},
|
||||
{"runtime.panicnildottype", 1},
|
||||
{"runtime.ifaceeq", 1},
|
||||
{"runtime.efaceeq", 1},
|
||||
{"runtime.fastrand", 1},
|
||||
{"runtime.makemap64", 1},
|
||||
{"runtime.makemap", 1},
|
||||
{"runtime.makemap_small", 1},
|
||||
{"runtime.mapaccess1", 1},
|
||||
{"runtime.mapaccess1_fast32", 1},
|
||||
{"runtime.mapaccess1_fast64", 1},
|
||||
{"runtime.mapaccess1_faststr", 1},
|
||||
{"runtime.mapaccess1_fat", 1},
|
||||
{"runtime.mapaccess2", 1},
|
||||
{"runtime.mapaccess2_fast32", 1},
|
||||
{"runtime.mapaccess2_fast64", 1},
|
||||
{"runtime.mapaccess2_faststr", 1},
|
||||
{"runtime.mapaccess2_fat", 1},
|
||||
{"runtime.mapassign", 1},
|
||||
{"runtime.mapassign_fast32", 1},
|
||||
{"runtime.mapassign_fast32ptr", 1},
|
||||
{"runtime.mapassign_fast64", 1},
|
||||
{"runtime.mapassign_fast64ptr", 1},
|
||||
{"runtime.mapassign_faststr", 1},
|
||||
{"runtime.mapiterinit", 1},
|
||||
{"runtime.mapdelete", 1},
|
||||
{"runtime.mapdelete_fast32", 1},
|
||||
{"runtime.mapdelete_fast64", 1},
|
||||
{"runtime.mapdelete_faststr", 1},
|
||||
{"runtime.mapiternext", 1},
|
||||
{"runtime.mapclear", 1},
|
||||
{"runtime.makechan64", 1},
|
||||
{"runtime.makechan", 1},
|
||||
{"runtime.chanrecv1", 1},
|
||||
{"runtime.chanrecv2", 1},
|
||||
{"runtime.chansend1", 1},
|
||||
{"runtime.closechan", 1},
|
||||
{"runtime.writeBarrier", 0},
|
||||
{"runtime.typedmemmove", 1},
|
||||
{"runtime.typedmemclr", 1},
|
||||
{"runtime.typedslicecopy", 1},
|
||||
{"runtime.selectnbsend", 1},
|
||||
{"runtime.selectnbrecv", 1},
|
||||
{"runtime.selectnbrecv2", 1},
|
||||
{"runtime.selectsetpc", 1},
|
||||
{"runtime.selectgo", 1},
|
||||
{"runtime.block", 1},
|
||||
{"runtime.makeslice", 1},
|
||||
{"runtime.makeslice64", 1},
|
||||
{"runtime.growslice", 1},
|
||||
{"runtime.memmove", 1},
|
||||
{"runtime.memclrNoHeapPointers", 1},
|
||||
{"runtime.memclrHasPointers", 1},
|
||||
{"runtime.memequal", 1},
|
||||
{"runtime.memequal0", 1},
|
||||
{"runtime.memequal8", 1},
|
||||
{"runtime.memequal16", 1},
|
||||
{"runtime.memequal32", 1},
|
||||
{"runtime.memequal64", 1},
|
||||
{"runtime.memequal128", 1},
|
||||
{"runtime.f32equal", 1},
|
||||
{"runtime.f64equal", 1},
|
||||
{"runtime.c64equal", 1},
|
||||
{"runtime.c128equal", 1},
|
||||
{"runtime.strequal", 1},
|
||||
{"runtime.interequal", 1},
|
||||
{"runtime.nilinterequal", 1},
|
||||
{"runtime.memhash", 1},
|
||||
{"runtime.memhash0", 1},
|
||||
{"runtime.memhash8", 1},
|
||||
{"runtime.memhash16", 1},
|
||||
{"runtime.memhash32", 1},
|
||||
{"runtime.memhash64", 1},
|
||||
{"runtime.memhash128", 1},
|
||||
{"runtime.f32hash", 1},
|
||||
{"runtime.f64hash", 1},
|
||||
{"runtime.c64hash", 1},
|
||||
{"runtime.c128hash", 1},
|
||||
{"runtime.strhash", 1},
|
||||
{"runtime.interhash", 1},
|
||||
{"runtime.nilinterhash", 1},
|
||||
{"runtime.int64div", 1},
|
||||
{"runtime.uint64div", 1},
|
||||
{"runtime.int64mod", 1},
|
||||
{"runtime.uint64mod", 1},
|
||||
{"runtime.float64toint64", 1},
|
||||
{"runtime.float64touint64", 1},
|
||||
{"runtime.float64touint32", 1},
|
||||
{"runtime.int64tofloat64", 1},
|
||||
{"runtime.uint64tofloat64", 1},
|
||||
{"runtime.uint32tofloat64", 1},
|
||||
{"runtime.complex128div", 1},
|
||||
{"runtime.racefuncenter", 1},
|
||||
{"runtime.racefuncenterfp", 1},
|
||||
{"runtime.racefuncexit", 1},
|
||||
{"runtime.raceread", 1},
|
||||
{"runtime.racewrite", 1},
|
||||
{"runtime.racereadrange", 1},
|
||||
{"runtime.racewriterange", 1},
|
||||
{"runtime.msanread", 1},
|
||||
{"runtime.msanwrite", 1},
|
||||
{"runtime.checkptrAlignment", 1},
|
||||
{"runtime.checkptrArithmetic", 1},
|
||||
{"runtime.x86HasPOPCNT", 0},
|
||||
{"runtime.x86HasSSE41", 0},
|
||||
{"runtime.arm64HasATOMICS", 0},
|
||||
{"runtime.gcWriteBarrier", 0},
|
||||
{"runtime.deferproc", 1},
|
||||
{"runtime.deferprocStack", 1},
|
||||
{"runtime.deferreturn", 1},
|
||||
{"runtime.newproc", 1},
|
||||
{"runtime.morestack", 0},
|
||||
{"runtime.morestackc", 0},
|
||||
{"runtime.morestack_noctxt", 0},
|
||||
}
|
124
src/cmd/internal/goobj2/mkbuiltin.go
Normal file
124
src/cmd/internal/goobj2/mkbuiltin.go
Normal file
@ -0,0 +1,124 @@
|
||||
// Copyright 2019 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
// +build ignore
|
||||
|
||||
// Generate builtinlist.go from cmd/compile/internal/gc/builtin/runtime.go.
|
||||
|
||||
package main
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"flag"
|
||||
"fmt"
|
||||
"go/ast"
|
||||
"go/format"
|
||||
"go/parser"
|
||||
"go/token"
|
||||
"io"
|
||||
"io/ioutil"
|
||||
"log"
|
||||
"os"
|
||||
"path/filepath"
|
||||
)
|
||||
|
||||
var stdout = flag.Bool("stdout", false, "write to stdout instead of builtinlist.go")
|
||||
|
||||
func main() {
|
||||
flag.Parse()
|
||||
|
||||
var b bytes.Buffer
|
||||
fmt.Fprintln(&b, "// Code generated by mkbuiltin.go. DO NOT EDIT.")
|
||||
fmt.Fprintln(&b)
|
||||
fmt.Fprintln(&b, "package goobj2")
|
||||
|
||||
mkbuiltin(&b)
|
||||
|
||||
out, err := format.Source(b.Bytes())
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
if *stdout {
|
||||
_, err = os.Stdout.Write(out)
|
||||
} else {
|
||||
err = ioutil.WriteFile("builtinlist.go", out, 0666)
|
||||
}
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
}
|
||||
|
||||
func mkbuiltin(w io.Writer) {
|
||||
pkg := "runtime"
|
||||
fset := token.NewFileSet()
|
||||
path := filepath.Join("..", "..", "compile", "internal", "gc", "builtin", "runtime.go")
|
||||
f, err := parser.ParseFile(fset, path, nil, 0)
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
|
||||
decls := make(map[string]bool)
|
||||
|
||||
fmt.Fprintf(w, "var builtins = [...]struct{ name string; abi int }{\n")
|
||||
for _, decl := range f.Decls {
|
||||
switch decl := decl.(type) {
|
||||
case *ast.FuncDecl:
|
||||
if decl.Recv != nil {
|
||||
log.Fatal("methods unsupported")
|
||||
}
|
||||
if decl.Body != nil {
|
||||
log.Fatal("unexpected function body")
|
||||
}
|
||||
declName := pkg + "." + decl.Name.Name
|
||||
decls[declName] = true
|
||||
fmt.Fprintf(w, "{%q, 1},\n", declName) // functions are ABIInternal (1)
|
||||
case *ast.GenDecl:
|
||||
if decl.Tok == token.IMPORT {
|
||||
continue
|
||||
}
|
||||
if decl.Tok != token.VAR {
|
||||
log.Fatal("unhandled declaration kind", decl.Tok)
|
||||
}
|
||||
for _, spec := range decl.Specs {
|
||||
spec := spec.(*ast.ValueSpec)
|
||||
if len(spec.Values) != 0 {
|
||||
log.Fatal("unexpected values")
|
||||
}
|
||||
for _, name := range spec.Names {
|
||||
declName := pkg + "." + name.Name
|
||||
decls[declName] = true
|
||||
fmt.Fprintf(w, "{%q, 0},\n", declName) // variables are ABI0
|
||||
}
|
||||
}
|
||||
default:
|
||||
log.Fatal("unhandled decl type", decl)
|
||||
}
|
||||
}
|
||||
|
||||
// The list above only contains ones that are used by the frontend.
|
||||
// The backend may create more references of builtin functions.
|
||||
// Add them.
|
||||
for _, b := range extra {
|
||||
name := pkg + "." + b.name
|
||||
if decls[name] {
|
||||
log.Fatalf("%q already added -- mkbuiltin.go out of sync?", name)
|
||||
}
|
||||
fmt.Fprintf(w, "{%q, %d},\n", name, b.abi)
|
||||
}
|
||||
fmt.Fprintln(w, "}")
|
||||
}
|
||||
|
||||
var extra = [...]struct {
|
||||
name string
|
||||
abi int
|
||||
}{
|
||||
{"gcWriteBarrier", 0}, // asm function, ABI0
|
||||
{"deferproc", 1},
|
||||
{"deferprocStack", 1},
|
||||
{"deferreturn", 1},
|
||||
{"newproc", 1},
|
||||
{"morestack", 0}, // asm function, ABI0
|
||||
{"morestackc", 0}, // asm function, ABI0
|
||||
{"morestack_noctxt", 0}, // asm function, ABI0
|
||||
}
|
@ -210,6 +210,17 @@ func (ctxt *Link) NumberSyms(asm bool) {
|
||||
if rs.PkgIdx != goobj2.PkgIdxInvalid {
|
||||
return
|
||||
}
|
||||
if !ctxt.Flag_linkshared {
|
||||
// Assign special index for builtin symbols.
|
||||
// Don't do it when linking against shared libraries, as the runtime
|
||||
// may be in a different library.
|
||||
if i := goobj2.BuiltinIdx(rs.Name, int(rs.ABI())); i != -1 {
|
||||
rs.PkgIdx = goobj2.PkgIdxBuiltin
|
||||
rs.SymIdx = int32(i)
|
||||
rs.Set(AttrIndexed, true)
|
||||
return
|
||||
}
|
||||
}
|
||||
pkg := rs.Pkg
|
||||
if pkg == "" || pkg == "\"\"" || pkg == "_" || !rs.Indexed() {
|
||||
rs.PkgIdx = goobj2.PkgIdxNone
|
||||
|
@ -91,11 +91,12 @@ func makeBitmap(n int) bitmap {
|
||||
|
||||
// A Loader loads new object files and resolves indexed symbol references.
|
||||
type Loader struct {
|
||||
start map[*oReader]Sym // map from object file to its start index
|
||||
objs []objIdx // sorted by start index (i.e. objIdx.i)
|
||||
max Sym // current max index
|
||||
extStart Sym // from this index on, the symbols are externally defined
|
||||
extSyms []nameVer // externally defined symbols
|
||||
start map[*oReader]Sym // map from object file to its start index
|
||||
objs []objIdx // sorted by start index (i.e. objIdx.i)
|
||||
max Sym // current max index
|
||||
extStart Sym // from this index on, the symbols are externally defined
|
||||
extSyms []nameVer // externally defined symbols
|
||||
builtinSyms []Sym // global index of builtin symbols
|
||||
|
||||
symsByName [2]map[string]Sym // map symbol name to index, two maps are for ABI0 and ABIInternal
|
||||
extStaticSyms map[nameVer]Sym // externally defined static symbols, keyed by name
|
||||
@ -111,6 +112,7 @@ type Loader struct {
|
||||
}
|
||||
|
||||
func NewLoader() *Loader {
|
||||
nbuiltin := goobj2.NBuiltin()
|
||||
return &Loader{
|
||||
start: make(map[*oReader]Sym),
|
||||
objs: []objIdx{{nil, 0}},
|
||||
@ -119,6 +121,7 @@ func NewLoader() *Loader {
|
||||
overwrite: make(map[Sym]Sym),
|
||||
itablink: make(map[Sym]struct{}),
|
||||
extStaticSyms: make(map[nameVer]Sym),
|
||||
builtinSyms: make([]Sym, nbuiltin),
|
||||
}
|
||||
}
|
||||
|
||||
@ -272,7 +275,7 @@ func (l *Loader) resolve(r *oReader, s goobj2.SymRef) Sym {
|
||||
v := abiToVer(osym.ABI, r.version)
|
||||
return l.Lookup(name, v)
|
||||
case goobj2.PkgIdxBuiltin:
|
||||
panic("PkgIdxBuiltin not used")
|
||||
return l.builtinSyms[s.SymIdx]
|
||||
case goobj2.PkgIdxSelf:
|
||||
rr = r
|
||||
default:
|
||||
@ -575,6 +578,12 @@ func (l *Loader) Preload(arch *sys.Arch, syms *sym.Symbols, f *bio.Reader, lib *
|
||||
if added && strings.HasPrefix(name, "go.itablink.") {
|
||||
l.itablink[istart+Sym(i)] = struct{}{}
|
||||
}
|
||||
if added && strings.HasPrefix(name, "runtime.") {
|
||||
if bi := goobj2.BuiltinIdx(name, v); bi != -1 {
|
||||
// This is a definition of a builtin symbol. Record where it is.
|
||||
l.builtinSyms[bi] = istart + Sym(i)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// The caller expects us consuming all the data
|
||||
|
Loading…
Reference in New Issue
Block a user