123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193 |
- /*
- * 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
- _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, option.DefaultEncoderBufferSize)
- }
- }
- 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, option.DefaultEncoderBufferSize))
- }
- }
- 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)
- }
|