diff options
| author | Austin Clements <austin@google.com> | 2023-02-05 21:37:07 -0500 |
|---|---|---|
| committer | Austin Clements <austin@google.com> | 2023-03-10 17:18:34 +0000 |
| commit | 166e5ee4f2b5f170663c25b56d4929919c13debf (patch) | |
| tree | bba7627dc6de2e8e1e4a9516ff37e81f0e260fb3 /src/runtime/symtab.go | |
| parent | 59d0de16e4f003e69403eeee969f0b4a96dd6dcb (diff) | |
| download | go-166e5ee4f2b5f170663c25b56d4929919c13debf.tar.xz | |
runtime: use inlineUnwinder
This converts all places in the runtime that perform inline expansion
to use the new inlineUnwinder abstraction.
For #54466.
Change-Id: I48d996fb6263ed5225bd21d30914a27ae434528d
Reviewed-on: https://go-review.googlesource.com/c/go/+/466099
Run-TryBot: Austin Clements <austin@google.com>
TryBot-Result: Gopher Robot <gobot@golang.org>
Reviewed-by: Michael Pratt <mpratt@google.com>
Diffstat (limited to 'src/runtime/symtab.go')
| -rw-r--r-- | src/runtime/symtab.go | 112 |
1 files changed, 40 insertions, 72 deletions
diff --git a/src/runtime/symtab.go b/src/runtime/symtab.go index c3329568b7..67648a4ebc 100644 --- a/src/runtime/symtab.go +++ b/src/runtime/symtab.go @@ -116,28 +116,21 @@ func (ci *Frames) Next() (frame Frame, more bool) { // work correctly for entries in the result of runtime.Callers. pc-- } - name := funcname(funcInfo) - startLine := f.startLine() - if inldata := funcdata(funcInfo, _FUNCDATA_InlTree); inldata != nil { - inltree := (*[1 << 20]inlinedCall)(inldata) - // Non-strict as cgoTraceback may have added bogus PCs - // with a valid funcInfo but invalid PCDATA. - ix := pcdatavalue1(funcInfo, _PCDATA_InlTreeIndex, pc, nil, false) - if ix >= 0 { - // Note: entry is not modified. It always refers to a real frame, not an inlined one. - f = nil - ic := inltree[ix] - name = funcnameFromNameOff(funcInfo, ic.nameOff) - startLine = ic.startLine - // File/line from funcline1 below are already correct. - } + // It's important that interpret pc non-strictly as cgoTraceback may + // have added bogus PCs with a valid funcInfo but invalid PCDATA. + u, uf := newInlineUnwinder(funcInfo, pc, nil) + sf := u.srcFunc(uf) + if u.isInlined(uf) { + // Note: entry is not modified. It always refers to a real frame, not an inlined one. + // File/line from funcline1 below are already correct. + f = nil } ci.frames = append(ci.frames, Frame{ PC: pc, Func: f, - Function: name, + Function: sf.name(), Entry: entry, - startLine: int(startLine), + startLine: int(sf.startLine), funcInfo: funcInfo, // Note: File,Line set below }) @@ -182,6 +175,8 @@ func runtime_FrameStartLine(f *Frame) int { // //go:linkname runtime_expandFinalInlineFrame runtime/pprof.runtime_expandFinalInlineFrame func runtime_expandFinalInlineFrame(stk []uintptr) []uintptr { + // TODO: It would be more efficient to report only physical PCs to pprof and + // just expand the whole stack. if len(stk) == 0 { return stk } @@ -194,46 +189,29 @@ func runtime_expandFinalInlineFrame(stk []uintptr) []uintptr { return stk } - inldata := funcdata(f, _FUNCDATA_InlTree) - if inldata == nil { - // Nothing inline in f. + var cache pcvalueCache + u, uf := newInlineUnwinder(f, tracepc, &cache) + if !u.isInlined(uf) { + // Nothing inline at tracepc. return stk } // Treat the previous func as normal. We haven't actually checked, but // since this pc was included in the stack, we know it shouldn't be // elided. - lastFuncID := funcID_normal + calleeID := funcID_normal // Remove pc from stk; we'll re-add it below. stk = stk[:len(stk)-1] - // See inline expansion in gentraceback. - var cache pcvalueCache - inltree := (*[1 << 20]inlinedCall)(inldata) - for { - // Non-strict as cgoTraceback may have added bogus PCs - // with a valid funcInfo but invalid PCDATA. - ix := pcdatavalue1(f, _PCDATA_InlTreeIndex, tracepc, &cache, false) - if ix < 0 { - break - } - if inltree[ix].funcID == funcID_wrapper && elideWrapperCalling(lastFuncID) { + for ; uf.valid(); uf = u.next(uf) { + funcID := u.srcFunc(uf).funcID + if funcID == funcID_wrapper && elideWrapperCalling(calleeID) { // ignore wrappers } else { - stk = append(stk, pc) + stk = append(stk, uf.pc+1) } - lastFuncID = inltree[ix].funcID - // Back up to an instruction in the "caller". - tracepc = f.entry() + uintptr(inltree[ix].parentPc) - pc = tracepc + 1 - } - - // N.B. we want to keep the last parentPC which is not inline. - if f.funcID == funcID_wrapper && elideWrapperCalling(lastFuncID) { - // Ignore wrapper functions (except when they trigger panics). - } else { - stk = append(stk, pc) + calleeID = funcID } return stk @@ -752,28 +730,25 @@ func FuncForPC(pc uintptr) *Func { if !f.valid() { return nil } - if inldata := funcdata(f, _FUNCDATA_InlTree); inldata != nil { - // Note: strict=false so bad PCs (those between functions) don't crash the runtime. - // We just report the preceding function in that situation. See issue 29735. - // TODO: Perhaps we should report no function at all in that case. - // The runtime currently doesn't have function end info, alas. - if ix := pcdatavalue1(f, _PCDATA_InlTreeIndex, pc, nil, false); ix >= 0 { - inltree := (*[1 << 20]inlinedCall)(inldata) - ic := inltree[ix] - name := funcnameFromNameOff(f, ic.nameOff) - file, line := funcline(f, pc) - fi := &funcinl{ - ones: ^uint32(0), - entry: f.entry(), // entry of the real (the outermost) function. - name: name, - file: file, - line: line, - startLine: ic.startLine, - } - return (*Func)(unsafe.Pointer(fi)) - } + // This must interpret PC non-strictly so bad PCs (those between functions) don't crash the runtime. + // We just report the preceding function in that situation. See issue 29735. + // TODO: Perhaps we should report no function at all in that case. + // The runtime currently doesn't have function end info, alas. + u, uf := newInlineUnwinder(f, pc, nil) + if !u.isInlined(uf) { + return f._Func() } - return f._Func() + sf := u.srcFunc(uf) + file, line := u.fileLine(uf) + fi := &funcinl{ + ones: ^uint32(0), + entry: f.entry(), // entry of the real (the outermost) function. + name: sf.name(), + file: file, + line: int32(line), + startLine: sf.startLine, + } + return (*Func)(unsafe.Pointer(fi)) } // Name returns the name of the function. @@ -1059,13 +1034,6 @@ func funcpkgpath(f funcInfo) string { return name[:i] } -func funcnameFromNameOff(f funcInfo, nameOff int32) string { - if !f.valid() { - return "" - } - return f.datap.funcName(nameOff) -} - func funcfile(f funcInfo, fileno int32) string { datap := f.datap if !f.valid() { |
