stack.go raw

   1  /**
   2   * Copyright 2024 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 vars
  18  
  19  import (
  20  	"bytes"
  21  	"sync"
  22  	"unsafe"
  23  
  24  	"github.com/bytedance/sonic/internal/caching"
  25  	"github.com/bytedance/sonic/internal/rt"
  26  	"github.com/bytedance/sonic/option"
  27  )
  28  
  29  type State struct {
  30  	x int
  31  	f uint64
  32  	p unsafe.Pointer
  33  	q unsafe.Pointer
  34  }
  35  
  36  type Stack struct {
  37  	sp uintptr
  38  	sb [MaxStack]State
  39  }
  40  
  41  var (
  42  	bytesPool    = sync.Pool{}
  43  	stackPool    = sync.Pool{
  44  		New: func() interface{} {
  45  			return &Stack{}
  46  		},
  47  	}
  48  	bufferPool   = sync.Pool{}
  49  	programCache = caching.CreateProgramCache()
  50  )
  51  
  52  func NewBytes() *[]byte {
  53  	if ret := bytesPool.Get(); ret != nil {
  54  		return ret.(*[]byte)
  55  	} else {
  56  		ret := make([]byte, 0, option.DefaultEncoderBufferSize)
  57  		return &ret
  58  	}
  59  }
  60  
  61  func NewStack() *Stack {
  62  	ret :=  stackPool.Get().(*Stack)
  63  	ret.sp = 0
  64  	return ret
  65  }
  66  
  67  func ResetStack(p *Stack) {
  68  	rt.MemclrNoHeapPointers(unsafe.Pointer(p), StackSize)
  69  }
  70  
  71  func (s *Stack) Top() *State {
  72  	return (*State)(rt.Add(unsafe.Pointer(&s.sb[0]), s.sp))
  73  }
  74  
  75  func (s *Stack) Cur() *State {
  76  	return (*State)(rt.Add(unsafe.Pointer(&s.sb[0]), s.sp - uintptr(StateSize)))
  77  }
  78  
  79  const _MaxStackSP = uintptr(MaxStack * StateSize)
  80  
  81  func (s *Stack) Push(v State) bool {
  82  	if uintptr(s.sp) >= _MaxStackSP {
  83  		return false
  84  	}
  85  	st := s.Top()
  86  	*st = v
  87  	s.sp += uintptr(StateSize)
  88  	return true
  89  }
  90  
  91  func (s *Stack) Pop() State {
  92  	s.sp -= uintptr(StateSize)
  93  	st := s.Top()
  94  	ret := *st
  95  	*st = State{}
  96  	return ret
  97  }
  98  
  99  func (s *Stack) Load() (int, uint64, unsafe.Pointer, unsafe.Pointer) {
 100  	st := s.Cur()
 101  	return st.x, st.f, st.p, st.q
 102  }
 103  
 104  func (s *Stack) Save(x int, f uint64, p unsafe.Pointer, q unsafe.Pointer) bool {
 105  	return s.Push(State{x: x, f:f, p: p, q: q})
 106  }
 107  
 108  func (s *Stack) Drop() (int, uint64, unsafe.Pointer, unsafe.Pointer) {
 109  	st := s.Pop()
 110  	return st.x, st.f, st.p, st.q
 111  }
 112  
 113  func NewBuffer() *bytes.Buffer {
 114  	if ret := bufferPool.Get(); ret != nil {
 115  		return ret.(*bytes.Buffer)
 116  	} else {
 117  		return bytes.NewBuffer(make([]byte, 0, option.DefaultEncoderBufferSize))
 118  	}
 119  }
 120  
 121  func FreeBytes(p *[]byte) {
 122  	if rt.CanSizeResue(cap(*p)) {
 123  		(*p) = (*p)[:0]
 124  		bytesPool.Put(p)
 125  	}
 126  }
 127  
 128  func FreeStack(p *Stack) {
 129  	p.sp = 0
 130  	stackPool.Put(p)
 131  }
 132  
 133  func FreeBuffer(p *bytes.Buffer) {
 134  	if rt.CanSizeResue(cap(p.Bytes())) {
 135  		p.Reset()
 136  		bufferPool.Put(p)
 137  	}
 138  }
 139  
 140  var (
 141  	ArgPtrs   = []bool{true, true, true, false}
 142  	LocalPtrs = []bool{}
 143  	
 144      ArgPtrs_generic   = []bool{true}
 145      LocalPtrs_generic = []bool{}
 146  )