github.com/goshafaq/sonic@v0.0.0-20231026082336-871835fb94c6/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/goshafaq/sonic/internal/caching"
    24  	"github.com/goshafaq/sonic/internal/native/types"
    25  	"github.com/goshafaq/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  }