funcdata.go (3045B)
1 /* 2 * Copyright 2021 ByteDance Inc. 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package loader 18 19 import ( 20 `reflect` 21 `sync` 22 `unsafe` 23 24 `github.com/bytedance/sonic/internal/rt` 25 ) 26 27 //go:linkname lastmoduledatap runtime.lastmoduledatap 28 //goland:noinspection GoUnusedGlobalVariable 29 var lastmoduledatap *_ModuleData 30 31 //go:linkname moduledataverify1 runtime.moduledataverify1 32 func moduledataverify1(_ *_ModuleData) 33 34 // PCDATA and FUNCDATA table indexes. 35 // 36 // See funcdata.h and $GROOT/src/cmd/internal/objabi/funcdata.go. 37 const ( 38 _FUNCDATA_ArgsPointerMaps = 0 39 _FUNCDATA_LocalsPointerMaps = 1 40 ) 41 42 type funcInfo struct { 43 *_Func 44 datap *_ModuleData 45 } 46 47 //go:linkname findfunc runtime.findfunc 48 func findfunc(pc uintptr) funcInfo 49 50 //go:linkname funcdata runtime.funcdata 51 func funcdata(f funcInfo, i uint8) unsafe.Pointer 52 53 var ( 54 modLock sync.Mutex 55 modList []*_ModuleData 56 ) 57 58 var emptyByte byte 59 60 func encodeVariant(v int) []byte { 61 var u int 62 var r []byte 63 64 /* split every 7 bits */ 65 for v > 127 { 66 u = v & 0x7f 67 v = v >> 7 68 r = append(r, byte(u) | 0x80) 69 } 70 71 /* check for last one */ 72 if v == 0 { 73 return r 74 } 75 76 /* add the last one */ 77 r = append(r, byte(v)) 78 return r 79 } 80 81 func registerModule(mod *_ModuleData) { 82 modLock.Lock() 83 modList = append(modList, mod) 84 lastmoduledatap.next = mod 85 lastmoduledatap = mod 86 modLock.Unlock() 87 } 88 89 func stackMap(f interface{}) (args uintptr, locals uintptr) { 90 fv := reflect.ValueOf(f) 91 if fv.Kind() != reflect.Func { 92 panic("f must be reflect.Func kind!") 93 } 94 fi := findfunc(fv.Pointer()) 95 return uintptr(funcdata(fi, uint8(_FUNCDATA_ArgsPointerMaps))), uintptr(funcdata(fi, uint8(_FUNCDATA_LocalsPointerMaps))) 96 } 97 98 var moduleCache = struct{ 99 m map[*_ModuleData][]byte 100 l sync.Mutex 101 }{ 102 m : make(map[*_ModuleData][]byte), 103 } 104 105 func cacheStackmap(argPtrs []bool, localPtrs []bool, mod *_ModuleData) (argptrs uintptr, localptrs uintptr) { 106 as := rt.StackMapBuilder{} 107 for _, b := range argPtrs { 108 as.AddField(b) 109 } 110 ab, _ := as.Build().MarshalBinary() 111 ls := rt.StackMapBuilder{} 112 for _, b := range localPtrs { 113 ls.AddField(b) 114 } 115 lb, _ := ls.Build().MarshalBinary() 116 cache := make([]byte, len(ab) + len(lb)) 117 copy(cache, ab) 118 copy(cache[len(ab):], lb) 119 moduleCache.l.Lock() 120 moduleCache.m[mod] = cache 121 moduleCache.l.Unlock() 122 return uintptr(rt.IndexByte(cache, 0)), uintptr(rt.IndexByte(cache, len(ab))) 123 124 }