gotosocial/vendor/github.com/bytedance/sonic/loader/funcdata.go
2023-02-25 12:12:40 +00:00

144 lines
4.2 KiB
Go

/**
* Copyright 2023 ByteDance Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package loader
import (
`encoding`
`encoding/binary`
`fmt`
`reflect`
`strings`
`sync`
`unsafe`
)
const (
_MinLC uint8 = 1
_PtrSize uint8 = 8
)
const (
_N_FUNCDATA = 8
_INVALID_FUNCDATA_OFFSET = ^uint32(0)
_FUNC_SIZE = unsafe.Sizeof(_func{})
_MINFUNC = 16 // minimum size for a function
_BUCKETSIZE = 256 * _MINFUNC
_SUBBUCKETS = 16
_SUB_BUCKETSIZE = _BUCKETSIZE / _SUBBUCKETS
)
// PCDATA and FUNCDATA table indexes.
//
// See funcdata.h and $GROOT/src/cmd/internal/objabi/funcdata.go.
const (
_FUNCDATA_ArgsPointerMaps = 0
_FUNCDATA_LocalsPointerMaps = 1
_FUNCDATA_StackObjects = 2
_FUNCDATA_InlTree = 3
_FUNCDATA_OpenCodedDeferInfo = 4
_FUNCDATA_ArgInfo = 5
_FUNCDATA_ArgLiveInfo = 6
_FUNCDATA_WrapInfo = 7
// ArgsSizeUnknown is set in Func.argsize to mark all functions
// whose argument size is unknown (C vararg functions, and
// assembly code without an explicit specification).
// This value is generated by the compiler, assembler, or linker.
ArgsSizeUnknown = -0x80000000
)
// moduledata used to cache the funcdata and findfuncbucket of one module
var moduleCache = struct {
m map[*moduledata][]byte
sync.Mutex
}{
m: make(map[*moduledata][]byte),
}
// Func contains information about a function.
type Func struct {
ID uint8 // see runtime/symtab.go
Flag uint8 // see runtime/symtab.go
ArgsSize int32 // args byte size
EntryOff uint32 // start pc, offset to moduledata.text
TextSize uint32 // size of func text
DeferReturn uint32 // offset of start of a deferreturn call instruction from entry, if any.
FileIndex uint32 // index into filetab
Name string // name of function
// PC data
Pcsp *Pcdata // PC -> SP delta
Pcfile *Pcdata // PC -> file index
Pcline *Pcdata // PC -> line number
PcUnsafePoint *Pcdata // PC -> unsafe point, must be PCDATA_UnsafePointSafe or PCDATA_UnsafePointUnsafe
PcStackMapIndex *Pcdata // PC -> stack map index, relative to ArgsPointerMaps and LocalsPointerMaps
PcInlTreeIndex *Pcdata // PC -> inlining tree index, relative to InlTree
PcArgLiveIndex *Pcdata // PC -> arg live index, relative to ArgLiveInfo
// Func data, must implement encoding.BinaryMarshaler
ArgsPointerMaps encoding.BinaryMarshaler // concrete type: *StackMap
LocalsPointerMaps encoding.BinaryMarshaler // concrete type: *StackMap
StackObjects encoding.BinaryMarshaler
InlTree encoding.BinaryMarshaler
OpenCodedDeferInfo encoding.BinaryMarshaler
ArgInfo encoding.BinaryMarshaler
ArgLiveInfo encoding.BinaryMarshaler
WrapInfo encoding.BinaryMarshaler
}
func getOffsetOf(data interface{}, field string) uintptr {
t := reflect.TypeOf(data)
fv, ok := t.FieldByName(field)
if !ok {
panic(fmt.Sprintf("field %s not found in struct %s", field, t.Name()))
}
return fv.Offset
}
func rnd(v int64, r int64) int64 {
if r <= 0 {
return v
}
v += r - 1
c := v % r
if c < 0 {
c += r
}
v -= c
return v
}
var (
byteOrder binary.ByteOrder = binary.LittleEndian
)
func funcNameParts(name string) (string, string, string) {
i := strings.IndexByte(name, '[')
if i < 0 {
return name, "", ""
}
// TODO: use LastIndexByte once the bootstrap compiler is >= Go 1.5.
j := len(name) - 1
for j > i && name[j] != ']' {
j--
}
if j <= i {
return name, "", ""
}
return name[:i], "[...]", name[j+1:]
}