1 // Copyright 2024 CloudWeGo Authors
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 // http://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14
15 package vm
16
17 import (
18 "encoding"
19 "encoding/json"
20 "fmt"
21 "math"
22 "reflect"
23 "unsafe"
24
25 "github.com/bytedance/sonic/internal/encoder/alg"
26 "github.com/bytedance/sonic/internal/encoder/ir"
27 "github.com/bytedance/sonic/internal/encoder/vars"
28 "github.com/bytedance/sonic/internal/rt"
29 )
30
31 const (
32 _S_cond = iota
33 _S_init
34 )
35
36 var (
37 _T_json_Marshaler = rt.UnpackType(vars.JsonMarshalerType)
38 _T_encoding_TextMarshaler = rt.UnpackType(vars.EncodingTextMarshalerType)
39 )
40
41 func print_instr(buf []byte, pc int, op ir.Op, ins *ir.Instr, p unsafe.Pointer) {
42 if len(buf) > 20 {
43 fmt.Println(string(buf[len(buf)-20:]))
44 } else {
45 fmt.Println(string(buf))
46 }
47 fmt.Printf("pc %04d, op %v, ins %#v, ptr: %x\n", pc, op, ins.Disassemble(), p)
48 }
49
50 func Execute(b *[]byte, p unsafe.Pointer, s *vars.Stack, flags uint64, prog *ir.Program) (error) {
51 pl := len(*prog)
52 if pl <= 0 {
53 return nil
54 }
55
56 var buf = *b
57 var x int
58 var q unsafe.Pointer
59 var f uint64
60
61 var pro = &(*prog)[0]
62 for pc := 0; pc < pl; {
63 ins := (*ir.Instr)(rt.Add(unsafe.Pointer(pro), ir.OpSize*uintptr(pc)))
64 pc++
65 op := ins.Op()
66
67 switch op {
68 case ir.OP_goto:
69 pc = ins.Vi()
70 continue
71 case ir.OP_byte:
72 v := ins.Byte()
73 buf = append(buf, v)
74 case ir.OP_text:
75 v := ins.Vs()
76 buf = append(buf, v...)
77 case ir.OP_deref:
78 p = *(*unsafe.Pointer)(p)
79 case ir.OP_index:
80 p = rt.Add(p, uintptr(ins.I64()))
81 case ir.OP_load:
82 // NOTICE: load CANNOT change f!
83 x, _, p, q = s.Load()
84 case ir.OP_save:
85 if !s.Save(x, f, p, q) {
86 return vars.ERR_too_deep
87 }
88 case ir.OP_drop:
89 x, f, p, q = s.Drop()
90 case ir.OP_drop_2:
91 s.Drop()
92 x, f, p, q = s.Drop()
93 case ir.OP_recurse:
94 vt, pv := ins.Vp2()
95 f := flags
96 if pv {
97 f |= (1 << alg.BitPointerValue)
98 }
99 *b = buf
100 if vt.Indirect() {
101 if err := EncodeTypedPointer(b, vt, (*unsafe.Pointer)(rt.NoEscape(unsafe.Pointer(&p))), s, f); err != nil {
102 return err
103 }
104 } else {
105 vp := (*unsafe.Pointer)(p)
106 if err := EncodeTypedPointer(b, vt, vp, s, f); err != nil {
107 return err
108 }
109 }
110 buf = *b
111 case ir.OP_is_nil:
112 if is_nil(p) {
113 pc = ins.Vi()
114 continue
115 }
116 case ir.OP_is_nil_p1:
117 if (*rt.GoEface)(p).Value == nil {
118 pc = ins.Vi()
119 continue
120 }
121 case ir.OP_null:
122 buf = append(buf, 'n', 'u', 'l', 'l')
123 case ir.OP_str:
124 v := *(*string)(p)
125 buf = alg.Quote(buf, v, false)
126 case ir.OP_bool:
127 if *(*bool)(p) {
128 buf = append(buf, 't', 'r', 'u', 'e')
129 } else {
130 buf = append(buf, 'f', 'a', 'l', 's', 'e')
131 }
132 case ir.OP_i8:
133 v := *(*int8)(p)
134 buf = alg.I64toa(buf, int64(v))
135 case ir.OP_i16:
136 v := *(*int16)(p)
137 buf = alg.I64toa(buf, int64(v))
138 case ir.OP_i32:
139 v := *(*int32)(p)
140 buf = alg.I64toa(buf, int64(v))
141 case ir.OP_i64:
142 v := *(*int64)(p)
143 buf = alg.I64toa(buf, int64(v))
144 case ir.OP_u8:
145 v := *(*uint8)(p)
146 buf = alg.U64toa(buf, uint64(v))
147 case ir.OP_u16:
148 v := *(*uint16)(p)
149 buf = alg.U64toa(buf, uint64(v))
150 case ir.OP_u32:
151 v := *(*uint32)(p)
152 buf = alg.U64toa(buf, uint64(v))
153 case ir.OP_u64:
154 v := *(*uint64)(p)
155 buf = alg.U64toa(buf, uint64(v))
156 case ir.OP_f32:
157 v := *(*float32)(p)
158 if math.IsNaN(float64(v)) || math.IsInf(float64(v), 0) {
159 if flags&(1<<alg.BitEncodeNullForInfOrNan) != 0 {
160 buf = append(buf, 'n', 'u', 'l', 'l')
161 continue
162 }
163 return vars.ERR_nan_or_infinite
164 }
165 buf = alg.F32toa(buf, v)
166 case ir.OP_f64:
167 v := *(*float64)(p)
168 if math.IsNaN(v) || math.IsInf(v, 0) {
169 if flags&(1<<alg.BitEncodeNullForInfOrNan) != 0 {
170 buf = append(buf, 'n', 'u', 'l', 'l')
171 continue
172 }
173 return vars.ERR_nan_or_infinite
174 }
175 buf = alg.F64toa(buf, v)
176 case ir.OP_bin:
177 v := *(*[]byte)(p)
178 buf = rt.EncodeBase64(buf, v)
179 case ir.OP_quote:
180 v := *(*string)(p)
181 buf = alg.Quote(buf, v, true)
182 case ir.OP_number:
183 v := *(*json.Number)(p)
184 if v == "" {
185 buf = append(buf, '0')
186 } else if !rt.IsValidNumber(string(v)) {
187 return vars.Error_number(v)
188 } else {
189 buf = append(buf, v...)
190 }
191 case ir.OP_eface:
192 *b = buf
193 if err := EncodeTypedPointer(b, *(**rt.GoType)(p), (*unsafe.Pointer)(rt.Add(p, 8)), s, flags); err != nil {
194 return err
195 }
196 buf = *b
197 case ir.OP_iface:
198 *b = buf
199 if err := EncodeTypedPointer(b, (*(**rt.GoItab)(p)).Vt, (*unsafe.Pointer)(rt.Add(p, 8)), s, flags); err != nil {
200 return err
201 }
202 buf = *b
203 case ir.OP_is_zero_map:
204 v := *(*unsafe.Pointer)(p)
205 if v == nil || rt.Maplen(v) == 0 {
206 pc = ins.Vi()
207 continue
208 }
209 case ir.OP_map_iter:
210 v := *(*unsafe.Pointer)(p)
211 vt := ins.Vr()
212 it, err := alg.IteratorStart(rt.MapType(vt), v, flags)
213 if err != nil {
214 return err
215 }
216 q = unsafe.Pointer(it)
217 case ir.OP_map_stop:
218 it := (*alg.MapIterator)(q)
219 alg.IteratorStop(it)
220 q = nil
221 case ir.OP_map_value_next:
222 it := (*alg.MapIterator)(q)
223 p = it.It.V
224 alg.IteratorNext(it)
225 case ir.OP_map_check_key:
226 it := (*alg.MapIterator)(q)
227 if it.It.K == nil {
228 pc = ins.Vi()
229 continue
230 }
231 p = it.It.K
232 case ir.OP_marshal_text:
233 vt, itab := ins.Vtab()
234 var it rt.GoIface
235 switch vt.Kind() {
236 case reflect.Interface :
237 if is_nil(p) {
238 buf = append(buf, 'n', 'u', 'l', 'l')
239 continue
240 }
241 it = rt.AssertI2I(_T_encoding_TextMarshaler, *(*rt.GoIface)(p))
242 case reflect.Ptr, reflect.Map : it = convT2I(p, true, itab)
243 default : it = convT2I(p, !vt.Indirect(), itab)
244 }
245 if err := alg.EncodeTextMarshaler(&buf, *(*encoding.TextMarshaler)(unsafe.Pointer(&it)), (flags)); err != nil {
246 return err
247 }
248 case ir.OP_marshal_text_p:
249 _, itab := ins.Vtab()
250 it := convT2I(p, false, itab)
251 if err := alg.EncodeTextMarshaler(&buf, *(*encoding.TextMarshaler)(unsafe.Pointer(&it)), (flags)); err != nil {
252 return err
253 }
254 case ir.OP_map_write_key:
255 if has_opts(flags, alg.BitSortMapKeys) {
256 v := *(*string)(p)
257 buf = alg.Quote(buf, v, false)
258 pc = ins.Vi()
259 continue
260 }
261 case ir.OP_slice_len:
262 v := (*rt.GoSlice)(p)
263 x = v.Len
264 p = v.Ptr
265 //TODO: why?
266 f |= 1<<_S_init
267 case ir.OP_slice_next:
268 if x == 0 {
269 pc = ins.Vi()
270 continue
271 }
272 x--
273 if has_opts(f, _S_init) {
274 f &= ^uint64(1 << _S_init)
275 } else {
276 p = rt.Add(p, uintptr(ins.Vlen()))
277 }
278 case ir.OP_cond_set:
279 f |= 1<<_S_cond
280 case ir.OP_cond_testc:
281 if has_opts(f, _S_cond) {
282 f &= ^uint64(1 << _S_cond)
283 pc = ins.Vi()
284 continue
285 }
286 case ir.OP_is_zero:
287 fv := ins.VField()
288 if alg.IsZero(p, fv) {
289 pc = ins.Vi()
290 continue
291 }
292 case ir.OP_is_zero_1:
293 if *(*uint8)(p) == 0 {
294 pc = ins.Vi()
295 continue
296 }
297 case ir.OP_is_zero_2:
298 if *(*uint16)(p) == 0 {
299 pc = ins.Vi()
300 continue
301 }
302 case ir.OP_is_zero_4:
303 if *(*uint32)(p) == 0 {
304 pc = ins.Vi()
305 continue
306 }
307 case ir.OP_is_zero_8:
308 if *(*uint64)(p) == 0 {
309 pc = ins.Vi()
310 continue
311 }
312 case ir.OP_empty_arr:
313 if has_opts(flags, alg.BitNoNullSliceOrMap) {
314 buf = append(buf, '[', ']')
315 } else {
316 buf = append(buf, 'n', 'u', 'l', 'l')
317 }
318 case ir.OP_empty_obj:
319 if has_opts(flags, alg.BitNoNullSliceOrMap) {
320 buf = append(buf, '{', '}')
321 } else {
322 buf = append(buf, 'n', 'u', 'l', 'l')
323 }
324 case ir.OP_marshal:
325 vt, itab := ins.Vtab()
326 var it rt.GoIface
327 switch vt.Kind() {
328 case reflect.Interface :
329 if is_nil(p) {
330 buf = append(buf, 'n', 'u', 'l', 'l')
331 continue
332 }
333 it = rt.AssertI2I(_T_json_Marshaler, *(*rt.GoIface)(p))
334 case reflect.Ptr, reflect.Map : it = convT2I(p, true, itab)
335 default : it = convT2I(p, !vt.Indirect(), itab)
336 }
337 if err := alg.EncodeJsonMarshaler(&buf, *(*json.Marshaler)(unsafe.Pointer(&it)), (flags)); err != nil {
338 return err
339 }
340 case ir.OP_marshal_p:
341 _, itab := ins.Vtab()
342 it := convT2I(p, false, itab)
343 if err := alg.EncodeJsonMarshaler(&buf, *(*json.Marshaler)(unsafe.Pointer(&it)), (flags)); err != nil {
344 return err
345 }
346 case ir.OP_unsupported:
347 return vars.Error_unsuppoted(ins.GoType())
348 default:
349 panic(fmt.Sprintf("not implement %s at %d", ins.Op().String(), pc))
350 }
351 }
352
353 *b = buf
354 return nil
355 }
356
357
358 func has_opts(opts uint64, bit int) bool {
359 return opts & (1<<bit) != 0
360 }
361
362 func is_nil(p unsafe.Pointer) bool {
363 return *(*unsafe.Pointer)(p) == nil
364 }
365
366 func convT2I(ptr unsafe.Pointer, deref bool, itab *rt.GoItab) (rt.GoIface) {
367 if deref {
368 ptr = *(*unsafe.Pointer)(ptr)
369 }
370 return rt.GoIface{
371 Itab: itab,
372 Value: ptr,
373 }
374 }
375