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  }