podman

Форк
0
729 строк · 36.7 Кб
1
// +build go1.17,!go1.22
2

3
/*
4
 * Copyright 2021 ByteDance Inc.
5
 *
6
 * Licensed under the Apache License, Version 2.0 (the "License");
7
 * you may not use this file except in compliance with the License.
8
 * You may obtain a copy of the License at
9
 *
10
 *     http://www.apache.org/licenses/LICENSE-2.0
11
 *
12
 * Unless required by applicable law or agreed to in writing, software
13
 * distributed under the License is distributed on an "AS IS" BASIS,
14
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15
 * See the License for the specific language governing permissions and
16
 * limitations under the License.
17
 */
18

19
package decoder
20

21
import (
22
    `encoding/json`
23
    `fmt`
24
    `reflect`
25

26
    `github.com/bytedance/sonic/internal/jit`
27
    `github.com/bytedance/sonic/internal/native`
28
    `github.com/bytedance/sonic/internal/native/types`
29
    `github.com/twitchyliquid64/golang-asm/obj`
30
)
31

32
/** Crucial Registers:
33
 *
34
 *      ST(R13) && 0(SP) : ro, decoder stack
35
 *      DF(AX)  : ro, decoder flags
36
 *      EP(BX) : wo, error pointer
37
 *      IP(R10) : ro, input pointer
38
 *      IL(R12) : ro, input length
39
 *      IC(R11) : rw, input cursor
40
 *      VP(R15) : ro, value pointer (to an interface{})
41
 */
42

43
const (
44
    _VD_args   = 8      // 8 bytes  for passing arguments to this functions
45
    _VD_fargs  = 64     // 64 bytes for passing arguments to other Go functions
46
    _VD_saves  = 48     // 48 bytes for saving the registers before CALL instructions
47
    _VD_locals = 96     // 96 bytes for local variables
48
)
49

50
const (
51
    _VD_offs = _VD_fargs + _VD_saves + _VD_locals
52
    _VD_size = _VD_offs + 8     // 8 bytes for the parent frame pointer
53
)
54

55
var (
56
    _VAR_ss = _VAR_ss_Vt
57
    _VAR_df = jit.Ptr(_SP, _VD_fargs + _VD_saves)
58
)
59

60
var (
61
    _VAR_ss_Vt = jit.Ptr(_SP, _VD_fargs + _VD_saves + 8)
62
    _VAR_ss_Dv = jit.Ptr(_SP, _VD_fargs + _VD_saves + 16)
63
    _VAR_ss_Iv = jit.Ptr(_SP, _VD_fargs + _VD_saves + 24)
64
    _VAR_ss_Ep = jit.Ptr(_SP, _VD_fargs + _VD_saves + 32)
65
    _VAR_ss_Db = jit.Ptr(_SP, _VD_fargs + _VD_saves + 40)
66
    _VAR_ss_Dc = jit.Ptr(_SP, _VD_fargs + _VD_saves + 48)
67
)
68

69
var (
70
    _VAR_R9 = jit.Ptr(_SP, _VD_fargs + _VD_saves + 56)
71
)
72
type _ValueDecoder struct {
73
    jit.BaseAssembler
74
}
75

76
var (
77
    _VAR_cs_LR = jit.Ptr(_SP, _VD_fargs + _VD_saves + 64)
78
    _VAR_cs_p = jit.Ptr(_SP, _VD_fargs + _VD_saves + 72)
79
    _VAR_cs_n = jit.Ptr(_SP, _VD_fargs + _VD_saves + 80)
80
    _VAR_cs_d = jit.Ptr(_SP, _VD_fargs + _VD_saves + 88)
81
)
82

83
func (self *_ValueDecoder) build() uintptr {
84
    self.Init(self.compile)
85
    return *(*uintptr)(self.Load("decode_value", _VD_size, _VD_args, argPtrs_generic, localPtrs_generic))
86
}
87

88
/** Function Calling Helpers **/
89

90
func (self *_ValueDecoder) save(r ...obj.Addr) {
91
    for i, v := range r {
92
        if i > _VD_saves / 8 - 1 {
93
            panic("too many registers to save")
94
        } else {
95
            self.Emit("MOVQ", v, jit.Ptr(_SP, _VD_fargs + int64(i) * 8))
96
        }
97
    }
98
}
99

100
func (self *_ValueDecoder) load(r ...obj.Addr) {
101
    for i, v := range r {
102
        if i > _VD_saves / 8 - 1 {
103
            panic("too many registers to load")
104
        } else {
105
            self.Emit("MOVQ", jit.Ptr(_SP, _VD_fargs + int64(i) * 8), v)
106
        }
107
    }
108
}
109

110
func (self *_ValueDecoder) call(fn obj.Addr) {
111
    self.Emit("MOVQ", fn, _R9)  // MOVQ ${fn}, AX
112
    self.Rjmp("CALL", _R9)      // CALL AX
113
}
114

115
func (self *_ValueDecoder) call_go(fn obj.Addr) {
116
    self.save(_REG_go...)   // SAVE $REG_go
117
    self.call(fn)           // CALL ${fn}
118
    self.load(_REG_go...)   // LOAD $REG_go
119
}
120

121
func (self *_ValueDecoder) callc(fn obj.Addr) {
122
    self.save(_IP)  
123
    self.call(fn)
124
    self.load(_IP)  
125
}
126

127
func (self *_ValueDecoder) call_c(fn obj.Addr) {
128
    self.Emit("XCHGQ", _IC, _BX)
129
    self.callc(fn)
130
    self.Emit("XCHGQ", _IC, _BX)
131
}
132

133
/** Decoder Assembler **/
134

135
const (
136
    _S_val = iota + 1
137
    _S_arr
138
    _S_arr_0
139
    _S_obj
140
    _S_obj_0
141
    _S_obj_delim
142
    _S_obj_sep
143
)
144

145
const (
146
    _S_omask_key = (1 << _S_obj_0) | (1 << _S_obj_sep)
147
    _S_omask_end = (1 << _S_obj_0) | (1 << _S_obj)
148
    _S_vmask = (1 << _S_val) | (1 << _S_arr_0)
149
)
150

151
const (
152
    _A_init_len = 1
153
    _A_init_cap = 16
154
)
155

156
const (
157
    _ST_Sp = 0
158
    _ST_Vt = _PtrBytes
159
    _ST_Vp = _PtrBytes * (types.MAX_RECURSE + 1)
160
)
161

162
var (
163
    _V_true  = jit.Imm(int64(pbool(true)))
164
    _V_false = jit.Imm(int64(pbool(false)))
165
    _F_value = jit.Imm(int64(native.S_value))
166
)
167

