diff options
author | Bryan C. Mills <bcmills@google.com> | 2019-11-08 21:50:35 -0500 |
---|---|---|
committer | Bryan C. Mills <bcmills@google.com> | 2019-11-11 15:15:06 +0000 |
commit | c31bcd13909edb53621c3dc47aa987365247df8d (patch) | |
tree | 960a40030a9a903cdc9a577e8adc81fc5ca64817 /src/runtime/pprof | |
parent | f07059d949057f414dd0f8303f93ca727d716c62 (diff) | |
download | go-c31bcd13909edb53621c3dc47aa987365247df8d.tar.gz go-c31bcd13909edb53621c3dc47aa987365247df8d.zip |
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>
Diffstat (limited to 'src/runtime/pprof')
-rw-r--r-- | src/runtime/pprof/mprof_test.go | 6 | ||||
-rw-r--r-- | src/runtime/pprof/pprof_test.go | 38 |
2 files changed, 44 insertions, 0 deletions
diff --git a/src/runtime/pprof/mprof_test.go b/src/runtime/pprof/mprof_test.go index 8bc1ae41f2..1c0d2c6ea9 100644 --- a/src/runtime/pprof/mprof_test.go +++ b/src/runtime/pprof/mprof_test.go @@ -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 diff --git a/src/runtime/pprof/pprof_test.go b/src/runtime/pprof/pprof_test.go index b553baf3a9..5cbe9ab7a8 100644 --- a/src/runtime/pprof/pprof_test.go +++ b/src/runtime/pprof/pprof_test.go @@ -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) }) |