github.com/bytedance/sonic@v1.11.7-0.20240517092252-d2edb31b167b/internal/decoder/generic_stkabi_amd64.go (about) 1 // +build go1.16,!go1.17 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(BX) : ro, decoder stack 35 * DF(R10) : ro, decoder flags 36 * EP(R11) : wo, error pointer 37 * IP(R12) : ro, input pointer 38 * IL(R13) : ro, input length 39 * IC(R14) : 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 = 40 // 40 bytes for saving the registers before CALL instructions 47 _VD_locals = 88 // 88 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_cs_LR = jit.Ptr(_SP, _VD_fargs + _VD_saves + 56) 71 _VAR_cs_p = jit.Ptr(_SP, _VD_fargs + _VD_saves + 64) 72 _VAR_cs_n = jit.Ptr(_SP, _VD_fargs + _VD_saves + 72) 73 _VAR_cs_d = jit.Ptr(_SP, _VD_fargs + _VD_saves + 80) 74 ) 75 76 type _ValueDecoder struct { 77 jit.BaseAssembler 78 } 79 80 func (self *_ValueDecoder) build() uintptr { 81 self.Init(self.compile) 82 return *(*uintptr)(self.Load("decode_value", _VD_size, _VD_args, argPtrs_generic, localPtrs_generic)) 83 } 84 85 /** Function Calling Helpers **/ 86 87 func (self *_ValueDecoder) save(r ...obj.Addr) { 88 for i, v := range r { 89 if i > _VD_saves / 8 - 1 { 90 panic("too many registers to save") 91 } else { 92 self.Emit("MOVQ", v, jit.Ptr(_SP, _VD_fargs + int64(i) * 8)) 93 } 94 } 95 } 96 97 func (self *_ValueDecoder) load(r ...obj.Addr) { 98 for i, v := range r { 99 if i > _VD_saves / 8 - 1 { 100 panic("too many registers to load") 101 } else { 102 self.Emit("MOVQ", jit.Ptr(_SP, _VD_fargs + int64(i) * 8), v) 103 } 104 } 105 } 106 107 func (self *_ValueDecoder) call(fn obj.Addr) { 108 self.Emit("MOVQ", fn, _AX) // MOVQ ${fn}, AX 109 self.Rjmp("CALL", _AX) // CALL AX 110 } 111 112 func (self *_ValueDecoder) call_go(fn obj.Addr) { 113 self.save(_REG_go...) // SAVE $REG_go 114 self.call(fn) // CALL ${fn} 115 self.load(_REG_go...) // LOAD $REG_go 116 } 117 118 /** Decoder Assembler **/ 119 120 const ( 121 _S_val = iota + 1 122 _S_arr 123 _S_arr_0 124 _S_obj 125 _S_obj_0 126 _S_obj_delim 127 _S_obj_sep 128 ) 129 130 const ( 131 _S_omask_key = (1 << _S_obj_0) | (1 << _S_obj_sep) 132 _S_omask_end = (1 << _S_obj_0) | (1 << _S_obj) 133 _S_vmask = (1 << _S_val) | (1 << _S_arr_0) 134 ) 135 136 const ( 137 _A_init_len = 1 138 _A_init_cap = 16 139 ) 140 141 const ( 142 _ST_Sp = 0 143 _ST_Vt = _PtrBytes 144 _ST_Vp = _PtrBytes * (types.MAX_RECURSE + 1) 145 ) 146 147 var ( 148 _V_true = jit.Imm(int64(pbool(true))) 149 _V_false = jit.Imm(int64(pbool(false))) 150 _F_value = jit.Imm(int64(native.S_value)) 151 ) 152 153 var ( 154 _V_max = jit.Imm(int64(types.V_MAX)) 155 _E_eof = jit.Imm(int64(types.ERR_EOF)) 156 _E_invalid = jit.Imm(int64(types.ERR_INVALID_CHAR)) 157 _E_recurse = jit.Imm(int64(types.ERR_RECURSE_EXCEED_MAX)) 158 ) 159 160 var ( 161 _F_convTslice = jit.Func(convTslice) 162 _F_convTstring = jit.Func(convTstring) 163 _F_invalid_vtype = jit.Func(invalid_vtype) 164 ) 165 166 var ( 167 _T_map = jit.Type(reflect.TypeOf((map[string]interface{})(nil))) 168 _T_bool = jit.Type(reflect.TypeOf(false)) 169 _T_int64 = jit.Type(reflect.TypeOf(int64(0))) 170 _T_eface = jit.Type(reflect.TypeOf((*interface{})(nil)).Elem()) 171 _T_slice = jit.Type(reflect.TypeOf(([]interface{})(nil))) 172 _T_string = jit.Type(reflect.TypeOf("")) 173 _T_number = jit.Type(reflect.TypeOf(json.Number(""))) 174 _T_float64 = jit.Type(reflect.TypeOf(float64(0))) 175 ) 176 177 var _R_tab = map[int]string { 178 '[': "_decode_V_ARRAY", 179 '{': "_decode_V_OBJECT", 180 ':': "_decode_V_KEY_SEP", 181 ',': "_decode_V_ELEM_SEP", 182 ']': "_decode_V_ARRAY_END", 183 '}': "_decode_V_OBJECT_END", 184 } 185 186 func (self *_ValueDecoder) compile() { 187 self.Emit("SUBQ", jit.Imm(_VD_size), _SP) // SUBQ $_VD_size, SP 188 self.Emit("MOVQ", _BP, jit.Ptr(_SP, _VD_offs)) // MOVQ BP, _VD_offs(SP) 189 self.Emit("LEAQ", jit.Ptr(_SP, _VD_offs), _BP) // LEAQ _VD_offs(SP), BP 190 191 /* initialize the state machine */ 192 self.Emit("XORL", _CX, _CX) // XORL CX, CX 193 self.Emit("MOVQ", _DF, _VAR_df) // MOVQ DF, df 194 /* initialize digital buffer first */ 195 self.Emit("MOVQ", jit.Imm(_MaxDigitNums), _VAR_ss_Dc) // MOVQ $_MaxDigitNums, ss.Dcap 196 self.Emit("LEAQ", jit.Ptr(_ST, _DbufOffset), _AX) // LEAQ _DbufOffset(ST), AX 197 self.Emit("MOVQ", _AX, _VAR_ss_Db) // MOVQ AX, ss.Dbuf 198 /* add ST offset */ 199 self.Emit("ADDQ", jit.Imm(_FsmOffset), _ST) // ADDQ _FsmOffset, _ST 200 self.Emit("MOVQ", _CX, jit.Ptr(_ST, _ST_Sp)) // MOVQ CX, ST.Sp 201 self.WriteRecNotAX(0, _VP, jit.Ptr(_ST, _ST_Vp), false) // MOVQ VP, ST.Vp[0] 202 self.Emit("MOVQ", jit.Imm(_S_val), jit.Ptr(_ST, _ST_Vt)) // MOVQ _S_val, ST.Vt[0] 203 self.Sjmp("JMP" , "_next") // JMP _next 204 205 /* set the value from previous round */ 206 self.Link("_set_value") // _set_value: 207 self.Emit("MOVL" , jit.Imm(_S_vmask), _DX) // MOVL _S_vmask, DX 208 self.Emit("MOVQ" , jit.Ptr(_ST, _ST_Sp), _CX) // MOVQ ST.Sp, CX 209 self.Emit("MOVQ" , jit.Sib(_ST, _CX, 8, _ST_Vt), _AX) // MOVQ ST.Vt[CX], AX 210 self.Emit("BTQ" , _AX, _DX) // BTQ AX, DX 211 self.Sjmp("JNC" , "_vtype_error") // JNC _vtype_error 212 self.Emit("XORL" , _SI, _SI) // XORL SI, SI 213 self.Emit("SUBQ" , jit.Imm(1), jit.Ptr(_ST, _ST_Sp)) // SUBQ $1, ST.Sp 214 self.Emit("XCHGQ", jit.Sib(_ST, _CX, 8, _ST_Vp), _SI) // XCHGQ ST.Vp[CX], SI 215 self.Emit("MOVQ" , _R8, jit.Ptr(_SI, 0)) // MOVQ R8, (SI) 216 self.WriteRecNotAX(1, _R9, jit.Ptr(_SI, 8), false) // MOVQ R9, 8(SI) 217 218 /* check for value stack */ 219 self.Link("_next") // _next: 220 self.Emit("MOVQ" , jit.Ptr(_ST, _ST_Sp), _AX) // MOVQ ST.Sp, AX 221 self.Emit("TESTQ", _AX, _AX) // TESTQ AX, AX 222 self.Sjmp("JS" , "_return") // JS _return 223 224 /* fast path: test up to 4 characters manually */ 225 self.Emit("CMPQ" , _IC, _IL) // CMPQ IC, IL 226 self.Sjmp("JAE" , "_decode_V_EOF") // JAE _decode_V_EOF 227 self.Emit("MOVBQZX", jit.Sib(_IP, _IC, 1, 0), _AX) // MOVBQZX (IP)(IC), AX 228 self.Emit("MOVQ" , jit.Imm(_BM_space), _DX) // MOVQ _BM_space, DX 229 self.Emit("CMPQ" , _AX, jit.Imm(' ')) // CMPQ AX, $' ' 230 self.Sjmp("JA" , "_decode_fast") // JA _decode_fast 231 self.Emit("BTQ" , _AX, _DX) // BTQ _AX, _DX 232 self.Sjmp("JNC" , "_decode_fast") // JNC _decode_fast 233 self.Emit("ADDQ" , jit.Imm(1), _IC) // ADDQ $1, IC 234 235 /* at least 1 to 3 spaces */ 236 for i := 0; i < 3; i++ { 237 self.Emit("CMPQ" , _IC, _IL) // CMPQ IC, IL 238 self.Sjmp("JAE" , "_decode_V_EOF") // JAE _decode_V_EOF 239 self.Emit("MOVBQZX", jit.Sib(_IP, _IC, 1, 0), _AX) // MOVBQZX (IP)(IC), AX 240 self.Emit("CMPQ" , _AX, jit.Imm(' ')) // CMPQ AX, $' ' 241 self.Sjmp("JA" , "_decode_fast") // JA _decode_fast 242 self.Emit("BTQ" , _AX, _DX) // BTQ _AX, _DX 243 self.Sjmp("JNC" , "_decode_fast") // JNC _decode_fast 244 self.Emit("ADDQ" , jit.Imm(1), _IC) // ADDQ $1, IC 245 } 246 247 /* at least 4 spaces */ 248 self.Emit("CMPQ" , _IC, _IL) // CMPQ IC, IL 249 self.Sjmp("JAE" , "_decode_V_EOF") // JAE _decode_V_EOF 250 self.Emit("MOVBQZX", jit.Sib(_IP, _IC, 1, 0), _AX) // MOVBQZX (IP)(IC), AX 251 252 /* fast path: use lookup table to select decoder */ 253 self.Link("_decode_fast") // _decode_fast: 254 self.Byte(0x48, 0x8d, 0x3d) // LEAQ ?(PC), DI 255 self.Sref("_decode_tab", 4) // .... &_decode_tab 256 self.Emit("MOVLQSX", jit.Sib(_DI, _AX, 4, 0), _AX) // MOVLQSX (DI)(AX*4), AX 257 self.Emit("TESTQ" , _AX, _AX) // TESTQ AX, AX 258 self.Sjmp("JZ" , "_decode_native") // JZ _decode_native 259 self.Emit("ADDQ" , jit.Imm(1), _IC) // ADDQ $1, IC 260 self.Emit("ADDQ" , _DI, _AX) // ADDQ DI, AX 261 self.Rjmp("JMP" , _AX) // JMP AX 262 263 /* decode with native decoder */ 264 self.Link("_decode_native") // _decode_native: 265 self.Emit("MOVQ", _IP, _DI) // MOVQ IP, DI 266 self.Emit("MOVQ", _IL, _SI) // MOVQ IL, SI 267 self.Emit("MOVQ", _IC, _DX) // MOVQ IC, DX 268 self.Emit("LEAQ", _VAR_ss, _CX) // LEAQ ss, CX 269 self.Emit("MOVQ", _VAR_df, _R8) // MOVQ $df, R8 270 self.Emit("BTSQ", jit.Imm(_F_allow_control), _R8) // ANDQ $1<<_F_allow_control, R8 271 self.call(_F_value) // CALL value 272 self.Emit("MOVQ", _AX, _IC) // MOVQ AX, IC 273 274 /* check for errors */ 275 self.Emit("MOVQ" , _VAR_ss_Vt, _AX) // MOVQ ss.Vt, AX 276 self.Emit("TESTQ", _AX, _AX) // TESTQ AX, AX 277 self.Sjmp("JS" , "_parsing_error") 278 self.Sjmp("JZ" , "_invalid_vtype") // JZ _invalid_vtype 279 self.Emit("CMPQ" , _AX, _V_max) // CMPQ AX, _V_max 280 self.Sjmp("JA" , "_invalid_vtype") // JA _invalid_vtype 281 282 /* jump table selector */ 283 self.Byte(0x48, 0x8d, 0x3d) // LEAQ ?(PC), DI 284 self.Sref("_switch_table", 4) // .... &_switch_table 285 self.Emit("MOVLQSX", jit.Sib(_DI, _AX, 4, -4), _AX) // MOVLQSX -4(DI)(AX*4), AX 286 self.Emit("ADDQ" , _DI, _AX) // ADDQ DI, AX 287 self.Rjmp("JMP" , _AX) // JMP AX 288 289 /** V_EOF **/ 290 self.Link("_decode_V_EOF") // _decode_V_EOF: 291 self.Emit("MOVL", _E_eof, _EP) // MOVL _E_eof, EP 292 self.Sjmp("JMP" , "_error") // JMP _error 293 294 /** V_NULL **/ 295 self.Link("_decode_V_NULL") // _decode_V_NULL: 296 self.Emit("XORL", _R8, _R8) // XORL R8, R8 297 self.Emit("XORL", _R9, _R9) // XORL R9, R9 298 self.Emit("LEAQ", jit.Ptr(_IC, -4), _DI) // LEAQ -4(IC), DI 299 self.Sjmp("JMP" , "_set_value") // JMP _set_value 300 301 /** V_TRUE **/ 302 self.Link("_decode_V_TRUE") // _decode_V_TRUE: 303 self.Emit("MOVQ", _T_bool, _R8) // MOVQ _T_bool, R8 304 // TODO: maybe modified by users? 305 self.Emit("MOVQ", _V_true, _R9) // MOVQ _V_true, R9 306 self.Emit("LEAQ", jit.Ptr(_IC, -4), _DI) // LEAQ -4(IC), DI 307 self.Sjmp("JMP" , "_set_value") // JMP _set_value 308 309 /** V_FALSE **/ 310 self.Link("_decode_V_FALSE") // _decode_V_FALSE: 311 self.Emit("MOVQ", _T_bool, _R8) // MOVQ _T_bool, R8 312 self.Emit("MOVQ", _V_false, _R9) // MOVQ _V_false, R9 313 self.Emit("LEAQ", jit.Ptr(_IC, -5), _DI) // LEAQ -5(IC), DI 314 self.Sjmp("JMP" , "_set_value") // JMP _set_value 315 316 /** V_ARRAY **/ 317 self.Link("_decode_V_ARRAY") // _decode_V_ARRAY 318 self.Emit("MOVL", jit.Imm(_S_vmask), _DX) // MOVL _S_vmask, DX 319 self.Emit("MOVQ", jit.Ptr(_ST, _ST_Sp), _CX) // MOVQ ST.Sp, CX 320 self.Emit("MOVQ", jit.Sib(_ST, _CX, 8, _ST_Vt), _AX) // MOVQ ST.Vt[CX], AX 321 self.Emit("BTQ" , _AX, _DX) // BTQ AX, DX 322 self.Sjmp("JNC" , "_invalid_char") // JNC _invalid_char 323 324 /* create a new array */ 325 self.Emit("MOVQ", _T_eface, _AX) // MOVQ _T_eface, AX 326 self.Emit("MOVQ", _AX, jit.Ptr(_SP, 0)) // MOVQ AX, (SP) 327 self.Emit("MOVQ", jit.Imm(_A_init_len), jit.Ptr(_SP, 8)) // MOVQ _A_init_len, 8(SP) 328 self.Emit("MOVQ", jit.Imm(_A_init_cap), jit.Ptr(_SP, 16)) // MOVQ _A_init_cap, 16(SP) 329 self.call_go(_F_makeslice) // CALL_GO runtime.makeslice 330 self.Emit("MOVQ", jit.Ptr(_SP, 24), _DX) // MOVQ 24(SP), DX 331 332 /* pack into an interface */ 333 self.Emit("MOVQ", _DX, jit.Ptr(_SP, 0)) // MOVQ DX, (SP) 334 self.Emit("MOVQ", jit.Imm(_A_init_len), jit.Ptr(_SP, 8)) // MOVQ _A_init_len, 8(SP) 335 self.Emit("MOVQ", jit.Imm(_A_init_cap), jit.Ptr(_SP, 16)) // MOVQ _A_init_cap, 16(SP) 336 self.call_go(_F_convTslice) // CALL_GO runtime.convTslice 337 self.Emit("MOVQ", jit.Ptr(_SP, 24), _R8) // MOVQ 24(SP), R8 338 339 /* replace current state with an array */ 340 self.Emit("MOVQ", jit.Ptr(_ST, _ST_Sp), _CX) // MOVQ ST.Sp, CX 341 self.Emit("MOVQ", jit.Sib(_ST, _CX, 8, _ST_Vp), _SI) // MOVQ ST.Vp[CX], SI 342 self.Emit("MOVQ", jit.Imm(_S_arr), jit.Sib(_ST, _CX, 8, _ST_Vt)) // MOVQ _S_arr, ST.Vt[CX] 343 self.Emit("MOVQ", _T_slice, _AX) // MOVQ _T_slice, AX 344 self.Emit("MOVQ", _AX, jit.Ptr(_SI, 0)) // MOVQ AX, (SI) 345 self.WriteRecNotAX(2, _R8, jit.Ptr(_SI, 8), false) // MOVQ R8, 8(SI) 346 347 /* add a new slot for the first element */ 348 self.Emit("ADDQ", jit.Imm(1), _CX) // ADDQ $1, CX 349 self.Emit("CMPQ", _CX, jit.Imm(types.MAX_RECURSE)) // CMPQ CX, ${types.MAX_RECURSE} 350 self.Sjmp("JAE" , "_stack_overflow") // JA _stack_overflow 351 self.Emit("MOVQ", jit.Ptr(_R8, 0), _AX) // MOVQ (R8), AX 352 self.Emit("MOVQ", _CX, jit.Ptr(_ST, _ST_Sp)) // MOVQ CX, ST.Sp 353 self.WritePtrAX(3, jit.Sib(_ST, _CX, 8, _ST_Vp), false) // MOVQ AX, ST.Vp[CX] 354 self.Emit("MOVQ", jit.Imm(_S_arr_0), jit.Sib(_ST, _CX, 8, _ST_Vt)) // MOVQ _S_arr_0, ST.Vt[CX] 355 self.Sjmp("JMP" , "_next") // JMP _next 356 357 /** V_OBJECT **/ 358 self.Link("_decode_V_OBJECT") // _decode_V_OBJECT: 359 self.Emit("MOVL", jit.Imm(_S_vmask), _DX) // MOVL _S_vmask, DX 360 self.Emit("MOVQ", jit.Ptr(_ST, _ST_Sp), _CX) // MOVQ ST.Sp, CX 361 self.Emit("MOVQ", jit.Sib(_ST, _CX, 8, _ST_Vt), _AX) // MOVQ ST.Vt[CX], AX 362 self.Emit("BTQ" , _AX, _DX) // BTQ AX, DX 363 self.Sjmp("JNC" , "_invalid_char") // JNC _invalid_char 364 self.call_go(_F_makemap_small) // CALL_GO runtime.makemap_small 365 self.Emit("MOVQ", jit.Ptr(_SP, 0), _AX) // MOVQ (SP), AX 366 self.Emit("MOVQ", jit.Ptr(_ST, _ST_Sp), _CX) // MOVQ ST.Sp, CX 367 self.Emit("MOVQ", jit.Imm(_S_obj_0), jit.Sib(_ST, _CX, 8, _ST_Vt)) // MOVQ _S_obj, ST.Vt[CX] 368 self.Emit("MOVQ", jit.Sib(_ST, _CX, 8, _ST_Vp), _SI) // MOVQ ST.Vp[CX], SI 369 self.Emit("MOVQ", _T_map, _DX) // MOVQ _T_map, DX 370 self.Emit("MOVQ", _DX, jit.Ptr(_SI, 0)) // MOVQ DX, (SI) 371 self.WritePtrAX(4, jit.Ptr(_SI, 8), false) // MOVQ AX, 8(SI) 372 self.Sjmp("JMP" , "_next") // JMP _next 373 374 /** V_STRING **/ 375 self.Link("_decode_V_STRING") // _decode_V_STRING: 376 self.Emit("MOVQ", _VAR_ss_Iv, _CX) // MOVQ ss.Iv, CX 377 self.Emit("MOVQ", _IC, _AX) // MOVQ IC, AX 378 self.Emit("SUBQ", _CX, _AX) // SUBQ CX, AX 379 380 /* check for escapes */ 381 self.Emit("CMPQ", _VAR_ss_Ep, jit.Imm(-1)) // CMPQ ss.Ep, $-1 382 self.Sjmp("JNE" , "_unquote") // JNE _unquote 383 self.Emit("SUBQ", jit.Imm(1), _AX) // SUBQ $1, AX 384 self.Emit("LEAQ", jit.Sib(_IP, _CX, 1, 0), _R8) // LEAQ (IP)(CX), R8 385 self.Byte(0x48, 0x8d, 0x3d) // LEAQ (PC), DI 386 self.Sref("_copy_string_end", 4) 387 self.Emit("BTQ", jit.Imm(_F_copy_string), _VAR_df) 388 self.Sjmp("JC", "copy_string") 389 self.Link("_copy_string_end") 390 self.Emit("XORL", _DX, _DX) // XORL DX, DX 391 /* strings with no escape sequences */ 392 self.Link("_noescape") // _noescape: 393 self.Emit("MOVL", jit.Imm(_S_omask_key), _DI) // MOVL _S_omask, DI 394 self.Emit("MOVQ", jit.Ptr(_ST, _ST_Sp), _CX) // MOVQ ST.Sp, CX 395 self.Emit("MOVQ", jit.Sib(_ST, _CX, 8, _ST_Vt), _SI) // MOVQ ST.Vt[CX], SI 396 self.Emit("BTQ" , _SI, _DI) // BTQ SI, DI 397 self.Sjmp("JC" , "_object_key") // JC _object_key 398 399 /* check for pre-packed strings, avoid 1 allocation */ 400 self.Emit("TESTQ", _DX, _DX) // TESTQ DX, DX 401 self.Sjmp("JNZ" , "_packed_str") // JNZ _packed_str 402 self.Emit("MOVQ" , _R8, jit.Ptr(_SP, 0)) // MOVQ R8, (SP) 403 self.Emit("MOVQ" , _AX, jit.Ptr(_SP, 8)) // MOVQ AX, 8(SP) 404 self.call_go(_F_convTstring) // CALL_GO runtime.convTstring 405 self.Emit("MOVQ" , jit.Ptr(_SP, 16), _R9) // MOVQ 16(SP), R9 406 407 /* packed string already in R9 */ 408 self.Link("_packed_str") // _packed_str: 409 self.Emit("MOVQ", _T_string, _R8) // MOVQ _T_string, R8 410 self.Emit("MOVQ", _VAR_ss_Iv, _DI) // MOVQ ss.Iv, DI 411 self.Emit("SUBQ", jit.Imm(1), _DI) // SUBQ $1, DI 412 self.Sjmp("JMP" , "_set_value") // JMP _set_value 413 414 /* the string is an object key, get the map */ 415 self.Link("_object_key") 416 self.Emit("MOVQ", jit.Ptr(_ST, _ST_Sp), _CX) // MOVQ ST.Sp, CX 417 self.Emit("MOVQ", jit.Sib(_ST, _CX, 8, _ST_Vp), _SI) // MOVQ ST.Vp[CX], SI 418 self.Emit("MOVQ", jit.Ptr(_SI, 8), _SI) // MOVQ 8(SI), SI 419 420 /* add a new delimiter */ 421 self.Emit("ADDQ", jit.Imm(1), _CX) // ADDQ $1, CX 422 self.Emit("CMPQ", _CX, jit.Imm(types.MAX_RECURSE)) // CMPQ CX, ${types.MAX_RECURSE} 423 self.Sjmp("JAE" , "_stack_overflow") // JA _stack_overflow 424 self.Emit("MOVQ", _CX, jit.Ptr(_ST, _ST_Sp)) // MOVQ CX, ST.Sp 425 self.Emit("MOVQ", jit.Imm(_S_obj_delim), jit.Sib(_ST, _CX, 8, _ST_Vt)) // MOVQ _S_obj_delim, ST.Vt[CX] 426 427 /* add a new slot int the map */ 428 self.Emit("MOVQ", _T_map, _DX) // MOVQ _T_map, DX 429 self.Emit("MOVQ", _DX, jit.Ptr(_SP, 0)) // MOVQ DX, (SP) 430 self.Emit("MOVQ", _SI, jit.Ptr(_SP, 8)) // MOVQ SI, 8(SP) 431 self.Emit("MOVQ", _R8, jit.Ptr(_SP, 16)) // MOVQ R9, 16(SP) 432 self.Emit("MOVQ", _AX, jit.Ptr(_SP, 24)) // MOVQ AX, 24(SP) 433 self.call_go(_F_mapassign_faststr) // CALL_GO runtime.mapassign_faststr 434 self.Emit("MOVQ", jit.Ptr(_SP, 32), _AX) // MOVQ 32(SP), AX 435 436 /* add to the pointer stack */ 437 self.Emit("MOVQ", jit.Ptr(_ST, _ST_Sp), _CX) // MOVQ ST.Sp, CX 438 self.WritePtrAX(6, jit.Sib(_ST, _CX, 8, _ST_Vp), false) // MOVQ AX, ST.Vp[CX] 439 self.Sjmp("JMP" , "_next") // JMP _next 440 441 /* allocate memory to store the string header and unquoted result */ 442 self.Link("_unquote") // _unquote: 443 self.Emit("ADDQ", jit.Imm(15), _AX) // ADDQ $15, AX 444 self.Emit("MOVQ", _T_byte, _CX) // MOVQ _T_byte, CX 445 self.Emit("MOVQ", _AX, jit.Ptr(_SP, 0)) // MOVQ AX, (SP) 446 self.Emit("MOVQ", _CX, jit.Ptr(_SP, 8)) // MOVQ CX, 8(SP) 447 self.Emit("MOVB", jit.Imm(0), jit.Ptr(_SP, 16)) // MOVB $0, 16(SP) 448 self.call_go(_F_mallocgc) // CALL_GO runtime.mallocgc 449 self.Emit("MOVQ", jit.Ptr(_SP, 24), _R9) // MOVQ 24(SP), R9 450 451 /* prepare the unquoting parameters */ 452 self.Emit("MOVQ" , _VAR_ss_Iv, _CX) // MOVQ ss.Iv, CX 453 self.Emit("LEAQ" , jit.Sib(_IP, _CX, 1, 0), _DI) // LEAQ (IP)(CX), DI 454 self.Emit("NEGQ" , _CX) // NEGQ CX 455 self.Emit("LEAQ" , jit.Sib(_IC, _CX, 1, -1), _SI) // LEAQ -1(IC)(CX), SI 456 self.Emit("LEAQ" , jit.Ptr(_R9, 16), _DX) // LEAQ 16(R8), DX 457 self.Emit("LEAQ" , _VAR_ss_Ep, _CX) // LEAQ ss.Ep, CX 458 self.Emit("XORL" , _R8, _R8) // XORL R8, R8 459 self.Emit("BTQ" , jit.Imm(_F_disable_urc), _VAR_df) // BTQ ${_F_disable_urc}, fv 460 self.Emit("SETCC", _R8) // SETCC R8 461 self.Emit("SHLQ" , jit.Imm(types.B_UNICODE_REPLACE), _R8) // SHLQ ${types.B_UNICODE_REPLACE}, R8 462 463 /* unquote the string, with R9 been preserved */ 464 self.save(_R9) // SAVE R9 465 self.call(_F_unquote) // CALL unquote 466 self.load(_R9) // LOAD R9 467 468 /* check for errors */ 469 self.Emit("TESTQ", _AX, _AX) // TESTQ AX, AX 470 self.Sjmp("JS" , "_unquote_error") // JS _unquote_error 471 self.Emit("MOVL" , jit.Imm(1), _DX) // MOVL $1, DX 472 self.Emit("LEAQ" , jit.Ptr(_R9, 16), _R8) // ADDQ $16, R8 473 self.Emit("MOVQ" , _R8, jit.Ptr(_R9, 0)) // MOVQ R8, (R9) 474 self.Emit("MOVQ" , _AX, jit.Ptr(_R9, 8)) // MOVQ AX, 8(R9) 475 self.Sjmp("JMP" , "_noescape") // JMP _noescape 476 477 /** V_DOUBLE **/ 478 self.Link("_decode_V_DOUBLE") // _decode_V_DOUBLE: 479 self.Emit("BTQ" , jit.Imm(_F_use_number), _VAR_df) // BTQ _F_use_number, df 480 self.Sjmp("JC" , "_use_number") // JC _use_number 481 self.Emit("MOVSD", _VAR_ss_Dv, _X0) // MOVSD ss.Dv, X0 482 self.Sjmp("JMP" , "_use_float64") // JMP _use_float64 483 484 /** V_INTEGER **/ 485 self.Link("_decode_V_INTEGER") // _decode_V_INTEGER: 486 self.Emit("BTQ" , jit.Imm(_F_use_number), _VAR_df) // BTQ _F_use_number, df 487 self.Sjmp("JC" , "_use_number") // JC _use_number 488 self.Emit("BTQ" , jit.Imm(_F_use_int64), _VAR_df) // BTQ _F_use_int64, df 489 self.Sjmp("JC" , "_use_int64") // JC _use_int64 490 self.Emit("MOVQ" , _VAR_ss_Iv, _AX) // MOVQ ss.Iv, AX 491 self.Emit("CVTSQ2SD", _AX, _X0) // CVTSQ2SD AX, X0 492 493 /* represent numbers as `float64` */ 494 self.Link("_use_float64") // _use_float64: 495 self.Emit("MOVSD", _X0, jit.Ptr(_SP, 0)) // MOVSD X0, (SP) 496 self.call_go(_F_convT64) // CALL_GO runtime.convT64 497 self.Emit("MOVQ" , _T_float64, _R8) // MOVQ _T_float64, R8 498 self.Emit("MOVQ" , jit.Ptr(_SP, 8), _R9) // MOVQ 8(SP), R9 499 self.Emit("MOVQ" , _VAR_ss_Ep, _DI) // MOVQ ss.Ep, DI 500 self.Sjmp("JMP" , "_set_value") // JMP _set_value 501 502 /* represent numbers as `json.Number` */ 503 self.Link("_use_number") // _use_number 504 self.Emit("MOVQ", _VAR_ss_Ep, _AX) // MOVQ ss.Ep, AX 505 self.Emit("LEAQ", jit.Sib(_IP, _AX, 1, 0), _SI) // LEAQ (IP)(AX), SI 506 self.Emit("MOVQ", _IC, _CX) // MOVQ IC, CX 507 self.Emit("SUBQ", _AX, _CX) // SUBQ AX, CX 508 self.Emit("MOVQ", _SI, jit.Ptr(_SP, 0)) // MOVQ SI, (SP) 509 self.Emit("MOVQ", _CX, jit.Ptr(_SP, 8)) // MOVQ CX, 8(SP) 510 self.call_go(_F_convTstring) // CALL_GO runtime.convTstring 511 self.Emit("MOVQ", _T_number, _R8) // MOVQ _T_number, R8 512 self.Emit("MOVQ", jit.Ptr(_SP, 16), _R9) // MOVQ 16(SP), R9 513 self.Emit("MOVQ", _VAR_ss_Ep, _DI) // MOVQ ss.Ep, DI 514 self.Sjmp("JMP" , "_set_value") // JMP _set_value 515 516 /* represent numbers as `int64` */ 517 self.Link("_use_int64") // _use_int64: 518 self.Emit("MOVQ", _VAR_ss_Iv, _AX) // MOVQ ss.Iv, AX 519 self.Emit("MOVQ", _AX, jit.Ptr(_SP, 0)) // MOVQ AX, (SP) 520 self.call_go(_F_convT64) // CALL_GO runtime.convT64 521 self.Emit("MOVQ", _T_int64, _R8) // MOVQ _T_int64, R8 522 self.Emit("MOVQ", jit.Ptr(_SP, 8), _R9) // MOVQ 8(SP), R9 523 self.Emit("MOVQ", _VAR_ss_Ep, _DI) // MOVQ ss.Ep, DI 524 self.Sjmp("JMP" , "_set_value") // JMP _set_value 525 526 /** V_KEY_SEP **/ 527 self.Link("_decode_V_KEY_SEP") // _decode_V_KEY_SEP: 528 // self.Byte(0xcc) 529 self.Emit("MOVQ", jit.Ptr(_ST, _ST_Sp), _CX) // MOVQ ST.Sp, CX 530 self.Emit("MOVQ", jit.Sib(_ST, _CX, 8, _ST_Vt), _AX) // MOVQ ST.Vt[CX], AX 531 self.Emit("CMPQ", _AX, jit.Imm(_S_obj_delim)) // CMPQ AX, _S_obj_delim 532 self.Sjmp("JNE" , "_invalid_char") // JNE _invalid_char 533 self.Emit("MOVQ", jit.Imm(_S_val), jit.Sib(_ST, _CX, 8, _ST_Vt)) // MOVQ _S_val, ST.Vt[CX] 534 self.Emit("MOVQ", jit.Imm(_S_obj), jit.Sib(_ST, _CX, 8, _ST_Vt - 8)) // MOVQ _S_obj, ST.Vt[CX - 1] 535 self.Sjmp("JMP" , "_next") // JMP _next 536 537 /** V_ELEM_SEP **/ 538 self.Link("_decode_V_ELEM_SEP") // _decode_V_ELEM_SEP: 539 self.Emit("MOVQ" , jit.Ptr(_ST, _ST_Sp), _CX) // MOVQ ST.Sp, CX 540 self.Emit("MOVQ" , jit.Sib(_ST, _CX, 8, _ST_Vt), _AX) // MOVQ ST.Vt[CX], AX 541 self.Emit("CMPQ" , _AX, jit.Imm(_S_arr)) // CMPQ _AX, _S_arr 542 self.Sjmp("JE" , "_array_sep") // JZ _next 543 self.Emit("CMPQ" , _AX, jit.Imm(_S_obj)) // CMPQ _AX, _S_arr 544 self.Sjmp("JNE" , "_invalid_char") // JNE _invalid_char 545 self.Emit("MOVQ" , jit.Imm(_S_obj_sep), jit.Sib(_ST, _CX, 8, _ST_Vt)) 546 self.Sjmp("JMP" , "_next") // JMP _next 547 548 /* arrays */ 549 self.Link("_array_sep") 550 self.Emit("MOVQ", jit.Sib(_ST, _CX, 8, _ST_Vp), _SI) // MOVQ ST.Vp[CX], SI 551 self.Emit("MOVQ", jit.Ptr(_SI, 8), _SI) // MOVQ 8(SI), SI 552 self.Emit("MOVQ", jit.Ptr(_SI, 8), _DX) // MOVQ 8(SI), DX 553 self.Emit("CMPQ", _DX, jit.Ptr(_SI, 16)) // CMPQ DX, 16(SI) 554 self.Sjmp("JAE" , "_array_more") // JAE _array_more 555 556 /* add a slot for the new element */ 557 self.Link("_array_append") // _array_append: 558 self.Emit("ADDQ", jit.Imm(1), jit.Ptr(_SI, 8)) // ADDQ $1, 8(SI) 559 self.Emit("MOVQ", jit.Ptr(_SI, 0), _SI) // MOVQ (SI), SI 560 self.Emit("ADDQ", jit.Imm(1), _CX) // ADDQ $1, CX 561 self.Emit("CMPQ", _CX, jit.Imm(types.MAX_RECURSE)) // CMPQ CX, ${types.MAX_RECURSE} 562 self.Sjmp("JAE" , "_stack_overflow") 563 self.Emit("SHLQ", jit.Imm(1), _DX) // SHLQ $1, DX 564 self.Emit("LEAQ", jit.Sib(_SI, _DX, 8, 0), _SI) // LEAQ (SI)(DX*8), SI 565 self.Emit("MOVQ", _CX, jit.Ptr(_ST, _ST_Sp)) // MOVQ CX, ST.Sp 566 self.WriteRecNotAX(7 , _SI, jit.Sib(_ST, _CX, 8, _ST_Vp), false) // MOVQ SI, ST.Vp[CX] 567 self.Emit("MOVQ", jit.Imm(_S_val), jit.Sib(_ST, _CX, 8, _ST_Vt)) // MOVQ _S_val, ST.Vt[CX} 568 self.Sjmp("JMP" , "_next") // JMP _next 569 570 /** V_ARRAY_END **/ 571 self.Link("_decode_V_ARRAY_END") // _decode_V_ARRAY_END: 572 self.Emit("XORL", _DX, _DX) // XORL DX, DX 573 self.Emit("MOVQ", jit.Ptr(_ST, _ST_Sp), _CX) // MOVQ ST.Sp, CX 574 self.Emit("MOVQ", jit.Sib(_ST, _CX, 8, _ST_Vt), _AX) // MOVQ ST.Vt[CX], AX 575 self.Emit("CMPQ", _AX, jit.Imm(_S_arr_0)) // CMPQ AX, _S_arr_0 576 self.Sjmp("JE" , "_first_item") // JE _first_item 577 self.Emit("CMPQ", _AX, jit.Imm(_S_arr)) // CMPQ AX, _S_arr 578 self.Sjmp("JNE" , "_invalid_char") // JNE _invalid_char 579 self.Emit("SUBQ", jit.Imm(1), jit.Ptr(_ST, _ST_Sp)) // SUBQ $1, ST.Sp 580 self.Emit("MOVQ", _DX, jit.Sib(_ST, _CX, 8, _ST_Vp)) // MOVQ DX, ST.Vp[CX] 581 self.Sjmp("JMP" , "_next") // JMP _next 582 583 /* first element of an array */ 584 self.Link("_first_item") // _first_item: 585 self.Emit("MOVQ", jit.Ptr(_ST, _ST_Sp), _CX) // MOVQ ST.Sp, CX 586 self.Emit("SUBQ", jit.Imm(2), jit.Ptr(_ST, _ST_Sp)) // SUBQ $2, ST.Sp 587 self.Emit("MOVQ", jit.Sib(_ST, _CX, 8, _ST_Vp - 8), _SI) // MOVQ ST.Vp[CX - 1], SI 588 self.Emit("MOVQ", jit.Ptr(_SI, 8), _SI) // MOVQ 8(SI), SI 589 self.Emit("MOVQ", _DX, jit.Sib(_ST, _CX, 8, _ST_Vp - 8)) // MOVQ DX, ST.Vp[CX - 1] 590 self.Emit("MOVQ", _DX, jit.Sib(_ST, _CX, 8, _ST_Vp)) // MOVQ DX, ST.Vp[CX] 591 self.Emit("MOVQ", _DX, jit.Ptr(_SI, 8)) // MOVQ DX, 8(SI) 592 self.Sjmp("JMP" , "_next") // JMP _next 593 594 /** V_OBJECT_END **/ 595 self.Link("_decode_V_OBJECT_END") // _decode_V_OBJECT_END: 596 self.Emit("MOVL", jit.Imm(_S_omask_end), _DX) // MOVL _S_omask, DI 597 self.Emit("MOVQ", jit.Ptr(_ST, _ST_Sp), _CX) // MOVQ ST.Sp, CX 598 self.Emit("MOVQ", jit.Sib(_ST, _CX, 8, _ST_Vt), _AX) // MOVQ ST.Vt[CX], AX 599 self.Emit("BTQ" , _AX, _DX) 600 self.Sjmp("JNC" , "_invalid_char") // JNE _invalid_char 601 self.Emit("XORL", _AX, _AX) // XORL AX, AX 602 self.Emit("SUBQ", jit.Imm(1), jit.Ptr(_ST, _ST_Sp)) // SUBQ $1, ST.Sp 603 self.Emit("MOVQ", _AX, jit.Sib(_ST, _CX, 8, _ST_Vp)) // MOVQ AX, ST.Vp[CX] 604 self.Sjmp("JMP" , "_next") // JMP _next 605 606 /* return from decoder */ 607 self.Link("_return") // _return: 608 self.Emit("XORL", _EP, _EP) // XORL EP, EP 609 self.Emit("MOVQ", _EP, jit.Ptr(_ST, _ST_Vp)) // MOVQ EP, ST.Vp[0] 610 self.Link("_epilogue") // _epilogue: 611 self.Emit("SUBQ", jit.Imm(_FsmOffset), _ST) // SUBQ _FsmOffset, _ST 612 self.Emit("MOVQ", jit.Ptr(_SP, _VD_offs), _BP) // MOVQ _VD_offs(SP), BP 613 self.Emit("ADDQ", jit.Imm(_VD_size), _SP) // ADDQ $_VD_size, SP 614 self.Emit("RET") // RET 615 616 /* array expand */ 617 self.Link("_array_more") // _array_more: 618 self.Emit("MOVQ" , _T_eface, _AX) // MOVQ _T_eface, AX 619 self.Emit("MOVOU", jit.Ptr(_SI, 0), _X0) // MOVOU (SI), X0 620 self.Emit("MOVQ" , jit.Ptr(_SI, 16), _DX) // MOVQ 16(SI), DX 621 self.Emit("MOVQ" , _AX, jit.Ptr(_SP, 0)) // MOVQ AX, (SP) 622 self.Emit("MOVOU", _X0, jit.Ptr(_SP, 8)) // MOVOU X0, 8(SP) 623 self.Emit("MOVQ" , _DX, jit.Ptr(_SP, 24)) // MOVQ DX, 24(SP) 624 self.Emit("SHLQ" , jit.Imm(1), _DX) // SHLQ $1, DX 625 self.Emit("MOVQ" , _DX, jit.Ptr(_SP, 32)) // MOVQ DX, 32(SP) 626 self.call_go(_F_growslice) // CALL_GO runtime.growslice 627 self.Emit("MOVQ" , jit.Ptr(_SP, 40), _DI) // MOVOU 40(SP), DI 628 self.Emit("MOVQ" , jit.Ptr(_SP, 48), _DX) // MOVOU 48(SP), DX 629 self.Emit("MOVQ" , jit.Ptr(_SP, 56), _AX) // MOVQ 56(SP), AX 630 631 /* update the slice */ 632 self.Emit("MOVQ", jit.Ptr(_ST, _ST_Sp), _CX) // MOVQ ST.Sp, CX 633 self.Emit("MOVQ", jit.Sib(_ST, _CX, 8, _ST_Vp), _SI) // MOVQ ST.Vp[CX], SI 634 self.Emit("MOVQ", jit.Ptr(_SI, 8), _SI) // MOVQ 8(SI), SI 635 self.Emit("MOVQ", _DX, jit.Ptr(_SI, 8)) // MOVQ DX, 8(SI) 636 self.Emit("MOVQ", _AX, jit.Ptr(_SI, 16)) // MOVQ AX, 16(AX) 637 self.WriteRecNotAX(8 , _DI, jit.Ptr(_SI, 0), false) // MOVQ R10, (SI) 638 self.Sjmp("JMP" , "_array_append") // JMP _array_append 639 640 /* copy string */ 641 self.Link("copy_string") // pointer: R8, length: AX, return addr: DI 642 // self.Byte(0xcc) 643 self.Emit("MOVQ", _R8, _VAR_cs_p) 644 self.Emit("MOVQ", _AX, _VAR_cs_n) 645 self.Emit("MOVQ", _DI, _VAR_cs_LR) 646 self.Emit("MOVQ", _T_byte, _R8) 647 self.Emit("MOVQ", _R8, jit.Ptr(_SP, 0)) 648 self.Emit("MOVQ", _AX, jit.Ptr(_SP, 8)) 649 self.Emit("MOVQ", _AX, jit.Ptr(_SP, 16)) 650 self.call_go(_F_makeslice) 651 self.Emit("MOVQ", jit.Ptr(_SP, 24), _R8) 652 self.Emit("MOVQ", _R8, _VAR_cs_d) 653 self.Emit("MOVQ", _R8, jit.Ptr(_SP, 0)) 654 self.Emit("MOVQ", _VAR_cs_p, _R8) 655 self.Emit("MOVQ", _R8, jit.Ptr(_SP, 8)) 656 self.Emit("MOVQ", _VAR_cs_n, _AX) 657 self.Emit("MOVQ", _AX, jit.Ptr(_SP, 16)) 658 self.call_go(_F_memmove) 659 self.Emit("MOVQ", _VAR_cs_d, _R8) 660 self.Emit("MOVQ", _VAR_cs_n, _AX) 661 self.Emit("MOVQ", _VAR_cs_LR, _DI) 662 // self.Byte(0xcc) 663 self.Rjmp("JMP", _DI) 664 665 /* error handlers */ 666 self.Link("_stack_overflow") 667 self.Emit("MOVL" , _E_recurse, _EP) // MOVQ _E_recurse, EP 668 self.Sjmp("JMP" , "_error") // JMP _error 669 self.Link("_vtype_error") // _vtype_error: 670 self.Emit("MOVQ" , _DI, _IC) // MOVQ DI, IC 671 self.Emit("MOVL" , _E_invalid, _EP) // MOVL _E_invalid, EP 672 self.Sjmp("JMP" , "_error") // JMP _error 673 self.Link("_invalid_char") // _invalid_char: 674 self.Emit("SUBQ" , jit.Imm(1), _IC) // SUBQ $1, IC 675 self.Emit("MOVL" , _E_invalid, _EP) // MOVL _E_invalid, EP 676 self.Sjmp("JMP" , "_error") // JMP _error 677 self.Link("_unquote_error") // _unquote_error: 678 self.Emit("MOVQ" , _VAR_ss_Iv, _IC) // MOVQ ss.Iv, IC 679 self.Emit("SUBQ" , jit.Imm(1), _IC) // SUBQ $1, IC 680 self.Link("_parsing_error") // _parsing_error: 681 self.Emit("NEGQ" , _AX) // NEGQ AX 682 self.Emit("MOVQ" , _AX, _EP) // MOVQ AX, EP 683 self.Link("_error") // _error: 684 self.Emit("PXOR" , _X0, _X0) // PXOR X0, X0 685 self.Emit("MOVOU", _X0, jit.Ptr(_VP, 0)) // MOVOU X0, (VP) 686 self.Sjmp("JMP" , "_epilogue") // JMP _epilogue 687 688 /* invalid value type, never returns */ 689 self.Link("_invalid_vtype") 690 self.Emit("MOVQ", _AX, jit.Ptr(_SP, 0)) // MOVQ AX, (SP) 691 self.call(_F_invalid_vtype) // CALL invalid_type 692 self.Emit("UD2") // UD2 693 694 /* switch jump table */ 695 self.Link("_switch_table") // _switch_table: 696 self.Sref("_decode_V_EOF", 0) // SREF &_decode_V_EOF, $0 697 self.Sref("_decode_V_NULL", -4) // SREF &_decode_V_NULL, $-4 698 self.Sref("_decode_V_TRUE", -8) // SREF &_decode_V_TRUE, $-8 699 self.Sref("_decode_V_FALSE", -12) // SREF &_decode_V_FALSE, $-12 700 self.Sref("_decode_V_ARRAY", -16) // SREF &_decode_V_ARRAY, $-16 701 self.Sref("_decode_V_OBJECT", -20) // SREF &_decode_V_OBJECT, $-20 702 self.Sref("_decode_V_STRING", -24) // SREF &_decode_V_STRING, $-24 703 self.Sref("_decode_V_DOUBLE", -28) // SREF &_decode_V_DOUBLE, $-28 704 self.Sref("_decode_V_INTEGER", -32) // SREF &_decode_V_INTEGER, $-32 705 self.Sref("_decode_V_KEY_SEP", -36) // SREF &_decode_V_KEY_SEP, $-36 706 self.Sref("_decode_V_ELEM_SEP", -40) // SREF &_decode_V_ELEM_SEP, $-40 707 self.Sref("_decode_V_ARRAY_END", -44) // SREF &_decode_V_ARRAY_END, $-44 708 self.Sref("_decode_V_OBJECT_END", -48) // SREF &_decode_V_OBJECT_END, $-48 709 710 /* fast character lookup table */ 711 self.Link("_decode_tab") // _decode_tab: 712 self.Sref("_decode_V_EOF", 0) // SREF &_decode_V_EOF, $0 713 714 /* generate rest of the tabs */ 715 for i := 1; i < 256; i++ { 716 if to, ok := _R_tab[i]; ok { 717 self.Sref(to, -int64(i) * 4) 718 } else { 719 self.Byte(0x00, 0x00, 0x00, 0x00) 720 } 721 } 722 } 723 724 /** Generic Decoder **/ 725 726 var ( 727 _subr_decode_value = new(_ValueDecoder).build() 728 ) 729 730 //go:nosplit 731 func invalid_vtype(vt types.ValueType) { 732 throw(fmt.Sprintf("invalid value type: %d", vt)) 733 }