168
var (
169
    _V_max     = jit.Imm(int64(types.V_MAX))
170
    _E_eof     = jit.Imm(int64(types.ERR_EOF))
171
    _E_invalid = jit.Imm(int64(types.ERR_INVALID_CHAR))
172
    _E_recurse = jit.Imm(int64(types.ERR_RECURSE_EXCEED_MAX))
173
)
174

175
var (
176
    _F_convTslice    = jit.Func(convTslice)
177
    _F_convTstring   = jit.Func(convTstring)
178
    _F_invalid_vtype = jit.Func(invalid_vtype)
179
)
180

181
var (
182
    _T_map     = jit.Type(reflect.TypeOf((map[string]interface{})(nil)))
183
    _T_bool    = jit.Type(reflect.TypeOf(false))
184
    _T_int64   = jit.Type(reflect.TypeOf(int64(0)))
185
    _T_eface   = jit.Type(reflect.TypeOf((*interface{})(nil)).Elem())
186
    _T_slice   = jit.Type(reflect.TypeOf(([]interface{})(nil)))
187
    _T_string  = jit.Type(reflect.TypeOf(""))
188
    _T_number  = jit.Type(reflect.TypeOf(json.Number("")))
189
    _T_float64 = jit.Type(reflect.TypeOf(float64(0)))
190
)
191

192
var _R_tab = map[int]string {
193
    '[': "_decode_V_ARRAY",
194
    '{': "_decode_V_OBJECT",
195
    ':': "_decode_V_KEY_SEP",
196
    ',': "_decode_V_ELEM_SEP",
197
    ']': "_decode_V_ARRAY_END",
198
    '}': "_decode_V_OBJECT_END",
199
}
200

