podman
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
19package decoder20
21import (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
43const (44_VD_args = 8 // 8 bytes for passing arguments to this functions45_VD_fargs = 64 // 64 bytes for passing arguments to other Go functions46_VD_saves = 48 // 48 bytes for saving the registers before CALL instructions47_VD_locals = 96 // 96 bytes for local variables48)
49
50const (51_VD_offs = _VD_fargs + _VD_saves + _VD_locals52_VD_size = _VD_offs + 8 // 8 bytes for the parent frame pointer53)
54
55var (56_VAR_ss = _VAR_ss_Vt57_VAR_df = jit.Ptr(_SP, _VD_fargs + _VD_saves)58)
59
60var (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
69var (70_VAR_R9 = jit.Ptr(_SP, _VD_fargs + _VD_saves + 56)71)
72type _ValueDecoder struct {73jit.BaseAssembler74}
75
76var (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
83func (self *_ValueDecoder) build() uintptr {84self.Init(self.compile)85return *(*uintptr)(self.Load("decode_value", _VD_size, _VD_args, argPtrs_generic, localPtrs_generic))86}
87
88/** Function Calling Helpers **/
89
90func (self *_ValueDecoder) save(r ...obj.Addr) {91for i, v := range r {92if i > _VD_saves / 8 - 1 {93panic("too many registers to save")94} else {95self.Emit("MOVQ", v, jit.Ptr(_SP, _VD_fargs + int64(i) * 8))96}97}98}
99
100func (self *_ValueDecoder) load(r ...obj.Addr) {101for i, v := range r {102if i > _VD_saves / 8 - 1 {103panic("too many registers to load")104} else {105self.Emit("MOVQ", jit.Ptr(_SP, _VD_fargs + int64(i) * 8), v)106}107}108}
109
110func (self *_ValueDecoder) call(fn obj.Addr) {111self.Emit("MOVQ", fn, _R9) // MOVQ ${fn}, AX112self.Rjmp("CALL", _R9) // CALL AX113}
114
115func (self *_ValueDecoder) call_go(fn obj.Addr) {116self.save(_REG_go...) // SAVE $REG_go117self.call(fn) // CALL ${fn}118self.load(_REG_go...) // LOAD $REG_go119}
120
121func (self *_ValueDecoder) callc(fn obj.Addr) {122self.save(_IP)123self.call(fn)124self.load(_IP)125}
126
127func (self *_ValueDecoder) call_c(fn obj.Addr) {128self.Emit("XCHGQ", _IC, _BX)129self.callc(fn)130self.Emit("XCHGQ", _IC, _BX)131}
132
133/** Decoder Assembler **/
134
135const (136_S_val = iota + 1137_S_arr
138_S_arr_0
139_S_obj
140_S_obj_0
141_S_obj_delim
142_S_obj_sep
143)
144
145const (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
151const (152_A_init_len = 1153_A_init_cap = 16154)
155
156const (157_ST_Sp = 0158_ST_Vt = _PtrBytes159_ST_Vp = _PtrBytes * (types.MAX_RECURSE + 1)160)
161
162var (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
168var (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
175var (176_F_convTslice = jit.Func(convTslice)177_F_convTstring = jit.Func(convTstring)178_F_invalid_vtype = jit.Func(invalid_vtype)179)
180
181var (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
192var _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
201func (self *_ValueDecoder) compile() {202self.Emit("SUBQ", jit.Imm(_VD_size), _SP) // SUBQ $_VD_size, SP203self.Emit("MOVQ", _BP, jit.Ptr(_SP, _VD_offs)) // MOVQ BP, _VD_offs(SP)204self.Emit("LEAQ", jit.Ptr(_SP, _VD_offs), _BP) // LEAQ _VD_offs(SP), BP205
206/* initialize the state machine */207self.Emit("XORL", _CX, _CX) // XORL CX, CX208self.Emit("MOVQ", _DF, _VAR_df) // MOVQ DF, df209/* initialize digital buffer first */210self.Emit("MOVQ", jit.Imm(_MaxDigitNums), _VAR_ss_Dc) // MOVQ $_MaxDigitNums, ss.Dcap211self.Emit("LEAQ", jit.Ptr(_ST, _DbufOffset), _AX) // LEAQ _DbufOffset(ST), AX212self.Emit("MOVQ", _AX, _VAR_ss_Db) // MOVQ AX, ss.Dbuf213/* add ST offset */214self.Emit("ADDQ", jit.Imm(_FsmOffset), _ST) // ADDQ _FsmOffset, _ST215self.Emit("MOVQ", _CX, jit.Ptr(_ST, _ST_Sp)) // MOVQ CX, ST.Sp216self.WriteRecNotAX(0, _VP, jit.Ptr(_ST, _ST_Vp), false) // MOVQ VP, ST.Vp[0]217self.Emit("MOVQ", jit.Imm(_S_val), jit.Ptr(_ST, _ST_Vt)) // MOVQ _S_val, ST.Vt[0]218self.Sjmp("JMP" , "_next") // JMP _next219
220/* set the value from previous round */221self.Link("_set_value") // _set_value:222self.Emit("MOVL" , jit.Imm(_S_vmask), _DX) // MOVL _S_vmask, DX223self.Emit("MOVQ" , jit.Ptr(_ST, _ST_Sp), _CX) // MOVQ ST.Sp, CX224self.Emit("MOVQ" , jit.Sib(_ST, _CX, 8, _ST_Vt), _AX) // MOVQ ST.Vt[CX], AX225self.Emit("BTQ" , _AX, _DX) // BTQ AX, DX226self.Sjmp("JNC" , "_vtype_error") // JNC _vtype_error227self.Emit("XORL" , _SI, _SI) // XORL SI, SI228self.Emit("SUBQ" , jit.Imm(1), jit.Ptr(_ST, _ST_Sp)) // SUBQ $1, ST.Sp229self.Emit("XCHGQ", jit.Sib(_ST, _CX, 8, _ST_Vp), _SI) // XCHGQ ST.Vp[CX], SI230self.Emit("MOVQ" , _R8, jit.Ptr(_SI, 0)) // MOVQ R8, (SI)231self.WriteRecNotAX(1, _R9, jit.Ptr(_SI, 8), false) // MOVQ R9, 8(SI)232
233/* check for value stack */234self.Link("_next") // _next:235self.Emit("MOVQ" , jit.Ptr(_ST, _ST_Sp), _AX) // MOVQ ST.Sp, AX236self.Emit("TESTQ", _AX, _AX) // TESTQ AX, AX237self.Sjmp("JS" , "_return") // JS _return238
239/* fast path: test up to 4 characters manually */240self.Emit("CMPQ" , _IC, _IL) // CMPQ IC, IL241self.Sjmp("JAE" , "_decode_V_EOF") // JAE _decode_V_EOF242self.Emit("MOVBQZX", jit.Sib(_IP, _IC, 1, 0), _AX) // MOVBQZX (IP)(IC), AX243self.Emit("MOVQ" , jit.Imm(_BM_space), _DX) // MOVQ _BM_space, DX244self.Emit("CMPQ" , _AX, jit.Imm(' ')) // CMPQ AX, $' '245self.Sjmp("JA" , "_decode_fast") // JA _decode_fast246self.Emit("BTQ" , _AX, _DX) // BTQ _AX, _DX247self.Sjmp("JNC" , "_decode_fast") // JNC _decode_fast248self.Emit("ADDQ" , jit.Imm(1), _IC) // ADDQ $1, IC249
250/* at least 1 to 3 spaces */251for i := 0; i < 3; i++ {252self.Emit("CMPQ" , _IC, _IL) // CMPQ IC, IL253self.Sjmp("JAE" , "_decode_V_EOF") // JAE _decode_V_EOF254self.Emit("MOVBQZX", jit.Sib(_IP, _IC, 1, 0), _AX) // MOVBQZX (IP)(IC), AX255self.Emit("CMPQ" , _AX, jit.Imm(' ')) // CMPQ AX, $' '256self.Sjmp("JA" , "_decode_fast") // JA _decode_fast257self.Emit("BTQ" , _AX, _DX) // BTQ _AX, _DX258self.Sjmp("JNC" , "_decode_fast") // JNC _decode_fast259self.Emit("ADDQ" , jit.Imm(1), _IC) // ADDQ $1, IC260}261
262/* at least 4 spaces */263self.Emit("CMPQ" , _IC, _IL) // CMPQ IC, IL264self.Sjmp("JAE" , "_decode_V_EOF") // JAE _decode_V_EOF265self.Emit("MOVBQZX", jit.Sib(_IP, _IC, 1, 0), _AX) // MOVBQZX (IP)(IC), AX266
267/* fast path: use lookup table to select decoder */268self.Link("_decode_fast") // _decode_fast:269self.Byte(0x48, 0x8d, 0x3d) // LEAQ ?(PC), DI270self.Sref("_decode_tab", 4) // .... &_decode_tab271self.Emit("MOVLQSX", jit.Sib(_DI, _AX, 4, 0), _AX) // MOVLQSX (DI)(AX*4), AX272self.Emit("TESTQ" , _AX, _AX) // TESTQ AX, AX273self.Sjmp("JZ" , "_decode_native") // JZ _decode_native274self.Emit("ADDQ" , jit.Imm(1), _IC) // ADDQ $1, IC275self.Emit("ADDQ" , _DI, _AX) // ADDQ DI, AX276self.Rjmp("JMP" , _AX) // JMP AX277
278/* decode with native decoder */279self.Link("_decode_native") // _decode_native:280self.Emit("MOVQ", _IP, _DI) // MOVQ IP, DI281self.Emit("MOVQ", _IL, _SI) // MOVQ IL, SI282self.Emit("MOVQ", _IC, _DX) // MOVQ IC, DX283self.Emit("LEAQ", _VAR_ss, _CX) // LEAQ ss, CX284self.Emit("MOVQ", _VAR_df, _R8) // MOVQ $df, R8285self.Emit("BTSQ", jit.Imm(_F_allow_control), _R8) // ANDQ $1<<_F_allow_control, R8286self.callc(_F_value) // CALL value287self.Emit("MOVQ", _AX, _IC) // MOVQ AX, IC288
289/* check for errors */290self.Emit("MOVQ" , _VAR_ss_Vt, _AX) // MOVQ ss.Vt, AX291self.Emit("TESTQ", _AX, _AX) // TESTQ AX, AX292self.Sjmp("JS" , "_parsing_error")293self.Sjmp("JZ" , "_invalid_vtype") // JZ _invalid_vtype294self.Emit("CMPQ" , _AX, _V_max) // CMPQ AX, _V_max295self.Sjmp("JA" , "_invalid_vtype") // JA _invalid_vtype296
297/* jump table selector */298self.Byte(0x48, 0x8d, 0x3d) // LEAQ ?(PC), DI299self.Sref("_switch_table", 4) // .... &_switch_table300self.Emit("MOVLQSX", jit.Sib(_DI, _AX, 4, -4), _AX) // MOVLQSX -4(DI)(AX*4), AX301self.Emit("ADDQ" , _DI, _AX) // ADDQ DI, AX302self.Rjmp("JMP" , _AX) // JMP AX303
304/** V_EOF **/305self.Link("_decode_V_EOF") // _decode_V_EOF:306self.Emit("MOVL", _E_eof, _EP) // MOVL _E_eof, EP307self.Sjmp("JMP" , "_error") // JMP _error308
309/** V_NULL **/310self.Link("_decode_V_NULL") // _decode_V_NULL:311self.Emit("XORL", _R8, _R8) // XORL R8, R8312self.Emit("XORL", _R9, _R9) // XORL R9, R9313self.Emit("LEAQ", jit.Ptr(_IC, -4), _DI) // LEAQ -4(IC), DI314self.Sjmp("JMP" , "_set_value") // JMP _set_value315
316/** V_TRUE **/317self.Link("_decode_V_TRUE") // _decode_V_TRUE:318self.Emit("MOVQ", _T_bool, _R8) // MOVQ _T_bool, R8319// TODO: maybe modified by users?320self.Emit("MOVQ", _V_true, _R9) // MOVQ _V_true, R9321self.Emit("LEAQ", jit.Ptr(_IC, -4), _DI) // LEAQ -4(IC), DI322self.Sjmp("JMP" , "_set_value") // JMP _set_value323
324/** V_FALSE **/325self.Link("_decode_V_FALSE") // _decode_V_FALSE:326self.Emit("MOVQ", _T_bool, _R8) // MOVQ _T_bool, R8327self.Emit("MOVQ", _V_false, _R9) // MOVQ _V_false, R9328self.Emit("LEAQ", jit.Ptr(_IC, -5), _DI) // LEAQ -5(IC), DI329self.Sjmp("JMP" , "_set_value") // JMP _set_value330
331/** V_ARRAY **/332self.Link("_decode_V_ARRAY") // _decode_V_ARRAY333self.Emit("MOVL", jit.Imm(_S_vmask), _DX) // MOVL _S_vmask, DX334self.Emit("MOVQ", jit.Ptr(_ST, _ST_Sp), _CX) // MOVQ ST.Sp, CX335self.Emit("MOVQ", jit.Sib(_ST, _CX, 8, _ST_Vt), _AX) // MOVQ ST.Vt[CX], AX336self.Emit("BTQ" , _AX, _DX) // BTQ AX, DX337self.Sjmp("JNC" , "_invalid_char") // JNC _invalid_char338
339/* create a new array */340self.Emit("MOVQ", _T_eface, _AX) // MOVQ _T_eface, AX341self.Emit("MOVQ", jit.Imm(_A_init_len), _BX) // MOVQ _A_init_len, BX342self.Emit("MOVQ", jit.Imm(_A_init_cap), _CX) // MOVQ _A_init_cap, CX343self.call_go(_F_makeslice) // CALL_GO runtime.makeslice344
345/* pack into an interface */346self.Emit("MOVQ", jit.Imm(_A_init_len), _BX) // MOVQ _A_init_len, BX347self.Emit("MOVQ", jit.Imm(_A_init_cap), _CX) // MOVQ _A_init_cap, CX348self.call_go(_F_convTslice) // CALL_GO runtime.convTslice349self.Emit("MOVQ", _AX, _R8) // MOVQ AX, R8350
351/* replace current state with an array */352self.Emit("MOVQ", jit.Ptr(_ST, _ST_Sp), _CX) // MOVQ ST.Sp, CX353self.Emit("MOVQ", jit.Sib(_ST, _CX, 8, _ST_Vp), _SI) // MOVQ ST.Vp[CX], SI354self.Emit("MOVQ", jit.Imm(_S_arr), jit.Sib(_ST, _CX, 8, _ST_Vt)) // MOVQ _S_arr, ST.Vt[CX]355self.Emit("MOVQ", _T_slice, _AX) // MOVQ _T_slice, AX356self.Emit("MOVQ", _AX, jit.Ptr(_SI, 0)) // MOVQ AX, (SI)357self.WriteRecNotAX(2, _R8, jit.Ptr(_SI, 8), false) // MOVQ R8, 8(SI)358
359/* add a new slot for the first element */360self.Emit("ADDQ", jit.Imm(1), _CX) // ADDQ $1, CX361self.Emit("CMPQ", _CX, jit.Imm(types.MAX_RECURSE)) // CMPQ CX, ${types.MAX_RECURSE}362self.Sjmp("JAE" , "_stack_overflow") // JA _stack_overflow363self.Emit("MOVQ", jit.Ptr(_R8, 0), _AX) // MOVQ (R8), AX364self.Emit("MOVQ", _CX, jit.Ptr(_ST, _ST_Sp)) // MOVQ CX, ST.Sp365self.WritePtrAX(3, jit.Sib(_ST, _CX, 8, _ST_Vp), false) // MOVQ AX, ST.Vp[CX]366self.Emit("MOVQ", jit.Imm(_S_arr_0), jit.Sib(_ST, _CX, 8, _ST_Vt)) // MOVQ _S_arr_0, ST.Vt[CX]367self.Sjmp("JMP" , "_next") // JMP _next368
369/** V_OBJECT **/370self.Link("_decode_V_OBJECT") // _decode_V_OBJECT:371self.Emit("MOVL", jit.Imm(_S_vmask), _DX) // MOVL _S_vmask, DX372self.Emit("MOVQ", jit.Ptr(_ST, _ST_Sp), _CX) // MOVQ ST.Sp, CX373self.Emit("MOVQ", jit.Sib(_ST, _CX, 8, _ST_Vt), _AX) // MOVQ ST.Vt[CX], AX374self.Emit("BTQ" , _AX, _DX) // BTQ AX, DX375self.Sjmp("JNC" , "_invalid_char") // JNC _invalid_char376self.call_go(_F_makemap_small) // CALL_GO runtime.makemap_small377self.Emit("MOVQ", jit.Ptr(_ST, _ST_Sp), _CX) // MOVQ ST.Sp, CX378self.Emit("MOVQ", jit.Imm(_S_obj_0), jit.Sib(_ST, _CX, 8, _ST_Vt)) // MOVQ _S_obj_0, ST.Vt[CX]379self.Emit("MOVQ", jit.Sib(_ST, _CX, 8, _ST_Vp), _SI) // MOVQ ST.Vp[CX], SI380self.Emit("MOVQ", _T_map, _DX) // MOVQ _T_map, DX381self.Emit("MOVQ", _DX, jit.Ptr(_SI, 0)) // MOVQ DX, (SI)382self.WritePtrAX(4, jit.Ptr(_SI, 8), false) // MOVQ AX, 8(SI)383self.Sjmp("JMP" , "_next") // JMP _next384
385/** V_STRING **/386self.Link("_decode_V_STRING") // _decode_V_STRING:387self.Emit("MOVQ", _VAR_ss_Iv, _CX) // MOVQ ss.Iv, CX388self.Emit("MOVQ", _IC, _AX) // MOVQ IC, AX389self.Emit("SUBQ", _CX, _AX) // SUBQ CX, AX390
391/* check for escapes */392self.Emit("CMPQ", _VAR_ss_Ep, jit.Imm(-1)) // CMPQ ss.Ep, $-1393self.Sjmp("JNE" , "_unquote") // JNE _unquote394self.Emit("SUBQ", jit.Imm(1), _AX) // SUBQ $1, AX395self.Emit("LEAQ", jit.Sib(_IP, _CX, 1, 0), _R8) // LEAQ (IP)(CX), R8396self.Byte(0x48, 0x8d, 0x3d) // LEAQ (PC), DI397self.Sref("_copy_string_end", 4)398self.Emit("BTQ", jit.Imm(_F_copy_string), _VAR_df)399self.Sjmp("JC", "copy_string")400self.Link("_copy_string_end")401self.Emit("XORL", _DX, _DX)402
403/* strings with no escape sequences */404self.Link("_noescape") // _noescape:405self.Emit("MOVL", jit.Imm(_S_omask_key), _DI) // MOVL _S_omask, DI406self.Emit("MOVQ", jit.Ptr(_ST, _ST_Sp), _CX) // MOVQ ST.Sp, CX407self.Emit("MOVQ", jit.Sib(_ST, _CX, 8, _ST_Vt), _SI) // MOVQ ST.Vt[CX], SI408self.Emit("BTQ" , _SI, _DI) // BTQ SI, DI409self.Sjmp("JC" , "_object_key") // JC _object_key410
411/* check for pre-packed strings, avoid 1 allocation */412self.Emit("TESTQ", _DX, _DX) // TESTQ DX, DX413self.Sjmp("JNZ" , "_packed_str") // JNZ _packed_str414self.Emit("MOVQ" , _AX, _BX) // MOVQ AX, BX415self.Emit("MOVQ" , _R8, _AX) // MOVQ R8, AX416self.call_go(_F_convTstring) // CALL_GO runtime.convTstring417self.Emit("MOVQ" , _AX, _R9) // MOVQ AX, R9418
419/* packed string already in R9 */420self.Link("_packed_str") // _packed_str:421self.Emit("MOVQ", _T_string, _R8) // MOVQ _T_string, R8422self.Emit("MOVQ", _VAR_ss_Iv, _DI) // MOVQ ss.Iv, DI423self.Emit("SUBQ", jit.Imm(1), _DI) // SUBQ $1, DI424self.Sjmp("JMP" , "_set_value") // JMP _set_value425
426/* the string is an object key, get the map */427self.Link("_object_key")428self.Emit("MOVQ", jit.Ptr(_ST, _ST_Sp), _CX) // MOVQ ST.Sp, CX429self.Emit("MOVQ", jit.Sib(_ST, _CX, 8, _ST_Vp), _SI) // MOVQ ST.Vp[CX], SI430self.Emit("MOVQ", jit.Ptr(_SI, 8), _SI) // MOVQ 8(SI), SI431
432/* add a new delimiter */433self.Emit("ADDQ", jit.Imm(1), _CX) // ADDQ $1, CX434self.Emit("CMPQ", _CX, jit.Imm(types.MAX_RECURSE)) // CMPQ CX, ${types.MAX_RECURSE}435self.Sjmp("JAE" , "_stack_overflow") // JA _stack_overflow436self.Emit("MOVQ", _CX, jit.Ptr(_ST, _ST_Sp)) // MOVQ CX, ST.Sp437self.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 */440self.Emit("MOVQ", _AX, _DI) // MOVQ AX, DI441self.Emit("MOVQ", _T_map, _AX) // MOVQ _T_map, AX442self.Emit("MOVQ", _SI, _BX) // MOVQ SI, BX443self.Emit("MOVQ", _R8, _CX) // MOVQ R9, CX444self.call_go(_F_mapassign_faststr) // CALL_GO runtime.mapassign_faststr445
446/* add to the pointer stack */447self.Emit("MOVQ", jit.Ptr(_ST, _ST_Sp), _CX) // MOVQ ST.Sp, CX448self.WritePtrAX(6, jit.Sib(_ST, _CX, 8, _ST_Vp), false) // MOVQ AX, ST.Vp[CX]449self.Sjmp("JMP" , "_next") // JMP _next450
451/* allocate memory to store the string header and unquoted result */452self.Link("_unquote") // _unquote:453self.Emit("ADDQ", jit.Imm(15), _AX) // ADDQ $15, AX454self.Emit("MOVQ", _T_byte, _BX) // MOVQ _T_byte, BX455self.Emit("MOVB", jit.Imm(0), _CX) // MOVB $0, CX456self.call_go(_F_mallocgc) // CALL_GO runtime.mallocgc457self.Emit("MOVQ", _AX, _R9) // MOVQ AX, R9458
459/* prepare the unquoting parameters */460self.Emit("MOVQ" , _VAR_ss_Iv, _CX) // MOVQ ss.Iv, CX461self.Emit("LEAQ" , jit.Sib(_IP, _CX, 1, 0), _DI) // LEAQ (IP)(CX), DI462self.Emit("NEGQ" , _CX) // NEGQ CX463self.Emit("LEAQ" , jit.Sib(_IC, _CX, 1, -1), _SI) // LEAQ -1(IC)(CX), SI464self.Emit("LEAQ" , jit.Ptr(_R9, 16), _DX) // LEAQ 16(R8), DX465self.Emit("LEAQ" , _VAR_ss_Ep, _CX) // LEAQ ss.Ep, CX466self.Emit("XORL" , _R8, _R8) // XORL R8, R8467self.Emit("BTQ" , jit.Imm(_F_disable_urc), _VAR_df) // BTQ ${_F_disable_urc}, fv468self.Emit("SETCC", _R8) // SETCC R8469self.Emit("SHLQ" , jit.Imm(types.B_UNICODE_REPLACE), _R8) // SHLQ ${types.B_UNICODE_REPLACE}, R8470
471/* unquote the string, with R9 been preserved */472self.Emit("MOVQ", _R9, _VAR_R9) // SAVE R9473self.call_c(_F_unquote) // CALL unquote474self.Emit("MOVQ", _VAR_R9, _R9) // LOAD R9475
476/* check for errors */477self.Emit("TESTQ", _AX, _AX) // TESTQ AX, AX478self.Sjmp("JS" , "_unquote_error") // JS _unquote_error479self.Emit("MOVL" , jit.Imm(1), _DX) // MOVL $1, DX480self.Emit("LEAQ" , jit.Ptr(_R9, 16), _R8) // ADDQ $16, R8481self.Emit("MOVQ" , _R8, jit.Ptr(_R9, 0)) // MOVQ R8, (R9)482self.Emit("MOVQ" , _AX, jit.Ptr(_R9, 8)) // MOVQ AX, 8(R9)483self.Sjmp("JMP" , "_noescape") // JMP _noescape484
485/** V_DOUBLE **/486self.Link("_decode_V_DOUBLE") // _decode_V_DOUBLE:487self.Emit("BTQ" , jit.Imm(_F_use_number), _VAR_df) // BTQ _F_use_number, df488self.Sjmp("JC" , "_use_number") // JC _use_number489self.Emit("MOVSD", _VAR_ss_Dv, _X0) // MOVSD ss.Dv, X0490self.Sjmp("JMP" , "_use_float64") // JMP _use_float64491
492/** V_INTEGER **/493self.Link("_decode_V_INTEGER") // _decode_V_INTEGER:494self.Emit("BTQ" , jit.Imm(_F_use_number), _VAR_df) // BTQ _F_use_number, df495self.Sjmp("JC" , "_use_number") // JC _use_number496self.Emit("BTQ" , jit.Imm(_F_use_int64), _VAR_df) // BTQ _F_use_int64, df497self.Sjmp("JC" , "_use_int64") // JC _use_int64498//TODO: use ss.Dv directly499self.Emit("MOVSD", _VAR_ss_Dv, _X0) // MOVSD ss.Dv, X0500
501/* represent numbers as `float64` */502self.Link("_use_float64") // _use_float64:503self.Emit("MOVQ" , _X0, _AX) // MOVQ X0, AX504self.call_go(_F_convT64) // CALL_GO runtime.convT64505self.Emit("MOVQ" , _T_float64, _R8) // MOVQ _T_float64, R8506self.Emit("MOVQ" , _AX, _R9) // MOVQ AX, R9507self.Emit("MOVQ" , _VAR_ss_Ep, _DI) // MOVQ ss.Ep, DI508self.Sjmp("JMP" , "_set_value") // JMP _set_value509
510/* represent numbers as `json.Number` */511self.Link("_use_number") // _use_number512self.Emit("MOVQ", _VAR_ss_Ep, _AX) // MOVQ ss.Ep, AX513self.Emit("LEAQ", jit.Sib(_IP, _AX, 1, 0), _SI) // LEAQ (IP)(AX), SI514self.Emit("MOVQ", _IC, _CX) // MOVQ IC, CX515self.Emit("SUBQ", _AX, _CX) // SUBQ AX, CX516self.Emit("MOVQ", _SI, _AX) // MOVQ SI, AX517self.Emit("MOVQ", _CX, _BX) // MOVQ CX, BX518self.call_go(_F_convTstring) // CALL_GO runtime.convTstring519self.Emit("MOVQ", _T_number, _R8) // MOVQ _T_number, R8520self.Emit("MOVQ", _AX, _R9) // MOVQ AX, R9521self.Emit("MOVQ", _VAR_ss_Ep, _DI) // MOVQ ss.Ep, DI522self.Sjmp("JMP" , "_set_value") // JMP _set_value523
524/* represent numbers as `int64` */525self.Link("_use_int64") // _use_int64:526self.Emit("MOVQ", _VAR_ss_Iv, _AX) // MOVQ ss.Iv, AX527self.call_go(_F_convT64) // CALL_GO runtime.convT64528self.Emit("MOVQ", _T_int64, _R8) // MOVQ _T_int64, R8529self.Emit("MOVQ", _AX, _R9) // MOVQ AX, R9530self.Emit("MOVQ", _VAR_ss_Ep, _DI) // MOVQ ss.Ep, DI531self.Sjmp("JMP" , "_set_value") // JMP _set_value532
533/** V_KEY_SEP **/534self.Link("_decode_V_KEY_SEP") // _decode_V_KEY_SEP:535self.Emit("MOVQ", jit.Ptr(_ST, _ST_Sp), _CX) // MOVQ ST.Sp, CX536self.Emit("MOVQ", jit.Sib(_ST, _CX, 8, _ST_Vt), _AX) // MOVQ ST.Vt[CX], AX537self.Emit("CMPQ", _AX, jit.Imm(_S_obj_delim)) // CMPQ AX, _S_obj_delim538self.Sjmp("JNE" , "_invalid_char") // JNE _invalid_char539self.Emit("MOVQ", jit.Imm(_S_val), jit.Sib(_ST, _CX, 8, _ST_Vt)) // MOVQ _S_val, ST.Vt[CX]540self.Emit("MOVQ", jit.Imm(_S_obj), jit.Sib(_ST, _CX, 8, _ST_Vt - 8)) // MOVQ _S_obj, ST.Vt[CX - 1]541self.Sjmp("JMP" , "_next") // JMP _next542
543/** V_ELEM_SEP **/544self.Link("_decode_V_ELEM_SEP") // _decode_V_ELEM_SEP:545self.Emit("MOVQ" , jit.Ptr(_ST, _ST_Sp), _CX) // MOVQ ST.Sp, CX546self.Emit("MOVQ" , jit.Sib(_ST, _CX, 8, _ST_Vt), _AX) // MOVQ ST.Vt[CX], AX547self.Emit("CMPQ" , _AX, jit.Imm(_S_arr))548self.Sjmp("JE" , "_array_sep") // JZ _next549self.Emit("CMPQ" , _AX, jit.Imm(_S_obj)) // CMPQ _AX, _S_arr550self.Sjmp("JNE" , "_invalid_char") // JNE _invalid_char551self.Emit("MOVQ" , jit.Imm(_S_obj_sep), jit.Sib(_ST, _CX, 8, _ST_Vt))552self.Sjmp("JMP" , "_next") // JMP _next553
554/* arrays */555self.Link("_array_sep")556self.Emit("MOVQ", jit.Sib(_ST, _CX, 8, _ST_Vp), _SI) // MOVQ ST.Vp[CX], SI557self.Emit("MOVQ", jit.Ptr(_SI, 8), _SI) // MOVQ 8(SI), SI558self.Emit("MOVQ", jit.Ptr(_SI, 8), _DX) // MOVQ 8(SI), DX559self.Emit("CMPQ", _DX, jit.Ptr(_SI, 16)) // CMPQ DX, 16(SI)560self.Sjmp("JAE" , "_array_more") // JAE _array_more561
562/* add a slot for the new element */563self.Link("_array_append") // _array_append:564self.Emit("ADDQ", jit.Imm(1), jit.Ptr(_SI, 8)) // ADDQ $1, 8(SI)565self.Emit("MOVQ", jit.Ptr(_SI, 0), _SI) // MOVQ (SI), SI566self.Emit("ADDQ", jit.Imm(1), _CX) // ADDQ $1, CX567self.Emit("CMPQ", _CX, jit.Imm(types.MAX_RECURSE)) // CMPQ CX, ${types.MAX_RECURSE}568self.Sjmp("JAE" , "_stack_overflow") // JA _stack_overflow569self.Emit("SHLQ", jit.Imm(1), _DX) // SHLQ $1, DX570self.Emit("LEAQ", jit.Sib(_SI, _DX, 8, 0), _SI) // LEAQ (SI)(DX*8), SI571self.Emit("MOVQ", _CX, jit.Ptr(_ST, _ST_Sp)) // MOVQ CX, ST.Sp572self.WriteRecNotAX(7 , _SI, jit.Sib(_ST, _CX, 8, _ST_Vp), false) // MOVQ SI, ST.Vp[CX]573self.Emit("MOVQ", jit.Imm(_S_val), jit.Sib(_ST, _CX, 8, _ST_Vt)) // MOVQ _S_val, ST.Vt[CX}574self.Sjmp("JMP" , "_next") // JMP _next575
576/** V_ARRAY_END **/577self.Link("_decode_V_ARRAY_END") // _decode_V_ARRAY_END:578self.Emit("XORL", _DX, _DX) // XORL DX, DX579self.Emit("MOVQ", jit.Ptr(_ST, _ST_Sp), _CX) // MOVQ ST.Sp, CX580self.Emit("MOVQ", jit.Sib(_ST, _CX, 8, _ST_Vt), _AX) // MOVQ ST.Vt[CX], AX581self.Emit("CMPQ", _AX, jit.Imm(_S_arr_0)) // CMPQ AX, _S_arr_0582self.Sjmp("JE" , "_first_item") // JE _first_item583self.Emit("CMPQ", _AX, jit.Imm(_S_arr)) // CMPQ AX, _S_arr584self.Sjmp("JNE" , "_invalid_char") // JNE _invalid_char585self.Emit("SUBQ", jit.Imm(1), jit.Ptr(_ST, _ST_Sp)) // SUBQ $1, ST.Sp586self.Emit("MOVQ", _DX, jit.Sib(_ST, _CX, 8, _ST_Vp)) // MOVQ DX, ST.Vp[CX]587self.Sjmp("JMP" , "_next") // JMP _next588
589/* first element of an array */590self.Link("_first_item") // _first_item:591self.Emit("MOVQ", jit.Ptr(_ST, _ST_Sp), _CX) // MOVQ ST.Sp, CX592self.Emit("SUBQ", jit.Imm(2), jit.Ptr(_ST, _ST_Sp)) // SUBQ $2, ST.Sp593self.Emit("MOVQ", jit.Sib(_ST, _CX, 8, _ST_Vp - 8), _SI) // MOVQ ST.Vp[CX - 1], SI594self.Emit("MOVQ", jit.Ptr(_SI, 8), _SI) // MOVQ 8(SI), SI595self.Emit("MOVQ", _DX, jit.Sib(_ST, _CX, 8, _ST_Vp - 8)) // MOVQ DX, ST.Vp[CX - 1]596self.Emit("MOVQ", _DX, jit.Sib(_ST, _CX, 8, _ST_Vp)) // MOVQ DX, ST.Vp[CX]597self.Emit("MOVQ", _DX, jit.Ptr(_SI, 8)) // MOVQ DX, 8(SI)598self.Sjmp("JMP" , "_next") // JMP _next599
600/** V_OBJECT_END **/601self.Link("_decode_V_OBJECT_END") // _decode_V_OBJECT_END:602self.Emit("MOVL", jit.Imm(_S_omask_end), _DI) // MOVL _S_omask, DI603self.Emit("MOVQ", jit.Ptr(_ST, _ST_Sp), _CX) // MOVQ ST.Sp, CX604self.Emit("MOVQ", jit.Sib(_ST, _CX, 8, _ST_Vt), _AX) // MOVQ ST.Vt[CX], AX605self.Emit("BTQ" , _AX, _DI)606self.Sjmp("JNC" , "_invalid_char") // JNE _invalid_char607self.Emit("XORL", _AX, _AX) // XORL AX, AX608self.Emit("SUBQ", jit.Imm(1), jit.Ptr(_ST, _ST_Sp)) // SUBQ $1, ST.Sp609self.Emit("MOVQ", _AX, jit.Sib(_ST, _CX, 8, _ST_Vp)) // MOVQ AX, ST.Vp[CX]610self.Sjmp("JMP" , "_next") // JMP _next611
612/* return from decoder */613self.Link("_return") // _return:614self.Emit("XORL", _EP, _EP) // XORL EP, EP615self.Emit("MOVQ", _EP, jit.Ptr(_ST, _ST_Vp)) // MOVQ EP, ST.Vp[0]616self.Link("_epilogue") // _epilogue:617self.Emit("SUBQ", jit.Imm(_FsmOffset), _ST) // SUBQ _FsmOffset, _ST618self.Emit("MOVQ", jit.Ptr(_SP, _VD_offs), _BP) // MOVQ _VD_offs(SP), BP619self.Emit("ADDQ", jit.Imm(_VD_size), _SP) // ADDQ $_VD_size, SP620self.Emit("RET") // RET621
622/* array expand */623self.Link("_array_more") // _array_more:624self.Emit("MOVQ" , _T_eface, _AX) // MOVQ _T_eface, AX625self.Emit("MOVQ" , jit.Ptr(_SI, 0), _BX) // MOVQ (SI), BX626self.Emit("MOVQ" , jit.Ptr(_SI, 8), _CX) // MOVQ 8(SI), CX627self.Emit("MOVQ" , jit.Ptr(_SI, 16), _DI) // MOVQ 16(SI), DI628self.Emit("MOVQ" , _DI, _SI) // MOVQ DI, 24(SP)629self.Emit("SHLQ" , jit.Imm(1), _SI) // SHLQ $1, SI630self.call_go(_F_growslice) // CALL_GO runtime.growslice631self.Emit("MOVQ" , _AX, _DI) // MOVQ AX, DI632self.Emit("MOVQ" , _BX, _DX) // MOVQ BX, DX633self.Emit("MOVQ" , _CX, _AX) // MOVQ CX, AX634
635/* update the slice */636self.Emit("MOVQ", jit.Ptr(_ST, _ST_Sp), _CX) // MOVQ ST.Sp, CX637self.Emit("MOVQ", jit.Sib(_ST, _CX, 8, _ST_Vp), _SI) // MOVQ ST.Vp[CX], SI638self.Emit("MOVQ", jit.Ptr(_SI, 8), _SI) // MOVQ 8(SI), SI639self.Emit("MOVQ", _DX, jit.Ptr(_SI, 8)) // MOVQ DX, 8(SI)640self.Emit("MOVQ", _AX, jit.Ptr(_SI, 16)) // MOVQ AX, 16(AX)641self.WriteRecNotAX(8 , _DI, jit.Ptr(_SI, 0), false) // MOVQ R10, (SI)642self.Sjmp("JMP" , "_array_append") // JMP _array_append643
644/* copy string */645self.Link("copy_string") // pointer: R8, length: AX, return addr: DI646self.Emit("MOVQ", _R8, _VAR_cs_p)647self.Emit("MOVQ", _AX, _VAR_cs_n)648self.Emit("MOVQ", _DI, _VAR_cs_LR)649self.Emit("MOVQ", _AX, _BX)650self.Emit("MOVQ", _AX, _CX)651self.Emit("MOVQ", _T_byte, _AX)652self.call_go(_F_makeslice)653self.Emit("MOVQ", _AX, _VAR_cs_d)654self.Emit("MOVQ", _VAR_cs_p, _BX)655self.Emit("MOVQ", _VAR_cs_n, _CX)656self.call_go(_F_memmove)657self.Emit("MOVQ", _VAR_cs_d, _R8)658self.Emit("MOVQ", _VAR_cs_n, _AX)659self.Emit("MOVQ", _VAR_cs_LR, _DI)660self.Rjmp("JMP", _DI)661
662/* error handlers */663self.Link("_stack_overflow")664self.Emit("MOVL" , _E_recurse, _EP) // MOVQ _E_recurse, EP665self.Sjmp("JMP" , "_error") // JMP _error666self.Link("_vtype_error") // _vtype_error:667self.Emit("MOVQ" , _DI, _IC) // MOVQ DI, IC668self.Emit("MOVL" , _E_invalid, _EP) // MOVL _E_invalid, EP669self.Sjmp("JMP" , "_error") // JMP _error670self.Link("_invalid_char") // _invalid_char:671self.Emit("SUBQ" , jit.Imm(1), _IC) // SUBQ $1, IC672self.Emit("MOVL" , _E_invalid, _EP) // MOVL _E_invalid, EP673self.Sjmp("JMP" , "_error") // JMP _error674self.Link("_unquote_error") // _unquote_error:675self.Emit("MOVQ" , _VAR_ss_Iv, _IC) // MOVQ ss.Iv, IC676self.Emit("SUBQ" , jit.Imm(1), _IC) // SUBQ $1, IC677self.Link("_parsing_error") // _parsing_error:678self.Emit("NEGQ" , _AX) // NEGQ AX679self.Emit("MOVQ" , _AX, _EP) // MOVQ AX, EP680self.Link("_error") // _error:681self.Emit("PXOR" , _X0, _X0) // PXOR X0, X0682self.Emit("MOVOU", _X0, jit.Ptr(_VP, 0)) // MOVOU X0, (VP)683self.Sjmp("JMP" , "_epilogue") // JMP _epilogue684
685/* invalid value type, never returns */686self.Link("_invalid_vtype")687self.call_go(_F_invalid_vtype) // CALL invalid_type688self.Emit("UD2") // UD2689
690/* switch jump table */691self.Link("_switch_table") // _switch_table:692self.Sref("_decode_V_EOF", 0) // SREF &_decode_V_EOF, $0693self.Sref("_decode_V_NULL", -4) // SREF &_decode_V_NULL, $-4694self.Sref("_decode_V_TRUE", -8) // SREF &_decode_V_TRUE, $-8695self.Sref("_decode_V_FALSE", -12) // SREF &_decode_V_FALSE, $-12696self.Sref("_decode_V_ARRAY", -16) // SREF &_decode_V_ARRAY, $-16697self.Sref("_decode_V_OBJECT", -20) // SREF &_decode_V_OBJECT, $-20698self.Sref("_decode_V_STRING", -24) // SREF &_decode_V_STRING, $-24699self.Sref("_decode_V_DOUBLE", -28) // SREF &_decode_V_DOUBLE, $-28700self.Sref("_decode_V_INTEGER", -32) // SREF &_decode_V_INTEGER, $-32701self.Sref("_decode_V_KEY_SEP", -36) // SREF &_decode_V_KEY_SEP, $-36702self.Sref("_decode_V_ELEM_SEP", -40) // SREF &_decode_V_ELEM_SEP, $-40703self.Sref("_decode_V_ARRAY_END", -44) // SREF &_decode_V_ARRAY_END, $-44704self.Sref("_decode_V_OBJECT_END", -48) // SREF &_decode_V_OBJECT_END, $-48705
706/* fast character lookup table */707self.Link("_decode_tab") // _decode_tab:708self.Sref("_decode_V_EOF", 0) // SREF &_decode_V_EOF, $0709
710/* generate rest of the tabs */711for i := 1; i < 256; i++ {712if to, ok := _R_tab[i]; ok {713self.Sref(to, -int64(i) * 4)714} else {715self.Byte(0x00, 0x00, 0x00, 0x00)716}717}718}
719
720/** Generic Decoder **/
721
722var (723_subr_decode_value = new(_ValueDecoder).build()724)
725
726//go:nosplit
727func invalid_vtype(vt types.ValueType) {728throw(fmt.Sprintf("invalid value type: %d", vt))729}
730