github.com/bytedance/sonic@v1.11.7-0.20240517092252-d2edb31b167b/internal/decoder/pools.go (about)

     1  /*
     2   * Copyright 2021 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 decoder
    18  
    19  import (
    20      `sync`
    21      `unsafe`
    22  
    23      `github.com/bytedance/sonic/internal/caching`
    24      `github.com/bytedance/sonic/internal/native/types`
    25      `github.com/bytedance/sonic/internal/rt`
    26  )
    27  
    28  const (
    29      _MinSlice = 2
    30      _MaxStack = 4096 // 4k slots
    31      _MaxStackBytes = _MaxStack * _PtrBytes
    32      _MaxDigitNums = types.MaxDigitNums  // used in atof fallback algorithm
    33  )
    34  
    35  const (
    36      _PtrBytes   = _PTR_SIZE / 8
    37      _FsmOffset  = (_MaxStack + 1) * _PtrBytes
    38      _DbufOffset = _FsmOffset + int64(unsafe.Sizeof(types.StateMachine{})) + types.MAX_RECURSE * _PtrBytes
    39      _StackSize  = unsafe.Sizeof(_Stack{})
    40  )
    41  
    42  var (
    43      stackPool     = sync.Pool{}
    44      valueCache    = []unsafe.Pointer(nil)
    45      fieldCache    = []*caching.FieldMap(nil)
    46      fieldCacheMux = sync.Mutex{}
    47      programCache  = caching.CreateProgramCache()
    48  )
    49  
    50  type _Stack struct {
    51      sp uintptr
    52      sb [_MaxStack]unsafe.Pointer
    53      mm types.StateMachine
    54      vp [types.MAX_RECURSE]unsafe.Pointer
    55      dp [_MaxDigitNums]byte
    56  }
    57  
    58  type _Decoder func(
    59      s  string,
    60      i  int,
    61      vp unsafe.Pointer,
    62      sb *_Stack,
    63      fv uint64,
    64      sv string, // DO NOT pass value to this arguement, since it is only used for local _VAR_sv
    65      vk unsafe.Pointer, // DO NOT pass value to this arguement, since it is only used for local _VAR_vk
    66  ) (int, error)
    67  
    68  var _KeepAlive struct {
    69      s string
    70      i int
    71      vp unsafe.Pointer
    72      sb *_Stack
    73      fv uint64
    74      sv string
    75      vk unsafe.Pointer
    76  
    77      ret int
    78      err error
    79  
    80      frame_decoder [_FP_offs]byte
    81      frame_generic [_VD_offs]byte
    82  }
    83  
    84  var (
    85      argPtrs   = []bool{true, false, false, true, true, false, true, false, true}
    86      localPtrs = []bool{}
    87  )
    88  
    89  var (
    90      argPtrs_generic   = []bool{true}
    91      localPtrs_generic = []bool{}
    92  )
    93  
    94  func newStack() *_Stack {
    95      if ret := stackPool.Get(); ret == nil {
    96          return new(_Stack)
    97      } else {
    98          return ret.(*_Stack)
    99      }
   100  }
   101  
   102  func resetStack(p *_Stack) {
   103      memclrNoHeapPointers(unsafe.Pointer(p), _StackSize)
   104  }
   105  
   106  func freeStack(p *_Stack) {
   107      p.sp = 0
   108      stackPool.Put(p)
   109  }
   110  
   111  func freezeValue(v unsafe.Pointer) uintptr {
   112      valueCache = append(valueCache, v)
   113      return uintptr(v)
   114  }
   115  
   116  func freezeFields(v *caching.FieldMap) int64 {
   117      fieldCacheMux.Lock()
   118      fieldCache = append(fieldCache, v)
   119      fieldCacheMux.Unlock()
   120      return referenceFields(v)
   121  }
   122  
   123  func referenceFields(v *caching.FieldMap) int64 {
   124      return int64(uintptr(unsafe.Pointer(v)))
   125  }
   126  
   127  func makeDecoder(vt *rt.GoType, _ ...interface{}) (interface{}, error) {
   128      if pp, err := newCompiler().compile(vt.Pack()); err != nil {
   129          return nil, err
   130      } else {
   131          return newAssembler(pp).Load(), nil
   132      }
   133  }
   134  
   135  func findOrCompile(vt *rt.GoType) (_Decoder, error) {
   136      if val := programCache.Get(vt); val != nil {
   137          return val.(_Decoder), nil
   138      } else if ret, err := programCache.Compute(vt, makeDecoder); err == nil {
   139          return ret.(_Decoder), nil
   140      } else {
   141          return nil, err
   142      }
   143  }