gtsocial-umbx

Unnamed repository; edit this file 'description' to name the repository.
Log | Files | Refs | README | LICENSE

pools.go (4653B)


      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 }