github.com/bytedance/sonic@v1.11.7-0.20240517092252-d2edb31b167b/internal/encoder/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 encoder 18 19 import ( 20 `bytes` 21 `sync` 22 `unsafe` 23 `errors` 24 `reflect` 25 26 `github.com/bytedance/sonic/internal/caching` 27 `github.com/bytedance/sonic/option` 28 `github.com/bytedance/sonic/internal/rt` 29 ) 30 31 const ( 32 _MaxStack = 4096 // 4k states 33 34 _StackSize = unsafe.Sizeof(_Stack{}) 35 ) 36 37 var ( 38 bytesPool = sync.Pool{} 39 stackPool = sync.Pool{} 40 bufferPool = sync.Pool{} 41 programCache = caching.CreateProgramCache() 42 ) 43 44 type _State struct { 45 x int 46 f uint64 47 p unsafe.Pointer 48 q unsafe.Pointer 49 } 50 51 type _Stack struct { 52 sp uint64 53 sb [_MaxStack]_State 54 } 55 56 type _Encoder func( 57 rb *[]byte, 58 vp unsafe.Pointer, 59 sb *_Stack, 60 fv uint64, 61 ) error 62 63 var _KeepAlive struct { 64 rb *[]byte 65 vp unsafe.Pointer 66 sb *_Stack 67 fv uint64 68 err error 69 frame [_FP_offs]byte 70 } 71 72 var errCallShadow = errors.New("DON'T CALL THIS!") 73 74 // Faker func of _Encoder, used to export its stackmap as _Encoder's 75 func _Encoder_Shadow(rb *[]byte, vp unsafe.Pointer, sb *_Stack, fv uint64) (err error) { 76 // align to assembler_amd64.go: _FP_offs 77 var frame [_FP_offs]byte 78 79 // must keep all args and frames noticeable to GC 80 _KeepAlive.rb = rb 81 _KeepAlive.vp = vp 82 _KeepAlive.sb = sb 83 _KeepAlive.fv = fv 84 _KeepAlive.err = err 85 _KeepAlive.frame = frame 86 87 return errCallShadow 88 } 89 90 func newBytes() []byte { 91 if ret := bytesPool.Get(); ret != nil { 92 return ret.([]byte) 93 } else { 94 return make([]byte, 0, option.DefaultEncoderBufferSize) 95 } 96 } 97 98 func newStack() *_Stack { 99 if ret := stackPool.Get(); ret == nil { 100 return new(_Stack) 101 } else { 102 return ret.(*_Stack) 103 } 104 } 105 106 func resetStack(p *_Stack) { 107 memclrNoHeapPointers(unsafe.Pointer(p), _StackSize) 108 } 109 110 func newBuffer() *bytes.Buffer { 111 if ret := bufferPool.Get(); ret != nil { 112 return ret.(*bytes.Buffer) 113 } else { 114 return bytes.NewBuffer(make([]byte, 0, option.DefaultEncoderBufferSize)) 115 } 116 } 117 118 func freeBytes(p []byte) { 119 p = p[:0] 120 bytesPool.Put(p) 121 } 122 123 func freeStack(p *_Stack) { 124 p.sp = 0 125 stackPool.Put(p) 126 } 127 128 func freeBuffer(p *bytes.Buffer) { 129 p.Reset() 130 bufferPool.Put(p) 131 } 132 133 func makeEncoder(vt *rt.GoType, ex ...interface{}) (interface{}, error) { 134 if pp, err := newCompiler().compile(vt.Pack(), ex[0].(bool)); err != nil { 135 return nil, err 136 } else { 137 as := newAssembler(pp) 138 as.name = vt.String() 139 return as.Load(), nil 140 } 141 } 142 143 func findOrCompile(vt *rt.GoType, pv bool) (_Encoder, error) { 144 if val := programCache.Get(vt); val != nil { 145 return val.(_Encoder), nil 146 } else if ret, err := programCache.Compute(vt, makeEncoder, pv); err == nil { 147 return ret.(_Encoder), nil 148 } else { 149 return nil, err 150 } 151 } 152 153 func pretouchType(_vt reflect.Type, opts option.CompileOptions, v uint8) (map[reflect.Type]uint8, error) { 154 /* compile function */ 155 compiler := newCompiler().apply(opts) 156 encoder := func(vt *rt.GoType, ex ...interface{}) (interface{}, error) { 157 if pp, err := compiler.compile(_vt, ex[0].(bool)); err != nil { 158 return nil, err 159 } else { 160 as := newAssembler(pp) 161 as.name = vt.String() 162 return as.Load(), nil 163 } 164 } 165 166 /* find or compile */ 167 vt := rt.UnpackType(_vt) 168 if val := programCache.Get(vt); val != nil { 169 return nil, nil 170 } else if _, err := programCache.Compute(vt, encoder, v == 1); err == nil { 171 return compiler.rec, nil 172 } else { 173 return nil, err 174 } 175 } 176 177 func pretouchRec(vtm map[reflect.Type]uint8, opts option.CompileOptions) error { 178 if opts.RecursiveDepth < 0 || len(vtm) == 0 { 179 return nil 180 } 181 next := make(map[reflect.Type]uint8) 182 for vt, v := range vtm { 183 sub, err := pretouchType(vt, opts, v) 184 if err != nil { 185 return err 186 } 187 for svt, v := range sub { 188 next[svt] = v 189 } 190 } 191 opts.RecursiveDepth -= 1 192 return pretouchRec(next, opts) 193 }