github.com/goshafaq/sonic@v0.0.0-20231026082336-871835fb94c6/internal/decoder/generic_stkabi_amd64.go (about)

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