github.com/cloudwego/frugal@v0.1.15/internal/rt/stackmap_test.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 rt 18 19 import ( 20 `fmt` 21 `reflect` 22 `testing` 23 `unsafe` 24 ) 25 26 const ( 27 _FUNCDATA_ArgsPointerMaps = 0 28 _FUNCDATA_LocalsPointerMaps = 1 29 ) 30 31 type funcInfo struct { 32 fn unsafe.Pointer 33 datap unsafe.Pointer 34 } 35 36 type bitvector struct { 37 n int32 // # of bits 38 bytedata *uint8 39 } 40 41 //go:nosplit 42 func addb(p *byte, n uintptr) *byte { 43 return (*byte)(unsafe.Pointer(uintptr(unsafe.Pointer(p)) + n)) 44 } 45 46 func (bv *bitvector) ptrbit(i uintptr) uint8 { 47 b := *(addb(bv.bytedata, i/8)) 48 return (b >> (i % 8)) & 1 49 } 50 51 //go:linkname findfunc runtime.findfunc 52 func findfunc(_ uintptr) funcInfo 53 54 //go:linkname funcdata runtime.funcdata 55 func funcdata(_ funcInfo, _ uint8) unsafe.Pointer 56 57 //go:linkname stackmapdata runtime.stackmapdata 58 func stackmapdata(_ *StackMap, _ int32) bitvector 59 60 func stackMap(f interface{}) (*StackMap, *StackMap) { 61 fv := reflect.ValueOf(f) 62 if fv.Kind() != reflect.Func { 63 panic("f must be reflect.Func kind!") 64 } 65 fi := findfunc(fv.Pointer()) 66 args := funcdata(fi, uint8(_FUNCDATA_ArgsPointerMaps)) 67 locals := funcdata(fi, uint8(_FUNCDATA_LocalsPointerMaps)) 68 return (*StackMap)(args), (*StackMap)(locals) 69 } 70 71 func dumpstackmap(m *StackMap) { 72 for i := int32(0); i < m.N; i++ { 73 fmt.Printf("bitmap #%d/%d: ", i, m.L) 74 bv := stackmapdata(m, i) 75 for j := int32(0); j < bv.n; j++ { 76 fmt.Printf("%d ", bv.ptrbit(uintptr(j))) 77 } 78 fmt.Printf("\n") 79 } 80 } 81 82 var keepalive struct { 83 s string 84 i int 85 vp unsafe.Pointer 86 sb interface{} 87 fv uint64 88 } 89 90 func stackmaptestfunc(s string, i int, vp unsafe.Pointer, sb interface{}, fv uint64) (x *uint64, y string, z *int) { 91 z = new(int) 92 x = new(uint64) 93 y = s + "asdf" 94 keepalive.s = s 95 keepalive.i = i 96 keepalive.vp = vp 97 keepalive.sb = sb 98 keepalive.fv = fv 99 return 100 } 101 102 func TestStackMap_Dump(t *testing.T) { 103 args, locals := stackMap(stackmaptestfunc) 104 println("--- args ---") 105 dumpstackmap(args) 106 println("--- locals ---") 107 dumpstackmap(locals) 108 }