201
func (self *_ValueDecoder) compile() {
202
    self.Emit("SUBQ", jit.Imm(_VD_size), _SP)       // SUBQ $_VD_size, SP
203
    self.Emit("MOVQ", _BP, jit.Ptr(_SP, _VD_offs))  // MOVQ BP, _VD_offs(SP)
204
    self.Emit("LEAQ", jit.Ptr(_SP, _VD_offs), _BP)  // LEAQ _VD_offs(SP), BP
205

206
    /* initialize the state machine */
207
    self.Emit("XORL", _CX, _CX)                                 // XORL CX, CX
208
    self.Emit("MOVQ", _DF, _VAR_df)                             // MOVQ DF, df
209
    /* initialize digital buffer first */
210
    self.Emit("MOVQ", jit.Imm(_MaxDigitNums), _VAR_ss_Dc)       // MOVQ $_MaxDigitNums, ss.Dcap
211
    self.Emit("LEAQ", jit.Ptr(_ST, _DbufOffset), _AX)           // LEAQ _DbufOffset(ST), AX
212
    self.Emit("MOVQ", _AX, _VAR_ss_Db)                          // MOVQ AX, ss.Dbuf
213
    /* add ST offset */
214
    self.Emit("ADDQ", jit.Imm(_FsmOffset), _ST)                 // ADDQ _FsmOffset, _ST
215
    self.Emit("MOVQ", _CX, jit.Ptr(_ST, _ST_Sp))                // MOVQ CX, ST.Sp
216
    self.WriteRecNotAX(0, _VP, jit.Ptr(_ST, _ST_Vp), false)                // MOVQ VP, ST.Vp[0]
217
    self.Emit("MOVQ", jit.Imm(_S_val), jit.Ptr(_ST, _ST_Vt))    // MOVQ _S_val, ST.Vt[0]
218
    self.Sjmp("JMP" , "_next")                                  // JMP  _next
219

220
    /* set the value from previous round */
221
    self.Link("_set_value")                                 // _set_value:
222
    self.Emit("MOVL" , jit.Imm(_S_vmask), _DX)              // MOVL  _S_vmask, DX
223
    self.Emit("MOVQ" , jit.Ptr(_ST, _ST_Sp), _CX)           // MOVQ  ST.Sp, CX
224
    self.Emit("MOVQ" , jit.Sib(_ST, _CX, 8, _ST_Vt), _AX)   // MOVQ  ST.Vt[CX], AX
225
    self.Emit("BTQ"  , _AX, _DX)                            // BTQ   AX, DX
226
    self.Sjmp("JNC"  , "_vtype_error")                      // JNC   _vtype_error
227
    self.Emit("XORL" , _SI, _SI)                            // XORL  SI, SI
228
    self.Emit("SUBQ" , jit.Imm(1), jit.Ptr(_ST, _ST_Sp))    // SUBQ  $1, ST.Sp
229
    self.Emit("XCHGQ", jit.Sib(_ST, _CX, 8, _ST_Vp), _SI)   // XCHGQ ST.Vp[CX], SI
230
    self.Emit("MOVQ" , _R8, jit.Ptr(_SI, 0))                // MOVQ  R8, (SI)
231
    self.WriteRecNotAX(1, _R9, jit.Ptr(_SI, 8), false)           // MOVQ  R9, 8(SI)
232

233
    /* check for value stack */
234
    self.Link("_next")                              // _next:
235
    self.Emit("MOVQ" , jit.Ptr(_ST, _ST_Sp), _AX)   // MOVQ  ST.Sp, AX
236
    self.Emit("TESTQ", _AX, _AX)                    // TESTQ AX, AX
237
    self.Sjmp("JS"   , "_return")                   // JS    _return
238

239
    /* fast path: test up to 4 characters manually */
240
    self.Emit("CMPQ"   , _IC, _IL)                      // CMPQ    IC, IL
241
    self.Sjmp("JAE"    , "_decode_V_EOF")               // JAE     _decode_V_EOF
242
    self.Emit("MOVBQZX", jit.Sib(_IP, _IC, 1, 0), _AX)  // MOVBQZX (IP)(IC), AX
243
    self.Emit("MOVQ"   , jit.Imm(_BM_space), _DX)       // MOVQ    _BM_space, DX
244
    self.Emit("CMPQ"   , _AX, jit.Imm(' '))             // CMPQ    AX, $' '
245
    self.Sjmp("JA"     , "_decode_fast")                // JA      _decode_fast
246
    self.Emit("BTQ"    , _AX, _DX)                      // BTQ     _AX, _DX
247
    self.Sjmp("JNC"    , "_decode_fast")                // JNC     _decode_fast
248
    self.Emit("ADDQ"   , jit.Imm(1), _IC)               // ADDQ    $1, IC
249

250
    /* at least 1 to 3 spaces */
251
    for i := 0; i < 3; i++ {
252
        self.Emit("CMPQ"   , _IC, _IL)                      // CMPQ    IC, IL
253
        self.Sjmp("JAE"    , "_decode_V_EOF")               // JAE     _decode_V_EOF
254
        self.Emit("MOVBQZX", jit.Sib(_IP, _IC, 1, 0), _AX)  // MOVBQZX (IP)(IC), AX
255
        self.Emit("CMPQ"   , _AX, jit.Imm(' '))             // CMPQ    AX, $' '
256
        self.Sjmp("JA"     , "_decode_fast")                // JA      _decode_fast
257
        self.Emit("BTQ"    , _AX, _DX)                      // BTQ     _AX, _DX
258
        self.Sjmp("JNC"    , "_decode_fast")                // JNC     _decode_fast
259
        self.Emit("ADDQ"   , jit.Imm(1), _IC)               // ADDQ    $1, IC
260
    }
261

262
    /* at least 4 spaces */
263
    self.Emit("CMPQ"   , _IC, _IL)                      // CMPQ    IC, IL
264
    self.Sjmp("JAE"    , "_decode_V_EOF")               // JAE     _decode_V_EOF
265
    self.Emit("MOVBQZX", jit.Sib(_IP, _IC, 1, 0), _AX)  // MOVBQZX (IP)(IC), AX
266

267
    /* fast path: use lookup table to select decoder */
268
    self.Link("_decode_fast")                           // _decode_fast:
269
    self.Byte(0x48, 0x8d, 0x3d)                         // LEAQ    ?(PC), DI
270
    self.Sref("_decode_tab", 4)                         // ....    &_decode_tab
271
    self.Emit("MOVLQSX", jit.Sib(_DI, _AX, 4, 0), _AX)  // MOVLQSX (DI)(AX*4), AX
272
    self.Emit("TESTQ"  , _AX, _AX)                      // TESTQ   AX, AX
273
    self.Sjmp("JZ"     , "_decode_native")              // JZ      _decode_native
274
    self.Emit("ADDQ"   , jit.Imm(1), _IC)               // ADDQ    $1, IC
275
    self.Emit("ADDQ"   , _DI, _AX)                      // ADDQ    DI, AX
276
    self.Rjmp("JMP"    , _AX)                           // JMP     AX
277

278
    /* decode with native decoder */
279
    self.Link("_decode_native")         // _decode_native:
280
    self.Emit("MOVQ", _IP, _DI)         // MOVQ IP, DI
281
    self.Emit("MOVQ", _IL, _SI)         // MOVQ IL, SI
282
    self.Emit("MOVQ", _IC, _DX)         // MOVQ IC, DX
283
    self.Emit("LEAQ", _VAR_ss, _CX)     // LEAQ ss, CX
284
    self.Emit("MOVQ", _VAR_df, _R8)     // MOVQ $df, R8
285
    self.Emit("BTSQ", jit.Imm(_F_allow_control), _R8)  // ANDQ $1<<_F_allow_control, R8
286
    self.callc(_F_value)                // CALL value
287
    self.Emit("MOVQ", _AX, _IC)         // MOVQ AX, IC
288

289
    /* check for errors */
290
    self.Emit("MOVQ" , _VAR_ss_Vt, _AX)     // MOVQ  ss.Vt, AX
291
    self.Emit("TESTQ", _AX, _AX)            // TESTQ AX, AX
292
    self.Sjmp("JS"   , "_parsing_error")       
293
    self.Sjmp("JZ"   , "_invalid_vtype")    // JZ    _invalid_vtype
294
    self.Emit("CMPQ" , _AX, _V_max)         // CMPQ  AX, _V_max
295
    self.Sjmp("JA"   , "_invalid_vtype")    // JA    _invalid_vtype
296

297
    /* jump table selector */
298
    self.Byte(0x48, 0x8d, 0x3d)                             // LEAQ    ?(PC), DI
299
    self.Sref("_switch_table", 4)                           // ....    &_switch_table
300
    self.Emit("MOVLQSX", jit.Sib(_DI, _AX, 4, -4), _AX)     // MOVLQSX -4(DI)(AX*4), AX
301
    self.Emit("ADDQ"   , _DI, _AX)                          // ADDQ    DI, AX
302
    self.Rjmp("JMP"    , _AX)                               // JMP     AX
303

304
    /** V_EOF **/
305
    self.Link("_decode_V_EOF")          // _decode_V_EOF:
306
    self.Emit("MOVL", _E_eof, _EP)      // MOVL _E_eof, EP
307
    self.Sjmp("JMP" , "_error")         // JMP  _error
308

309
    /** V_NULL **/
310
    self.Link("_decode_V_NULL")                 // _decode_V_NULL:
311
    self.Emit("XORL", _R8, _R8)                 // XORL R8, R8
312
    self.Emit("XORL", _R9, _R9)                 // XORL R9, R9
313
    self.Emit("LEAQ", jit.Ptr(_IC, -4), _DI)    // LEAQ -4(IC), DI
314
    self.Sjmp("JMP" , "_set_value")             // JMP  _set_value
315

316
    /** V_TRUE **/
317
    self.Link("_decode_V_TRUE")                 // _decode_V_TRUE:
318
    self.Emit("MOVQ", _T_bool, _R8)             // MOVQ _T_bool, R8
319
    // TODO: maybe modified by users?
320
    self.Emit("MOVQ", _V_true, _R9)             // MOVQ _V_true, R9 
321
    self.Emit("LEAQ", jit.Ptr(_IC, -4), _DI)    // LEAQ -4(IC), DI
322
    self.Sjmp("JMP" , "_set_value")             // JMP  _set_value
323

324
    /** V_FALSE **/
325
    self.Link("_decode_V_FALSE")                // _decode_V_FALSE:
326
    self.Emit("MOVQ", _T_bool, _R8)             // MOVQ _T_bool, R8
327
    self.Emit("MOVQ", _V_false, _R9)            // MOVQ _V_false, R9
328
    self.Emit("LEAQ", jit.Ptr(_IC, -5), _DI)    // LEAQ -5(IC), DI
329
    self.Sjmp("JMP" , "_set_value")             // JMP  _set_value
330

331
    /** V_ARRAY **/
332
    self.Link("_decode_V_ARRAY")                            // _decode_V_ARRAY
333
    self.Emit("MOVL", jit.Imm(_S_vmask), _DX)               // MOVL _S_vmask, DX
334
    self.Emit("MOVQ", jit.Ptr(_ST, _ST_Sp), _CX)            // MOVQ ST.Sp, CX
335
    self.Emit("MOVQ", jit.Sib(_ST, _CX, 8, _ST_Vt), _AX)    // MOVQ ST.Vt[CX], AX
336
    self.Emit("BTQ" , _AX, _DX)                             // BTQ  AX, DX
337
    self.Sjmp("JNC" , "_invalid_char")                      // JNC  _invalid_char
338

339
    /* create a new array */
340
    self.Emit("MOVQ", _T_eface, _AX)                            // MOVQ    _T_eface, AX
341
    self.Emit("MOVQ", jit.Imm(_A_init_len), _BX)                // MOVQ    _A_init_len, BX
342
    self.Emit("MOVQ", jit.Imm(_A_init_cap), _CX)                // MOVQ    _A_init_cap, CX
343
    self.call_go(_F_makeslice)                                  // CALL_GO runtime.makeslice
344

345
    /* pack into an interface */
346
    self.Emit("MOVQ", jit.Imm(_A_init_len), _BX)                // MOVQ    _A_init_len, BX
347
    self.Emit("MOVQ", jit.Imm(_A_init_cap), _CX)                // MOVQ    _A_init_cap, CX
348
    self.call_go(_F_convTslice)                                 // CALL_GO runtime.convTslice
349
    self.Emit("MOVQ", _AX, _R8)                                 // MOVQ    AX, R8
350

351
    /* replace current state with an array */
352
    self.Emit("MOVQ", jit.Ptr(_ST, _ST_Sp), _CX)                        // MOVQ ST.Sp, CX
353
    self.Emit("MOVQ", jit.Sib(_ST, _CX, 8, _ST_Vp), _SI)                // MOVQ ST.Vp[CX], SI
354
    self.Emit("MOVQ", jit.Imm(_S_arr), jit.Sib(_ST, _CX, 8, _ST_Vt))    // MOVQ _S_arr, ST.Vt[CX]
355
    self.Emit("MOVQ", _T_slice, _AX)                                    // MOVQ _T_slice, AX
356
    self.Emit("MOVQ", _AX, jit.Ptr(_SI, 0))                             // MOVQ AX, (SI)
357
    self.WriteRecNotAX(2, _R8, jit.Ptr(_SI, 8), false)                  // MOVQ R8, 8(SI)
358

359
    /* add a new slot for the first element */
360
    self.Emit("ADDQ", jit.Imm(1), _CX)                                  // ADDQ $1, CX
361
    self.Emit("CMPQ", _CX, jit.Imm(types.MAX_RECURSE))                  // CMPQ CX, ${types.MAX_RECURSE}
362
    self.Sjmp("JAE"  , "_stack_overflow")                                // JA   _stack_overflow
363
    self.Emit("MOVQ", jit.Ptr(_R8, 0), _AX)                             // MOVQ (R8), AX
364
    self.Emit("MOVQ", _CX, jit.Ptr(_ST, _ST_Sp))                        // MOVQ CX, ST.Sp
365
    self.WritePtrAX(3, jit.Sib(_ST, _CX, 8, _ST_Vp), false)             // MOVQ AX, ST.Vp[CX]
366
    self.Emit("MOVQ", jit.Imm(_S_arr_0), jit.Sib(_ST, _CX, 8, _ST_Vt))  // MOVQ _S_arr_0, ST.Vt[CX]
367
    self.Sjmp("JMP" , "_next")                                          // JMP  _next
368

369
    /** V_OBJECT **/
370
    self.Link("_decode_V_OBJECT")                                       // _decode_V_OBJECT:
371
    self.Emit("MOVL", jit.Imm(_S_vmask), _DX)                           // MOVL    _S_vmask, DX
372
    self.Emit("MOVQ", jit.Ptr(_ST, _ST_Sp), _CX)                        // MOVQ    ST.Sp, CX
373
    self.Emit("MOVQ", jit.Sib(_ST, _CX, 8, _ST_Vt), _AX)                // MOVQ    ST.Vt[CX], AX
374
    self.Emit("BTQ" , _AX, _DX)                                         // BTQ     AX, DX
375
    self.Sjmp("JNC" , "_invalid_char")                                  // JNC     _invalid_char
376
    self.call_go(_F_makemap_small)                                      // CALL_GO runtime.makemap_small
377
    self.Emit("MOVQ", jit.Ptr(_ST, _ST_Sp), _CX)                        // MOVQ    ST.Sp, CX
378
    self.Emit("MOVQ", jit.Imm(_S_obj_0), jit.Sib(_ST, _CX, 8, _ST_Vt))    // MOVQ    _S_obj_0, ST.Vt[CX]
379
    self.Emit("MOVQ", jit.Sib(_ST, _CX, 8, _ST_Vp), _SI)                // MOVQ    ST.Vp[CX], SI
380
    self.Emit("MOVQ", _T_map, _DX)                                      // MOVQ    _T_map, DX
381
    self.Emit("MOVQ", _DX, jit.Ptr(_SI, 0))                             // MOVQ    DX, (SI)
382
    self.WritePtrAX(4, jit.Ptr(_SI, 8), false)                          // MOVQ    AX, 8(SI)
383
    self.Sjmp("JMP" , "_next")                                          // JMP     _next
384

385
    /** V_STRING **/
386
    self.Link("_decode_V_STRING")       // _decode_V_STRING:
387
    self.Emit("MOVQ", _VAR_ss_Iv, _CX)  // MOVQ ss.Iv, CX
388
    self.Emit("MOVQ", _IC, _AX)         // MOVQ IC, AX
389
    self.Emit("SUBQ", _CX, _AX)         // SUBQ CX, AX
390

391
    /* check for escapes */
392
    self.Emit("CMPQ", _VAR_ss_Ep, jit.Imm(-1))          // CMPQ ss.Ep, $-1
393
    self.Sjmp("JNE" , "_unquote")                       // JNE  _unquote
394
    self.Emit("SUBQ", jit.Imm(1), _AX)                  // SUBQ $1, AX
395
    self.Emit("LEAQ", jit.Sib(_IP, _CX, 1, 0), _R8)     // LEAQ (IP)(CX), R8
396
    self.Byte(0x48, 0x8d, 0x3d)                         // LEAQ (PC), DI
397
    self.Sref("_copy_string_end", 4)
398
    self.Emit("BTQ", jit.Imm(_F_copy_string), _VAR_df)
399
    self.Sjmp("JC", "copy_string")
400
    self.Link("_copy_string_end")                                 
401
    self.Emit("XORL", _DX, _DX)   
402

403
    /* strings with no escape sequences */
404
    self.Link("_noescape")                                  // _noescape:
405
    self.Emit("MOVL", jit.Imm(_S_omask_key), _DI)               // MOVL _S_omask, DI
406
    self.Emit("MOVQ", jit.Ptr(_ST, _ST_Sp), _CX)            // MOVQ ST.Sp, CX
407
    self.Emit("MOVQ", jit.Sib(_ST, _CX, 8, _ST_Vt), _SI)    // MOVQ ST.Vt[CX], SI
408
    self.Emit("BTQ" , _SI, _DI)                             // BTQ  SI, DI
409
    self.Sjmp("JC"  , "_object_key")                        // JC   _object_key
410

411
    /* check for pre-packed strings, avoid 1 allocation */
412
    self.Emit("TESTQ", _DX, _DX)                // TESTQ   DX, DX
413
    self.Sjmp("JNZ"  , "_packed_str")           // JNZ     _packed_str
414
    self.Emit("MOVQ" , _AX, _BX)                // MOVQ    AX, BX
415
    self.Emit("MOVQ" , _R8, _AX)                // MOVQ    R8, AX
416
    self.call_go(_F_convTstring)                // CALL_GO runtime.convTstring
417
    self.Emit("MOVQ" , _AX, _R9)                // MOVQ    AX, R9
418

419
    /* packed string already in R9 */
420
    self.Link("_packed_str")            // _packed_str:
421
    self.Emit("MOVQ", _T_string, _R8)   // MOVQ _T_string, R8
422
    self.Emit("MOVQ", _VAR_ss_Iv, _DI)  // MOVQ ss.Iv, DI
423
    self.Emit("SUBQ", jit.Imm(1), _DI)  // SUBQ $1, DI
424
    self.Sjmp("JMP" , "_set_value")     // JMP  _set_value
425

426
    /* the string is an object key, get the map */
427
    self.Link("_object_key")
428
    self.Emit("MOVQ", jit.Ptr(_ST, _ST_Sp), _CX)            // MOVQ ST.Sp, CX
429
    self.Emit("MOVQ", jit.Sib(_ST, _CX, 8, _ST_Vp), _SI)    // MOVQ ST.Vp[CX], SI
430
    self.Emit("MOVQ", jit.Ptr(_SI, 8), _SI)                 // MOVQ 8(SI), SI
431

432
    /* add a new delimiter */
433
    self.Emit("ADDQ", jit.Imm(1), _CX)                                      // ADDQ $1, CX
434
    self.Emit("CMPQ", _CX, jit.Imm(types.MAX_RECURSE))                      // CMPQ CX, ${types.MAX_RECURSE}
435
    self.Sjmp("JAE"  , "_stack_overflow")                                    // JA   _stack_overflow
436
    self.Emit("MOVQ", _CX, jit.Ptr(_ST, _ST_Sp))                            // MOVQ CX, ST.Sp
437
    self.Emit("MOVQ", jit.Imm(_S_obj_delim), jit.Sib(_ST, _CX, 8, _ST_Vt))  // MOVQ _S_obj_delim, ST.Vt[CX]
438

439
    /* add a new slot int the map */
440
    self.Emit("MOVQ", _AX, _DI)                         // MOVQ    AX, DI
441
    self.Emit("MOVQ", _T_map, _AX)                      // MOVQ    _T_map, AX
442
    self.Emit("MOVQ", _SI, _BX)                         // MOVQ    SI, BX
443
    self.Emit("MOVQ", _R8, _CX)                         // MOVQ    R9, CX
444
    self.call_go(_F_mapassign_faststr)                  // CALL_GO runtime.mapassign_faststr
445

446
    /* add to the pointer stack */
447
    self.Emit("MOVQ", jit.Ptr(_ST, _ST_Sp), _CX)                 // MOVQ ST.Sp, CX
448
    self.WritePtrAX(6, jit.Sib(_ST, _CX, 8, _ST_Vp), false)    // MOVQ AX, ST.Vp[CX]
449
    self.Sjmp("JMP" , "_next")                                   // JMP  _next
450

451
    /* allocate memory to store the string header and unquoted result */
452
    self.Link("_unquote")                               // _unquote:
453
    self.Emit("ADDQ", jit.Imm(15), _AX)                 // ADDQ    $15, AX
454
    self.Emit("MOVQ", _T_byte, _BX)                     // MOVQ    _T_byte, BX
455
    self.Emit("MOVB", jit.Imm(0), _CX)                  // MOVB    $0, CX
456
    self.call_go(_F_mallocgc)                           // CALL_GO runtime.mallocgc
457
    self.Emit("MOVQ", _AX, _R9)                         // MOVQ    AX, R9
458

459
    /* prepare the unquoting parameters */
460
    self.Emit("MOVQ" , _VAR_ss_Iv, _CX)                         // MOVQ  ss.Iv, CX
461
    self.Emit("LEAQ" , jit.Sib(_IP, _CX, 1, 0), _DI)            // LEAQ  (IP)(CX), DI
462
    self.Emit("NEGQ" , _CX)                                     // NEGQ  CX
463
    self.Emit("LEAQ" , jit.Sib(_IC, _CX, 1, -1), _SI)           // LEAQ  -1(IC)(CX), SI
464
    self.Emit("LEAQ" , jit.Ptr(_R9, 16), _DX)                   // LEAQ  16(R8), DX
465
    self.Emit("LEAQ" , _VAR_ss_Ep, _CX)                         // LEAQ  ss.Ep, CX
466
    self.Emit("XORL" , _R8, _R8)                                // XORL  R8, R8
467
    self.Emit("BTQ"  , jit.Imm(_F_disable_urc), _VAR_df)        // BTQ   ${_F_disable_urc}, fv
468
    self.Emit("SETCC", _R8)                                     // SETCC R8
469
    self.Emit("SHLQ" , jit.Imm(types.B_UNICODE_REPLACE), _R8)   // SHLQ  ${types.B_UNICODE_REPLACE}, R8
470

471
    /* unquote the string, with R9 been preserved */
472
    self.Emit("MOVQ", _R9, _VAR_R9)             // SAVE R9
473
    self.call_c(_F_unquote)                     // CALL unquote
474
    self.Emit("MOVQ", _VAR_R9, _R9)             // LOAD R9
475

476
    /* check for errors */
477
    self.Emit("TESTQ", _AX, _AX)                // TESTQ AX, AX
478
    self.Sjmp("JS"   , "_unquote_error")        // JS    _unquote_error
479
    self.Emit("MOVL" , jit.Imm(1), _DX)         // MOVL  $1, DX
480
    self.Emit("LEAQ" , jit.Ptr(_R9, 16), _R8)   // ADDQ  $16, R8
481
    self.Emit("MOVQ" , _R8, jit.Ptr(_R9, 0))    // MOVQ  R8, (R9)
482
    self.Emit("MOVQ" , _AX, jit.Ptr(_R9, 8))    // MOVQ  AX, 8(R9)
483
    self.Sjmp("JMP"  , "_noescape")             // JMP   _noescape
484

485
    /** V_DOUBLE **/
486
    self.Link("_decode_V_DOUBLE")                           // _decode_V_DOUBLE:
487
    self.Emit("BTQ"  , jit.Imm(_F_use_number), _VAR_df)     // BTQ     _F_use_number, df
488
    self.Sjmp("JC"   , "_use_number")                       // JC      _use_number
489
    self.Emit("MOVSD", _VAR_ss_Dv, _X0)                     // MOVSD   ss.Dv, X0
490
    self.Sjmp("JMP"  , "_use_float64")                      // JMP     _use_float64
491

492
    /** V_INTEGER **/
493
    self.Link("_decode_V_INTEGER")                          // _decode_V_INTEGER:
494
    self.Emit("BTQ"     , jit.Imm(_F_use_number), _VAR_df)  // BTQ      _F_use_number, df
495
    self.Sjmp("JC"      , "_use_number")                    // JC       _use_number
496
    self.Emit("BTQ"     , jit.Imm(_F_use_int64), _VAR_df)   // BTQ      _F_use_int64, df
497
    self.Sjmp("JC"      , "_use_int64")                     // JC       _use_int64
498
    //TODO: use ss.Dv directly
499
    self.Emit("MOVSD", _VAR_ss_Dv, _X0)                  // MOVSD   ss.Dv, X0
500

501
    /* represent numbers as `float64` */
502
    self.Link("_use_float64")                   // _use_float64:
503
    self.Emit("MOVQ" , _X0, _AX)                // MOVQ   X0, AX
504
    self.call_go(_F_convT64)                    // CALL_GO runtime.convT64
505
    self.Emit("MOVQ" , _T_float64, _R8)         // MOVQ    _T_float64, R8
506
    self.Emit("MOVQ" , _AX, _R9)                // MOVQ    AX, R9
507
    self.Emit("MOVQ" , _VAR_ss_Ep, _DI)         // MOVQ    ss.Ep, DI
508
    self.Sjmp("JMP"  , "_set_value")            // JMP     _set_value
509

510
    /* represent numbers as `json.Number` */
511
    self.Link("_use_number")                            // _use_number
512
    self.Emit("MOVQ", _VAR_ss_Ep, _AX)                  // MOVQ    ss.Ep, AX
513
    self.Emit("LEAQ", jit.Sib(_IP, _AX, 1, 0), _SI)     // LEAQ    (IP)(AX), SI
514
    self.Emit("MOVQ", _IC, _CX)                         // MOVQ    IC, CX
515
    self.Emit("SUBQ", _AX, _CX)                         // SUBQ    AX, CX
516
    self.Emit("MOVQ", _SI, _AX)                         // MOVQ    SI, AX
517
    self.Emit("MOVQ", _CX, _BX)                         // MOVQ    CX, BX
518
    self.call_go(_F_convTstring)                        // CALL_GO runtime.convTstring
519
    self.Emit("MOVQ", _T_number, _R8)                   // MOVQ    _T_number, R8
520
    self.Emit("MOVQ", _AX, _R9)                         // MOVQ    AX, R9
521
    self.Emit("MOVQ", _VAR_ss_Ep, _DI)                  // MOVQ    ss.Ep, DI
522
    self.Sjmp("JMP" , "_set_value")                     // JMP     _set_value
523

524
    /* represent numbers as `int64` */
525
    self.Link("_use_int64")                     // _use_int64:
526
    self.Emit("MOVQ", _VAR_ss_Iv, _AX)          // MOVQ    ss.Iv, AX
527
    self.call_go(_F_convT64)                    // CALL_GO runtime.convT64
528
    self.Emit("MOVQ", _T_int64, _R8)            // MOVQ    _T_int64, R8
529
    self.Emit("MOVQ", _AX, _R9)                 // MOVQ    AX, R9
530
    self.Emit("MOVQ", _VAR_ss_Ep, _DI)          // MOVQ    ss.Ep, DI
531
    self.Sjmp("JMP" , "_set_value")             // JMP     _set_value
532

533
    /** V_KEY_SEP **/
534
    self.Link("_decode_V_KEY_SEP")                                          // _decode_V_KEY_SEP:
535
    self.Emit("MOVQ", jit.Ptr(_ST, _ST_Sp), _CX)                            // MOVQ ST.Sp, CX
536
    self.Emit("MOVQ", jit.Sib(_ST, _CX, 8, _ST_Vt), _AX)                    // MOVQ ST.Vt[CX], AX
537
    self.Emit("CMPQ", _AX, jit.Imm(_S_obj_delim))                           // CMPQ AX, _S_obj_delim
538
    self.Sjmp("JNE" , "_invalid_char")                                      // JNE  _invalid_char
539
    self.Emit("MOVQ", jit.Imm(_S_val), jit.Sib(_ST, _CX, 8, _ST_Vt))        // MOVQ _S_val, ST.Vt[CX]
540
    self.Emit("MOVQ", jit.Imm(_S_obj), jit.Sib(_ST, _CX, 8, _ST_Vt - 8))    // MOVQ _S_obj, ST.Vt[CX - 1]
541
    self.Sjmp("JMP" , "_next")                                              // JMP  _next
542

543
    /** V_ELEM_SEP **/
544
    self.Link("_decode_V_ELEM_SEP")                          // _decode_V_ELEM_SEP:
545
    self.Emit("MOVQ" , jit.Ptr(_ST, _ST_Sp), _CX)            // MOVQ     ST.Sp, CX
546
    self.Emit("MOVQ" , jit.Sib(_ST, _CX, 8, _ST_Vt), _AX)    // MOVQ     ST.Vt[CX], AX
547
    self.Emit("CMPQ" , _AX, jit.Imm(_S_arr))      
548
    self.Sjmp("JE"   , "_array_sep")                         // JZ       _next
549
    self.Emit("CMPQ" , _AX, jit.Imm(_S_obj))                 // CMPQ     _AX, _S_arr
550
    self.Sjmp("JNE"  , "_invalid_char")                      // JNE      _invalid_char
551
    self.Emit("MOVQ" , jit.Imm(_S_obj_sep), jit.Sib(_ST, _CX, 8, _ST_Vt))
552
    self.Sjmp("JMP"  , "_next")                              // JMP      _next
553

554
    /* arrays */
555
    self.Link("_array_sep")
556
    self.Emit("MOVQ", jit.Sib(_ST, _CX, 8, _ST_Vp), _SI)    // MOVQ ST.Vp[CX], SI
557
    self.Emit("MOVQ", jit.Ptr(_SI, 8), _SI)                 // MOVQ 8(SI), SI
558
    self.Emit("MOVQ", jit.Ptr(_SI, 8), _DX)                 // MOVQ 8(SI), DX
559
    self.Emit("CMPQ", _DX, jit.Ptr(_SI, 16))                // CMPQ DX, 16(SI)
560
    self.Sjmp("JAE" , "_array_more")                        // JAE  _array_more
561

562
    /* add a slot for the new element */
563
    self.Link("_array_append")                                          // _array_append:
564
    self.Emit("ADDQ", jit.Imm(1), jit.Ptr(_SI, 8))                      // ADDQ $1, 8(SI)
565
    self.Emit("MOVQ", jit.Ptr(_SI, 0), _SI)                             // MOVQ (SI), SI
566
    self.Emit("ADDQ", jit.Imm(1), _CX)                                  // ADDQ $1, CX
567
    self.Emit("CMPQ", _CX, jit.Imm(types.MAX_RECURSE))                  // CMPQ CX, ${types.MAX_RECURSE}
568
    self.Sjmp("JAE"  , "_stack_overflow")                                // JA   _stack_overflow
569
    self.Emit("SHLQ", jit.Imm(1), _DX)                                  // SHLQ $1, DX
570
    self.Emit("LEAQ", jit.Sib(_SI, _DX, 8, 0), _SI)                     // LEAQ (SI)(DX*8), SI
571
    self.Emit("MOVQ", _CX, jit.Ptr(_ST, _ST_Sp))                        // MOVQ CX, ST.Sp
572
    self.WriteRecNotAX(7 , _SI, jit.Sib(_ST, _CX, 8, _ST_Vp), false)           // MOVQ SI, ST.Vp[CX]
573
    self.Emit("MOVQ", jit.Imm(_S_val), jit.Sib(_ST, _CX, 8, _ST_Vt))    // MOVQ _S_val, ST.Vt[CX}
574
    self.Sjmp("JMP" , "_next")                                          // JMP  _next
575

576
    /** V_ARRAY_END **/
577
    self.Link("_decode_V_ARRAY_END")                        // _decode_V_ARRAY_END:
578
    self.Emit("XORL", _DX, _DX)                             // XORL DX, DX
579
    self.Emit("MOVQ", jit.Ptr(_ST, _ST_Sp), _CX)            // MOVQ ST.Sp, CX
580
    self.Emit("MOVQ", jit.Sib(_ST, _CX, 8, _ST_Vt), _AX)    // MOVQ ST.Vt[CX], AX
581
    self.Emit("CMPQ", _AX, jit.Imm(_S_arr_0))               // CMPQ AX, _S_arr_0
582
    self.Sjmp("JE"  , "_first_item")                        // JE   _first_item
583
    self.Emit("CMPQ", _AX, jit.Imm(_S_arr))                 // CMPQ AX, _S_arr
584
    self.Sjmp("JNE" , "_invalid_char")                      // JNE  _invalid_char
585
    self.Emit("SUBQ", jit.Imm(1), jit.Ptr(_ST, _ST_Sp))     // SUBQ $1, ST.Sp
586
    self.Emit("MOVQ", _DX, jit.Sib(_ST, _CX, 8, _ST_Vp))    // MOVQ DX, ST.Vp[CX]
587
    self.Sjmp("JMP" , "_next")                              // JMP  _next
588

589
    /* first element of an array */
590
    self.Link("_first_item")                                    // _first_item:
591
    self.Emit("MOVQ", jit.Ptr(_ST, _ST_Sp), _CX)                // MOVQ ST.Sp, CX
592
    self.Emit("SUBQ", jit.Imm(2), jit.Ptr(_ST, _ST_Sp))         // SUBQ $2, ST.Sp
593
    self.Emit("MOVQ", jit.Sib(_ST, _CX, 8, _ST_Vp - 8), _SI)    // MOVQ ST.Vp[CX - 1], SI
594
    self.Emit("MOVQ", jit.Ptr(_SI, 8), _SI)                     // MOVQ 8(SI), SI
595
    self.Emit("MOVQ", _DX, jit.Sib(_ST, _CX, 8, _ST_Vp - 8))    // MOVQ DX, ST.Vp[CX - 1]
596
    self.Emit("MOVQ", _DX, jit.Sib(_ST, _CX, 8, _ST_Vp))        // MOVQ DX, ST.Vp[CX]
597
    self.Emit("MOVQ", _DX, jit.Ptr(_SI, 8))                     // MOVQ DX, 8(SI)
598
    self.Sjmp("JMP" , "_next")                                  // JMP  _next
599

600
    /** V_OBJECT_END **/
601
    self.Link("_decode_V_OBJECT_END")                       // _decode_V_OBJECT_END:
602
    self.Emit("MOVL", jit.Imm(_S_omask_end), _DI)           // MOVL _S_omask, DI
603
    self.Emit("MOVQ", jit.Ptr(_ST, _ST_Sp), _CX)            // MOVQ ST.Sp, CX
604
    self.Emit("MOVQ", jit.Sib(_ST, _CX, 8, _ST_Vt), _AX)    // MOVQ ST.Vt[CX], AX
605
    self.Emit("BTQ" , _AX, _DI)                    
606
    self.Sjmp("JNC" , "_invalid_char")                      // JNE  _invalid_char
607
    self.Emit("XORL", _AX, _AX)                             // XORL AX, AX
608
    self.Emit("SUBQ", jit.Imm(1), jit.Ptr(_ST, _ST_Sp))     // SUBQ $1, ST.Sp
609
    self.Emit("MOVQ", _AX, jit.Sib(_ST, _CX, 8, _ST_Vp))    // MOVQ AX, ST.Vp[CX]
610
    self.Sjmp("JMP" , "_next")                              // JMP  _next
611

612
    /* return from decoder */
613
    self.Link("_return")                            // _return:
614
    self.Emit("XORL", _EP, _EP)                     // XORL EP, EP
615
    self.Emit("MOVQ", _EP, jit.Ptr(_ST, _ST_Vp))    // MOVQ EP, ST.Vp[0]
616
    self.Link("_epilogue")                          // _epilogue:
617
    self.Emit("SUBQ", jit.Imm(_FsmOffset), _ST)     // SUBQ _FsmOffset, _ST
618
    self.Emit("MOVQ", jit.Ptr(_SP, _VD_offs), _BP)  // MOVQ _VD_offs(SP), BP
619
    self.Emit("ADDQ", jit.Imm(_VD_size), _SP)       // ADDQ $_VD_size, SP
620
    self.Emit("RET")                                // RET
621

622
    /* array expand */
623
    self.Link("_array_more")                    // _array_more:
624
    self.Emit("MOVQ" , _T_eface, _AX)           // MOVQ    _T_eface, AX
625
    self.Emit("MOVQ" , jit.Ptr(_SI, 0), _BX)    // MOVQ   (SI), BX
626
    self.Emit("MOVQ" , jit.Ptr(_SI, 8), _CX)    // MOVQ   8(SI), CX
627
    self.Emit("MOVQ" , jit.Ptr(_SI, 16), _DI)   // MOVQ    16(SI), DI
628
    self.Emit("MOVQ" , _DI, _SI)                // MOVQ    DI, 24(SP)
629
    self.Emit("SHLQ" , jit.Imm(1), _SI)         // SHLQ    $1, SI
630
    self.call_go(_F_growslice)                  // CALL_GO runtime.growslice
631
    self.Emit("MOVQ" , _AX, _DI)                // MOVQ   AX, DI
632
    self.Emit("MOVQ" , _BX, _DX)                // MOVQ   BX, DX
633
    self.Emit("MOVQ" , _CX, _AX)                // MOVQ   CX, AX
634
             
635
    /* update the slice */
636
    self.Emit("MOVQ", jit.Ptr(_ST, _ST_Sp), _CX)            // MOVQ ST.Sp, CX
637
    self.Emit("MOVQ", jit.Sib(_ST, _CX, 8, _ST_Vp), _SI)    // MOVQ ST.Vp[CX], SI
638
    self.Emit("MOVQ", jit.Ptr(_SI, 8), _SI)                 // MOVQ 8(SI), SI
639
    self.Emit("MOVQ", _DX, jit.Ptr(_SI, 8))                 // MOVQ DX, 8(SI)
640
    self.Emit("MOVQ", _AX, jit.Ptr(_SI, 16))                // MOVQ AX, 16(AX)
641
    self.WriteRecNotAX(8 , _DI, jit.Ptr(_SI, 0), false)                 // MOVQ R10, (SI)
642
    self.Sjmp("JMP" , "_array_append")                      // JMP  _array_append
643

644
    /* copy string */
645
    self.Link("copy_string")  // pointer: R8, length: AX, return addr: DI
646
    self.Emit("MOVQ", _R8, _VAR_cs_p)
647
    self.Emit("MOVQ", _AX, _VAR_cs_n)
648
    self.Emit("MOVQ", _DI, _VAR_cs_LR)
649
    self.Emit("MOVQ", _AX, _BX)
650
    self.Emit("MOVQ", _AX, _CX)
651
    self.Emit("MOVQ", _T_byte, _AX)
652
    self.call_go(_F_makeslice)                              
653
    self.Emit("MOVQ", _AX, _VAR_cs_d)                    
654
    self.Emit("MOVQ", _VAR_cs_p, _BX)
655
    self.Emit("MOVQ", _VAR_cs_n, _CX)
656
    self.call_go(_F_memmove)
657
    self.Emit("MOVQ", _VAR_cs_d, _R8)
658
    self.Emit("MOVQ", _VAR_cs_n, _AX)
659
    self.Emit("MOVQ", _VAR_cs_LR, _DI)
660
    self.Rjmp("JMP", _DI)
661

662
    /* error handlers */
663
    self.Link("_stack_overflow")
664
    self.Emit("MOVL" , _E_recurse, _EP)         // MOVQ  _E_recurse, EP
665
    self.Sjmp("JMP"  , "_error")                // JMP   _error
666
    self.Link("_vtype_error")                   // _vtype_error:
667
    self.Emit("MOVQ" , _DI, _IC)                // MOVQ  DI, IC
668
    self.Emit("MOVL" , _E_invalid, _EP)         // MOVL  _E_invalid, EP
669
    self.Sjmp("JMP"  , "_error")                // JMP   _error
670
    self.Link("_invalid_char")                  // _invalid_char:
671
    self.Emit("SUBQ" , jit.Imm(1), _IC)         // SUBQ  $1, IC
672
    self.Emit("MOVL" , _E_invalid, _EP)         // MOVL  _E_invalid, EP
673
    self.Sjmp("JMP"  , "_error")                // JMP   _error
674
    self.Link("_unquote_error")                 // _unquote_error:
675
    self.Emit("MOVQ" , _VAR_ss_Iv, _IC)         // MOVQ  ss.Iv, IC
676
    self.Emit("SUBQ" , jit.Imm(1), _IC)         // SUBQ  $1, IC
677
    self.Link("_parsing_error")                 // _parsing_error:
678
    self.Emit("NEGQ" , _AX)                     // NEGQ  AX
679
    self.Emit("MOVQ" , _AX, _EP)                // MOVQ  AX, EP
680
    self.Link("_error")                         // _error:
681
    self.Emit("PXOR" , _X0, _X0)                // PXOR  X0, X0
682
    self.Emit("MOVOU", _X0, jit.Ptr(_VP, 0))    // MOVOU X0, (VP)
683
    self.Sjmp("JMP"  , "_epilogue")             // JMP   _epilogue
684

685
    /* invalid value type, never returns */
686
    self.Link("_invalid_vtype")
687
    self.call_go(_F_invalid_vtype)                 // CALL invalid_type
688
    self.Emit("UD2")                            // UD2
689

690
    /* switch jump table */
691
    self.Link("_switch_table")              // _switch_table:
692
    self.Sref("_decode_V_EOF", 0)           // SREF &_decode_V_EOF, $0
693
    self.Sref("_decode_V_NULL", -4)         // SREF &_decode_V_NULL, $-4
694
    self.Sref("_decode_V_TRUE", -8)         // SREF &_decode_V_TRUE, $-8
695
    self.Sref("_decode_V_FALSE", -12)       // SREF &_decode_V_FALSE, $-12
696
    self.Sref("_decode_V_ARRAY", -16)       // SREF &_decode_V_ARRAY, $-16
697
    self.Sref("_decode_V_OBJECT", -20)      // SREF &_decode_V_OBJECT, $-20
698
    self.Sref("_decode_V_STRING", -24)      // SREF &_decode_V_STRING, $-24
699
    self.Sref("_decode_V_DOUBLE", -28)      // SREF &_decode_V_DOUBLE, $-28
700
    self.Sref("_decode_V_INTEGER", -32)     // SREF &_decode_V_INTEGER, $-32
701
    self.Sref("_decode_V_KEY_SEP", -36)     // SREF &_decode_V_KEY_SEP, $-36
702
    self.Sref("_decode_V_ELEM_SEP", -40)    // SREF &_decode_V_ELEM_SEP, $-40
703
    self.Sref("_decode_V_ARRAY_END", -44)   // SREF &_decode_V_ARRAY_END, $-44
704
    self.Sref("_decode_V_OBJECT_END", -48)  // SREF &_decode_V_OBJECT_END, $-48
705

706
    /* fast character lookup table */
707
    self.Link("_decode_tab")        // _decode_tab:
708
    self.Sref("_decode_V_EOF", 0)   // SREF &_decode_V_EOF, $0
709

710
    /* generate rest of the tabs */
711
    for i := 1; i < 256; i++ {
712
        if to, ok := _R_tab[i]; ok {
713
            self.Sref(to, -int64(i) * 4)
714
        } else {
715
            self.Byte(0x00, 0x00, 0x00, 0x00)
716
        }
717
    }
718
}
719

720
/** Generic Decoder **/
721

722
var (
723
    _subr_decode_value = new(_ValueDecoder).build()
724
)
725

726
//go:nosplit
727
func invalid_vtype(vt types.ValueType) {
728
    throw(fmt.Sprintf("invalid value type: %d", vt))
729
}
730

Использование cookies

Мы используем файлы cookie в соответствии с Политикой конфиденциальности и Политикой использования cookies.

Нажимая кнопку «Принимаю», Вы даете АО «СберТех» согласие на обработку Ваших персональных данных в целях совершенствования нашего веб-сайта и Сервиса GitVerse, а также повышения удобства их использования.

Запретить использование cookies Вы можете самостоятельно в настройках Вашего браузера.