return t.IsStruct() || t.IsArray() || t.IsComplex() || t.IsInterface() || t.IsString() || t.IsSlice()
}
- // Populate the data.
- // The data is a stream of bytes, which contains the offsets and sizes of the
- // non-aggregate arguments or non-aggregate fields/elements of aggregate-typed
- // arguments, along with special "operators". Specifically,
- // - for each non-aggrgate arg/field/element, its offset from FP (1 byte) and
- // size (1 byte)
- // - special operators:
- // - 0xff - end of sequence
- // - 0xfe - print { (at the start of an aggregate-typed argument)
- // - 0xfd - print } (at the end of an aggregate-typed argument)
- // - 0xfc - print ... (more args/fields/elements)
- // - 0xfb - print _ (offset too large)
- // These constants need to be in sync with runtime.traceback.go:printArgs.
- const (
- _endSeq = 0xff
- _startAgg = 0xfe
- _endAgg = 0xfd
- _dotdotdot = 0xfc
- _offsetTooLarge = 0xfb
- _special = 0xf0 // above this are operators, below this are ordinary offsets
- )
-
- const (
- limit = 10 // print no more than 10 args/components
- maxDepth = 5 // no more than 5 layers of nesting
-
- // maxLen is a (conservative) upper bound of the byte stream length. For
- // each arg/component, it has no more than 2 bytes of data (size, offset),
- // and no more than one {, }, ... at each level (it cannot have both the
- // data and ... unless it is the last one, just be conservative). Plus 1
- // for _endSeq.
- maxLen = (maxDepth*3+2)*limit + 1
- )
-
wOff := 0
n := 0
writebyte := func(o uint8) { wOff = objw.Uint8(x, wOff, o) }
// Write one non-aggregate arg/field/element.
write1 := func(sz, offset int64) {
- if offset >= _special {
- writebyte(_offsetTooLarge)
+ if offset >= rtabi.TraceArgsSpecial {
+ writebyte(rtabi.TraceArgsOffsetTooLarge)
} else {
writebyte(uint8(offset))
writebyte(uint8(sz))
// Returns whether to continue visiting.
var visitType func(baseOffset int64, t *types.Type, depth int) bool
visitType = func(baseOffset int64, t *types.Type, depth int) bool {
- if n >= limit {
- writebyte(_dotdotdot)
+ if n >= rtabi.TraceArgsLimit {
+ writebyte(rtabi.TraceArgsDotdotdot)
return false
}
if !isAggregate(t) {
write1(t.Size(), baseOffset)
return true
}
- writebyte(_startAgg)
+ writebyte(rtabi.TraceArgsStartAgg)
depth++
- if depth >= maxDepth {
- writebyte(_dotdotdot)
- writebyte(_endAgg)
+ if depth >= rtabi.TraceArgsMaxDepth {
+ writebyte(rtabi.TraceArgsDotdotdot)
+ writebyte(rtabi.TraceArgsEndAgg)
n++
return true
}
}
}
}
- writebyte(_endAgg)
+ writebyte(rtabi.TraceArgsEndAgg)
return true
}
break
}
}
- writebyte(_endSeq)
- if wOff > maxLen {
+ writebyte(rtabi.TraceArgsEndSeq)
+ if wOff > rtabi.TraceArgsMaxLen {
base.Fatalf("ArgInfo too large")
}
return Name{Bytes: &b[0]}
}
+
+const (
+ TraceArgsLimit = 10 // print no more than 10 args/components
+ TraceArgsMaxDepth = 5 // no more than 5 layers of nesting
+
+ // maxLen is a (conservative) upper bound of the byte stream length. For
+ // each arg/component, it has no more than 2 bytes of data (size, offset),
+ // and no more than one {, }, ... at each level (it cannot have both the
+ // data and ... unless it is the last one, just be conservative). Plus 1
+ // for _endSeq.
+ TraceArgsMaxLen = (TraceArgsMaxDepth*3+2)*TraceArgsLimit + 1
+)
+
+// Populate the data.
+// The data is a stream of bytes, which contains the offsets and sizes of the
+// non-aggregate arguments or non-aggregate fields/elements of aggregate-typed
+// arguments, along with special "operators". Specifically,
+// - for each non-aggrgate arg/field/element, its offset from FP (1 byte) and
+// size (1 byte)
+// - special operators:
+// - 0xff - end of sequence
+// - 0xfe - print { (at the start of an aggregate-typed argument)
+// - 0xfd - print } (at the end of an aggregate-typed argument)
+// - 0xfc - print ... (more args/fields/elements)
+// - 0xfb - print _ (offset too large)
+const (
+ TraceArgsEndSeq = 0xff
+ TraceArgsStartAgg = 0xfe
+ TraceArgsEndAgg = 0xfd
+ TraceArgsDotdotdot = 0xfc
+ TraceArgsOffsetTooLarge = 0xfb
+ TraceArgsSpecial = 0xf0 // above this are operators, below this are ordinary offsets
+)
// printArgs prints function arguments in traceback.
func printArgs(f funcInfo, argp unsafe.Pointer, pc uintptr) {
- // The "instruction" of argument printing is encoded in _FUNCDATA_ArgInfo.
- // See cmd/compile/internal/ssagen.emitArgInfo for the description of the
- // encoding.
- // These constants need to be in sync with the compiler.
- const (
- _endSeq = 0xff
- _startAgg = 0xfe
- _endAgg = 0xfd
- _dotdotdot = 0xfc
- _offsetTooLarge = 0xfb
- )
-
- const (
- limit = 10 // print no more than 10 args/components
- maxDepth = 5 // no more than 5 layers of nesting
- maxLen = (maxDepth*3+2)*limit + 1 // max length of _FUNCDATA_ArgInfo (see the compiler side for reasoning)
- )
-
- p := (*[maxLen]uint8)(funcdata(f, abi.FUNCDATA_ArgInfo))
+ p := (*[abi.TraceArgsMaxLen]uint8)(funcdata(f, abi.FUNCDATA_ArgInfo))
if p == nil {
return
}
o := p[pi]
pi++
switch o {
- case _endSeq:
+ case abi.TraceArgsEndSeq:
break printloop
- case _startAgg:
+ case abi.TraceArgsStartAgg:
printcomma()
print("{")
start = true
continue
- case _endAgg:
+ case abi.TraceArgsEndAgg:
print("}")
- case _dotdotdot:
+ case abi.TraceArgsDotdotdot:
printcomma()
print("...")
- case _offsetTooLarge:
+ case abi.TraceArgsOffsetTooLarge:
printcomma()
print("_")
default: