From a378486b7b60b968adb62a7f5efcb528e3c2042a Mon Sep 17 00:00:00 2001 From: phuslu Date: Sun, 5 May 2024 23:37:11 +0800 Subject: [PATCH] make pcNameFileLine 0-allocs by forbidden magic --- runtime.go | 2 +- runtime_go1.18.go | 3 --- runtime_go1.19.go | 3 --- runtime_go1.20.go | 3 --- runtime_go1.21.go | 38 +++++++++++++++++++++++++++----------- runtime_go1.22.go | 42 +++++++++++++++++++++++++++++------------- runtime_go1.23.go | 11 ++--------- 7 files changed, 59 insertions(+), 43 deletions(-) diff --git a/runtime.go b/runtime.go index 9d41d8c1..38fdb943 100644 --- a/runtime.go +++ b/runtime.go @@ -5,7 +5,7 @@ import ( ) type funcInfo struct { - _func *uintptr + _func unsafe.Pointer datap unsafe.Pointer //nolint:unused } diff --git a/runtime_go1.18.go b/runtime_go1.18.go index c57928fa..c71c373a 100644 --- a/runtime_go1.18.go +++ b/runtime_go1.18.go @@ -62,9 +62,6 @@ func funcname(f funcInfo) string //go:linkname funcdata runtime.funcdata func funcdata(f funcInfo, i uint8) unsafe.Pointer -//go:linkname pcdatavalue runtime.pcdatavalue -func pcdatavalue(f funcInfo, table int32, targetpc uintptr, cache unsafe.Pointer) int32 - //go:linkname pcdatavalue1 runtime.pcdatavalue1 func pcdatavalue1(f funcInfo, table int32, targetpc uintptr, cache unsafe.Pointer, strict bool) int32 diff --git a/runtime_go1.19.go b/runtime_go1.19.go index 24151a79..c67dd910 100644 --- a/runtime_go1.19.go +++ b/runtime_go1.19.go @@ -62,9 +62,6 @@ func funcname(f funcInfo) string //go:linkname funcdata runtime.funcdata func funcdata(f funcInfo, i uint8) unsafe.Pointer -//go:linkname pcdatavalue runtime.pcdatavalue -func pcdatavalue(f funcInfo, table int32, targetpc uintptr, cache unsafe.Pointer) int32 - //go:linkname pcdatavalue1 runtime.pcdatavalue1 func pcdatavalue1(f funcInfo, table int32, targetpc uintptr, cache unsafe.Pointer, strict bool) int32 diff --git a/runtime_go1.20.go b/runtime_go1.20.go index 58c3ec42..aad60a0e 100644 --- a/runtime_go1.20.go +++ b/runtime_go1.20.go @@ -62,9 +62,6 @@ func funcname(f funcInfo) string //go:linkname funcdata runtime.funcdata func funcdata(f funcInfo, i uint8) unsafe.Pointer -//go:linkname pcdatavalue runtime.pcdatavalue -func pcdatavalue(f funcInfo, table int32, targetpc uintptr, cache unsafe.Pointer) int32 - //go:linkname pcdatavalue1 runtime.pcdatavalue1 func pcdatavalue1(f funcInfo, table int32, targetpc uintptr, cache unsafe.Pointer, strict bool) int32 diff --git a/runtime_go1.21.go b/runtime_go1.21.go index 828d3e87..40b5b3ee 100644 --- a/runtime_go1.21.go +++ b/runtime_go1.21.go @@ -37,6 +37,25 @@ type srcFunc struct { funcID uint8 } +type _func struct { + entryOff uint32 // start pc, as offset from moduledata.text/pcHeader.textStart + nameOff int32 // function name, as index into moduledata.funcnametab. + + args int32 // in/out args size + deferreturn uint32 // offset of start of a deferreturn call instruction from entry, if any. + + pcsp uint32 + pcfile uint32 + pcln uint32 + npcdata uint32 + cuOffset uint32 // runtime.cutab offset of this function's CU + startLine int32 // line number of start of function (func keyword/TEXT directive) + funcID uint8 // set for certain special runtime functions + flag uint8 + _ [1]byte // pad + nfuncdata uint8 // must be last, must end on a uint32-aligned boundary +} + func pcNameFileLine(pc uintptr) (name, file string, line int32) { funcInfo := findfunc(pc) if funcInfo._func == nil { @@ -58,9 +77,15 @@ func pcNameFileLine(pc uintptr) (name, file string, line int32) { // It's important that interpret pc non-strictly as cgoTraceback may // have added bogus PCs with a valid funcInfo but invalid PCDATA. u, uf := newInlineUnwinder(funcInfo, pc, nil) - sf := inlineUnwinder_srcFunc(&u, uf) + var sf srcFunc + if uf.index < 0 { + f := (*_func)(funcInfo._func) + sf = srcFunc{funcInfo.datap, f.nameOff, f.startLine, f.funcID} + } else { + t := &u.inlTree[uf.index] + sf = srcFunc{u.f.datap, t.nameOff, t.startLine, t.funcID} + } name = srcFunc_name(sf) - // name = funcNameForPrint(srcFunc_name(sf)) return } @@ -68,18 +93,9 @@ func pcNameFileLine(pc uintptr) (name, file string, line int32) { //go:linkname newInlineUnwinder runtime.newInlineUnwinder func newInlineUnwinder(f funcInfo, pc uintptr, cache unsafe.Pointer) (inlineUnwinder, inlineFrame) -//go:linkname inlineUnwinder_srcFunc runtime.(*inlineUnwinder).srcFunc -func inlineUnwinder_srcFunc(*inlineUnwinder, inlineFrame) srcFunc - -//go:linkname inlineUnwinder_isInlined runtime.(*inlineUnwinder).isInlined -func inlineUnwinder_isInlined(*inlineUnwinder, inlineFrame) bool - //go:linkname srcFunc_name runtime.srcFunc.name func srcFunc_name(srcFunc) string -//go:linkname funcNameForPrint runtime.funcNameForPrint -func funcNameForPrint(name string) string - // Fastrandn returns a pseudorandom uint32 in [0,n). // //go:noescape diff --git a/runtime_go1.22.go b/runtime_go1.22.go index c2f9a957..27f465df 100644 --- a/runtime_go1.22.go +++ b/runtime_go1.22.go @@ -7,7 +7,7 @@ package log import ( - _ "unsafe" + "unsafe" ) // inlinedCall is the encoding of entries in the FUNCDATA_InlTree table. @@ -30,12 +30,31 @@ type inlineFrame struct { } type srcFunc struct { - datap *uintptr + datap unsafe.Pointer nameOff int32 startLine int32 funcID uint8 } +type _func struct { + entryOff uint32 // start pc, as offset from moduledata.text/pcHeader.textStart + nameOff int32 // function name, as index into moduledata.funcnametab. + + args int32 // in/out args size + deferreturn uint32 // offset of start of a deferreturn call instruction from entry, if any. + + pcsp uint32 + pcfile uint32 + pcln uint32 + npcdata uint32 + cuOffset uint32 // runtime.cutab offset of this function's CU + startLine int32 // line number of start of function (func keyword/TEXT directive) + funcID uint8 // set for certain special runtime functions + flag uint8 + _ [1]byte // pad + nfuncdata uint8 // must be last, must end on a uint32-aligned boundary +} + func pcNameFileLine(pc uintptr) (name, file string, line int32) { funcInfo := findfunc(pc) if funcInfo._func == nil { @@ -57,9 +76,15 @@ func pcNameFileLine(pc uintptr) (name, file string, line int32) { // It's important that interpret pc non-strictly as cgoTraceback may // have added bogus PCs with a valid funcInfo but invalid PCDATA. u, uf := newInlineUnwinder(funcInfo, pc) - sf := inlineUnwinder_srcFunc(&u, uf) + var sf srcFunc + if uf.index < 0 { + f := (*_func)(funcInfo._func) + sf = srcFunc{funcInfo.datap, f.nameOff, f.startLine, f.funcID} + } else { + t := &u.inlTree[uf.index] + sf = srcFunc{u.f.datap, t.nameOff, t.startLine, t.funcID} + } name = srcFunc_name(sf) - // name = funcNameForPrint(srcFunc_name(sf)) return } @@ -67,18 +92,9 @@ func pcNameFileLine(pc uintptr) (name, file string, line int32) { //go:linkname newInlineUnwinder runtime.newInlineUnwinder func newInlineUnwinder(f funcInfo, pc uintptr) (inlineUnwinder, inlineFrame) -//go:linkname inlineUnwinder_srcFunc runtime.(*inlineUnwinder).srcFunc -func inlineUnwinder_srcFunc(*inlineUnwinder, inlineFrame) srcFunc - -//go:linkname inlineUnwinder_isInlined runtime.(*inlineUnwinder).isInlined -func inlineUnwinder_isInlined(*inlineUnwinder, inlineFrame) bool - //go:linkname srcFunc_name runtime.srcFunc.name func srcFunc_name(srcFunc) string -//go:linkname funcNameForPrint runtime.funcNameForPrint -func funcNameForPrint(name string) string - // Fastrandn returns a pseudorandom uint32 in [0,n). // //go:noescape diff --git a/runtime_go1.23.go b/runtime_go1.23.go index 11b38ad0..2722baee 100644 --- a/runtime_go1.23.go +++ b/runtime_go1.23.go @@ -7,7 +7,7 @@ package log import ( - _ "unsafe" + "unsafe" ) // inlinedCall is the encoding of entries in the FUNCDATA_InlTree table. @@ -30,7 +30,7 @@ type inlineFrame struct { } type srcFunc struct { - datap *uintptr + datap unsafe.Pointer nameOff int32 startLine int32 funcID uint8 @@ -59,7 +59,6 @@ func pcNameFileLine(pc uintptr) (name, file string, line int32) { u, uf := newInlineUnwinder(funcInfo, pc) sf := inlineUnwinder_srcFunc(&u, uf) name = srcFunc_name(sf) - // name = funcNameForPrint(srcFunc_name(sf)) return } @@ -70,15 +69,9 @@ func newInlineUnwinder(f funcInfo, pc uintptr) (inlineUnwinder, inlineFrame) //go:linkname inlineUnwinder_srcFunc runtime.(*inlineUnwinder).srcFunc func inlineUnwinder_srcFunc(*inlineUnwinder, inlineFrame) srcFunc -//go:linkname inlineUnwinder_isInlined runtime.(*inlineUnwinder).isInlined -func inlineUnwinder_isInlined(*inlineUnwinder, inlineFrame) bool - //go:linkname srcFunc_name runtime.srcFunc.name func srcFunc_name(srcFunc) string -//go:linkname funcNameForPrint runtime.funcNameForPrint -func funcNameForPrint(name string) string - // Fastrandn returns a pseudorandom uint32 in [0,n). // //go:noescape