github.com/bytedance/sonic@v1.11.7-0.20240517092252-d2edb31b167b/internal/decoder/generic_stkabi_amd64.go (about)

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