github.com/cloudwego/frugal@v0.1.15/internal/loader/funcdata_go118_121.go (about) 1 //go:build go1.18 && !go1.23 2 // +build go1.18,!go1.23 3 4 /* 5 * Copyright 2022 ByteDance Inc. 6 * 7 * Licensed under the Apache License, Version 2.0 (the "License"); 8 * you may not use this file except in compliance with the License. 9 * You may obtain a copy of the License at 10 * 11 * http://www.apache.org/licenses/LICENSE-2.0 12 * 13 * Unless required by applicable law or agreed to in writing, software 14 * distributed under the License is distributed on an "AS IS" BASIS, 15 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 16 * See the License for the specific language governing permissions and 17 * limitations under the License. 18 */ 19 20 package loader 21 22 import ( 23 `unsafe` 24 25 `github.com/cloudwego/frugal/internal/rt` 26 `github.com/cloudwego/frugal/internal/utils` 27 ) 28 29 type _FuncTab struct { 30 entry uint32 31 funcoff uint32 32 } 33 34 type _PCHeader struct { 35 magic uint32 36 pad1, pad2 uint8 37 minLC uint8 38 ptrSize uint8 39 nfunc int 40 nfiles uint 41 textStart uintptr 42 funcnameOffset uintptr 43 cuOffset uintptr 44 filetabOffset uintptr 45 pctabOffset uintptr 46 pclnOffset uintptr 47 } 48 49 type _BitVector struct { 50 n int32 // # of bits 51 bytedata *uint8 52 } 53 54 type _FindFuncBucket struct { 55 idx uint32 56 subbuckets [16]byte 57 } 58 59 const minfunc = 16 60 const pcbucketsize = 256 * minfunc 61 62 var ( 63 emptyByte byte 64 65 /* retain local reference of all buckets to bypass gc */ 66 bucketList = &utils.ListNode{} 67 ) 68 69 func registerFunction(name string, pc uintptr, size uintptr, frame rt.Frame) { 70 var pbase uintptr 71 var sbase uintptr 72 73 /* PC ranges */ 74 minpc := pc 75 maxpc := pc + size 76 pctab := make([]byte, 1) 77 ffunc := make([]_FindFuncBucket, size / pcbucketsize + 1) 78 79 /* define the PC-SP ranges */ 80 for i, r := range frame.SpTab { 81 nb := r.Nb 82 ds := int(r.Sp - sbase) 83 84 /* check for remaining size */ 85 if nb == 0 { 86 if i == len(frame.SpTab) - 1 { 87 nb = size - pbase 88 } else { 89 panic("invalid PC-SP tab") 90 } 91 } 92 93 /* check for the first entry */ 94 if i == 0 { 95 pctab = append(pctab, encodeFirst(ds)...) 96 } else { 97 pctab = append(pctab, encodeValue(ds)...) 98 } 99 100 /* encode the length */ 101 sbase = r.Sp 102 pbase = pbase + nb 103 pctab = append(pctab, encodeVariant(int(nb))...) 104 } 105 106 /* pin the find function bucket */ 107 ftab := &ffunc[0] 108 pctab = append(pctab, 0) 109 bucketList.Prepend(unsafe.Pointer(ftab)) 110 111 112 /* pin the pointer maps */ 113 argptrs := frame.ArgPtrs.Pin() 114 localptrs := frame.LocalPtrs.Pin() 115 116 /* find the lower base */ 117 if argptrs < localptrs { 118 pbase = argptrs 119 } else { 120 pbase = localptrs 121 } 122 123 /* function entry */ 124 fn := _Func { 125 entryOff : 0, 126 nameoff : 1, 127 args : int32(frame.ArgSize), 128 pcsp : 1, 129 npcdata : 2, 130 cuOffset : 1, 131 nfuncdata : 2, 132 argptrs : uint32(argptrs - pbase), 133 localptrs : uint32(localptrs - pbase), 134 } 135 136 /* mark the entire function as a single line of code */ 137 fn.pcln = uint32(len(pctab)) 138 fn.pcfile = uint32(len(pctab)) 139 pctab = append(pctab, encodeFirst(1)...) 140 pctab = append(pctab, encodeVariant(int(size))...) 141 pctab = append(pctab, 0) 142 143 /* set the entire function to use stack map 0 */ 144 fn.pcdata[_PCDATA_StackMapIndex] = uint32(len(pctab)) 145 pctab = append(pctab, encodeFirst(0)...) 146 pctab = append(pctab, encodeVariant(int(size))...) 147 pctab = append(pctab, 0) 148 149 /* mark the entire function as unsafe to async-preempt */ 150 fn.pcdata[_PCDATA_UnsafePoint] = uint32(len(pctab)) 151 pctab = append(pctab, encodeFirst(_PCDATA_UnsafePointUnsafe)...) 152 pctab = append(pctab, encodeVariant(int(size))...) 153 pctab = append(pctab, 0) 154 155 /* module header */ 156 hdr := &_PCHeader { 157 magic : _ModuleMagic, 158 minLC : 1, 159 nfunc : 1, 160 ptrSize : 4 << (^uintptr(0) >> 63), 161 textStart : minpc, 162 } 163 164 /* function table */ 165 tab := []_FuncTab { 166 { entry: 0 }, 167 { entry: uint32(size) }, 168 } 169 170 /* module data */ 171 mod := &_ModuleData { 172 pcHeader : hdr, 173 funcnametab : append(append([]byte{0}, name...), 0), 174 cutab : []uint32{0, 0, 1}, 175 filetab : []byte("\x00(jit-generated)\x00"), 176 pctab : pctab, 177 pclntable : ((*[unsafe.Sizeof(_Func{})]byte)(unsafe.Pointer(&fn)))[:], 178 ftab : tab, 179 findfunctab : uintptr(unsafe.Pointer(ftab)), 180 minpc : minpc, 181 maxpc : maxpc, 182 text : minpc, 183 etext : maxpc, 184 modulename : name, 185 gcdata : uintptr(unsafe.Pointer(&emptyByte)), 186 gcbss : uintptr(unsafe.Pointer(&emptyByte)), 187 gofunc : pbase, 188 } 189 190 /* verify and register the new module */ 191 moduledataverify1(mod) 192 registerModule(mod) 193 }