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