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

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