proc: avoid constructing unnecessary strings when evaluating variables
Avoids constructing: 1. name of runtime.curg fields while executing parseG 2. the location expression while evaluating any variable. Benchmark before: BenchmarkConditionalBreakpoints-4 1 4953889884 ns/op Benchmark after: BenchmarkConditionalBreakpoints-4 1 4419775128 ns/op Updates #1549
This commit is contained in:
parent
431dea7ee6
commit
a61b6c0d7c
@ -809,29 +809,51 @@ func (bi *BinaryInfo) LoadImageFromData(dwdata *dwarf.Data, debugFrameBytes, deb
|
||||
bi.Images = append(bi.Images, image)
|
||||
}
|
||||
|
||||
func (bi *BinaryInfo) locationExpr(entry godwarf.Entry, attr dwarf.Attr, pc uint64) ([]byte, string, error) {
|
||||
func (bi *BinaryInfo) locationExpr(entry godwarf.Entry, attr dwarf.Attr, pc uint64) ([]byte, *locationExpr, error) {
|
||||
a := entry.Val(attr)
|
||||
if a == nil {
|
||||
return nil, "", fmt.Errorf("no location attribute %s", attr)
|
||||
return nil, nil, fmt.Errorf("no location attribute %s", attr)
|
||||
}
|
||||
if instr, ok := a.([]byte); ok {
|
||||
var descr bytes.Buffer
|
||||
fmt.Fprintf(&descr, "[block] ")
|
||||
op.PrettyPrint(&descr, instr)
|
||||
return instr, descr.String(), nil
|
||||
return instr, &locationExpr{isBlock: true, instr: instr}, nil
|
||||
}
|
||||
off, ok := a.(int64)
|
||||
if !ok {
|
||||
return nil, "", fmt.Errorf("could not interpret location attribute %s", attr)
|
||||
return nil, nil, fmt.Errorf("could not interpret location attribute %s", attr)
|
||||
}
|
||||
instr := bi.loclistEntry(off, pc)
|
||||
if instr == nil {
|
||||
return nil, "", fmt.Errorf("could not find loclist entry at %#x for address %#x", off, pc)
|
||||
return nil, nil, fmt.Errorf("could not find loclist entry at %#x for address %#x", off, pc)
|
||||
}
|
||||
return instr, &locationExpr{pc: pc, off: off, instr: instr}, nil
|
||||
}
|
||||
|
||||
type locationExpr struct {
|
||||
isBlock bool
|
||||
isEscaped bool
|
||||
off int64
|
||||
pc uint64
|
||||
instr []byte
|
||||
}
|
||||
|
||||
func (le *locationExpr) String() string {
|
||||
if le == nil {
|
||||
return ""
|
||||
}
|
||||
var descr bytes.Buffer
|
||||
fmt.Fprintf(&descr, "[%#x:%#x] ", off, pc)
|
||||
op.PrettyPrint(&descr, instr)
|
||||
return instr, descr.String(), nil
|
||||
|
||||
if le.isBlock {
|
||||
fmt.Fprintf(&descr, "[block] ")
|
||||
op.PrettyPrint(&descr, le.instr)
|
||||
} else {
|
||||
fmt.Fprintf(&descr, "[%#x:%#x] ", le.off, le.pc)
|
||||
op.PrettyPrint(&descr, le.instr)
|
||||
}
|
||||
|
||||
if le.isEscaped {
|
||||
fmt.Fprintf(&descr, " (escaped)")
|
||||
}
|
||||
return descr.String()
|
||||
}
|
||||
|
||||
// LocationCovers returns the list of PC addresses that is covered by the
|
||||
@ -877,10 +899,10 @@ func (bi *BinaryInfo) LocationCovers(entry *dwarf.Entry, attr dwarf.Attr) ([][2]
|
||||
// This will either be an int64 address or a slice of Pieces for locations
|
||||
// that don't correspond to a single memory address (registers, composite
|
||||
// locations).
|
||||
func (bi *BinaryInfo) Location(entry godwarf.Entry, attr dwarf.Attr, pc uint64, regs op.DwarfRegisters) (int64, []op.Piece, string, error) {
|
||||
func (bi *BinaryInfo) Location(entry godwarf.Entry, attr dwarf.Attr, pc uint64, regs op.DwarfRegisters) (int64, []op.Piece, *locationExpr, error) {
|
||||
instr, descr, err := bi.locationExpr(entry, attr, pc)
|
||||
if err != nil {
|
||||
return 0, nil, "", err
|
||||
return 0, nil, nil, err
|
||||
}
|
||||
addr, pieces, err := op.ExecuteStackProgram(regs, instr, bi.Arch.PtrSize())
|
||||
return addr, pieces, descr, err
|
||||
|
||||
@ -266,7 +266,8 @@ func (scope *EvalScope) Locals() ([]*Variable, error) {
|
||||
}
|
||||
v.Name = name[1:]
|
||||
v.Flags |= VariableEscaped
|
||||
v.LocationExpr = locationExpr + " (escaped)"
|
||||
locationExpr.isEscaped = true
|
||||
v.LocationExpr = locationExpr
|
||||
v.DeclLine = declLine
|
||||
vars[i] = v
|
||||
}
|
||||
|
||||
@ -118,8 +118,8 @@ type Variable struct {
|
||||
loaded bool
|
||||
Unreadable error
|
||||
|
||||
LocationExpr string // location expression
|
||||
DeclLine int64 // line number of this variable's declaration
|
||||
LocationExpr *locationExpr // location expression
|
||||
DeclLine int64 // line number of this variable's declaration
|
||||
}
|
||||
|
||||
// LoadConfig controls how variables are loaded from the targets memory.
|
||||
@ -441,8 +441,6 @@ func newGVariable(thread Thread, gaddr uintptr, deref bool) (*Variable, error) {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
name := ""
|
||||
|
||||
if deref {
|
||||
typ = &godwarf.PtrType{
|
||||
CommonType: godwarf.CommonType{
|
||||
@ -453,11 +451,9 @@ func newGVariable(thread Thread, gaddr uintptr, deref bool) (*Variable, error) {
|
||||
},
|
||||
Type: typ,
|
||||
}
|
||||
} else {
|
||||
name = "runtime.curg"
|
||||
}
|
||||
|
||||
return newVariableFromThread(thread, name, gaddr, typ), nil
|
||||
return newVariableFromThread(thread, "", gaddr, typ), nil
|
||||
}
|
||||
|
||||
// Defer returns the top-most defer of the goroutine.
|
||||
@ -851,6 +847,8 @@ func (v *Variable) parseG() (*G, error) {
|
||||
|
||||
f, l, fn := v.bi.PCToLine(uint64(pc))
|
||||
|
||||
v.Name = "runtime.curg"
|
||||
|
||||
g := &G{
|
||||
ID: int(id),
|
||||
GoPC: uint64(gopc),
|
||||
|
||||
@ -148,7 +148,7 @@ func ConvertVar(v *proc.Variable) *Variable {
|
||||
Flags: VariableFlags(v.Flags),
|
||||
Base: v.Base,
|
||||
|
||||
LocationExpr: v.LocationExpr,
|
||||
LocationExpr: v.LocationExpr.String(),
|
||||
DeclLine: v.DeclLine,
|
||||
}
|
||||
|
||||
|
||||
Loading…
Reference in New Issue
Block a user