aboutsummaryrefslogtreecommitdiff
path: root/src/cmd/link
diff options
context:
space:
mode:
authorMichael Pratt <mpratt@google.com>2022-09-07 13:23:19 -0400
committerGopher Robot <gobot@golang.org>2022-10-14 14:47:12 +0000
commitf2656f20ea420ada5f15ef06ddf18d2797e18841 (patch)
treeca71ed64eec8c6027dc5f88af83c4509076adb05 /src/cmd/link
parenta4b4717f23334547f40f90f1457f3dc086259fa3 (diff)
downloadgo-f2656f20ea420ada5f15ef06ddf18d2797e18841.tar.xz
cmd/compile,cmd/link,runtime: add start line numbers to func metadata
This adds the function "start line number" to runtime._func and runtime.inlinedCall objects. The "start line number" is the line number of the func keyword or TEXT directive for assembly. Subtracting the start line number from PC line number provides the relative line offset of a PC from the the start of the function. This helps with source stability by allowing code above the function to move without invalidating samples within the function. Encoding start line rather than relative lines directly is convenient because the pprof format already contains a start line field. This CL uses a straightforward encoding of explictly including a start line field in every _func and inlinedCall. It is possible that we could compress this further in the future. e.g., functions with a prologue usually have <line of PC 0> == <start line>. In runtime.test, 95% of functions have <line of PC 0> == <start line>. According to bent, this is geomean +0.83% binary size vs master and -0.31% binary size vs 1.19. Note that //line directives can change the file and line numbers arbitrarily. The encoded start line is as adjusted by //line directives. Since this can change in the middle of a function, `line - start line` offset calculations may not be meaningful if //line directives are in use. For #55022. Change-Id: Iaabbc6dd4f85ffdda294266ef982ae838cc692f6 Reviewed-on: https://go-review.googlesource.com/c/go/+/429638 Run-TryBot: Michael Pratt <mpratt@google.com> Auto-Submit: Michael Pratt <mpratt@google.com> Reviewed-by: Matthew Dempsky <mdempsky@google.com> TryBot-Result: Gopher Robot <gobot@golang.org> Reviewed-by: Cherry Mui <cherryyz@google.com>
Diffstat (limited to 'src/cmd/link')
-rw-r--r--src/cmd/link/internal/ld/pcln.go12
-rw-r--r--src/cmd/link/internal/loader/loader.go4
2 files changed, 14 insertions, 2 deletions
diff --git a/src/cmd/link/internal/ld/pcln.go b/src/cmd/link/internal/ld/pcln.go
index 2f13a24e04..34ab86cf12 100644
--- a/src/cmd/link/internal/ld/pcln.go
+++ b/src/cmd/link/internal/ld/pcln.go
@@ -17,7 +17,7 @@ import (
"strings"
)
-const funcSize = 10 * 4 // funcSize is the size of the _func object in runtime/runtime2.go
+const funcSize = 11 * 4 // funcSize is the size of the _func object in runtime/runtime2.go
// pclntab holds the state needed for pclntab generation.
type pclntab struct {
@@ -169,8 +169,10 @@ func genInlTreeSym(ctxt *Link, cu *sym.CompilationUnit, fi loader.FuncInfo, arch
inlFunc := ldr.FuncInfo(call.Func)
var funcID objabi.FuncID
+ startLine := int32(0)
if inlFunc.Valid() {
funcID = inlFunc.FuncID()
+ startLine = inlFunc.StartLine()
} else if !ctxt.linkShared {
// Inlined functions are always Go functions, and thus
// must have FuncInfo.
@@ -184,11 +186,12 @@ func genInlTreeSym(ctxt *Link, cu *sym.CompilationUnit, fi loader.FuncInfo, arch
}
// Construct runtime.inlinedCall value.
- const size = 12
+ const size = 16
inlTreeSym.SetUint8(arch, int64(i*size+0), uint8(funcID))
// Bytes 1-3 are unused.
inlTreeSym.SetUint32(arch, int64(i*size+4), uint32(nameOff))
inlTreeSym.SetUint32(arch, int64(i*size+8), uint32(call.ParentPC))
+ inlTreeSym.SetUint32(arch, int64(i*size+12), uint32(startLine))
}
return its
}
@@ -643,10 +646,12 @@ func writeFuncs(ctxt *Link, sb *loader.SymbolBuilder, funcs []loader.Sym, inlSym
// Write the individual func objects.
for i, s := range funcs {
+ startLine := int32(0)
fi := ldr.FuncInfo(s)
if fi.Valid() {
fi.Preload()
pcsp, pcfile, pcline, pcinline, pcdata = ldr.PcdataAuxs(s, pcdata)
+ startLine = fi.StartLine()
}
off := int64(startLocations[i])
@@ -693,6 +698,9 @@ func writeFuncs(ctxt *Link, sb *loader.SymbolBuilder, funcs []loader.Sym, inlSym
}
off = sb.SetUint32(ctxt.Arch, off, cuIdx)
+ // startLine int32
+ off = sb.SetUint32(ctxt.Arch, off, uint32(startLine))
+
// funcID uint8
var funcID objabi.FuncID
if fi.Valid() {
diff --git a/src/cmd/link/internal/loader/loader.go b/src/cmd/link/internal/loader/loader.go
index 40ad950fe5..23837379b5 100644
--- a/src/cmd/link/internal/loader/loader.go
+++ b/src/cmd/link/internal/loader/loader.go
@@ -1958,6 +1958,10 @@ func (fi *FuncInfo) FuncFlag() objabi.FuncFlag {
return (*goobj.FuncInfo)(nil).ReadFuncFlag(fi.data)
}
+func (fi *FuncInfo) StartLine() int32 {
+ return (*goobj.FuncInfo)(nil).ReadStartLine(fi.data)
+}
+
// Preload has to be called prior to invoking the various methods
// below related to pcdata, funcdataoff, files, and inltree nodes.
func (fi *FuncInfo) Preload() {