diff options
Diffstat (limited to 'vendor/github.com/bytedance/sonic/encoder/pools.go')
-rw-r--r-- | vendor/github.com/bytedance/sonic/encoder/pools.go | 194 |
1 files changed, 194 insertions, 0 deletions
diff --git a/vendor/github.com/bytedance/sonic/encoder/pools.go b/vendor/github.com/bytedance/sonic/encoder/pools.go new file mode 100644 index 000000000..600605d7c --- /dev/null +++ b/vendor/github.com/bytedance/sonic/encoder/pools.go @@ -0,0 +1,194 @@ +/* + * Copyright 2021 ByteDance Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package encoder + +import ( + `bytes` + `sync` + `unsafe` + `errors` + `reflect` + + `github.com/bytedance/sonic/internal/caching` + `github.com/bytedance/sonic/option` + `github.com/bytedance/sonic/internal/rt` +) + +const ( + _MaxStack = 4096 // 4k states + _MaxBuffer = 1048576 // 1MB buffer size + + _StackSize = unsafe.Sizeof(_Stack{}) +) + +var ( + bytesPool = sync.Pool{} + stackPool = sync.Pool{} + bufferPool = sync.Pool{} + programCache = caching.CreateProgramCache() +) + +type _State struct { + x int + f uint64 + p unsafe.Pointer + q unsafe.Pointer +} + +type _Stack struct { + sp uint64 + sb [_MaxStack]_State +} + +type _Encoder func( + rb *[]byte, + vp unsafe.Pointer, + sb *_Stack, + fv uint64, +) error + +var _KeepAlive struct { + rb *[]byte + vp unsafe.Pointer + sb *_Stack + fv uint64 + err error + frame [_FP_offs]byte +} + +var errCallShadow = errors.New("DON'T CALL THIS!") + +// Faker func of _Encoder, used to export its stackmap as _Encoder's +func _Encoder_Shadow(rb *[]byte, vp unsafe.Pointer, sb *_Stack, fv uint64) (err error) { + // align to assembler_amd64.go: _FP_offs + var frame [_FP_offs]byte + + // must keep all args and frames noticeable to GC + _KeepAlive.rb = rb + _KeepAlive.vp = vp + _KeepAlive.sb = sb + _KeepAlive.fv = fv + _KeepAlive.err = err + _KeepAlive.frame = frame + + return errCallShadow +} + +func newBytes() []byte { + if ret := bytesPool.Get(); ret != nil { + return ret.([]byte) + } else { + return make([]byte, 0, _MaxBuffer) + } +} + +func newStack() *_Stack { + if ret := stackPool.Get(); ret == nil { + return new(_Stack) + } else { + return ret.(*_Stack) + } +} + +func resetStack(p *_Stack) { + memclrNoHeapPointers(unsafe.Pointer(p), _StackSize) +} + +func newBuffer() *bytes.Buffer { + if ret := bufferPool.Get(); ret != nil { + return ret.(*bytes.Buffer) + } else { + return bytes.NewBuffer(make([]byte, 0, _MaxBuffer)) + } +} + +func freeBytes(p []byte) { + p = p[:0] + bytesPool.Put(p) +} + +func freeStack(p *_Stack) { + p.sp = 0 + stackPool.Put(p) +} + +func freeBuffer(p *bytes.Buffer) { + p.Reset() + bufferPool.Put(p) +} + +func makeEncoder(vt *rt.GoType, ex ...interface{}) (interface{}, error) { + if pp, err := newCompiler().compile(vt.Pack(), ex[0].(bool)); err != nil { + return nil, err + } else { + as := newAssembler(pp) + as.name = vt.String() + return as.Load(), nil + } +} + +func findOrCompile(vt *rt.GoType, pv bool) (_Encoder, error) { + if val := programCache.Get(vt); val != nil { + return val.(_Encoder), nil + } else if ret, err := programCache.Compute(vt, makeEncoder, pv); err == nil { + return ret.(_Encoder), nil + } else { + return nil, err + } +} + +func pretouchType(_vt reflect.Type, opts option.CompileOptions, v uint8) (map[reflect.Type]uint8, error) { + /* compile function */ + compiler := newCompiler().apply(opts) + encoder := func(vt *rt.GoType, ex ...interface{}) (interface{}, error) { + if pp, err := compiler.compile(_vt, ex[0].(bool)); err != nil { + return nil, err + } else { + as := newAssembler(pp) + as.name = vt.String() + return as.Load(), nil + } + } + + /* find or compile */ + vt := rt.UnpackType(_vt) + if val := programCache.Get(vt); val != nil { + return nil, nil + } else if _, err := programCache.Compute(vt, encoder, v == 1); err == nil { + return compiler.rec, nil + } else { + return nil, err + } +} + +func pretouchRec(vtm map[reflect.Type]uint8, opts option.CompileOptions) error { + if opts.RecursiveDepth < 0 || len(vtm) == 0 { + return nil + } + next := make(map[reflect.Type]uint8) + for vt, v := range vtm { + sub, err := pretouchType(vt, opts, v) + if err != nil { + return err + } + for svt, v := range sub { + next[svt] = v + } + } + opts.RecursiveDepth -= 1 + return pretouchRec(next, opts) +}
\ No newline at end of file |