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  }