1
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
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
75 func _Encoder_Shadow(rb *[]byte, vp unsafe.Pointer, sb *_Stack, fv uint64) (err error) {
76
77 var frame [_FP_offs]byte
78
79
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
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
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 }
194
View as plain text