github.com/cloudwego/frugal@v0.1.15/internal/loader/funcdata.go (about) 1 /* 2 * Copyright 2022 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 `sync/atomic` 21 `unsafe` 22 23 `github.com/cloudwego/frugal/internal/utils` 24 ) 25 26 const ( 27 _PCDATA_UnsafePoint = 0 28 _PCDATA_StackMapIndex = 1 29 _PCDATA_UnsafePointUnsafe = -2 30 ) 31 32 //go:linkname lastmoduledatap runtime.lastmoduledatap 33 //goland:noinspection GoUnusedGlobalVariable 34 var lastmoduledatap *_ModuleData 35 36 //go:linkname moduledataverify1 runtime.moduledataverify1 37 func moduledataverify1(_ *_ModuleData) 38 39 var ( 40 /* retains local reference of all modules to bypass gc */ 41 modList = utils.ListNode{} 42 ) 43 44 func toZigzag(v int) int { 45 return (v << 1) ^ (v >> 31) 46 } 47 48 func encodeFirst(v int) []byte { 49 return encodeValue(v + 1) 50 } 51 52 func encodeValue(v int) []byte { 53 return encodeVariant(toZigzag(v)) 54 } 55 56 func encodeVariant(v int) []byte { 57 var u int 58 var r []byte 59 60 /* split every 7 bits */ 61 for v > 127 { 62 u = v & 0x7f 63 v = v >> 7 64 r = append(r, byte(u) | 0x80) 65 } 66 67 /* check for last one */ 68 if v == 0 { 69 return r 70 } 71 72 /* add the last one */ 73 r = append(r, byte(v)) 74 return r 75 } 76 77 func registerModule(mod *_ModuleData) { 78 modList.Prepend(unsafe.Pointer(mod)) 79 registerModuleLockFree(&lastmoduledatap, mod) 80 } 81 82 func registerModuleLockFree(tail **_ModuleData, mod *_ModuleData) { 83 for { 84 oldTail := loadModule(tail) 85 if casModule(tail, oldTail, mod) { 86 storeModule(&oldTail.next, mod) 87 break 88 } 89 } 90 } 91 92 func loadModule(p **_ModuleData) *_ModuleData { 93 return (*_ModuleData)(atomic.LoadPointer((*unsafe.Pointer)(unsafe.Pointer(p)))) 94 } 95 96 func storeModule(p **_ModuleData, value *_ModuleData) { 97 atomic.StorePointer((*unsafe.Pointer)(unsafe.Pointer(p)), unsafe.Pointer(value)) 98 } 99 100 func casModule(p **_ModuleData, oldValue *_ModuleData, newValue *_ModuleData) bool { 101 return atomic.CompareAndSwapPointer( 102 (*unsafe.Pointer)(unsafe.Pointer(p)), 103 unsafe.Pointer(oldValue), 104 unsafe.Pointer(newValue), 105 ) 106 }