func lastFunc(s trace.Stack) string {
var last trace.StackFrame
- s.Frames(func(f trace.StackFrame) bool {
+ s.Frames()(func(f trace.StackFrame) bool {
last = f
return true
})
for stack, record := range m.stacks {
rec := *record
i := 0
- stack.Frames(func(frame trace.StackFrame) bool {
+ stack.Frames()(func(frame trace.StackFrame) bool {
rec.Stack = append(rec.Stack, &trace.Frame{
PC: frame.PC,
Fn: frame.Func,
// pcsForStack extracts the first pprofMaxStack PCs from stack into pcs.
func pcsForStack(stack trace.Stack, pcs *[pprofMaxStack]uint64) {
i := 0
- stack.Frames(func(frame trace.StackFrame) bool {
+ stack.Frames()(func(frame trace.StackFrame) bool {
pcs[i] = frame.PC
i++
return i < len(pcs)
func regionTopStackFrame(r *trace.UserRegionSummary) trace.StackFrame {
var frame trace.StackFrame
if r.Start != nil && r.Start.Stack() != trace.NoStack {
- r.Start.Stack().Frames(func(f trace.StackFrame) bool {
+ r.Start.Stack().Frames()(func(f trace.StackFrame) bool {
frame = f
return false
})
// used to store the frames to reduce allocations.
func viewerFrames(stk trace.Stack) []*trace.Frame {
var frames []*trace.Frame
- stk.Frames(func(f trace.StackFrame) bool {
+ stk.Frames()(func(f trace.StackFrame) bool {
frames = append(frames, &trace.Frame{
PC: f.PC,
Fn: f.Func,
import (
"fmt"
+ "iter"
"math"
"strings"
"time"
}
// Frames is an iterator over the frames in a Stack.
-func (s Stack) Frames(yield func(f StackFrame) bool) bool {
- if s.id == 0 {
- return true
- }
- stk := s.table.stacks.mustGet(s.id)
- for _, pc := range stk.pcs {
- f := s.table.pcs[pc]
- sf := StackFrame{
- PC: f.pc,
- Func: s.table.strings.mustGet(f.funcID),
- File: s.table.strings.mustGet(f.fileID),
- Line: f.line,
+func (s Stack) Frames() iter.Seq[StackFrame] {
+ return func(yield func(StackFrame) bool) {
+ if s.id == 0 {
+ return
}
- if !yield(sf) {
- return false
+ stk := s.table.stacks.mustGet(s.id)
+ for _, pc := range stk.pcs {
+ f := s.table.pcs[pc]
+ sf := StackFrame{
+ PC: f.pc,
+ Func: s.table.strings.mustGet(f.funcID),
+ File: s.table.strings.mustGet(f.fileID),
+ Line: f.line,
+ }
+ if !yield(sf) {
+ return
+ }
}
}
- return true
}
// NoStack is a sentinel value that can be compared against any Stack value, indicating
if s.Stack != NoStack {
fmt.Fprintln(&sb)
fmt.Fprintln(&sb, "TransitionStack=")
- s.Stack.Frames(func(f StackFrame) bool {
+ s.Stack.Frames()(func(f StackFrame) bool {
fmt.Fprintf(&sb, "\t%s @ 0x%x\n", f.Func, f.PC)
fmt.Fprintf(&sb, "\t\t%s:%d\n", f.File, f.Line)
return true
if stk := e.Stack(); stk != NoStack {
fmt.Fprintln(&sb)
fmt.Fprintln(&sb, "Stack=")
- stk.Frames(func(f StackFrame) bool {
+ stk.Frames()(func(f StackFrame) bool {
fmt.Fprintf(&sb, "\t%s @ 0x%x\n", f.Func, f.PC)
fmt.Fprintf(&sb, "\t\t%s:%d\n", f.File, f.Line)
return true
if stk != NoStack {
var frame StackFrame
var ok bool
- stk.Frames(func(f StackFrame) bool {
+ stk.Frames()(func(f StackFrame) bool {
frame = f
ok = true
return true
func checkStack(e *errAccumulator, stk trace.Stack) {
// Check for non-empty values, but we also check for crashes due to incorrect validation.
i := 0
- stk.Frames(func(f trace.StackFrame) bool {
+ stk.Frames()(func(f trace.StackFrame) bool {
if i == 0 {
// Allow for one fully zero stack.
//
if hogRegion != nil && ev.Goroutine() == hogRegion.Goroutine() {
traceSamples++
var fns []string
- ev.Stack().Frames(func(frame trace.StackFrame) bool {
+ ev.Stack().Frames()(func(frame trace.StackFrame) bool {
if frame.Func != "runtime.goexit" {
fns = append(fns, fmt.Sprintf("%s:%d", frame.Func, frame.Line))
}
stackMatches := func(stk trace.Stack, frames []frame) bool {
i := 0
match := true
- stk.Frames(func(f trace.StackFrame) bool {
+ stk.Frames()(func(f trace.StackFrame) bool {
if f.Func != frames[i].fn {
match = false
return false
// dumpStack returns e.Stack() as a string.
func dumpStackV2(e *trace.Event) string {
var buf bytes.Buffer
- e.Stack().Frames(func(f trace.StackFrame) bool {
+ e.Stack().Frames()(func(f trace.StackFrame) bool {
file := strings.TrimPrefix(f.File, runtime.GOROOT())
fmt.Fprintf(&buf, "%s\n\t%s:%d\n", f.Func, file, f.Line)
return true