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 )