1
0
mirror of https://github.com/golang/go synced 2024-11-17 10:34:49 -07:00

runtime/pprof: skip checks for inlined functions when inlining is disabled

Fixes #35463

Change-Id: I29af27b77cc651395c20570943847729ff12586c
Reviewed-on: https://go-review.googlesource.com/c/go/+/206297
Run-TryBot: Bryan C. Mills <bcmills@google.com>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Brad Fitzpatrick <bradfitz@golang.org>
This commit is contained in:
Bryan C. Mills 2019-11-08 21:50:35 -05:00
parent f07059d949
commit c31bcd1390
2 changed files with 44 additions and 0 deletions

View File

@ -151,6 +151,12 @@ func TestMemoryProfiler(t *testing.T) {
t.Fatalf("No matching stack entry for %q\n\nProfile:\n%v\n", test.stk, p)
}
}
if !containsInlinedCall(TestMemoryProfiler, 4<<10) {
t.Logf("Can't determine whether allocateTransient2MInline was inlined into TestMemoryProfiler.")
return
}
// Check the inlined function location is encoded correctly.
for _, loc := range p.Location {
inlinedCaller, inlinedCallee := false, false

View File

@ -16,6 +16,7 @@ import (
"math/big"
"os"
"os/exec"
"reflect"
"regexp"
"runtime"
"runtime/pprof/internal/profile"
@ -104,7 +105,44 @@ func TestCPUProfileMultithreaded(t *testing.T) {
})
}
// containsInlinedCall reports whether the function body for the function f is
// known to contain an inlined function call within the first maxBytes bytes.
func containsInlinedCall(f interface{}, maxBytes int) bool {
rf := reflect.ValueOf(f)
if rf.Kind() != reflect.Func {
panic(fmt.Sprintf("%T is not a function", f))
}
fFunc := runtime.FuncForPC(rf.Pointer())
if fFunc == nil || fFunc.Entry() == 0 {
panic("failed to locate function entry")
}
for offset := 0; offset < maxBytes; offset++ {
inner := runtime.FuncForPC(fFunc.Entry() + uintptr(offset))
if inner == nil {
// No function known for this PC value.
// It might simply be misaligned, so keep searching.
continue
}
if inner.Entry() != fFunc.Entry() {
// Scanned past f and didn't find any inlined functions.
break
}
if inner.Name() != fFunc.Name() {
// This PC has f as its entry-point, but is not f. Therefore, it must be a
// function inlined into f.
return true
}
}
return false
}
func TestCPUProfileInlining(t *testing.T) {
if !containsInlinedCall(inlinedCaller, 4<<10) {
t.Skipf("Can't determine whether inlinedCallee was inlined into inlinedCaller.")
}
p := testCPUProfile(t, stackContains, []string{"runtime/pprof.inlinedCallee", "runtime/pprof.inlinedCaller"}, avoidFunctions(), func(dur time.Duration) {
cpuHogger(inlinedCaller, &salt1, dur)
})