From: David Lazar Date: Thu, 13 Apr 2017 13:40:49 +0000 (-0400) Subject: runtime/trace: iterate over frames instead of PCs X-Git-Tag: go1.9beta1~684 X-Git-Url: http://www.git.cypherpunks.su/?a=commitdiff_plain;h=3249cb0ab465c5310e09868236405ba6c40929a4;p=gostls13.git runtime/trace: iterate over frames instead of PCs Now the runtime/trace tests pass with -l=4. This also gets rid of the frames cache for multiple reasons: 1) The frames cache was used to avoid repeated calls to funcname and funcline. Now these calls happen inside the CallersFrames iterator. 2) Maintaining a frames cache is harder: map[uintptr]traceFrame doesn't work since each PC can map to multiple traceFrames. 3) It's not clear that the cache is important. Change-Id: I2914ac0b3ba08e39b60149d99a98f9f532b35bbb Reviewed-on: https://go-review.googlesource.com/40591 Run-TryBot: David Lazar TryBot-Result: Gobot Gobot Reviewed-by: Austin Clements --- diff --git a/src/runtime/trace.go b/src/runtime/trace.go index 4f87d4ce2a..93d52a9844 100644 --- a/src/runtime/trace.go +++ b/src/runtime/trace.go @@ -764,10 +764,22 @@ func (tab *traceStackTable) newStack(n int) *traceStack { return (*traceStack)(tab.mem.alloc(unsafe.Sizeof(traceStack{}) + uintptr(n)*sys.PtrSize)) } +// allFrames returns all of the Frames corresponding to pcs. +func allFrames(pcs []uintptr) []Frame { + frames := make([]Frame, 0, len(pcs)) + ci := CallersFrames(pcs) + for { + f, more := ci.Next() + frames = append(frames, f) + if !more { + return frames + } + } +} + // dump writes all previously cached stacks to trace buffers, // releases all memory and resets state. func (tab *traceStackTable) dump() { - frames := make(map[uintptr]traceFrame) var tmp [(2 + 4*traceStackSize) * traceBytesPerNumber]byte buf := traceFlush(0).ptr() for _, stk := range tab.tab { @@ -775,11 +787,12 @@ func (tab *traceStackTable) dump() { for ; stk != nil; stk = stk.link.ptr() { tmpbuf := tmp[:0] tmpbuf = traceAppend(tmpbuf, uint64(stk.id)) - tmpbuf = traceAppend(tmpbuf, uint64(stk.n)) - for _, pc := range stk.stack() { + frames := allFrames(stk.stack()) + tmpbuf = traceAppend(tmpbuf, uint64(len(frames))) + for _, f := range frames { var frame traceFrame - frame, buf = traceFrameForPC(buf, frames, pc) - tmpbuf = traceAppend(tmpbuf, uint64(pc)) + frame, buf = traceFrameForPC(buf, f) + tmpbuf = traceAppend(tmpbuf, uint64(f.PC)) tmpbuf = traceAppend(tmpbuf, uint64(frame.funcID)) tmpbuf = traceAppend(tmpbuf, uint64(frame.fileID)) tmpbuf = traceAppend(tmpbuf, uint64(frame.line)) @@ -809,26 +822,17 @@ type traceFrame struct { line uint64 } -func traceFrameForPC(buf *traceBuf, frames map[uintptr]traceFrame, pc uintptr) (traceFrame, *traceBuf) { - if frame, ok := frames[pc]; ok { - return frame, buf - } - +func traceFrameForPC(buf *traceBuf, f Frame) (traceFrame, *traceBuf) { var frame traceFrame - f := findfunc(pc) - if !f.valid() { - frames[pc] = frame - return frame, buf - } - fn := funcname(f) + fn := f.Function const maxLen = 1 << 10 if len(fn) > maxLen { fn = fn[len(fn)-maxLen:] } frame.funcID, buf = traceString(buf, fn) - file, line := funcline(f, pc-sys.PCQuantum) - frame.line = uint64(line) + frame.line = uint64(f.Line) + file := f.File if len(file) > maxLen { file = file[len(file)-maxLen:] }