github.com/bytedance/sonic@v1.11.7-0.20240517092252-d2edb31b167b/internal/encoder/assembler_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 encoder
    20  
    21  import (
    22      `fmt`
    23      `reflect`
    24      `strconv`
    25      `unsafe`
    26  
    27      `github.com/bytedance/sonic/internal/cpu`
    28      `github.com/bytedance/sonic/internal/jit`
    29      `github.com/bytedance/sonic/internal/native/types`
    30      `github.com/twitchyliquid64/golang-asm/obj`
    31      `github.com/twitchyliquid64/golang-asm/obj/x86`
    32  
    33      `github.com/bytedance/sonic/internal/native`
    34      `github.com/bytedance/sonic/internal/rt`
    35  )
    36  
    37  /** Register Allocations
    38   *
    39   *  State Registers:
    40   *
    41   *      %rbx : stack base
    42   *      %rdi : result pointer
    43   *      %rsi : result length
    44   *      %rdx : result capacity
    45   *      %r12 : sp->p
    46   *      %r13 : sp->q
    47   *      %r14 : sp->x
    48   *      %r15 : sp->f
    49   *
    50   *  Error Registers:
    51   *
    52   *      %r10 : error type register
    53   *      %r11 : error pointer register
    54   */
    55  
    56  /** Function Prototype & Stack Map
    57   *
    58   *  func (buf *[]byte, p unsafe.Pointer, sb *_Stack, fv uint64) (err error)
    59   *
    60   *  buf    :   (FP)
    61   *  p      :  8(FP)
    62   *  sb     : 16(FP)
    63   *  fv     : 24(FP)
    64   *  err.vt : 32(FP)
    65   *  err.vp : 40(FP)
    66   */
    67  
    68  const (
    69      _S_cond = iota
    70      _S_init
    71  )
    72  
    73  const (
    74      _FP_args   = 32     // 32 bytes for spill registers of arguments
    75      _FP_fargs  = 40     // 40 bytes for passing arguments to other Go functions
    76      _FP_saves  = 64     // 64 bytes for saving the registers before CALL instructions
    77      _FP_locals = 24     // 24 bytes for local variables
    78  )
    79  
    80  const (
    81      _FP_loffs = _FP_fargs + _FP_saves
    82      _FP_offs  = _FP_loffs + _FP_locals
    83      // _FP_offs  = _FP_loffs + _FP_locals + _FP_debug
    84      _FP_size  = _FP_offs + 8     // 8 bytes for the parent frame pointer
    85      _FP_base  = _FP_size + 8     // 8 bytes for the return address
    86  )
    87  
    88  const (
    89      _FM_exp32 = 0x7f800000
    90      _FM_exp64 = 0x7ff0000000000000
    91  )
    92  
    93  const (
    94      _IM_null   = 0x6c6c756e           // 'null'
    95      _IM_true   = 0x65757274           // 'true'
    96      _IM_fals   = 0x736c6166           // 'fals' ('false' without the 'e')
    97      _IM_open   = 0x00225c22           // '"\"∅'
    98      _IM_array  = 0x5d5b               // '[]'
    99      _IM_object = 0x7d7b               // '{}'
   100      _IM_mulv   = -0x5555555555555555
   101  )
   102  
   103  const (
   104      _LB_more_space        = "_more_space"
   105      _LB_more_space_return = "_more_space_return_"
   106  )
   107  
   108  const (
   109      _LB_error                 = "_error"
   110      _LB_error_too_deep        = "_error_too_deep"
   111      _LB_error_invalid_number  = "_error_invalid_number"
   112      _LB_error_nan_or_infinite = "_error_nan_or_infinite"
   113      _LB_panic = "_panic"
   114  )
   115  
   116  var (
   117      _AX = jit.Reg("AX")
   118      _BX = jit.Reg("BX")
   119      _CX = jit.Reg("CX")
   120      _DX = jit.Reg("DX")
   121      _DI = jit.Reg("DI")
   122      _SI = jit.Reg("SI")
   123      _BP = jit.Reg("BP")
   124      _SP = jit.Reg("SP")
   125      _R8 = jit.Reg("R8")
   126      _R9 = jit.Reg("R9")
   127  )
   128  
   129  var (
   130      _X0 = jit.Reg("X0")
   131      _X15 = jit.Reg("X15")
   132      _Y0 = jit.Reg("Y0")
   133  )
   134  
   135  var (
   136      _ST = jit.Reg("R15")     // can't use R14 since it's always scratched by Go...
   137      _RP = jit.Reg("DI")
   138      _RL = jit.Reg("SI")
   139      _RC = jit.Reg("DX")
   140  )
   141  
   142  var (
   143      _LR = jit.Reg("R9")
   144      _ET = jit.Reg("AX")
   145      _EP = jit.Reg("BX")
   146  )
   147  
   148  var (
   149      _SP_p = jit.Reg("R10") // saved on BX when call_c
   150      _SP_q = jit.Reg("R11") // saved on BP when call_c
   151      _SP_x = jit.Reg("R12")
   152      _SP_f = jit.Reg("R13") 
   153  )
   154  
   155  var (
   156      _ARG_rb = jit.Ptr(_SP, _FP_base)
   157      _ARG_vp = jit.Ptr(_SP, _FP_base + 8)
   158      _ARG_sb = jit.Ptr(_SP, _FP_base + 16)
   159      _ARG_fv = jit.Ptr(_SP, _FP_base + 24)
   160  )
   161  
   162  var (
   163      _RET_et = _ET
   164      _RET_ep = _EP
   165  )
   166  
   167  var (
   168      _VAR_sp = jit.Ptr(_SP, _FP_fargs + _FP_saves)
   169      _VAR_dn = jit.Ptr(_SP, _FP_fargs + _FP_saves + 8)
   170      _VAR_vp = jit.Ptr(_SP, _FP_fargs + _FP_saves + 16)
   171  )
   172  
   173  var (
   174      _REG_ffi = []obj.Addr{ _RP, _RL, _RC, _SP_q}
   175      _REG_b64 = []obj.Addr{_SP_p, _SP_q}
   176  
   177      _REG_all = []obj.Addr{_ST, _SP_x, _SP_f, _SP_p, _SP_q, _RP, _RL, _RC}
   178      _REG_ms  = []obj.Addr{_ST, _SP_x, _SP_f, _SP_p, _SP_q, _LR}
   179      _REG_enc = []obj.Addr{_ST, _SP_x, _SP_f, _SP_p, _SP_q, _RL}
   180  )
   181  
   182  type _Assembler struct {
   183      jit.BaseAssembler
   184      p _Program
   185      x int
   186      name string
   187  }
   188  
   189  func newAssembler(p _Program) *_Assembler {
   190      return new(_Assembler).Init(p)
   191  }
   192  
   193  /** Assembler Interface **/
   194  
   195  func (self *_Assembler) Load() _Encoder {
   196      return ptoenc(self.BaseAssembler.Load("encode_"+self.name, _FP_size, _FP_args, argPtrs, localPtrs))
   197  }
   198  
   199  func (self *_Assembler) Init(p _Program) *_Assembler {
   200      self.p = p
   201      self.BaseAssembler.Init(self.compile)
   202      return self
   203  }
   204  
   205  func (self *_Assembler) compile() {
   206      self.prologue()
   207      self.instrs()
   208      self.epilogue()
   209      self.builtins()
   210  }
   211  
   212  /** Assembler Stages **/
   213  
   214  var _OpFuncTab = [256]func(*_Assembler, *_Instr) {
   215      _OP_null           : (*_Assembler)._asm_OP_null,
   216      _OP_empty_arr      : (*_Assembler)._asm_OP_empty_arr,
   217      _OP_empty_obj      : (*_Assembler)._asm_OP_empty_obj, 
   218      _OP_bool           : (*_Assembler)._asm_OP_bool,
   219      _OP_i8             : (*_Assembler)._asm_OP_i8,
   220      _OP_i16            : (*_Assembler)._asm_OP_i16,
   221      _OP_i32            : (*_Assembler)._asm_OP_i32,
   222      _OP_i64            : (*_Assembler)._asm_OP_i64,
   223      _OP_u8             : (*_Assembler)._asm_OP_u8,
   224      _OP_u16            : (*_Assembler)._asm_OP_u16,
   225      _OP_u32            : (*_Assembler)._asm_OP_u32,
   226      _OP_u64            : (*_Assembler)._asm_OP_u64,
   227      _OP_f32            : (*_Assembler)._asm_OP_f32,
   228      _OP_f64            : (*_Assembler)._asm_OP_f64,
   229      _OP_str            : (*_Assembler)._asm_OP_str,
   230      _OP_bin            : (*_Assembler)._asm_OP_bin,
   231      _OP_quote          : (*_Assembler)._asm_OP_quote,
   232      _OP_number         : (*_Assembler)._asm_OP_number,
   233      _OP_eface          : (*_Assembler)._asm_OP_eface,
   234      _OP_iface          : (*_Assembler)._asm_OP_iface,
   235      _OP_byte           : (*_Assembler)._asm_OP_byte,
   236      _OP_text           : (*_Assembler)._asm_OP_text,
   237      _OP_deref          : (*_Assembler)._asm_OP_deref,
   238      _OP_index          : (*_Assembler)._asm_OP_index,
   239      _OP_load           : (*_Assembler)._asm_OP_load,
   240      _OP_save           : (*_Assembler)._asm_OP_save,
   241      _OP_drop           : (*_Assembler)._asm_OP_drop,
   242      _OP_drop_2         : (*_Assembler)._asm_OP_drop_2,
   243      _OP_recurse        : (*_Assembler)._asm_OP_recurse,
   244      _OP_is_nil         : (*_Assembler)._asm_OP_is_nil,
   245      _OP_is_nil_p1      : (*_Assembler)._asm_OP_is_nil_p1,
   246      _OP_is_zero_1      : (*_Assembler)._asm_OP_is_zero_1,
   247      _OP_is_zero_2      : (*_Assembler)._asm_OP_is_zero_2,
   248      _OP_is_zero_4      : (*_Assembler)._asm_OP_is_zero_4,
   249      _OP_is_zero_8      : (*_Assembler)._asm_OP_is_zero_8,
   250      _OP_is_zero_map    : (*_Assembler)._asm_OP_is_zero_map,
   251      _OP_goto           : (*_Assembler)._asm_OP_goto,
   252      _OP_map_iter       : (*_Assembler)._asm_OP_map_iter,
   253      _OP_map_stop       : (*_Assembler)._asm_OP_map_stop,
   254      _OP_map_check_key  : (*_Assembler)._asm_OP_map_check_key,
   255      _OP_map_write_key  : (*_Assembler)._asm_OP_map_write_key,
   256      _OP_map_value_next : (*_Assembler)._asm_OP_map_value_next,
   257      _OP_slice_len      : (*_Assembler)._asm_OP_slice_len,
   258      _OP_slice_next     : (*_Assembler)._asm_OP_slice_next,
   259      _OP_marshal        : (*_Assembler)._asm_OP_marshal,
   260      _OP_marshal_p      : (*_Assembler)._asm_OP_marshal_p,
   261      _OP_marshal_text   : (*_Assembler)._asm_OP_marshal_text,
   262      _OP_marshal_text_p : (*_Assembler)._asm_OP_marshal_text_p,
   263      _OP_cond_set       : (*_Assembler)._asm_OP_cond_set,
   264      _OP_cond_testc     : (*_Assembler)._asm_OP_cond_testc,
   265  }
   266  
   267  func (self *_Assembler) instr(v *_Instr) {
   268      if fn := _OpFuncTab[v.op()]; fn != nil {
   269          fn(self, v)
   270      } else {
   271          panic(fmt.Sprintf("invalid opcode: %d", v.op()))
   272      }
   273  }
   274  
   275  func (self *_Assembler) instrs() {
   276      for i, v := range self.p {
   277          self.Mark(i)
   278          self.instr(&v)
   279          self.debug_instr(i, &v)
   280      }
   281  }
   282  
   283  func (self *_Assembler) builtins() {
   284      self.more_space()
   285      self.error_too_deep()
   286      self.error_invalid_number()
   287      self.error_nan_or_infinite()
   288      self.go_panic()
   289  }
   290  
   291  func (self *_Assembler) epilogue() {
   292      self.Mark(len(self.p))
   293      self.Emit("XORL", _ET, _ET)
   294      self.Emit("XORL", _EP, _EP)
   295      self.Link(_LB_error)
   296      self.Emit("MOVQ", _ARG_rb, _CX)                 // MOVQ rb<>+0(FP), CX
   297      self.Emit("MOVQ", _RL, jit.Ptr(_CX, 8))         // MOVQ RL, 8(CX)
   298      self.Emit("MOVQ", jit.Imm(0), _ARG_rb)          // MOVQ AX, rb<>+0(FP)
   299      self.Emit("MOVQ", jit.Imm(0), _ARG_vp)          // MOVQ BX, vp<>+8(FP)
   300      self.Emit("MOVQ", jit.Imm(0), _ARG_sb)          // MOVQ CX, sb<>+16(FP)
   301      self.Emit("MOVQ", jit.Ptr(_SP, _FP_offs), _BP)  // MOVQ _FP_offs(SP), BP
   302      self.Emit("ADDQ", jit.Imm(_FP_size), _SP)       // ADDQ $_FP_size, SP
   303      self.Emit("RET")                                // RET
   304  }
   305  
   306  func (self *_Assembler) prologue() {
   307      self.Emit("SUBQ", jit.Imm(_FP_size), _SP)       // SUBQ $_FP_size, SP
   308      self.Emit("MOVQ", _BP, jit.Ptr(_SP, _FP_offs))  // MOVQ BP, _FP_offs(SP)
   309      self.Emit("LEAQ", jit.Ptr(_SP, _FP_offs), _BP)  // LEAQ _FP_offs(SP), BP
   310      self.Emit("MOVQ", _AX, _ARG_rb)                 // MOVQ AX, rb<>+0(FP)
   311      self.Emit("MOVQ", _BX, _ARG_vp)                 // MOVQ BX, vp<>+8(FP)
   312      self.Emit("MOVQ", _CX, _ARG_sb)                 // MOVQ CX, sb<>+16(FP)
   313      self.Emit("MOVQ", _DI, _ARG_fv)                 // MOVQ DI, rb<>+24(FP)
   314      self.Emit("MOVQ", jit.Ptr(_AX,  0), _RP)        // MOVQ (AX)  , DI
   315      self.Emit("MOVQ", jit.Ptr(_AX,  8), _RL)        // MOVQ 8(AX) , SI
   316      self.Emit("MOVQ", jit.Ptr(_AX, 16), _RC)        // MOVQ 16(AX), DX
   317      self.Emit("MOVQ", _BX, _SP_p)                   // MOVQ BX, R10
   318      self.Emit("MOVQ", _CX, _ST)                     // MOVQ CX, R8
   319      self.Emit("XORL", _SP_x, _SP_x)                 // XORL R10, R12
   320      self.Emit("XORL", _SP_f, _SP_f)                 // XORL R11, R13
   321      self.Emit("XORL", _SP_q, _SP_q)                 // XORL R13, R11
   322  }
   323  
   324  /** Assembler Inline Functions **/
   325  
   326  func (self *_Assembler) xsave(reg ...obj.Addr) {
   327      for i, v := range reg {
   328          if i > _FP_saves / 8 - 1 {
   329              panic("too many registers to save")
   330          } else {
   331              self.Emit("MOVQ", v, jit.Ptr(_SP, _FP_fargs + int64(i) * 8))
   332          }
   333      }
   334  }
   335  
   336  func (self *_Assembler) xload(reg ...obj.Addr) {
   337      for i, v := range reg {
   338          if i > _FP_saves / 8 - 1 {
   339              panic("too many registers to load")
   340          } else {
   341              self.Emit("MOVQ", jit.Ptr(_SP, _FP_fargs + int64(i) * 8), v)
   342          }
   343      }
   344  }
   345  
   346  func (self *_Assembler) rbuf_di() {
   347      if _RP.Reg != x86.REG_DI {
   348          panic("register allocation messed up: RP != DI")
   349      } else {
   350          self.Emit("ADDQ", _RL, _RP)
   351      }
   352  }
   353  
   354  func (self *_Assembler) store_int(nd int, fn obj.Addr, ins string) {
   355      self.check_size(nd)
   356      self.save_c()                           // SAVE   $C_regs
   357      self.rbuf_di()                          // MOVQ   RP, DI
   358      self.Emit(ins, jit.Ptr(_SP_p, 0), _SI)  // $ins   (SP.p), SI
   359      self.call_c(fn)                         // CALL_C $fn
   360      self.Emit("ADDQ", _AX, _RL)             // ADDQ   AX, RL
   361  }
   362  
   363  func (self *_Assembler) store_str(s string) {
   364      i := 0
   365      m := rt.Str2Mem(s)
   366  
   367      /* 8-byte stores */
   368      for i <= len(m) - 8 {
   369          self.Emit("MOVQ", jit.Imm(rt.Get64(m[i:])), _AX)        // MOVQ $s[i:], AX
   370          self.Emit("MOVQ", _AX, jit.Sib(_RP, _RL, 1, int64(i)))  // MOVQ AX, i(RP)(RL)
   371          i += 8
   372      }
   373  
   374      /* 4-byte stores */
   375      if i <= len(m) - 4 {
   376          self.Emit("MOVL", jit.Imm(int64(rt.Get32(m[i:]))), jit.Sib(_RP, _RL, 1, int64(i)))  // MOVL $s[i:], i(RP)(RL)
   377          i += 4
   378      }
   379  
   380      /* 2-byte stores */
   381      if i <= len(m) - 2 {
   382          self.Emit("MOVW", jit.Imm(int64(rt.Get16(m[i:]))), jit.Sib(_RP, _RL, 1, int64(i)))  // MOVW $s[i:], i(RP)(RL)
   383          i += 2
   384      }
   385  
   386      /* last byte */
   387      if i < len(m) {
   388          self.Emit("MOVB", jit.Imm(int64(m[i])), jit.Sib(_RP, _RL, 1, int64(i)))     // MOVB $s[i:], i(RP)(RL)
   389      }
   390  }
   391  
   392  func (self *_Assembler) check_size(n int) {
   393      self.check_size_rl(jit.Ptr(_RL, int64(n)))
   394  }
   395  
   396  func (self *_Assembler) check_size_r(r obj.Addr, d int) {
   397      self.check_size_rl(jit.Sib(_RL, r, 1, int64(d)))
   398  }
   399  
   400  func (self *_Assembler) check_size_rl(v obj.Addr) {
   401      idx := self.x
   402      key := _LB_more_space_return + strconv.Itoa(idx)
   403  
   404      /* the following code relies on LR == R9 to work */
   405      if _LR.Reg != x86.REG_R9 {
   406          panic("register allocation messed up: LR != R9")
   407      }
   408  
   409      /* check for buffer capacity */
   410      self.x++
   411      self.Emit("LEAQ", v, _AX)       // LEAQ $v, AX
   412      self.Emit("CMPQ", _AX, _RC)     // CMPQ AX, RC
   413      self.Sjmp("JBE" , key)          // JBE  _more_space_return_{n}
   414      self.slice_grow_ax(key)         // GROW $key
   415      self.Link(key)                  // _more_space_return_{n}:
   416  }
   417  
   418  func (self *_Assembler) slice_grow_ax(ret string) {
   419      self.Byte(0x4c, 0x8d, 0x0d)         // LEAQ ?(PC), R9
   420      self.Sref(ret, 4)                   // .... &ret
   421      self.Sjmp("JMP" , _LB_more_space)   // JMP  _more_space
   422  }
   423  
   424  /** State Stack Helpers **/
   425  
   426  const (
   427      _StateSize  = int64(unsafe.Sizeof(_State{}))
   428      _StackLimit = _MaxStack * _StateSize
   429  )
   430  
   431  func (self *_Assembler) save_state() {
   432      self.Emit("MOVQ", jit.Ptr(_ST, 0), _CX)             // MOVQ (ST), CX
   433      self.Emit("LEAQ", jit.Ptr(_CX, _StateSize), _R9)    // LEAQ _StateSize(CX), R9
   434      self.Emit("CMPQ", _R9, jit.Imm(_StackLimit))        // CMPQ R9, $_StackLimit
   435      self.Sjmp("JAE" , _LB_error_too_deep)               // JA   _error_too_deep
   436      self.Emit("MOVQ", _SP_x, jit.Sib(_ST, _CX, 1, 8))   // MOVQ SP.x, 8(ST)(CX)
   437      self.Emit("MOVQ", _SP_f, jit.Sib(_ST, _CX, 1, 16))  // MOVQ SP.f, 16(ST)(CX)
   438      self.WritePtr(0, _SP_p, jit.Sib(_ST, _CX, 1, 24))  // MOVQ SP.p, 24(ST)(CX)
   439      self.WritePtr(1, _SP_q, jit.Sib(_ST, _CX, 1, 32))  // MOVQ SP.q, 32(ST)(CX)
   440      self.Emit("MOVQ", _R9, jit.Ptr(_ST, 0))             // MOVQ R9, (ST)
   441  }
   442  
   443  func (self *_Assembler) drop_state(decr int64) {
   444      self.Emit("MOVQ" , jit.Ptr(_ST, 0), _AX)                // MOVQ  (ST), AX
   445      self.Emit("SUBQ" , jit.Imm(decr), _AX)                  // SUBQ  $decr, AX
   446      self.Emit("MOVQ" , _AX, jit.Ptr(_ST, 0))                // MOVQ  AX, (ST)
   447      self.Emit("MOVQ" , jit.Sib(_ST, _AX, 1, 8), _SP_x)      // MOVQ  8(ST)(AX), SP.x
   448      self.Emit("MOVQ" , jit.Sib(_ST, _AX, 1, 16), _SP_f)     // MOVQ  16(ST)(AX), SP.f
   449      self.Emit("MOVQ" , jit.Sib(_ST, _AX, 1, 24), _SP_p)     // MOVQ  24(ST)(AX), SP.p
   450      self.Emit("MOVQ" , jit.Sib(_ST, _AX, 1, 32), _SP_q)     // MOVQ  32(ST)(AX), SP.q
   451      self.Emit("PXOR" , _X0, _X0)                            // PXOR  X0, X0
   452      self.Emit("MOVOU", _X0, jit.Sib(_ST, _AX, 1, 8))        // MOVOU X0, 8(ST)(AX)
   453      self.Emit("MOVOU", _X0, jit.Sib(_ST, _AX, 1, 24))       // MOVOU X0, 24(ST)(AX)
   454  }
   455  
   456  /** Buffer Helpers **/
   457  
   458  func (self *_Assembler) add_char(ch byte) {
   459      self.Emit("MOVB", jit.Imm(int64(ch)), jit.Sib(_RP, _RL, 1, 0))  // MOVB $ch, (RP)(RL)
   460      self.Emit("ADDQ", jit.Imm(1), _RL)                              // ADDQ $1, RL
   461  }
   462  
   463  func (self *_Assembler) add_long(ch uint32, n int64) {
   464      self.Emit("MOVL", jit.Imm(int64(ch)), jit.Sib(_RP, _RL, 1, 0))  // MOVL $ch, (RP)(RL)
   465      self.Emit("ADDQ", jit.Imm(n), _RL)                              // ADDQ $n, RL
   466  }
   467  
   468  func (self *_Assembler) add_text(ss string) {
   469      self.store_str(ss)                                  // TEXT $ss
   470      self.Emit("ADDQ", jit.Imm(int64(len(ss))), _RL)     // ADDQ ${len(ss)}, RL
   471  }
   472  
   473  // get *buf at AX
   474  func (self *_Assembler) prep_buffer_AX() {
   475      self.Emit("MOVQ", _ARG_rb, _AX)             // MOVQ rb<>+0(FP), AX
   476      self.Emit("MOVQ", _RL, jit.Ptr(_AX, 8))     // MOVQ RL, 8(AX)
   477  }
   478  
   479  func (self *_Assembler) save_buffer() {
   480      self.Emit("MOVQ", _ARG_rb, _CX)             // MOVQ rb<>+0(FP), CX
   481      self.Emit("MOVQ", _RP, jit.Ptr(_CX,  0))    // MOVQ RP, (CX)
   482      self.Emit("MOVQ", _RL, jit.Ptr(_CX,  8))    // MOVQ RL, 8(CX)
   483      self.Emit("MOVQ", _RC, jit.Ptr(_CX, 16))    // MOVQ RC, 16(CX)
   484  }
   485  
   486  // get *buf at AX
   487  func (self *_Assembler) load_buffer_AX() {
   488      self.Emit("MOVQ", _ARG_rb, _AX)             // MOVQ rb<>+0(FP), AX
   489      self.Emit("MOVQ", jit.Ptr(_AX,  0), _RP)    // MOVQ (AX), RP
   490      self.Emit("MOVQ", jit.Ptr(_AX,  8), _RL)    // MOVQ 8(AX), RL
   491      self.Emit("MOVQ", jit.Ptr(_AX, 16), _RC)    // MOVQ 16(AX), RC
   492  }
   493  
   494  /** Function Interface Helpers **/
   495  
   496  func (self *_Assembler) call(pc obj.Addr) {
   497      self.Emit("MOVQ", pc, _LR)  // MOVQ $pc, AX
   498      self.Rjmp("CALL", _LR)      // CALL AX
   499  }
   500  
   501  func (self *_Assembler) save_c() {
   502      self.xsave(_REG_ffi...)     // SAVE $REG_ffi
   503  }
   504  
   505  func (self *_Assembler) call_b64(pc obj.Addr) {
   506      self.xsave(_REG_b64...)     // SAVE $REG_all
   507      self.call(pc)               // CALL $pc
   508      self.xload(_REG_b64...)     // LOAD $REG_ffi
   509  }
   510  
   511  func (self *_Assembler) call_c(pc obj.Addr) {
   512      self.Emit("XCHGQ", _SP_p, _BX)
   513      self.call(pc)               // CALL $pc
   514      self.xload(_REG_ffi...)     // LOAD $REG_ffi
   515      self.Emit("XCHGQ", _SP_p, _BX)
   516      self.Emit("XORPS", _X15, _X15)
   517  }
   518  
   519  func (self *_Assembler) call_go(pc obj.Addr) {
   520      self.xsave(_REG_all...)     // SAVE $REG_all
   521      self.call(pc)               // CALL $pc
   522      self.xload(_REG_all...)     // LOAD $REG_all
   523  }
   524  
   525  func (self *_Assembler) call_more_space(pc obj.Addr) {
   526      self.xsave(_REG_ms...)     // SAVE $REG_all
   527      self.call(pc)               // CALL $pc
   528      self.xload(_REG_ms...)     // LOAD $REG_all
   529  }
   530  
   531  func (self *_Assembler) call_encoder(pc obj.Addr) {
   532      self.xsave(_REG_enc...)     // SAVE $REG_all
   533      self.call(pc)               // CALL $pc
   534      self.xload(_REG_enc...)     // LOAD $REG_all
   535  }
   536  
   537  func (self *_Assembler) call_marshaler(fn obj.Addr, it *rt.GoType, vt reflect.Type) {
   538      switch vt.Kind() {
   539          case reflect.Interface        : self.call_marshaler_i(fn, it)
   540          case reflect.Ptr, reflect.Map : self.call_marshaler_v(fn, it, vt, true)
   541          // struct/array of 1 direct iface type can be direct
   542          default                       : self.call_marshaler_v(fn, it, vt, !rt.UnpackType(vt).Indirect())
   543      }
   544  }
   545  
   546  func (self *_Assembler) call_marshaler_i(fn obj.Addr, it *rt.GoType) {
   547      self.Emit("MOVQ" , jit.Ptr(_SP_p, 0), _AX)                      // MOVQ    (SP.p), AX
   548      self.Emit("TESTQ", _AX, _AX)                                    // TESTQ   AX, AX
   549      self.Sjmp("JZ"   , "_null_{n}")                                 // JZ      _null_{n}
   550      self.Emit("MOVQ" , _AX, _BX)                                    // MOVQ    AX, BX
   551      self.Emit("MOVQ" , jit.Ptr(_SP_p, 8), _CX)                      // MOVQ    8(SP.p), CX
   552      self.Emit("MOVQ" , jit.Gtype(it), _AX)                          // MOVQ    $it, AX
   553      self.call_go(_F_assertI2I)                                       // CALL_GO assertI2I
   554      self.Emit("TESTQ", _AX, _AX)                                    // TESTQ   AX, AX
   555      self.Sjmp("JZ"   , "_null_{n}")                                 // JZ      _null_{n}
   556      self.Emit("MOVQ", _BX, _CX)                                     // MOVQ   BX, CX
   557      self.Emit("MOVQ", _AX, _BX)                                     // MOVQ   AX, BX
   558      self.prep_buffer_AX()
   559      self.Emit("MOVQ", _ARG_fv, _DI)                                 // MOVQ   ARG.fv, DI
   560      self.call_go(fn)                                                // CALL    $fn
   561      self.Emit("TESTQ", _ET, _ET)                                    // TESTQ ET, ET
   562      self.Sjmp("JNZ"  , _LB_error)                                   // JNZ   _error
   563      self.load_buffer_AX()
   564      self.Sjmp("JMP"  , "_done_{n}")                                 // JMP     _done_{n}
   565      self.Link("_null_{n}")                                          // _null_{n}:
   566      self.check_size(4)                                              // SIZE    $4
   567      self.Emit("MOVL", jit.Imm(_IM_null), jit.Sib(_RP, _RL, 1, 0))   // MOVL    $'null', (RP)(RL*1)
   568      self.Emit("ADDQ", jit.Imm(4), _RL)                              // ADDQ    $4, RL
   569      self.Link("_done_{n}")                                          // _done_{n}:
   570  }
   571  
   572  func (self *_Assembler) call_marshaler_v(fn obj.Addr, it *rt.GoType, vt reflect.Type, deref bool) {
   573      self.prep_buffer_AX()                          // MOVE {buf}, (SP)
   574      self.Emit("MOVQ", jit.Itab(it, vt), _BX)       // MOVQ $(itab(it, vt)), BX
   575  
   576      /* dereference the pointer if needed */
   577      if !deref {
   578          self.Emit("MOVQ", _SP_p, _CX)              // MOVQ SP.p, CX
   579      } else {
   580          self.Emit("MOVQ", jit.Ptr(_SP_p, 0), _CX)   // MOVQ 0(SP.p), CX
   581      }
   582  
   583      /* call the encoder, and perform error checks */
   584      self.Emit("MOVQ", _ARG_fv, _DI)                 // MOVQ   ARG.fv, DI
   585      self.call_go(fn)                                // CALL  $fn
   586      self.Emit("TESTQ", _ET, _ET)                // TESTQ ET, ET
   587      self.Sjmp("JNZ"  , _LB_error)               // JNZ   _error
   588      self.load_buffer_AX()
   589  }
   590  
   591  /** Builtin: _more_space **/
   592  
   593  var (
   594      _T_byte      = jit.Type(byteType)
   595      _F_growslice = jit.Func(rt.GrowSlice)
   596  )
   597  
   598  // AX must saving n 
   599  func (self *_Assembler) more_space() {
   600      self.Link(_LB_more_space)
   601      self.Emit("MOVQ", _RP, _BX)        // MOVQ DI, BX
   602      self.Emit("MOVQ", _RL, _CX)        // MOVQ SI, CX
   603      self.Emit("MOVQ", _RC, _DI)        // MOVQ DX, DI
   604      self.Emit("MOVQ", _AX, _SI)        // MOVQ AX, SI
   605      self.Emit("MOVQ", _T_byte, _AX)    // MOVQ $_T_byte, AX
   606      self.call_more_space(_F_growslice)            // CALL $pc    
   607      self.Emit("MOVQ", _AX, _RP)        // MOVQ AX, DI
   608      self.Emit("MOVQ", _BX, _RL)        // MOVQ BX, SI
   609      self.Emit("MOVQ", _CX, _RC)        // MOVQ CX, DX
   610      self.save_buffer()                 // SAVE {buf}
   611      self.Rjmp("JMP" , _LR)             // JMP  LR
   612  }
   613  
   614  /** Builtin Errors **/
   615  
   616  var (
   617      _V_ERR_too_deep               = jit.Imm(int64(uintptr(unsafe.Pointer(_ERR_too_deep))))
   618      _V_ERR_nan_or_infinite        = jit.Imm(int64(uintptr(unsafe.Pointer(_ERR_nan_or_infinite))))
   619      _I_json_UnsupportedValueError = jit.Itab(rt.UnpackType(errorType), jsonUnsupportedValueType)
   620  )
   621  
   622  func (self *_Assembler) error_too_deep() {
   623      self.Link(_LB_error_too_deep)
   624      self.Emit("MOVQ", _V_ERR_too_deep, _EP)                 // MOVQ $_V_ERR_too_deep, EP
   625      self.Emit("MOVQ", _I_json_UnsupportedValueError, _ET)   // MOVQ $_I_json_UnsupportedValuError, ET
   626      self.Sjmp("JMP" , _LB_error)                            // JMP  _error
   627  }
   628  
   629  func (self *_Assembler) error_invalid_number() {
   630      self.Link(_LB_error_invalid_number)
   631      self.Emit("MOVQ", jit.Ptr(_SP_p, 0), _AX)  // MOVQ    0(SP), AX
   632      self.Emit("MOVQ", jit.Ptr(_SP_p, 8), _BX)  // MOVQ    8(SP), BX
   633      self.call_go(_F_error_number)              // CALL_GO error_number
   634      self.Sjmp("JMP" , _LB_error)               // JMP     _error
   635  }
   636  
   637  func (self *_Assembler) error_nan_or_infinite()  {
   638      self.Link(_LB_error_nan_or_infinite)
   639      self.Emit("MOVQ", _V_ERR_nan_or_infinite, _EP)          // MOVQ $_V_ERR_nan_or_infinite, EP
   640      self.Emit("MOVQ", _I_json_UnsupportedValueError, _ET)   // MOVQ $_I_json_UnsupportedValuError, ET
   641      self.Sjmp("JMP" , _LB_error)                            // JMP  _error
   642  }
   643  
   644  /** String Encoding Routine **/
   645  
   646  var (
   647      _F_quote = jit.Imm(int64(native.S_quote))
   648      _F_panic = jit.Func(goPanic)
   649  )
   650  
   651  func (self *_Assembler) go_panic() {
   652      self.Link(_LB_panic)
   653      self.Emit("MOVQ", _SP_p, _BX)
   654      self.call_go(_F_panic)
   655  }
   656  
   657  func (self *_Assembler) encode_string(doubleQuote bool) {       
   658      self.Emit("MOVQ" , jit.Ptr(_SP_p, 8), _AX)  // MOVQ  8(SP.p), AX
   659      self.Emit("TESTQ", _AX, _AX)                // TESTQ AX, AX
   660      self.Sjmp("JZ"   , "_str_empty_{n}")        // JZ    _str_empty_{n}
   661      self.Emit("CMPQ", jit.Ptr(_SP_p, 0), jit.Imm(0))
   662      self.Sjmp("JNE"   , "_str_next_{n}") 
   663      self.Emit("MOVQ", jit.Imm(int64(panicNilPointerOfNonEmptyString)), _AX)
   664      self.Sjmp("JMP", _LB_panic)
   665      self.Link("_str_next_{n}")
   666  
   667      /* openning quote, check for double quote */
   668      if !doubleQuote {
   669          self.check_size_r(_AX, 2)   // SIZE $2
   670          self.add_char('"')          // CHAR $'"'
   671      } else {
   672          self.check_size_r(_AX, 6)   // SIZE $6
   673          self.add_long(_IM_open, 3)  // TEXT $`"\"`
   674      }
   675  
   676      /* quoting loop */
   677      self.Emit("XORL", _AX, _AX)         // XORL AX, AX
   678      self.Emit("MOVQ", _AX, _VAR_sp)     // MOVQ AX, sp
   679      self.Link("_str_loop_{n}")          // _str_loop_{n}:
   680      self.save_c()                       // SAVE $REG_ffi
   681  
   682      /* load the output buffer first, and then input buffer,
   683       * because the parameter registers collide with RP / RL / RC */
   684      self.Emit("MOVQ", _RC, _CX)                         // MOVQ RC, CX
   685      self.Emit("SUBQ", _RL, _CX)                         // SUBQ RL, CX
   686      self.Emit("MOVQ", _CX, _VAR_dn)                     // MOVQ CX, dn
   687      self.Emit("LEAQ", jit.Sib(_RP, _RL, 1, 0), _DX)     // LEAQ (RP)(RL), DX
   688      self.Emit("LEAQ", _VAR_dn, _CX)                     // LEAQ dn, CX
   689      self.Emit("MOVQ", _VAR_sp, _AX)                     // MOVQ sp, AX
   690      self.Emit("MOVQ", jit.Ptr(_SP_p, 0), _DI)           // MOVQ (SP.p), DI
   691      self.Emit("MOVQ", jit.Ptr(_SP_p, 8), _SI)           // MOVQ 8(SP.p), SI
   692      self.Emit("ADDQ", _AX, _DI)                         // ADDQ AX, DI
   693      self.Emit("SUBQ", _AX, _SI)                         // SUBQ AX, SI
   694  
   695      /* set the flags based on `doubleQuote` */
   696      if !doubleQuote {
   697          self.Emit("XORL", _R8, _R8)                                 // XORL R8, R8
   698      } else {
   699          self.Emit("MOVL", jit.Imm(types.F_DOUBLE_UNQUOTE), _R8)     // MOVL ${types.F_DOUBLE_UNQUOTE}, R8
   700      }
   701  
   702      /* call the native quoter */
   703      self.call_c(_F_quote)                   // CALL  quote
   704      self.Emit("ADDQ" , _VAR_dn, _RL)        // ADDQ  dn, RL
   705  
   706      self.Emit("TESTQ", _AX, _AX)            // TESTQ AX, AX
   707      self.Sjmp("JS"   , "_str_space_{n}")    // JS    _str_space_{n}
   708  
   709      /* close the string, check for double quote */
   710      if !doubleQuote {
   711          self.check_size(1)                  // SIZE $1
   712          self.add_char('"')                  // CHAR $'"'
   713          self.Sjmp("JMP", "_str_end_{n}")    // JMP  _str_end_{n}
   714      } else {
   715          self.check_size(3)                  // SIZE $3
   716          self.add_text("\\\"\"")             // TEXT $'\""'
   717          self.Sjmp("JMP", "_str_end_{n}")    // JMP  _str_end_{n}
   718      }
   719  
   720      /* not enough space to contain the quoted string */
   721      self.Link("_str_space_{n}")                         // _str_space_{n}:
   722      self.Emit("NOTQ", _AX)                              // NOTQ AX
   723      self.Emit("ADDQ", _AX, _VAR_sp)                     // ADDQ AX, sp
   724      self.Emit("LEAQ", jit.Sib(_RC, _RC, 1, 0), _AX)     // LEAQ (RC)(RC), AX
   725      self.slice_grow_ax("_str_loop_{n}")                 // GROW _str_loop_{n}
   726  
   727      /* empty string, check for double quote */
   728      if !doubleQuote {
   729          self.Link("_str_empty_{n}")     // _str_empty_{n}:
   730          self.check_size(2)              // SIZE $2
   731          self.add_text("\"\"")           // TEXT $'""'
   732          self.Link("_str_end_{n}")       // _str_end_{n}:
   733      } else {
   734          self.Link("_str_empty_{n}")     // _str_empty_{n}:
   735          self.check_size(6)              // SIZE $6
   736          self.add_text("\"\\\"\\\"\"")   // TEXT $'"\"\""'
   737          self.Link("_str_end_{n}")       // _str_end_{n}:
   738      }
   739  }
   740  
   741  /** OpCode Assembler Functions **/
   742  
   743  var (
   744      _T_json_Marshaler         = rt.UnpackType(jsonMarshalerType)
   745      _T_encoding_TextMarshaler = rt.UnpackType(encodingTextMarshalerType)
   746  )
   747  
   748  var (
   749      _F_f64toa    = jit.Imm(int64(native.S_f64toa))
   750      _F_f32toa    = jit.Imm(int64(native.S_f32toa))
   751      _F_i64toa    = jit.Imm(int64(native.S_i64toa))
   752      _F_u64toa    = jit.Imm(int64(native.S_u64toa))
   753      _F_b64encode = jit.Imm(int64(_subr__b64encode))
   754  )
   755  
   756  var (
   757      _F_memmove       = jit.Func(memmove)
   758      _F_error_number  = jit.Func(error_number)
   759      _F_isValidNumber = jit.Func(isValidNumber)
   760  )
   761  
   762  var (
   763      _F_iteratorStop  = jit.Func(iteratorStop)
   764      _F_iteratorNext  = jit.Func(iteratorNext)
   765      _F_iteratorStart = jit.Func(iteratorStart)
   766  )
   767  
   768  var (
   769      _F_encodeTypedPointer  obj.Addr
   770      _F_encodeJsonMarshaler obj.Addr
   771      _F_encodeTextMarshaler obj.Addr
   772  )
   773  
   774  const (
   775      _MODE_AVX2 = 1 << 2
   776  )
   777  
   778  func init() {
   779      _F_encodeTypedPointer  = jit.Func(encodeTypedPointer)
   780      _F_encodeJsonMarshaler = jit.Func(encodeJsonMarshaler)
   781      _F_encodeTextMarshaler = jit.Func(encodeTextMarshaler)
   782  }
   783  
   784  func (self *_Assembler) _asm_OP_null(_ *_Instr) {
   785      self.check_size(4)
   786      self.Emit("MOVL", jit.Imm(_IM_null), jit.Sib(_RP, _RL, 1, 0))  // MOVL $'null', (RP)(RL*1)
   787      self.Emit("ADDQ", jit.Imm(4), _RL)                             // ADDQ $4, RL
   788  }
   789  
   790  func (self *_Assembler) _asm_OP_empty_arr(_ *_Instr) {
   791      self.Emit("BTQ", jit.Imm(int64(bitNoNullSliceOrMap)), _ARG_fv)
   792      self.Sjmp("JC", "_empty_arr_{n}")
   793      self._asm_OP_null(nil)
   794      self.Sjmp("JMP", "_empty_arr_end_{n}")
   795      self.Link("_empty_arr_{n}")
   796      self.check_size(2)
   797      self.Emit("MOVW", jit.Imm(_IM_array), jit.Sib(_RP, _RL, 1, 0)) 
   798      self.Emit("ADDQ", jit.Imm(2), _RL)    
   799      self.Link("_empty_arr_end_{n}")                  
   800  }
   801  
   802  func (self *_Assembler) _asm_OP_empty_obj(_ *_Instr) {
   803      self.Emit("BTQ", jit.Imm(int64(bitNoNullSliceOrMap)), _ARG_fv)
   804      self.Sjmp("JC", "_empty_obj_{n}")
   805      self._asm_OP_null(nil)
   806      self.Sjmp("JMP", "_empty_obj_end_{n}")
   807      self.Link("_empty_obj_{n}")
   808      self.check_size(2)
   809      self.Emit("MOVW", jit.Imm(_IM_object), jit.Sib(_RP, _RL, 1, 0))  
   810      self.Emit("ADDQ", jit.Imm(2), _RL) 
   811      self.Link("_empty_obj_end_{n}")                                             
   812  }
   813  
   814  func (self *_Assembler) _asm_OP_bool(_ *_Instr) {
   815      self.Emit("CMPB", jit.Ptr(_SP_p, 0), jit.Imm(0))                // CMPB (SP.p), $0
   816      self.Sjmp("JE"  , "_false_{n}")                                 // JE   _false_{n}
   817      self.check_size(4)                                              // SIZE $4
   818      self.Emit("MOVL", jit.Imm(_IM_true), jit.Sib(_RP, _RL, 1, 0))   // MOVL $'true', (RP)(RL*1)
   819      self.Emit("ADDQ", jit.Imm(4), _RL)                              // ADDQ $4, RL
   820      self.Sjmp("JMP" , "_end_{n}")                                   // JMP  _end_{n}
   821      self.Link("_false_{n}")                                         // _false_{n}:
   822      self.check_size(5)                                              // SIZE $5
   823      self.Emit("MOVL", jit.Imm(_IM_fals), jit.Sib(_RP, _RL, 1, 0))   // MOVL $'fals', (RP)(RL*1)
   824      self.Emit("MOVB", jit.Imm('e'), jit.Sib(_RP, _RL, 1, 4))        // MOVB $'e', 4(RP)(RL*1)
   825      self.Emit("ADDQ", jit.Imm(5), _RL)                              // ADDQ $5, RL
   826      self.Link("_end_{n}")                                           // _end_{n}:
   827  }
   828  
   829  func (self *_Assembler) _asm_OP_i8(_ *_Instr) {
   830      self.store_int(4, _F_i64toa, "MOVBQSX")
   831  }
   832  
   833  func (self *_Assembler) _asm_OP_i16(_ *_Instr) {
   834      self.store_int(6, _F_i64toa, "MOVWQSX")
   835  }
   836  
   837  func (self *_Assembler) _asm_OP_i32(_ *_Instr) {
   838      self.store_int(17, _F_i64toa, "MOVLQSX")
   839  }
   840  
   841  func (self *_Assembler) _asm_OP_i64(_ *_Instr) {
   842      self.store_int(21, _F_i64toa, "MOVQ")
   843  }
   844  
   845  func (self *_Assembler) _asm_OP_u8(_ *_Instr) {
   846      self.store_int(3, _F_u64toa, "MOVBQZX")
   847  }
   848  
   849  func (self *_Assembler) _asm_OP_u16(_ *_Instr) {
   850      self.store_int(5, _F_u64toa, "MOVWQZX")
   851  }
   852  
   853  func (self *_Assembler) _asm_OP_u32(_ *_Instr) {
   854      self.store_int(16, _F_u64toa, "MOVLQZX")
   855  }
   856  
   857  func (self *_Assembler) _asm_OP_u64(_ *_Instr) {
   858      self.store_int(20, _F_u64toa, "MOVQ")
   859  }
   860  
   861  func (self *_Assembler) _asm_OP_f32(_ *_Instr) {
   862      self.check_size(32)
   863      self.Emit("MOVL"    , jit.Ptr(_SP_p, 0), _AX)       // MOVL     (SP.p), AX
   864      self.Emit("ANDL"    , jit.Imm(_FM_exp32), _AX)      // ANDL     $_FM_exp32, AX
   865      self.Emit("XORL"    , jit.Imm(_FM_exp32), _AX)      // XORL     $_FM_exp32, AX
   866      self.Sjmp("JZ"      , _LB_error_nan_or_infinite)    // JZ       _error_nan_or_infinite
   867      self.save_c()                                       // SAVE     $C_regs
   868      self.rbuf_di()                                      // MOVQ     RP, DI
   869      self.Emit("MOVSS"   , jit.Ptr(_SP_p, 0), _X0)       // MOVSS    (SP.p), X0
   870      self.call_c(_F_f32toa)                              // CALL_C   f64toa
   871      self.Emit("ADDQ"    , _AX, _RL)                     // ADDQ     AX, RL
   872  }
   873  
   874  func (self *_Assembler) _asm_OP_f64(_ *_Instr) {
   875      self.check_size(32)
   876      self.Emit("MOVQ"  , jit.Ptr(_SP_p, 0), _AX)     // MOVQ   (SP.p), AX
   877      self.Emit("MOVQ"  , jit.Imm(_FM_exp64), _CX)    // MOVQ   $_FM_exp64, CX
   878      self.Emit("ANDQ"  , _CX, _AX)                   // ANDQ   CX, AX
   879      self.Emit("XORQ"  , _CX, _AX)                   // XORQ   CX, AX
   880      self.Sjmp("JZ"    , _LB_error_nan_or_infinite)  // JZ     _error_nan_or_infinite
   881      self.save_c()                                   // SAVE   $C_regs
   882      self.rbuf_di()                                  // MOVQ   RP, DI
   883      self.Emit("MOVSD" , jit.Ptr(_SP_p, 0), _X0)     // MOVSD  (SP.p), X0
   884      self.call_c(_F_f64toa)                          // CALL_C f64toa
   885      self.Emit("ADDQ"  , _AX, _RL)                   // ADDQ   AX, RL
   886  }
   887  
   888  func (self *_Assembler) _asm_OP_str(_ *_Instr) {
   889      self.encode_string(false)
   890  }
   891  
   892  func (self *_Assembler) _asm_OP_bin(_ *_Instr) {
   893      self.Emit("MOVQ", jit.Ptr(_SP_p, 8), _AX)           // MOVQ 8(SP.p), AX
   894      self.Emit("ADDQ", jit.Imm(2), _AX)                  // ADDQ $2, AX
   895      self.Emit("MOVQ", jit.Imm(_IM_mulv), _CX)           // MOVQ $_MF_mulv, CX
   896      self.Emit("MOVQ", _DX, _BX)                         // MOVQ DX, BX
   897      self.From("MULQ", _CX)                              // MULQ CX
   898      self.Emit("LEAQ", jit.Sib(_DX, _DX, 1, 1), _AX)     // LEAQ 1(DX)(DX), AX
   899      self.Emit("ORQ" , jit.Imm(2), _AX)                  // ORQ  $2, AX
   900      self.Emit("MOVQ", _BX, _DX)                         // MOVQ BX, DX
   901      self.check_size_r(_AX, 0)                           // SIZE AX
   902      self.add_char('"')                                  // CHAR $'"'
   903      self.Emit("MOVQ", _ARG_rb, _DI)                     // MOVQ rb<>+0(FP), DI
   904      self.Emit("MOVQ", _RL, jit.Ptr(_DI, 8))             // MOVQ SI, 8(DI)
   905      self.Emit("MOVQ", _SP_p, _SI)                       // MOVQ SP.p, SI
   906  
   907      /* check for AVX2 support */
   908      if !cpu.HasAVX2 {
   909          self.Emit("XORL", _DX, _DX)                     // XORL DX, DX
   910      } else {
   911          self.Emit("MOVL", jit.Imm(_MODE_AVX2), _DX)     // MOVL $_MODE_AVX2, DX
   912      }
   913  
   914      /* call the encoder */
   915      self.call_b64(_F_b64encode)   // CALL b64encode
   916      self.load_buffer_AX()       // LOAD {buf}
   917      self.add_char('"')          // CHAR $'"'
   918  }
   919  
   920  func (self *_Assembler) _asm_OP_quote(_ *_Instr) {
   921      self.encode_string(true)
   922  }
   923  
   924  func (self *_Assembler) _asm_OP_number(_ *_Instr) {
   925      self.Emit("MOVQ" , jit.Ptr(_SP_p, 8), _BX)          // MOVQ    (SP.p), BX
   926      self.Emit("TESTQ", _BX, _BX)                        // TESTQ   BX, BX
   927      self.Sjmp("JZ"   , "_empty_{n}")
   928      self.Emit("MOVQ" , jit.Ptr(_SP_p, 0), _AX)          // MOVQ    (SP.p), AX
   929      self.Emit("TESTQ", _AX, _AX)                        // TESTQ   AX, AX
   930      self.Sjmp("JNZ"   , "_number_next_{n}") 
   931      self.Emit("MOVQ", jit.Imm(int64(panicNilPointerOfNonEmptyString)), _AX)
   932      self.Sjmp("JMP", _LB_panic)
   933      self.Link("_number_next_{n}")
   934      self.call_go(_F_isValidNumber)                      // CALL_GO isValidNumber
   935      self.Emit("CMPB" , _AX, jit.Imm(0))                 // CMPB    AX, $0
   936      self.Sjmp("JE"   , _LB_error_invalid_number)        // JE      _error_invalid_number
   937      self.Emit("MOVQ" , jit.Ptr(_SP_p, 8), _BX)          // MOVQ    (SP.p), BX
   938      self.check_size_r(_BX, 0)                           // SIZE    BX
   939      self.Emit("LEAQ" , jit.Sib(_RP, _RL, 1, 0), _AX)    // LEAQ    (RP)(RL), AX
   940      self.Emit("ADDQ" , jit.Ptr(_SP_p, 8), _RL)          // ADDQ    8(SP.p), RL
   941      self.Emit("MOVQ", jit.Ptr(_SP_p, 0), _BX)           // MOVOU   (SP.p), BX
   942      self.Emit("MOVQ", jit.Ptr(_SP_p, 8), _CX)           // MOVOU   X0, 8(SP)
   943      self.call_go(_F_memmove)                            // CALL_GO memmove
   944      self.Emit("MOVQ", _ARG_rb, _AX)                     // MOVQ rb<>+0(FP), AX
   945      self.Emit("MOVQ", _RL, jit.Ptr(_AX, 8))             // MOVQ RL, 8(AX)
   946      self.Sjmp("JMP"  , "_done_{n}")                     // JMP     _done_{n}
   947      self.Link("_empty_{n}")                             // _empty_{n}
   948      self.check_size(1)                                  // SIZE    $1
   949      self.add_char('0')                                  // CHAR    $'0'
   950      self.Link("_done_{n}")                              // _done_{n}:
   951  }
   952  
   953  func (self *_Assembler) _asm_OP_eface(_ *_Instr) {
   954      self.prep_buffer_AX()                       // MOVE  {buf}, AX
   955      self.Emit("MOVQ" , jit.Ptr(_SP_p, 0), _BX)  // MOVQ  (SP.p), BX
   956      self.Emit("LEAQ" , jit.Ptr(_SP_p, 8), _CX)  // LEAQ  8(SP.p), CX
   957      self.Emit("MOVQ" , _ST, _DI)                // MOVQ  ST, DI
   958      self.Emit("MOVQ" , _ARG_fv, _SI)            // MOVQ  fv, AX
   959      self.call_encoder(_F_encodeTypedPointer)            // CALL  encodeTypedPointer
   960      self.Emit("TESTQ", _ET, _ET)                // TESTQ ET, ET
   961      self.Sjmp("JNZ"  , _LB_error)               // JNZ   _error
   962      self.load_buffer_AX()
   963  }
   964  
   965  func (self *_Assembler) _asm_OP_iface(_ *_Instr) {
   966      self.prep_buffer_AX()                       // MOVE  {buf}, AX
   967      self.Emit("MOVQ" , jit.Ptr(_SP_p, 0), _CX)  // MOVQ  (SP.p), CX
   968      self.Emit("MOVQ" , jit.Ptr(_CX, 8), _BX)    // MOVQ  8(CX), BX
   969      self.Emit("LEAQ" , jit.Ptr(_SP_p, 8), _CX)  // LEAQ  8(SP.p), CX
   970      self.Emit("MOVQ" , _ST, _DI)                // MOVQ  ST, DI
   971      self.Emit("MOVQ" , _ARG_fv, _SI)            // MOVQ  fv, AX
   972      self.call_encoder(_F_encodeTypedPointer)    // CALL  encodeTypedPointer
   973      self.Emit("TESTQ", _ET, _ET)                // TESTQ ET, ET
   974      self.Sjmp("JNZ"  , _LB_error)               // JNZ   _error
   975      self.load_buffer_AX()
   976  }
   977  
   978  func (self *_Assembler) _asm_OP_byte(p *_Instr) {
   979      self.check_size(1)
   980      self.Emit("MOVB", jit.Imm(p.i64()), jit.Sib(_RP, _RL, 1, 0))    // MOVL p.vi(), (RP)(RL*1)
   981      self.Emit("ADDQ", jit.Imm(1), _RL)                              // ADDQ $1, RL
   982  }
   983  
   984  func (self *_Assembler) _asm_OP_text(p *_Instr) {
   985      self.check_size(len(p.vs()))    // SIZE ${len(p.vs())}
   986      self.add_text(p.vs())           // TEXT ${p.vs()}
   987  }
   988  
   989  func (self *_Assembler) _asm_OP_deref(_ *_Instr) {
   990      self.Emit("MOVQ", jit.Ptr(_SP_p, 0), _SP_p)     // MOVQ (SP.p), SP.p
   991  }
   992  
   993  func (self *_Assembler) _asm_OP_index(p *_Instr) {
   994      self.Emit("MOVQ", jit.Imm(p.i64()), _AX)    // MOVQ $p.vi(), AX
   995      self.Emit("ADDQ", _AX, _SP_p)               // ADDQ AX, SP.p
   996  }
   997  
   998  func (self *_Assembler) _asm_OP_load(_ *_Instr) {
   999      self.Emit("MOVQ", jit.Ptr(_ST, 0), _AX)                 // MOVQ (ST), AX
  1000      self.Emit("MOVQ", jit.Sib(_ST, _AX, 1, -24), _SP_x)     // MOVQ -24(ST)(AX), SP.x
  1001      self.Emit("MOVQ", jit.Sib(_ST, _AX, 1, -8), _SP_p)      // MOVQ -8(ST)(AX), SP.p
  1002      self.Emit("MOVQ", jit.Sib(_ST, _AX, 1, 0), _SP_q)       // MOVQ (ST)(AX), SP.q
  1003  }
  1004  
  1005  func (self *_Assembler) _asm_OP_save(_ *_Instr) {
  1006      self.save_state()
  1007  }
  1008  
  1009  func (self *_Assembler) _asm_OP_drop(_ *_Instr) {
  1010      self.drop_state(_StateSize)
  1011  }
  1012  
  1013  func (self *_Assembler) _asm_OP_drop_2(_ *_Instr) {
  1014      self.drop_state(_StateSize * 2)                     // DROP  $(_StateSize * 2)
  1015      self.Emit("MOVOU", _X0, jit.Sib(_ST, _AX, 1, 56))   // MOVOU X0, 56(ST)(AX)
  1016  }
  1017  
  1018  func (self *_Assembler) _asm_OP_recurse(p *_Instr) {
  1019      self.prep_buffer_AX()                       // MOVE {buf}, (SP)
  1020      vt, pv := p.vp()
  1021      self.Emit("MOVQ", jit.Type(vt), _BX)    // MOVQ $(type(p.vt())), BX
  1022  
  1023      /* check for indirection */
  1024      if !rt.UnpackType(vt).Indirect() {
  1025          self.Emit("MOVQ", _SP_p, _CX)           // MOVQ SP.p, CX
  1026      } else {
  1027          self.Emit("MOVQ", _SP_p, _VAR_vp)  // MOVQ SP.p, VAR.vp
  1028          self.Emit("LEAQ", _VAR_vp, _CX)    // LEAQ VAR.vp, CX
  1029      }
  1030  
  1031      /* call the encoder */
  1032      self.Emit("MOVQ" , _ST, _DI)                // MOVQ  ST, DI
  1033      self.Emit("MOVQ" , _ARG_fv, _SI)            // MOVQ  $fv, SI
  1034      if pv {
  1035          self.Emit("BTCQ", jit.Imm(bitPointerValue), _SI)  // BTCQ $1, SI
  1036      }
  1037      self.call_encoder(_F_encodeTypedPointer)    // CALL  encodeTypedPointer
  1038      self.Emit("TESTQ", _ET, _ET)                // TESTQ ET, ET
  1039      self.Sjmp("JNZ"  , _LB_error)               // JNZ   _error
  1040      self.load_buffer_AX()
  1041  }
  1042  
  1043  func (self *_Assembler) _asm_OP_is_nil(p *_Instr) {
  1044      self.Emit("CMPQ", jit.Ptr(_SP_p, 0), jit.Imm(0))    // CMPQ (SP.p), $0
  1045      self.Xjmp("JE"  , p.vi())                           // JE   p.vi()
  1046  }
  1047  
  1048  func (self *_Assembler) _asm_OP_is_nil_p1(p *_Instr) {
  1049      self.Emit("CMPQ", jit.Ptr(_SP_p, 8), jit.Imm(0))    // CMPQ 8(SP.p), $0
  1050      self.Xjmp("JE"  , p.vi())                           // JE   p.vi()
  1051  }
  1052  
  1053  func (self *_Assembler) _asm_OP_is_zero_1(p *_Instr) {
  1054      self.Emit("CMPB", jit.Ptr(_SP_p, 0), jit.Imm(0))    // CMPB (SP.p), $0
  1055      self.Xjmp("JE"  , p.vi())                           // JE   p.vi()
  1056  }
  1057  
  1058  func (self *_Assembler) _asm_OP_is_zero_2(p *_Instr) {
  1059      self.Emit("CMPW", jit.Ptr(_SP_p, 0), jit.Imm(0))    // CMPW (SP.p), $0
  1060      self.Xjmp("JE"  , p.vi())                           // JE   p.vi()
  1061  }
  1062  
  1063  func (self *_Assembler) _asm_OP_is_zero_4(p *_Instr) {
  1064      self.Emit("CMPL", jit.Ptr(_SP_p, 0), jit.Imm(0))    // CMPL (SP.p), $0
  1065      self.Xjmp("JE"  , p.vi())                           // JE   p.vi()
  1066  }
  1067  
  1068  func (self *_Assembler) _asm_OP_is_zero_8(p *_Instr) {
  1069      self.Emit("CMPQ", jit.Ptr(_SP_p, 0), jit.Imm(0))    // CMPQ (SP.p), $0
  1070      self.Xjmp("JE"  , p.vi())                           // JE   p.vi()
  1071  }
  1072  
  1073  func (self *_Assembler) _asm_OP_is_zero_map(p *_Instr) {
  1074      self.Emit("MOVQ" , jit.Ptr(_SP_p, 0), _AX)          // MOVQ  (SP.p), AX
  1075      self.Emit("TESTQ", _AX, _AX)                        // TESTQ AX, AX
  1076      self.Xjmp("JZ"   , p.vi())                          // JZ    p.vi()
  1077      self.Emit("CMPQ" , jit.Ptr(_AX, 0), jit.Imm(0))     // CMPQ  (AX), $0
  1078      self.Xjmp("JE"   , p.vi())                          // JE    p.vi()
  1079  }
  1080  
  1081  func (self *_Assembler) _asm_OP_goto(p *_Instr) {
  1082      self.Xjmp("JMP", p.vi())
  1083  }
  1084  
  1085  func (self *_Assembler) _asm_OP_map_iter(p *_Instr) {
  1086      self.Emit("MOVQ" , jit.Type(p.vt()), _AX)       // MOVQ    $p.vt(), AX
  1087      self.Emit("MOVQ" , jit.Ptr(_SP_p, 0), _BX)      // MOVQ    (SP.p), BX
  1088      self.Emit("MOVQ" , _ARG_fv, _CX)                // MOVQ    fv, CX
  1089      self.call_go(_F_iteratorStart)                  // CALL_GO iteratorStart
  1090      self.Emit("MOVQ" , _AX, _SP_q)                  // MOVQ    AX, SP.q
  1091      self.Emit("MOVQ" , _BX, _ET)                    // MOVQ    32(SP), ET
  1092      self.Emit("MOVQ" , _CX, _EP)                    // MOVQ    40(SP), EP
  1093      self.Emit("TESTQ", _ET, _ET)                    // TESTQ   ET, ET
  1094      self.Sjmp("JNZ"  , _LB_error)                   // JNZ     _error
  1095  }
  1096  
  1097  func (self *_Assembler) _asm_OP_map_stop(_ *_Instr) {
  1098      self.Emit("MOVQ", _SP_q, _AX)               // MOVQ    SP.q, AX
  1099      self.call_go(_F_iteratorStop)               // CALL_GO iteratorStop
  1100      self.Emit("XORL", _SP_q, _SP_q)             // XORL    SP.q, SP.q
  1101  }
  1102  
  1103  func (self *_Assembler) _asm_OP_map_check_key(p *_Instr) {
  1104      self.Emit("MOVQ" , jit.Ptr(_SP_q, 0), _SP_p)    // MOVQ    (SP.q), SP.p
  1105      self.Emit("TESTQ", _SP_p, _SP_p)                // TESTQ   SP.p, SP.p
  1106      self.Xjmp("JZ"   , p.vi())                      // JNZ     p.vi()
  1107  }
  1108  
  1109  func (self *_Assembler) _asm_OP_map_write_key(p *_Instr) {
  1110      self.Emit("BTQ", jit.Imm(bitSortMapKeys), _ARG_fv)      // BTQ ${SortMapKeys}, fv
  1111      self.Sjmp("JNC", "_unordered_key_{n}")                  // JNC _unordered_key_{n}
  1112      self.encode_string(false)                               // STR $false
  1113      self.Xjmp("JMP", p.vi())                                // JMP ${p.vi()}
  1114      self.Link("_unordered_key_{n}")                         // _unordered_key_{n}:
  1115  }
  1116  
  1117  func (self *_Assembler) _asm_OP_map_value_next(_ *_Instr) {
  1118      self.Emit("MOVQ", jit.Ptr(_SP_q, 8), _SP_p)     // MOVQ    8(SP.q), SP.p
  1119      self.Emit("MOVQ", _SP_q, _AX)                   // MOVQ    SP.q, AX
  1120      self.call_go(_F_iteratorNext)                   // CALL_GO iteratorNext
  1121  }
  1122  
  1123  func (self *_Assembler) _asm_OP_slice_len(_ *_Instr) {
  1124      self.Emit("MOVQ" , jit.Ptr(_SP_p, 8), _SP_x)        // MOVQ  8(SP.p), SP.x
  1125      self.Emit("MOVQ" , jit.Ptr(_SP_p, 0), _SP_p)        // MOVQ  (SP.p), SP.p
  1126      self.Emit("ORQ"  , jit.Imm(1 << _S_init), _SP_f)    // ORQ   $(1<<_S_init), SP.f
  1127  }
  1128  
  1129  func (self *_Assembler) _asm_OP_slice_next(p *_Instr) {
  1130      self.Emit("TESTQ"  , _SP_x, _SP_x)                          // TESTQ   SP.x, SP.x
  1131      self.Xjmp("JZ"     , p.vi())                                // JZ      p.vi()
  1132      self.Emit("SUBQ"   , jit.Imm(1), _SP_x)                     // SUBQ    $1, SP.x
  1133      self.Emit("BTRQ"   , jit.Imm(_S_init), _SP_f)               // BTRQ    $_S_init, SP.f
  1134      self.Emit("LEAQ"   , jit.Ptr(_SP_p, int64(p.vlen())), _AX)  // LEAQ    $(p.vlen())(SP.p), AX
  1135      self.Emit("CMOVQCC", _AX, _SP_p)                            // CMOVQNC AX, SP.p
  1136  }
  1137  
  1138  func (self *_Assembler) _asm_OP_marshal(p *_Instr) {
  1139      self.call_marshaler(_F_encodeJsonMarshaler, _T_json_Marshaler, p.vt())
  1140  }
  1141  
  1142  func (self *_Assembler) _asm_OP_marshal_p(p *_Instr) {
  1143      if p.vk() != reflect.Ptr {
  1144          panic("marshal_p: invalid type")
  1145      } else {
  1146          self.call_marshaler_v(_F_encodeJsonMarshaler, _T_json_Marshaler, p.vt(), false)
  1147      }
  1148  }
  1149  
  1150  func (self *_Assembler) _asm_OP_marshal_text(p *_Instr) {
  1151      self.call_marshaler(_F_encodeTextMarshaler, _T_encoding_TextMarshaler, p.vt())
  1152  }
  1153  
  1154  func (self *_Assembler) _asm_OP_marshal_text_p(p *_Instr) {
  1155      if p.vk() != reflect.Ptr {
  1156          panic("marshal_text_p: invalid type")
  1157      } else {
  1158          self.call_marshaler_v(_F_encodeTextMarshaler, _T_encoding_TextMarshaler, p.vt(), false)
  1159      }
  1160  }
  1161  
  1162  func (self *_Assembler) _asm_OP_cond_set(_ *_Instr) {
  1163      self.Emit("ORQ", jit.Imm(1 << _S_cond), _SP_f)  // ORQ $(1<<_S_cond), SP.f
  1164  }
  1165  
  1166  func (self *_Assembler) _asm_OP_cond_testc(p *_Instr) {
  1167      self.Emit("BTRQ", jit.Imm(_S_cond), _SP_f)      // BTRQ $_S_cond, SP.f
  1168      self.Xjmp("JC"  , p.vi())
  1169  }
  1170  
  1171  func (self *_Assembler) print_gc(i int, p1 *_Instr, p2 *_Instr) {
  1172      self.Emit("MOVQ", jit.Imm(int64(p2.op())),  _CX) // MOVQ $(p2.op()), AX
  1173      self.Emit("MOVQ", jit.Imm(int64(p1.op())),  _BX) // MOVQ $(p1.op()), BX
  1174      self.Emit("MOVQ", jit.Imm(int64(i)),  _AX)       // MOVQ $(i), CX
  1175      self.call_go(_F_println)
  1176  }