github.com/cloudwego/frugal@v0.1.7/internal/loader/funcdata_go118_120.go (about)

     1  // +build go1.18,!go1.21
     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 _FuncTab struct {
    28      entry   uint32
    29      funcoff uint32
    30  }
    31  
    32  type _PCHeader struct {
    33      magic          uint32
    34      pad1, pad2     uint8
    35      minLC          uint8
    36      ptrSize        uint8
    37      nfunc          int
    38      nfiles         uint
    39      textStart      uintptr
    40      funcnameOffset uintptr
    41      cuOffset       uintptr
    42      filetabOffset  uintptr
    43      pctabOffset    uintptr
    44      pclnOffset     uintptr
    45  }
    46  
    47  type _BitVector struct {
    48      n        int32 // # of bits
    49      bytedata *uint8
    50  }
    51  
    52  type _FindFuncBucket struct {
    53      idx        uint32
    54      subbuckets [16]byte
    55  }
    56  
    57  const minfunc = 16
    58  const pcbucketsize = 256 * minfunc
    59  
    60  var (
    61      emptyByte  byte
    62      bucketList []*_FindFuncBucket
    63  )
    64  
    65  func registerFunction(name string, pc uintptr, size uintptr, frame rt.Frame) {
    66      var pbase uintptr
    67      var sbase uintptr
    68  
    69      /* PC ranges */
    70      minpc := pc
    71      maxpc := pc + size
    72      pctab := make([]byte, 1)
    73      ffunc := make([]_FindFuncBucket, size / pcbucketsize + 1)
    74  
    75      /* define the PC-SP ranges */
    76      for i, r := range frame.SpTab {
    77          nb := r.Nb
    78          ds := int(r.Sp - sbase)
    79  
    80          /* check for remaining size */
    81          if nb == 0 {
    82              if i == len(frame.SpTab) - 1 {
    83                  nb = size - pbase
    84              } else {
    85                  panic("invalid PC-SP tab")
    86              }
    87          }
    88  
    89          /* check for the first entry */
    90          if i == 0 {
    91              pctab = append(pctab, encodeFirst(ds)...)
    92          } else {
    93              pctab = append(pctab, encodeValue(ds)...)
    94          }
    95  
    96          /* encode the length */
    97          sbase = r.Sp
    98          pbase = pbase + nb
    99          pctab = append(pctab, encodeVariant(int(nb))...)
   100      }
   101  
   102      /* pin the find function bucket */
   103      ftab := &ffunc[0]
   104      pctab = append(pctab, 0)
   105      bucketList = append(bucketList, ftab)
   106  
   107      /* pin the pointer maps */
   108      argptrs := frame.ArgPtrs.Pin()
   109      localptrs := frame.LocalPtrs.Pin()
   110  
   111      /* find the lower base */
   112      if argptrs < localptrs {
   113          pbase = argptrs
   114      } else {
   115          pbase = localptrs
   116      }
   117  
   118      /* function entry */
   119      fn := _Func {
   120          entryOff  : 0,
   121          nameoff   : 1,
   122          args      : int32(frame.ArgSize),
   123          pcsp      : 1,
   124          npcdata   : 2,
   125          cuOffset  : 1,
   126          nfuncdata : 2,
   127          argptrs   : uint32(argptrs - pbase),
   128          localptrs : uint32(localptrs - pbase),
   129      }
   130  
   131      /* mark the entire function as a single line of code */
   132      fn.pcln = uint32(len(pctab))
   133      fn.pcfile = uint32(len(pctab))
   134      pctab = append(pctab, encodeFirst(1)...)
   135      pctab = append(pctab, encodeVariant(int(size))...)
   136      pctab = append(pctab, 0)
   137  
   138      /* set the entire function to use stack map 0 */
   139      fn.pcdata[_PCDATA_StackMapIndex] = uint32(len(pctab))
   140      pctab = append(pctab, encodeFirst(0)...)
   141      pctab = append(pctab, encodeVariant(int(size))...)
   142      pctab = append(pctab, 0)
   143  
   144      /* mark the entire function as unsafe to async-preempt */
   145      fn.pcdata[_PCDATA_UnsafePoint] = uint32(len(pctab))
   146      pctab = append(pctab, encodeFirst(_PCDATA_UnsafePointUnsafe)...)
   147      pctab = append(pctab, encodeVariant(int(size))...)
   148      pctab = append(pctab, 0)
   149  
   150      /* module header */
   151      hdr := &_PCHeader {
   152          magic     : _ModuleMagic,
   153          minLC     : 1,
   154          nfunc     : 1,
   155          ptrSize   : 4 << (^uintptr(0) >> 63),
   156          textStart : minpc,
   157      }
   158  
   159      /* function table */
   160      tab := []_FuncTab {
   161          { entry: 0 },
   162          { entry: uint32(size) },
   163      }
   164  
   165      /* module data */
   166      mod := &_ModuleData {
   167          pcHeader    : hdr,
   168          funcnametab : append(append([]byte{0}, name...), 0),
   169          cutab       : []uint32{0, 0, 1},
   170          filetab     : []byte("\x00(jit-generated)\x00"),
   171          pctab       : pctab,
   172          pclntable   : ((*[unsafe.Sizeof(_Func{})]byte)(unsafe.Pointer(&fn)))[:],
   173          ftab        : tab,
   174          findfunctab : uintptr(unsafe.Pointer(ftab)),
   175          minpc       : minpc,
   176          maxpc       : maxpc,
   177          text        : minpc,
   178          etext       : maxpc,
   179          modulename  : name,
   180          gcdata      : uintptr(unsafe.Pointer(&emptyByte)), 
   181          gcbss       : uintptr(unsafe.Pointer(&emptyByte)),
   182          gofunc      : pbase,
   183      }
   184  
   185      /* verify and register the new module */
   186      moduledataverify1(mod)
   187      registerModule(mod)
   188  }