github.com/cloudwego/frugal@v0.1.7/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  )
    26  
    27  type _Func struct {
    28      entry       uintptr
    29      nameoff     int32
    30      args        int32
    31      deferreturn uint32
    32      pcsp        uint32
    33      pcfile      uint32
    34      pcln        uint32
    35      npcdata     uint32
    36      cuOffset    uint32
    37      funcID      uint8
    38      _           [2]byte
    39      nfuncdata   uint8
    40      pcdata      [2]uint32
    41      argptrs     uintptr
    42      localptrs   uintptr
    43  }
    44  
    45  type _FuncTab struct {
    46      entry   uintptr
    47      funcoff uintptr
    48  }
    49  
    50  type _PCHeader struct {
    51      magic          uint32
    52      pad1, pad2     uint8
    53      minLC          uint8
    54      ptrSize        uint8
    55      nfunc          int
    56      nfiles         uint
    57      funcnameOffset uintptr
    58      cuOffset       uintptr
    59      filetabOffset  uintptr
    60      pctabOffset    uintptr
    61      pclnOffset     uintptr
    62  }
    63  
    64  type _BitVector struct {
    65      n        int32
    66      bytedata *uint8
    67  }
    68  
    69  type _ModuleData struct {
    70      pcHeader              *_PCHeader
    71      funcnametab           []byte
    72      cutab                 []uint32
    73      filetab               []byte
    74      pctab                 []byte
    75      pclntable             []_Func
    76      ftab                  []_FuncTab
    77      findfunctab           *_FindFuncBucket
    78      minpc, maxpc          uintptr
    79      text, etext           uintptr
    80      noptrdata, enoptrdata uintptr
    81      data, edata           uintptr
    82      bss, ebss             uintptr
    83      noptrbss, enoptrbss   uintptr
    84      end, gcdata, gcbss    uintptr
    85      types, etypes         uintptr
    86      textsectmap           [][3]uintptr
    87      typelinks             []int32
    88      itablinks             []unsafe.Pointer
    89      ptab                  [][2]int32
    90      pluginpath            string
    91      pkghashes             []struct{}
    92      modulename            string
    93      modulehashes          []struct{}
    94      hasmain               uint8
    95      gcdatamask, gcbssmask _BitVector
    96      typemap               map[int32]unsafe.Pointer
    97      bad                   bool
    98      next                  *_ModuleData
    99  }
   100  
   101  type _FindFuncBucket struct {
   102      idx        uint32
   103      subbuckets [16]byte
   104  }
   105  
   106  const minfunc = 16                 // minimum function size
   107  const pcbucketsize = 256 * minfunc // size of bucket in the pc->func lookup table
   108  
   109  var modHeader = &_PCHeader {
   110      magic   : 0xfffffffa,
   111      minLC   : 1,
   112      nfunc   : 1,
   113      ptrSize : 4 << (^uintptr(0) >> 63),
   114  }
   115  
   116  var (
   117      emptyByte  byte
   118      bucketList []*_FindFuncBucket
   119  )
   120  
   121  func registerFunction(name string, pc uintptr, size uintptr, frame rt.Frame) {
   122      var pbase uintptr
   123      var sbase uintptr
   124  
   125      /* PC ranges */
   126      minpc := pc
   127      maxpc := pc + size
   128      pctab := make([]byte, 1)
   129      ffunc := make([]_FindFuncBucket, size / pcbucketsize + 1)
   130  
   131      /* initialize the find function buckets */
   132      for i := range ffunc {
   133          ffunc[i].idx = 1
   134      }
   135  
   136      /* define the PC-SP ranges */
   137      for i, r := range frame.SpTab {
   138          nb := r.Nb
   139          ds := int(r.Sp - sbase)
   140  
   141          /* check for remaining size */
   142          if nb == 0 {
   143              if i == len(frame.SpTab) - 1 {
   144                  nb = size - pbase
   145              } else {
   146                  panic("invalid PC-SP tab")
   147              }
   148          }
   149  
   150          /* check for the first entry */
   151          if i == 0 {
   152              pctab = append(pctab, encodeFirst(ds)...)
   153          } else {
   154              pctab = append(pctab, encodeValue(ds)...)
   155          }
   156  
   157          /* encode the length */
   158          sbase = r.Sp
   159          pbase = pbase + nb
   160          pctab = append(pctab, encodeVariant(int(nb))...)
   161      }
   162  
   163      /* pin the find function bucket */
   164      ftab := &ffunc[0]
   165      pctab = append(pctab, 0)
   166      bucketList = append(bucketList, ftab)
   167  
   168      /* function entry */
   169      fn := _Func {
   170          entry     : pc,
   171          nameoff   : 1,
   172          args      : int32(frame.ArgSize),
   173          pcsp      : 1,
   174          npcdata   : 2,
   175          nfuncdata : 2,
   176          cuOffset  : 1,
   177          argptrs   : frame.ArgPtrs.Pin(),
   178          localptrs : frame.LocalPtrs.Pin(),
   179      }
   180  
   181      /* mark the entire function as a single line of code */
   182      fn.pcln = uint32(len(pctab))
   183      fn.pcfile = uint32(len(pctab))
   184      pctab = append(pctab, encodeFirst(1)...)
   185      pctab = append(pctab, encodeVariant(int(size))...)
   186      pctab = append(pctab, 0)
   187  
   188      /* set the entire function to use stack map 0 */
   189      fn.pcdata[_PCDATA_StackMapIndex] = uint32(len(pctab))
   190      pctab = append(pctab, encodeFirst(0)...)
   191      pctab = append(pctab, encodeVariant(int(size))...)
   192      pctab = append(pctab, 0)
   193  
   194      /* mark the entire function as unsafe to async-preempt */
   195      fn.pcdata[_PCDATA_UnsafePoint] = uint32(len(pctab))
   196      pctab = append(pctab, encodeFirst(_PCDATA_UnsafePointUnsafe)...)
   197      pctab = append(pctab, encodeVariant(int(size))...)
   198      pctab = append(pctab, 0)
   199  
   200      /* function table */
   201      tab := []_FuncTab {
   202          {entry: pc},
   203          {entry: pc},
   204          {entry: maxpc},
   205      }
   206  
   207      /* module data */
   208      mod := &_ModuleData {
   209          pcHeader    : modHeader,
   210          funcnametab : append(append([]byte{0}, name...), 0),
   211          cutab       : []uint32{0, 0, 1},
   212          filetab     : []byte("\x00(jit-generated)\x00"),
   213          pctab       : pctab,
   214          pclntable   : []_Func{fn},
   215          ftab        : tab,
   216          findfunctab : ftab,
   217          minpc       : minpc,
   218          maxpc       : maxpc,
   219          modulename  : name,
   220          gcdata      : uintptr(unsafe.Pointer(&emptyByte)), 
   221          gcbss       : uintptr(unsafe.Pointer(&emptyByte)),
   222      }
   223  
   224      /* verify and register the new module */
   225      moduledataverify1(mod)
   226      registerModule(mod)
   227  }