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