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