Commit 3249cb0a authored by David Lazar's avatar David Lazar

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 <lazard@golang.org>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: default avatarAustin Clements <austin@google.com>
parent a7276742
...@@ -764,10 +764,22 @@ func (tab *traceStackTable) newStack(n int) *traceStack { ...@@ -764,10 +764,22 @@ func (tab *traceStackTable) newStack(n int) *traceStack {
return (*traceStack)(tab.mem.alloc(unsafe.Sizeof(traceStack{}) + uintptr(n)*sys.PtrSize)) 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, // dump writes all previously cached stacks to trace buffers,
// releases all memory and resets state. // releases all memory and resets state.
func (tab *traceStackTable) dump() { func (tab *traceStackTable) dump() {
frames := make(map[uintptr]traceFrame)
var tmp [(2 + 4*traceStackSize) * traceBytesPerNumber]byte var tmp [(2 + 4*traceStackSize) * traceBytesPerNumber]byte
buf := traceFlush(0).ptr() buf := traceFlush(0).ptr()
for _, stk := range tab.tab { for _, stk := range tab.tab {
...@@ -775,11 +787,12 @@ func (tab *traceStackTable) dump() { ...@@ -775,11 +787,12 @@ func (tab *traceStackTable) dump() {
for ; stk != nil; stk = stk.link.ptr() { for ; stk != nil; stk = stk.link.ptr() {
tmpbuf := tmp[:0] tmpbuf := tmp[:0]
tmpbuf = traceAppend(tmpbuf, uint64(stk.id)) tmpbuf = traceAppend(tmpbuf, uint64(stk.id))
tmpbuf = traceAppend(tmpbuf, uint64(stk.n)) frames := allFrames(stk.stack())
for _, pc := range stk.stack() { tmpbuf = traceAppend(tmpbuf, uint64(len(frames)))
for _, f := range frames {
var frame traceFrame var frame traceFrame
frame, buf = traceFrameForPC(buf, frames, pc) frame, buf = traceFrameForPC(buf, f)
tmpbuf = traceAppend(tmpbuf, uint64(pc)) tmpbuf = traceAppend(tmpbuf, uint64(f.PC))
tmpbuf = traceAppend(tmpbuf, uint64(frame.funcID)) tmpbuf = traceAppend(tmpbuf, uint64(frame.funcID))
tmpbuf = traceAppend(tmpbuf, uint64(frame.fileID)) tmpbuf = traceAppend(tmpbuf, uint64(frame.fileID))
tmpbuf = traceAppend(tmpbuf, uint64(frame.line)) tmpbuf = traceAppend(tmpbuf, uint64(frame.line))
...@@ -809,26 +822,17 @@ type traceFrame struct { ...@@ -809,26 +822,17 @@ type traceFrame struct {
line uint64 line uint64
} }
func traceFrameForPC(buf *traceBuf, frames map[uintptr]traceFrame, pc uintptr) (traceFrame, *traceBuf) { func traceFrameForPC(buf *traceBuf, f Frame) (traceFrame, *traceBuf) {
if frame, ok := frames[pc]; ok {
return frame, buf
}
var frame traceFrame 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 const maxLen = 1 << 10
if len(fn) > maxLen { if len(fn) > maxLen {
fn = fn[len(fn)-maxLen:] fn = fn[len(fn)-maxLen:]
} }
frame.funcID, buf = traceString(buf, fn) frame.funcID, buf = traceString(buf, fn)
file, line := funcline(f, pc-sys.PCQuantum) frame.line = uint64(f.Line)
frame.line = uint64(line) file := f.File
if len(file) > maxLen { if len(file) > maxLen {
file = file[len(file)-maxLen:] file = file[len(file)-maxLen:]
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment