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

     1  /*
     2   * Copyright 2021 ByteDance Inc.
     3   *
     4   * Licensed under the Apache License, Version 2.0 (the "License");
     5   * you may not use this file except in compliance with the License.
     6   * You may obtain a copy of the License at
     7   *
     8   *     http://www.apache.org/licenses/LICENSE-2.0
     9   *
    10   * Unless required by applicable law or agreed to in writing, software
    11   * distributed under the License is distributed on an "AS IS" BASIS,
    12   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    13   * See the License for the specific language governing permissions and
    14   * limitations under the License.
    15   */
    16  
    17  package encoder
    18  
    19  import (
    20      `fmt`
    21      `reflect`
    22      `strconv`
    23      `strings`
    24      `unsafe`
    25  
    26      `github.com/bytedance/sonic/internal/resolver`
    27      `github.com/bytedance/sonic/internal/rt`
    28      `github.com/bytedance/sonic/option`
    29  )
    30  
    31  type _Op uint8
    32  
    33  const (
    34      _OP_null _Op = iota + 1
    35      _OP_empty_arr
    36      _OP_empty_obj
    37      _OP_bool
    38      _OP_i8
    39      _OP_i16
    40      _OP_i32
    41      _OP_i64
    42      _OP_u8
    43      _OP_u16
    44      _OP_u32
    45      _OP_u64
    46      _OP_f32
    47      _OP_f64
    48      _OP_str
    49      _OP_bin
    50      _OP_quote
    51      _OP_number
    52      _OP_eface
    53      _OP_iface
    54      _OP_byte
    55      _OP_text
    56      _OP_deref
    57      _OP_index
    58      _OP_load
    59      _OP_save
    60      _OP_drop
    61      _OP_drop_2
    62      _OP_recurse
    63      _OP_is_nil
    64      _OP_is_nil_p1
    65      _OP_is_zero_1
    66      _OP_is_zero_2
    67      _OP_is_zero_4
    68      _OP_is_zero_8
    69      _OP_is_zero_map
    70      _OP_goto
    71      _OP_map_iter
    72      _OP_map_stop
    73      _OP_map_check_key
    74      _OP_map_write_key
    75      _OP_map_value_next
    76      _OP_slice_len
    77      _OP_slice_next
    78      _OP_marshal
    79      _OP_marshal_p
    80      _OP_marshal_text
    81      _OP_marshal_text_p
    82      _OP_cond_set
    83      _OP_cond_testc
    84  )
    85  
    86  const (
    87      _INT_SIZE = 32 << (^uint(0) >> 63)
    88      _PTR_SIZE = 32 << (^uintptr(0) >> 63)
    89      _PTR_BYTE = unsafe.Sizeof(uintptr(0))
    90  )
    91  
    92  const (
    93      _MAX_ILBUF = 100000     // cutoff at 100k of IL instructions
    94      _MAX_FIELDS = 50        // cutoff at 50 fields struct
    95  )
    96  
    97  var _OpNames = [256]string {
    98      _OP_null           : "null",
    99      _OP_empty_arr      : "empty_arr",
   100      _OP_empty_obj      : "empty_obj",
   101      _OP_bool           : "bool",
   102      _OP_i8             : "i8",
   103      _OP_i16            : "i16",
   104      _OP_i32            : "i32",
   105      _OP_i64            : "i64",
   106      _OP_u8             : "u8",
   107      _OP_u16            : "u16",
   108      _OP_u32            : "u32",
   109      _OP_u64            : "u64",
   110      _OP_f32            : "f32",
   111      _OP_f64            : "f64",
   112      _OP_str            : "str",
   113      _OP_bin            : "bin",
   114      _OP_quote          : "quote",
   115      _OP_number         : "number",
   116      _OP_eface          : "eface",
   117      _OP_iface          : "iface",
   118      _OP_byte           : "byte",
   119      _OP_text           : "text",
   120      _OP_deref          : "deref",
   121      _OP_index          : "index",
   122      _OP_load           : "load",
   123      _OP_save           : "save",
   124      _OP_drop           : "drop",
   125      _OP_drop_2         : "drop_2",
   126      _OP_recurse        : "recurse",
   127      _OP_is_nil         : "is_nil",
   128      _OP_is_nil_p1      : "is_nil_p1",
   129      _OP_is_zero_1      : "is_zero_1",
   130      _OP_is_zero_2      : "is_zero_2",
   131      _OP_is_zero_4      : "is_zero_4",
   132      _OP_is_zero_8      : "is_zero_8",
   133      _OP_is_zero_map    : "is_zero_map",
   134      _OP_goto           : "goto",
   135      _OP_map_iter       : "map_iter",
   136      _OP_map_stop       : "map_stop",
   137      _OP_map_check_key  : "map_check_key",
   138      _OP_map_write_key  : "map_write_key",
   139      _OP_map_value_next : "map_value_next",
   140      _OP_slice_len      : "slice_len",
   141      _OP_slice_next     : "slice_next",
   142      _OP_marshal        : "marshal",
   143      _OP_marshal_p      : "marshal_p",
   144      _OP_marshal_text   : "marshal_text",
   145      _OP_marshal_text_p : "marshal_text_p",
   146      _OP_cond_set       : "cond_set",
   147      _OP_cond_testc     : "cond_testc",
   148  }
   149  
   150  func (self _Op) String() string {
   151      if ret := _OpNames[self]; ret != "" {
   152          return ret
   153      } else {
   154          return "<invalid>"
   155      }
   156  }
   157  
   158  func _OP_int() _Op {
   159      switch _INT_SIZE {
   160          case 32: return _OP_i32
   161          case 64: return _OP_i64
   162          default: panic("unsupported int size")
   163      }
   164  }
   165  
   166  func _OP_uint() _Op {
   167      switch _INT_SIZE {
   168          case 32: return _OP_u32
   169          case 64: return _OP_u64
   170          default: panic("unsupported uint size")
   171      }
   172  }
   173  
   174  func _OP_uintptr() _Op {
   175      switch _PTR_SIZE {
   176          case 32: return _OP_u32
   177          case 64: return _OP_u64
   178          default: panic("unsupported pointer size")
   179      }
   180  }
   181  
   182  func _OP_is_zero_ints() _Op {
   183      switch _INT_SIZE {
   184          case 32: return _OP_is_zero_4
   185          case 64: return _OP_is_zero_8
   186          default: panic("unsupported integer size")
   187      }
   188  }
   189  
   190  type _Instr struct {
   191      u uint64            // union {op: 8, _: 8, vi: 48}, vi maybe int or len(str)
   192      p unsafe.Pointer    // maybe GoString.Ptr, or *GoType
   193  }
   194  
   195  func packOp(op _Op) uint64 {
   196      return uint64(op) << 56
   197  }
   198  
   199  func newInsOp(op _Op) _Instr {
   200      return _Instr{u: packOp(op)}
   201  }
   202  
   203  func newInsVi(op _Op, vi int) _Instr {
   204      return _Instr{u: packOp(op) | rt.PackInt(vi)}
   205  }
   206  
   207  func newInsVs(op _Op, vs string) _Instr {
   208      return _Instr {
   209          u: packOp(op) | rt.PackInt(len(vs)),
   210          p: (*rt.GoString)(unsafe.Pointer(&vs)).Ptr,
   211      }
   212  }
   213  
   214  func newInsVt(op _Op, vt reflect.Type) _Instr {
   215      return _Instr {
   216          u: packOp(op),
   217          p: unsafe.Pointer(rt.UnpackType(vt)),
   218      }
   219  }
   220  
   221  func newInsVp(op _Op, vt reflect.Type, pv bool) _Instr {
   222      i := 0
   223      if pv {
   224          i = 1
   225      }
   226      return _Instr {
   227          u: packOp(op) | rt.PackInt(i),
   228          p: unsafe.Pointer(rt.UnpackType(vt)),
   229      }
   230  }
   231  
   232  func (self _Instr) op() _Op {
   233      return _Op(self.u >> 56)
   234  }
   235  
   236  func (self _Instr) vi() int {
   237      return rt.UnpackInt(self.u)
   238  }
   239  
   240  func (self _Instr) vf() uint8 {
   241      return (*rt.GoType)(self.p).KindFlags
   242  }
   243  
   244  func (self _Instr) vs() (v string) {
   245      (*rt.GoString)(unsafe.Pointer(&v)).Ptr = self.p
   246      (*rt.GoString)(unsafe.Pointer(&v)).Len = self.vi()
   247      return
   248  }
   249  
   250  func (self _Instr) vk() reflect.Kind {
   251      return (*rt.GoType)(self.p).Kind()
   252  }
   253  
   254  func (self _Instr) vt() reflect.Type {
   255      return (*rt.GoType)(self.p).Pack()
   256  }
   257  
   258  func (self _Instr) vp() (vt reflect.Type, pv bool) {
   259      return (*rt.GoType)(self.p).Pack(), rt.UnpackInt(self.u) == 1
   260  }
   261  
   262  func (self _Instr) i64() int64 {
   263      return int64(self.vi())
   264  }
   265  
   266  func (self _Instr) vlen() int {
   267      return int((*rt.GoType)(self.p).Size)
   268  }
   269  
   270  func (self _Instr) isBranch() bool {
   271      switch self.op() {
   272          case _OP_goto          : fallthrough
   273          case _OP_is_nil        : fallthrough
   274          case _OP_is_nil_p1     : fallthrough
   275          case _OP_is_zero_1     : fallthrough
   276          case _OP_is_zero_2     : fallthrough
   277          case _OP_is_zero_4     : fallthrough
   278          case _OP_is_zero_8     : fallthrough
   279          case _OP_map_check_key : fallthrough
   280          case _OP_map_write_key : fallthrough
   281          case _OP_slice_next    : fallthrough
   282          case _OP_cond_testc    : return true
   283          default                : return false
   284      }
   285  }
   286  
   287  func (self _Instr) disassemble() string {
   288      switch self.op() {
   289          case _OP_byte           : return fmt.Sprintf("%-18s%s", self.op().String(), strconv.QuoteRune(rune(self.vi())))
   290          case _OP_text           : return fmt.Sprintf("%-18s%s", self.op().String(), strconv.Quote(self.vs()))
   291          case _OP_index          : return fmt.Sprintf("%-18s%d", self.op().String(), self.vi())
   292          case _OP_recurse        : fallthrough
   293          case _OP_map_iter       : fallthrough
   294          case _OP_marshal        : fallthrough
   295          case _OP_marshal_p      : fallthrough
   296          case _OP_marshal_text   : fallthrough
   297          case _OP_marshal_text_p : return fmt.Sprintf("%-18s%s", self.op().String(), self.vt())
   298          case _OP_goto           : fallthrough
   299          case _OP_is_nil         : fallthrough
   300          case _OP_is_nil_p1      : fallthrough
   301          case _OP_is_zero_1      : fallthrough
   302          case _OP_is_zero_2      : fallthrough
   303          case _OP_is_zero_4      : fallthrough
   304          case _OP_is_zero_8      : fallthrough
   305          case _OP_is_zero_map    : fallthrough
   306          case _OP_cond_testc     : fallthrough
   307          case _OP_map_check_key  : fallthrough
   308          case _OP_map_write_key  : return fmt.Sprintf("%-18sL_%d", self.op().String(), self.vi())
   309          case _OP_slice_next     : return fmt.Sprintf("%-18sL_%d, %s", self.op().String(), self.vi(), self.vt())
   310          default                 : return self.op().String()
   311      }
   312  }
   313  
   314  type (
   315  	_Program []_Instr
   316  )
   317  
   318  func (self _Program) pc() int {
   319      return len(self)
   320  }
   321  
   322  func (self _Program) tag(n int) {
   323      if n >= _MaxStack {
   324          panic("type nesting too deep")
   325      }
   326  }
   327  
   328  func (self _Program) pin(i int) {
   329      v := &self[i]
   330      v.u &= 0xffff000000000000
   331      v.u |= rt.PackInt(self.pc())
   332  }
   333  
   334  func (self _Program) rel(v []int) {
   335      for _, i := range v {
   336          self.pin(i)
   337      }
   338  }
   339  
   340  func (self *_Program) add(op _Op) {
   341      *self = append(*self, newInsOp(op))
   342  }
   343  
   344  func (self *_Program) key(op _Op) {
   345      *self = append(*self,
   346          newInsVi(_OP_byte, '"'),
   347          newInsOp(op),
   348          newInsVi(_OP_byte, '"'),
   349      )
   350  }
   351  
   352  func (self *_Program) int(op _Op, vi int) {
   353      *self = append(*self, newInsVi(op, vi))
   354  }
   355  
   356  func (self *_Program) str(op _Op, vs string) {
   357      *self = append(*self, newInsVs(op, vs))
   358  }
   359  
   360  func (self *_Program) rtt(op _Op, vt reflect.Type) {
   361      *self = append(*self, newInsVt(op, vt))
   362  }
   363  
   364  func (self *_Program) vp(op _Op, vt reflect.Type, pv bool) {
   365      *self = append(*self, newInsVp(op, vt, pv))
   366  }
   367  
   368  func (self _Program) disassemble() string {
   369      nb  := len(self)
   370      tab := make([]bool, nb + 1)
   371      ret := make([]string, 0, nb + 1)
   372  
   373      /* prescan to get all the labels */
   374      for _, ins := range self {
   375          if ins.isBranch() {
   376              tab[ins.vi()] = true
   377          }
   378      }
   379  
   380      /* disassemble each instruction */
   381      for i, ins := range self {
   382          if !tab[i] {
   383              ret = append(ret, "\t" + ins.disassemble())
   384          } else {
   385              ret = append(ret, fmt.Sprintf("L_%d:\n\t%s", i, ins.disassemble()))
   386          }
   387      }
   388  
   389      /* add the last label, if needed */
   390      if tab[nb] {
   391          ret = append(ret, fmt.Sprintf("L_%d:", nb))
   392      }
   393  
   394      /* add an "end" indicator, and join all the strings */
   395      return strings.Join(append(ret, "\tend"), "\n")
   396  }
   397  
   398  type _Compiler struct {
   399      opts option.CompileOptions
   400      pv   bool
   401      tab  map[reflect.Type]bool
   402      rec  map[reflect.Type]uint8
   403  }
   404  
   405  func newCompiler() *_Compiler {
   406      return &_Compiler {
   407          opts: option.DefaultCompileOptions(),
   408          tab: map[reflect.Type]bool{},
   409          rec: map[reflect.Type]uint8{},
   410      }
   411  }
   412  
   413  func (self *_Compiler) apply(opts option.CompileOptions) *_Compiler {
   414      self.opts = opts
   415      if self.opts.RecursiveDepth > 0 {
   416          self.rec = map[reflect.Type]uint8{}
   417      }
   418      return self
   419  }
   420  
   421  func (self *_Compiler) rescue(ep *error) {
   422      if val := recover(); val != nil {
   423          if err, ok := val.(error); ok {
   424              *ep = err
   425          } else {
   426              panic(val)
   427          }
   428      }
   429  }
   430  
   431  func (self *_Compiler) compile(vt reflect.Type, pv bool) (ret _Program, err error) {
   432      defer self.rescue(&err)
   433      self.compileOne(&ret, 0, vt, pv)
   434      return
   435  }
   436  
   437  func (self *_Compiler) compileOne(p *_Program, sp int, vt reflect.Type, pv bool) {
   438      if self.tab[vt] {
   439          p.vp(_OP_recurse, vt, pv)
   440      } else {
   441          self.compileRec(p, sp, vt, pv)
   442      }
   443  }
   444  
   445  func (self *_Compiler) compileRec(p *_Program, sp int, vt reflect.Type, pv bool) {
   446      pr := self.pv
   447      pt := reflect.PtrTo(vt)
   448  
   449      /* check for addressable `json.Marshaler` with pointer receiver */
   450      if pv && pt.Implements(jsonMarshalerType) {
   451          p.rtt(_OP_marshal_p, pt)
   452          return
   453      }
   454  
   455      /* check for `json.Marshaler` */
   456      if vt.Implements(jsonMarshalerType) {
   457          self.compileMarshaler(p, _OP_marshal, vt, jsonMarshalerType)
   458          return
   459      }
   460  
   461      /* check for addressable `encoding.TextMarshaler` with pointer receiver */
   462      if pv && pt.Implements(encodingTextMarshalerType) {
   463          p.rtt(_OP_marshal_text_p, pt)
   464          return
   465      }
   466  
   467      /* check for `encoding.TextMarshaler` */
   468      if vt.Implements(encodingTextMarshalerType) {
   469          self.compileMarshaler(p, _OP_marshal_text, vt, encodingTextMarshalerType)
   470          return
   471      }
   472  
   473      /* enter the recursion, and compile the type */
   474      self.pv = pv
   475      self.tab[vt] = true
   476      self.compileOps(p, sp, vt)
   477  
   478      /* exit the recursion */
   479      self.pv = pr
   480      delete(self.tab, vt)
   481  }
   482  
   483  func (self *_Compiler) compileOps(p *_Program, sp int, vt reflect.Type) {
   484      switch vt.Kind() {
   485          case reflect.Bool      : p.add(_OP_bool)
   486          case reflect.Int       : p.add(_OP_int())
   487          case reflect.Int8      : p.add(_OP_i8)
   488          case reflect.Int16     : p.add(_OP_i16)
   489          case reflect.Int32     : p.add(_OP_i32)
   490          case reflect.Int64     : p.add(_OP_i64)
   491          case reflect.Uint      : p.add(_OP_uint())
   492          case reflect.Uint8     : p.add(_OP_u8)
   493          case reflect.Uint16    : p.add(_OP_u16)
   494          case reflect.Uint32    : p.add(_OP_u32)
   495          case reflect.Uint64    : p.add(_OP_u64)
   496          case reflect.Uintptr   : p.add(_OP_uintptr())
   497          case reflect.Float32   : p.add(_OP_f32)
   498          case reflect.Float64   : p.add(_OP_f64)
   499          case reflect.String    : self.compileString    (p, vt)
   500          case reflect.Array     : self.compileArray     (p, sp, vt.Elem(), vt.Len())
   501          case reflect.Interface : self.compileInterface (p, vt)
   502          case reflect.Map       : self.compileMap       (p, sp, vt)
   503          case reflect.Ptr       : self.compilePtr       (p, sp, vt.Elem())
   504          case reflect.Slice     : self.compileSlice     (p, sp, vt.Elem())
   505          case reflect.Struct    : self.compileStruct    (p, sp, vt)
   506          default                : panic                 (error_type(vt))
   507      }
   508  }
   509  
   510  func (self *_Compiler) compileNil(p *_Program, sp int, vt reflect.Type, nil_op _Op, fn func(*_Program, int, reflect.Type)) {
   511      x := p.pc()
   512      p.add(_OP_is_nil)
   513      fn(p, sp, vt)
   514      e := p.pc()
   515      p.add(_OP_goto)
   516      p.pin(x)
   517      p.add(nil_op)
   518      p.pin(e)
   519  }
   520  
   521  func (self *_Compiler) compilePtr(p *_Program, sp int, vt reflect.Type) {
   522      self.compileNil(p, sp, vt, _OP_null, self.compilePtrBody)
   523  }
   524  
   525  func (self *_Compiler) compilePtrBody(p *_Program, sp int, vt reflect.Type) {
   526      p.tag(sp)
   527      p.add(_OP_save)
   528      p.add(_OP_deref)
   529      self.compileOne(p, sp + 1, vt, true)
   530      p.add(_OP_drop)
   531  }
   532  
   533  func (self *_Compiler) compileMap(p *_Program, sp int, vt reflect.Type) {
   534      self.compileNil(p, sp, vt, _OP_empty_obj, self.compileMapBody)
   535  }
   536  
   537  func (self *_Compiler) compileMapBody(p *_Program, sp int, vt reflect.Type) {
   538      p.tag(sp + 1)
   539      p.int(_OP_byte, '{')
   540      p.add(_OP_save)
   541      p.rtt(_OP_map_iter, vt)
   542      p.add(_OP_save)
   543      i := p.pc()
   544      p.add(_OP_map_check_key)
   545      u := p.pc()
   546      p.add(_OP_map_write_key)
   547      self.compileMapBodyKey(p, vt.Key())
   548      p.pin(u)
   549      p.int(_OP_byte, ':')
   550      p.add(_OP_map_value_next)
   551      self.compileOne(p, sp + 2, vt.Elem(), false)
   552      j := p.pc()
   553      p.add(_OP_map_check_key)
   554      p.int(_OP_byte, ',')
   555      v := p.pc()
   556      p.add(_OP_map_write_key)
   557      self.compileMapBodyKey(p, vt.Key())
   558      p.pin(v)
   559      p.int(_OP_byte, ':')
   560      p.add(_OP_map_value_next)
   561      self.compileOne(p, sp + 2, vt.Elem(), false)
   562      p.int(_OP_goto, j)
   563      p.pin(i)
   564      p.pin(j)
   565      p.add(_OP_map_stop)
   566      p.add(_OP_drop_2)
   567      p.int(_OP_byte, '}')
   568  }
   569  
   570  func (self *_Compiler) compileMapBodyKey(p *_Program, vk reflect.Type) {
   571      if !vk.Implements(encodingTextMarshalerType) {
   572          self.compileMapBodyTextKey(p, vk)
   573      } else {
   574          self.compileMapBodyUtextKey(p, vk)
   575      }
   576  }
   577  
   578  func (self *_Compiler) compileMapBodyTextKey(p *_Program, vk reflect.Type) {
   579      switch vk.Kind() {
   580          case reflect.Invalid : panic("map key is nil")
   581          case reflect.Bool    : p.key(_OP_bool)
   582          case reflect.Int     : p.key(_OP_int())
   583          case reflect.Int8    : p.key(_OP_i8)
   584          case reflect.Int16   : p.key(_OP_i16)
   585          case reflect.Int32   : p.key(_OP_i32)
   586          case reflect.Int64   : p.key(_OP_i64)
   587          case reflect.Uint    : p.key(_OP_uint())
   588          case reflect.Uint8   : p.key(_OP_u8)
   589          case reflect.Uint16  : p.key(_OP_u16)
   590          case reflect.Uint32  : p.key(_OP_u32)
   591          case reflect.Uint64  : p.key(_OP_u64)
   592          case reflect.Uintptr : p.key(_OP_uintptr())
   593          case reflect.Float32 : p.key(_OP_f32)
   594          case reflect.Float64 : p.key(_OP_f64)
   595          case reflect.String  : self.compileString(p, vk)
   596          default              : panic(error_type(vk))
   597      }
   598  }
   599  
   600  func (self *_Compiler) compileMapBodyUtextKey(p *_Program, vk reflect.Type) {
   601      if vk.Kind() != reflect.Ptr {
   602          p.rtt(_OP_marshal_text, vk)
   603      } else {
   604          self.compileMapBodyUtextPtr(p, vk)
   605      }
   606  }
   607  
   608  func (self *_Compiler) compileMapBodyUtextPtr(p *_Program, vk reflect.Type) {
   609      i := p.pc()
   610      p.add(_OP_is_nil)
   611      p.rtt(_OP_marshal_text, vk)
   612      j := p.pc()
   613      p.add(_OP_goto)
   614      p.pin(i)
   615      p.str(_OP_text, "\"\"")
   616      p.pin(j)
   617  }
   618  
   619  func (self *_Compiler) compileSlice(p *_Program, sp int, vt reflect.Type) {
   620      self.compileNil(p, sp, vt, _OP_empty_arr, self.compileSliceBody)
   621  }
   622  
   623  func (self *_Compiler) compileSliceBody(p *_Program, sp int, vt reflect.Type) {
   624      if isSimpleByte(vt) {
   625          p.add(_OP_bin)
   626      } else {
   627          self.compileSliceArray(p, sp, vt)
   628      }
   629  }
   630  
   631  func (self *_Compiler) compileSliceArray(p *_Program, sp int, vt reflect.Type) {
   632      p.tag(sp)
   633      p.int(_OP_byte, '[')
   634      p.add(_OP_save)
   635      p.add(_OP_slice_len)
   636      i := p.pc()
   637      p.rtt(_OP_slice_next, vt)
   638      self.compileOne(p, sp + 1, vt, true)
   639      j := p.pc()
   640      p.rtt(_OP_slice_next, vt)
   641      p.int(_OP_byte, ',')
   642      self.compileOne(p, sp + 1, vt, true)
   643      p.int(_OP_goto, j)
   644      p.pin(i)
   645      p.pin(j)
   646      p.add(_OP_drop)
   647      p.int(_OP_byte, ']')
   648  }
   649  
   650  func (self *_Compiler) compileArray(p *_Program, sp int, vt reflect.Type, nb int) {
   651      p.tag(sp)
   652      p.int(_OP_byte, '[')
   653      p.add(_OP_save)
   654  
   655      /* first item */
   656      if nb != 0 {
   657          self.compileOne(p, sp + 1, vt, self.pv)
   658          p.add(_OP_load)
   659      }
   660  
   661      /* remaining items */
   662      for i := 1; i < nb; i++ {
   663          p.int(_OP_byte, ',')
   664          p.int(_OP_index, i * int(vt.Size()))
   665          self.compileOne(p, sp + 1, vt, self.pv)
   666          p.add(_OP_load)
   667      }
   668  
   669      /* end of array */
   670      p.add(_OP_drop)
   671      p.int(_OP_byte, ']')
   672  }
   673  
   674  func (self *_Compiler) compileString(p *_Program, vt reflect.Type) {
   675      if vt != jsonNumberType {
   676          p.add(_OP_str)
   677      } else {
   678          p.add(_OP_number)
   679      }
   680  }
   681  
   682  func (self *_Compiler) compileStruct(p *_Program, sp int, vt reflect.Type) {
   683      if sp >= self.opts.MaxInlineDepth || p.pc() >= _MAX_ILBUF || (sp > 0 && vt.NumField() >= _MAX_FIELDS) {
   684          p.vp(_OP_recurse, vt, self.pv)
   685          if self.opts.RecursiveDepth > 0 {
   686              if self.pv {
   687                  self.rec[vt] = 1
   688              } else {
   689                  self.rec[vt] = 0
   690              }
   691          }
   692      } else {
   693          self.compileStructBody(p, sp, vt)
   694      }
   695  }
   696  
   697  func (self *_Compiler) compileStructBody(p *_Program, sp int, vt reflect.Type) {
   698      p.tag(sp)
   699      p.int(_OP_byte, '{')
   700      p.add(_OP_save)
   701      p.add(_OP_cond_set)
   702  
   703      /* compile each field */
   704      for _, fv := range resolver.ResolveStruct(vt) {
   705          var s []int
   706          var o resolver.Offset
   707  
   708          /* "omitempty" for arrays */
   709          if fv.Type.Kind() == reflect.Array {
   710              if fv.Type.Len() == 0 && (fv.Opts & resolver.F_omitempty) != 0 {
   711                  continue
   712              }
   713          }
   714  
   715          /* index to the field */
   716          for _, o = range fv.Path {
   717              if p.int(_OP_index, int(o.Size)); o.Kind == resolver.F_deref {
   718                  s = append(s, p.pc())
   719                  p.add(_OP_is_nil)
   720                  p.add(_OP_deref)
   721              }
   722          }
   723  
   724          /* check for "omitempty" option */
   725          if fv.Type.Kind() != reflect.Struct && fv.Type.Kind() != reflect.Array && (fv.Opts & resolver.F_omitempty) != 0 {
   726              s = append(s, p.pc())
   727              self.compileStructFieldZero(p, fv.Type)
   728          }
   729  
   730          /* add the comma if not the first element */
   731          i := p.pc()
   732          p.add(_OP_cond_testc)
   733          p.int(_OP_byte, ',')
   734          p.pin(i)
   735  
   736          /* compile the key and value */
   737          ft := fv.Type
   738          p.str(_OP_text, Quote(fv.Name) + ":")
   739  
   740          /* check for "stringnize" option */
   741          if (fv.Opts & resolver.F_stringize) == 0 {
   742              self.compileOne(p, sp + 1, ft, self.pv)
   743          } else {
   744              self.compileStructFieldStr(p, sp + 1, ft)
   745          }
   746  
   747          /* patch the skipping jumps and reload the struct pointer */
   748          p.rel(s)
   749          p.add(_OP_load)
   750      }
   751  
   752      /* end of object */
   753      p.add(_OP_drop)
   754      p.int(_OP_byte, '}')
   755  }
   756  
   757  func (self *_Compiler) compileStructFieldStr(p *_Program, sp int, vt reflect.Type) {
   758      pc := -1
   759      ft := vt
   760      sv := false
   761  
   762      /* dereference the pointer if needed */
   763      if ft.Kind() == reflect.Ptr {
   764          ft = ft.Elem()
   765      }
   766  
   767      /* check if it can be stringized */
   768      switch ft.Kind() {
   769          case reflect.Bool    : sv = true
   770          case reflect.Int     : sv = true
   771          case reflect.Int8    : sv = true
   772          case reflect.Int16   : sv = true
   773          case reflect.Int32   : sv = true
   774          case reflect.Int64   : sv = true
   775          case reflect.Uint    : sv = true
   776          case reflect.Uint8   : sv = true
   777          case reflect.Uint16  : sv = true
   778          case reflect.Uint32  : sv = true
   779          case reflect.Uint64  : sv = true
   780          case reflect.Uintptr : sv = true
   781          case reflect.Float32 : sv = true
   782          case reflect.Float64 : sv = true
   783          case reflect.String  : sv = true
   784      }
   785  
   786      /* if it's not, ignore the "string" and follow the regular path */
   787      if !sv {
   788          self.compileOne(p, sp, vt, self.pv)
   789          return
   790      }
   791  
   792      /* dereference the pointer */
   793      if vt.Kind() == reflect.Ptr {
   794          pc = p.pc()
   795          vt = vt.Elem()
   796          p.add(_OP_is_nil)
   797          p.add(_OP_deref)
   798      }
   799  
   800      /* special case of a double-quoted string */
   801      if ft != jsonNumberType && ft.Kind() == reflect.String {
   802          p.add(_OP_quote)
   803      } else {
   804          self.compileStructFieldQuoted(p, sp, vt)
   805      }
   806  
   807      /* the "null" case of the pointer */
   808      if pc != -1 {
   809          e := p.pc()
   810          p.add(_OP_goto)
   811          p.pin(pc)
   812          p.add(_OP_null)
   813          p.pin(e)
   814      }
   815  }
   816  
   817  func (self *_Compiler) compileStructFieldZero(p *_Program, vt reflect.Type) {
   818      switch vt.Kind() {
   819          case reflect.Bool      : p.add(_OP_is_zero_1)
   820          case reflect.Int       : p.add(_OP_is_zero_ints())
   821          case reflect.Int8      : p.add(_OP_is_zero_1)
   822          case reflect.Int16     : p.add(_OP_is_zero_2)
   823          case reflect.Int32     : p.add(_OP_is_zero_4)
   824          case reflect.Int64     : p.add(_OP_is_zero_8)
   825          case reflect.Uint      : p.add(_OP_is_zero_ints())
   826          case reflect.Uint8     : p.add(_OP_is_zero_1)
   827          case reflect.Uint16    : p.add(_OP_is_zero_2)
   828          case reflect.Uint32    : p.add(_OP_is_zero_4)
   829          case reflect.Uint64    : p.add(_OP_is_zero_8)
   830          case reflect.Uintptr   : p.add(_OP_is_nil)
   831          case reflect.Float32   : p.add(_OP_is_zero_4)
   832          case reflect.Float64   : p.add(_OP_is_zero_8)
   833          case reflect.String    : p.add(_OP_is_nil_p1)
   834          case reflect.Interface : p.add(_OP_is_nil)
   835          case reflect.Map       : p.add(_OP_is_zero_map)
   836          case reflect.Ptr       : p.add(_OP_is_nil)
   837          case reflect.Slice     : p.add(_OP_is_nil_p1)
   838          default                : panic(error_type(vt))
   839      }
   840  }
   841  
   842  func (self *_Compiler) compileStructFieldQuoted(p *_Program, sp int, vt reflect.Type) {
   843      p.int(_OP_byte, '"')
   844      self.compileOne(p, sp, vt, self.pv)
   845      p.int(_OP_byte, '"')
   846  }
   847  
   848  func (self *_Compiler) compileInterface(p *_Program, vt reflect.Type) {
   849      x := p.pc()
   850      p.add(_OP_is_nil_p1)
   851  
   852      /* iface and efaces are different */
   853      if vt.NumMethod() == 0 {
   854          p.add(_OP_eface)
   855      } else {
   856          p.add(_OP_iface)
   857      }
   858  
   859      /* the "null" value */
   860      e := p.pc()
   861      p.add(_OP_goto)
   862      p.pin(x)
   863      p.add(_OP_null)
   864      p.pin(e)
   865  }
   866  
   867  func (self *_Compiler) compileMarshaler(p *_Program, op _Op, vt reflect.Type, mt reflect.Type) {
   868      pc := p.pc()
   869      vk := vt.Kind()
   870  
   871      /* direct receiver */
   872      if vk != reflect.Ptr {
   873          p.rtt(op, vt)
   874          return
   875      }
   876  
   877      /* value receiver with a pointer type, check for nil before calling the marshaler */
   878      p.add(_OP_is_nil)
   879      p.rtt(op, vt)
   880      i := p.pc()
   881      p.add(_OP_goto)
   882      p.pin(pc)
   883      p.add(_OP_null)
   884      p.pin(i)
   885  }