github.com/goshafaq/sonic@v0.0.0-20231026082336-871835fb94c6/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/goshafaq/sonic/internal/resolver"
    27  	"github.com/goshafaq/sonic/internal/rt"
    28  	"github.com/goshafaq/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:
   161  		return _OP_i32
   162  	case 64:
   163  		return _OP_i64
   164  	default:
   165  		panic("unsupported int size")
   166  	}
   167  }
   168  
   169  func _OP_uint() _Op {
   170  	switch _INT_SIZE {
   171  	case 32:
   172  		return _OP_u32
   173  	case 64:
   174  		return _OP_u64
   175  	default:
   176  		panic("unsupported uint size")
   177  	}
   178  }
   179  
   180  func _OP_uintptr() _Op {
   181  	switch _PTR_SIZE {
   182  	case 32:
   183  		return _OP_u32
   184  	case 64:
   185  		return _OP_u64
   186  	default:
   187  		panic("unsupported pointer size")
   188  	}
   189  }
   190  
   191  func _OP_is_zero_ints() _Op {
   192  	switch _INT_SIZE {
   193  	case 32:
   194  		return _OP_is_zero_4
   195  	case 64:
   196  		return _OP_is_zero_8
   197  	default:
   198  		panic("unsupported integer size")
   199  	}
   200  }
   201  
   202  type _Instr struct {
   203  	u uint64         // union {op: 8, _: 8, vi: 48}, vi maybe int or len(str)
   204  	p unsafe.Pointer // maybe GoString.Ptr, or *GoType
   205  }
   206  
   207  func packOp(op _Op) uint64 {
   208  	return uint64(op) << 56
   209  }
   210  
   211  func newInsOp(op _Op) _Instr {
   212  	return _Instr{u: packOp(op)}
   213  }
   214  
   215  func newInsVi(op _Op, vi int) _Instr {
   216  	return _Instr{u: packOp(op) | rt.PackInt(vi)}
   217  }
   218  
   219  func newInsVs(op _Op, vs string) _Instr {
   220  	return _Instr{
   221  		u: packOp(op) | rt.PackInt(len(vs)),
   222  		p: (*rt.GoString)(unsafe.Pointer(&vs)).Ptr,
   223  	}
   224  }
   225  
   226  func newInsVt(op _Op, vt reflect.Type) _Instr {
   227  	return _Instr{
   228  		u: packOp(op),
   229  		p: unsafe.Pointer(rt.UnpackType(vt)),
   230  	}
   231  }
   232  
   233  func newInsVp(op _Op, vt reflect.Type, pv bool) _Instr {
   234  	i := 0
   235  	if pv {
   236  		i = 1
   237  	}
   238  	return _Instr{
   239  		u: packOp(op) | rt.PackInt(i),
   240  		p: unsafe.Pointer(rt.UnpackType(vt)),
   241  	}
   242  }
   243  
   244  func (self _Instr) op() _Op {
   245  	return _Op(self.u >> 56)
   246  }
   247  
   248  func (self _Instr) vi() int {
   249  	return rt.UnpackInt(self.u)
   250  }
   251  
   252  func (self _Instr) vf() uint8 {
   253  	return (*rt.GoType)(self.p).KindFlags
   254  }
   255  
   256  func (self _Instr) vs() (v string) {
   257  	(*rt.GoString)(unsafe.Pointer(&v)).Ptr = self.p
   258  	(*rt.GoString)(unsafe.Pointer(&v)).Len = self.vi()
   259  	return
   260  }
   261  
   262  func (self _Instr) vk() reflect.Kind {
   263  	return (*rt.GoType)(self.p).Kind()
   264  }
   265  
   266  func (self _Instr) vt() reflect.Type {
   267  	return (*rt.GoType)(self.p).Pack()
   268  }
   269  
   270  func (self _Instr) vp() (vt reflect.Type, pv bool) {
   271  	return (*rt.GoType)(self.p).Pack(), rt.UnpackInt(self.u) == 1
   272  }
   273  
   274  func (self _Instr) i64() int64 {
   275  	return int64(self.vi())
   276  }
   277  
   278  func (self _Instr) vlen() int {
   279  	return int((*rt.GoType)(self.p).Size)
   280  }
   281  
   282  func (self _Instr) isBranch() bool {
   283  	switch self.op() {
   284  	case _OP_goto:
   285  		fallthrough
   286  	case _OP_is_nil:
   287  		fallthrough
   288  	case _OP_is_nil_p1:
   289  		fallthrough
   290  	case _OP_is_zero_1:
   291  		fallthrough
   292  	case _OP_is_zero_2:
   293  		fallthrough
   294  	case _OP_is_zero_4:
   295  		fallthrough
   296  	case _OP_is_zero_8:
   297  		fallthrough
   298  	case _OP_map_check_key:
   299  		fallthrough
   300  	case _OP_map_write_key:
   301  		fallthrough
   302  	case _OP_slice_next:
   303  		fallthrough
   304  	case _OP_cond_testc:
   305  		return true
   306  	default:
   307  		return false
   308  	}
   309  }
   310  
   311  func (self _Instr) disassemble() string {
   312  	switch self.op() {
   313  	case _OP_byte:
   314  		return fmt.Sprintf("%-18s%s", self.op().String(), strconv.QuoteRune(rune(self.vi())))
   315  	case _OP_text:
   316  		return fmt.Sprintf("%-18s%s", self.op().String(), strconv.Quote(self.vs()))
   317  	case _OP_index:
   318  		return fmt.Sprintf("%-18s%d", self.op().String(), self.vi())
   319  	case _OP_recurse:
   320  		fallthrough
   321  	case _OP_map_iter:
   322  		fallthrough
   323  	case _OP_marshal:
   324  		fallthrough
   325  	case _OP_marshal_p:
   326  		fallthrough
   327  	case _OP_marshal_text:
   328  		fallthrough
   329  	case _OP_marshal_text_p:
   330  		return fmt.Sprintf("%-18s%s", self.op().String(), self.vt())
   331  	case _OP_goto:
   332  		fallthrough
   333  	case _OP_is_nil:
   334  		fallthrough
   335  	case _OP_is_nil_p1:
   336  		fallthrough
   337  	case _OP_is_zero_1:
   338  		fallthrough
   339  	case _OP_is_zero_2:
   340  		fallthrough
   341  	case _OP_is_zero_4:
   342  		fallthrough
   343  	case _OP_is_zero_8:
   344  		fallthrough
   345  	case _OP_is_zero_map:
   346  		fallthrough
   347  	case _OP_cond_testc:
   348  		fallthrough
   349  	case _OP_map_check_key:
   350  		fallthrough
   351  	case _OP_map_write_key:
   352  		return fmt.Sprintf("%-18sL_%d", self.op().String(), self.vi())
   353  	case _OP_slice_next:
   354  		return fmt.Sprintf("%-18sL_%d, %s", self.op().String(), self.vi(), self.vt())
   355  	default:
   356  		return self.op().String()
   357  	}
   358  }
   359  
   360  type (
   361  	_Program []_Instr
   362  )
   363  
   364  func (self _Program) pc() int {
   365  	return len(self)
   366  }
   367  
   368  func (self _Program) tag(n int) {
   369  	if n >= _MaxStack {
   370  		panic("type nesting too deep")
   371  	}
   372  }
   373  
   374  func (self _Program) pin(i int) {
   375  	v := &self[i]
   376  	v.u &= 0xffff000000000000
   377  	v.u |= rt.PackInt(self.pc())
   378  }
   379  
   380  func (self _Program) rel(v []int) {
   381  	for _, i := range v {
   382  		self.pin(i)
   383  	}
   384  }
   385  
   386  func (self *_Program) add(op _Op) {
   387  	*self = append(*self, newInsOp(op))
   388  }
   389  
   390  func (self *_Program) key(op _Op) {
   391  	*self = append(*self,
   392  		newInsVi(_OP_byte, '"'),
   393  		newInsOp(op),
   394  		newInsVi(_OP_byte, '"'),
   395  	)
   396  }
   397  
   398  func (self *_Program) int(op _Op, vi int) {
   399  	*self = append(*self, newInsVi(op, vi))
   400  }
   401  
   402  func (self *_Program) str(op _Op, vs string) {
   403  	*self = append(*self, newInsVs(op, vs))
   404  }
   405  
   406  func (self *_Program) rtt(op _Op, vt reflect.Type) {
   407  	*self = append(*self, newInsVt(op, vt))
   408  }
   409  
   410  func (self *_Program) vp(op _Op, vt reflect.Type, pv bool) {
   411  	*self = append(*self, newInsVp(op, vt, pv))
   412  }
   413  
   414  func (self _Program) disassemble() string {
   415  	nb := len(self)
   416  	tab := make([]bool, nb+1)
   417  	ret := make([]string, 0, nb+1)
   418  
   419  	/* prescan to get all the labels */
   420  	for _, ins := range self {
   421  		if ins.isBranch() {
   422  			tab[ins.vi()] = true
   423  		}
   424  	}
   425  
   426  	/* disassemble each instruction */
   427  	for i, ins := range self {
   428  		if !tab[i] {
   429  			ret = append(ret, "\t"+ins.disassemble())
   430  		} else {
   431  			ret = append(ret, fmt.Sprintf("L_%d:\n\t%s", i, ins.disassemble()))
   432  		}
   433  	}
   434  
   435  	/* add the last label, if needed */
   436  	if tab[nb] {
   437  		ret = append(ret, fmt.Sprintf("L_%d:", nb))
   438  	}
   439  
   440  	/* add an "end" indicator, and join all the strings */
   441  	return strings.Join(append(ret, "\tend"), "\n")
   442  }
   443  
   444  type _Compiler struct {
   445  	opts option.CompileOptions
   446  	pv   bool
   447  	tab  map[reflect.Type]bool
   448  	rec  map[reflect.Type]uint8
   449  }
   450  
   451  func newCompiler() *_Compiler {
   452  	return &_Compiler{
   453  		opts: option.DefaultCompileOptions(),
   454  		tab:  map[reflect.Type]bool{},
   455  		rec:  map[reflect.Type]uint8{},
   456  	}
   457  }
   458  
   459  func (self *_Compiler) apply(opts option.CompileOptions) *_Compiler {
   460  	self.opts = opts
   461  	if self.opts.RecursiveDepth > 0 {
   462  		self.rec = map[reflect.Type]uint8{}
   463  	}
   464  	return self
   465  }
   466  
   467  func (self *_Compiler) rescue(ep *error) {
   468  	if val := recover(); val != nil {
   469  		if err, ok := val.(error); ok {
   470  			*ep = err
   471  		} else {
   472  			panic(val)
   473  		}
   474  	}
   475  }
   476  
   477  func (self *_Compiler) compile(vt reflect.Type, pv bool) (ret _Program, err error) {
   478  	defer self.rescue(&err)
   479  	self.compileOne(&ret, 0, vt, pv)
   480  	return
   481  }
   482  
   483  func (self *_Compiler) compileOne(p *_Program, sp int, vt reflect.Type, pv bool) {
   484  	if self.tab[vt] {
   485  		p.vp(_OP_recurse, vt, pv)
   486  	} else {
   487  		self.compileRec(p, sp, vt, pv)
   488  	}
   489  }
   490  
   491  func (self *_Compiler) compileRec(p *_Program, sp int, vt reflect.Type, pv bool) {
   492  	pr := self.pv
   493  	pt := reflect.PtrTo(vt)
   494  
   495  	/* check for addressable `json.Marshaler` with pointer receiver */
   496  	if pv && pt.Implements(jsonMarshalerType) {
   497  		p.rtt(_OP_marshal_p, pt)
   498  		return
   499  	}
   500  
   501  	/* check for `json.Marshaler` */
   502  	if vt.Implements(jsonMarshalerType) {
   503  		self.compileMarshaler(p, _OP_marshal, vt, jsonMarshalerType)
   504  		return
   505  	}
   506  
   507  	/* check for addressable `encoding.TextMarshaler` with pointer receiver */
   508  	if pv && pt.Implements(encodingTextMarshalerType) {
   509  		p.rtt(_OP_marshal_text_p, pt)
   510  		return
   511  	}
   512  
   513  	/* check for `encoding.TextMarshaler` */
   514  	if vt.Implements(encodingTextMarshalerType) {
   515  		self.compileMarshaler(p, _OP_marshal_text, vt, encodingTextMarshalerType)
   516  		return
   517  	}
   518  
   519  	/* enter the recursion, and compile the type */
   520  	self.pv = pv
   521  	self.tab[vt] = true
   522  	self.compileOps(p, sp, vt)
   523  
   524  	/* exit the recursion */
   525  	self.pv = pr
   526  	delete(self.tab, vt)
   527  }
   528  
   529  func (self *_Compiler) compileOps(p *_Program, sp int, vt reflect.Type) {
   530  	switch vt.Kind() {
   531  	case reflect.Bool:
   532  		p.add(_OP_bool)
   533  	case reflect.Int:
   534  		p.add(_OP_int())
   535  	case reflect.Int8:
   536  		p.add(_OP_i8)
   537  	case reflect.Int16:
   538  		p.add(_OP_i16)
   539  	case reflect.Int32:
   540  		p.add(_OP_i32)
   541  	case reflect.Int64:
   542  		p.add(_OP_i64)
   543  	case reflect.Uint:
   544  		p.add(_OP_uint())
   545  	case reflect.Uint8:
   546  		p.add(_OP_u8)
   547  	case reflect.Uint16:
   548  		p.add(_OP_u16)
   549  	case reflect.Uint32:
   550  		p.add(_OP_u32)
   551  	case reflect.Uint64:
   552  		p.add(_OP_u64)
   553  	case reflect.Uintptr:
   554  		p.add(_OP_uintptr())
   555  	case reflect.Float32:
   556  		p.add(_OP_f32)
   557  	case reflect.Float64:
   558  		p.add(_OP_f64)
   559  	case reflect.String:
   560  		self.compileString(p, vt)
   561  	case reflect.Array:
   562  		self.compileArray(p, sp, vt.Elem(), vt.Len())
   563  	case reflect.Interface:
   564  		self.compileInterface(p, vt)
   565  	case reflect.Map:
   566  		self.compileMap(p, sp, vt)
   567  	case reflect.Ptr:
   568  		self.compilePtr(p, sp, vt.Elem())
   569  	case reflect.Slice:
   570  		self.compileSlice(p, sp, vt.Elem())
   571  	case reflect.Struct:
   572  		self.compileStruct(p, sp, vt)
   573  	default:
   574  		panic(error_type(vt))
   575  	}
   576  }
   577  
   578  func (self *_Compiler) compileNil(p *_Program, sp int, vt reflect.Type, nil_op _Op, fn func(*_Program, int, reflect.Type)) {
   579  	x := p.pc()
   580  	p.add(_OP_is_nil)
   581  	fn(p, sp, vt)
   582  	e := p.pc()
   583  	p.add(_OP_goto)
   584  	p.pin(x)
   585  	p.add(nil_op)
   586  	p.pin(e)
   587  }
   588  
   589  func (self *_Compiler) compilePtr(p *_Program, sp int, vt reflect.Type) {
   590  	self.compileNil(p, sp, vt, _OP_null, self.compilePtrBody)
   591  }
   592  
   593  func (self *_Compiler) compilePtrBody(p *_Program, sp int, vt reflect.Type) {
   594  	p.tag(sp)
   595  	p.add(_OP_save)
   596  	p.add(_OP_deref)
   597  	self.compileOne(p, sp+1, vt, true)
   598  	p.add(_OP_drop)
   599  }
   600  
   601  func (self *_Compiler) compileMap(p *_Program, sp int, vt reflect.Type) {
   602  	self.compileNil(p, sp, vt, _OP_empty_obj, self.compileMapBody)
   603  }
   604  
   605  func (self *_Compiler) compileMapBody(p *_Program, sp int, vt reflect.Type) {
   606  	p.tag(sp + 1)
   607  	p.int(_OP_byte, '{')
   608  	p.add(_OP_save)
   609  	p.rtt(_OP_map_iter, vt)
   610  	p.add(_OP_save)
   611  	i := p.pc()
   612  	p.add(_OP_map_check_key)
   613  	u := p.pc()
   614  	p.add(_OP_map_write_key)
   615  	self.compileMapBodyKey(p, vt.Key())
   616  	p.pin(u)
   617  	p.int(_OP_byte, ':')
   618  	p.add(_OP_map_value_next)
   619  	self.compileOne(p, sp+2, vt.Elem(), false)
   620  	j := p.pc()
   621  	p.add(_OP_map_check_key)
   622  	p.int(_OP_byte, ',')
   623  	v := p.pc()
   624  	p.add(_OP_map_write_key)
   625  	self.compileMapBodyKey(p, vt.Key())
   626  	p.pin(v)
   627  	p.int(_OP_byte, ':')
   628  	p.add(_OP_map_value_next)
   629  	self.compileOne(p, sp+2, vt.Elem(), false)
   630  	p.int(_OP_goto, j)
   631  	p.pin(i)
   632  	p.pin(j)
   633  	p.add(_OP_map_stop)
   634  	p.add(_OP_drop_2)
   635  	p.int(_OP_byte, '}')
   636  }
   637  
   638  func (self *_Compiler) compileMapBodyKey(p *_Program, vk reflect.Type) {
   639  	if !vk.Implements(encodingTextMarshalerType) {
   640  		self.compileMapBodyTextKey(p, vk)
   641  	} else {
   642  		self.compileMapBodyUtextKey(p, vk)
   643  	}
   644  }
   645  
   646  func (self *_Compiler) compileMapBodyTextKey(p *_Program, vk reflect.Type) {
   647  	switch vk.Kind() {
   648  	case reflect.Invalid:
   649  		panic("map key is nil")
   650  	case reflect.Bool:
   651  		p.key(_OP_bool)
   652  	case reflect.Int:
   653  		p.key(_OP_int())
   654  	case reflect.Int8:
   655  		p.key(_OP_i8)
   656  	case reflect.Int16:
   657  		p.key(_OP_i16)
   658  	case reflect.Int32:
   659  		p.key(_OP_i32)
   660  	case reflect.Int64:
   661  		p.key(_OP_i64)
   662  	case reflect.Uint:
   663  		p.key(_OP_uint())
   664  	case reflect.Uint8:
   665  		p.key(_OP_u8)
   666  	case reflect.Uint16:
   667  		p.key(_OP_u16)
   668  	case reflect.Uint32:
   669  		p.key(_OP_u32)
   670  	case reflect.Uint64:
   671  		p.key(_OP_u64)
   672  	case reflect.Uintptr:
   673  		p.key(_OP_uintptr())
   674  	case reflect.Float32:
   675  		p.key(_OP_f32)
   676  	case reflect.Float64:
   677  		p.key(_OP_f64)
   678  	case reflect.String:
   679  		self.compileString(p, vk)
   680  	default:
   681  		panic(error_type(vk))
   682  	}
   683  }
   684  
   685  func (self *_Compiler) compileMapBodyUtextKey(p *_Program, vk reflect.Type) {
   686  	if vk.Kind() != reflect.Ptr {
   687  		p.rtt(_OP_marshal_text, vk)
   688  	} else {
   689  		self.compileMapBodyUtextPtr(p, vk)
   690  	}
   691  }
   692  
   693  func (self *_Compiler) compileMapBodyUtextPtr(p *_Program, vk reflect.Type) {
   694  	i := p.pc()
   695  	p.add(_OP_is_nil)
   696  	p.rtt(_OP_marshal_text, vk)
   697  	j := p.pc()
   698  	p.add(_OP_goto)
   699  	p.pin(i)
   700  	p.str(_OP_text, "\"\"")
   701  	p.pin(j)
   702  }
   703  
   704  func (self *_Compiler) compileSlice(p *_Program, sp int, vt reflect.Type) {
   705  	self.compileNil(p, sp, vt, _OP_empty_arr, self.compileSliceBody)
   706  }
   707  
   708  func (self *_Compiler) compileSliceBody(p *_Program, sp int, vt reflect.Type) {
   709  	if isSimpleByte(vt) {
   710  		p.add(_OP_bin)
   711  	} else {
   712  		self.compileSliceArray(p, sp, vt)
   713  	}
   714  }
   715  
   716  func (self *_Compiler) compileSliceArray(p *_Program, sp int, vt reflect.Type) {
   717  	p.tag(sp)
   718  	p.int(_OP_byte, '[')
   719  	p.add(_OP_save)
   720  	p.add(_OP_slice_len)
   721  	i := p.pc()
   722  	p.rtt(_OP_slice_next, vt)
   723  	self.compileOne(p, sp+1, vt, true)
   724  	j := p.pc()
   725  	p.rtt(_OP_slice_next, vt)
   726  	p.int(_OP_byte, ',')
   727  	self.compileOne(p, sp+1, vt, true)
   728  	p.int(_OP_goto, j)
   729  	p.pin(i)
   730  	p.pin(j)
   731  	p.add(_OP_drop)
   732  	p.int(_OP_byte, ']')
   733  }
   734  
   735  func (self *_Compiler) compileArray(p *_Program, sp int, vt reflect.Type, nb int) {
   736  	p.tag(sp)
   737  	p.int(_OP_byte, '[')
   738  	p.add(_OP_save)
   739  
   740  	/* first item */
   741  	if nb != 0 {
   742  		self.compileOne(p, sp+1, vt, self.pv)
   743  		p.add(_OP_load)
   744  	}
   745  
   746  	/* remaining items */
   747  	for i := 1; i < nb; i++ {
   748  		p.int(_OP_byte, ',')
   749  		p.int(_OP_index, i*int(vt.Size()))
   750  		self.compileOne(p, sp+1, vt, self.pv)
   751  		p.add(_OP_load)
   752  	}
   753  
   754  	/* end of array */
   755  	p.add(_OP_drop)
   756  	p.int(_OP_byte, ']')
   757  }
   758  
   759  func (self *_Compiler) compileString(p *_Program, vt reflect.Type) {
   760  	if vt != jsonNumberType {
   761  		p.add(_OP_str)
   762  	} else {
   763  		p.add(_OP_number)
   764  	}
   765  }
   766  
   767  func (self *_Compiler) compileStruct(p *_Program, sp int, vt reflect.Type) {
   768  	if sp >= self.opts.MaxInlineDepth || p.pc() >= _MAX_ILBUF || (sp > 0 && vt.NumField() >= _MAX_FIELDS) {
   769  		p.vp(_OP_recurse, vt, self.pv)
   770  		if self.opts.RecursiveDepth > 0 {
   771  			if self.pv {
   772  				self.rec[vt] = 1
   773  			} else {
   774  				self.rec[vt] = 0
   775  			}
   776  		}
   777  	} else {
   778  		self.compileStructBody(p, sp, vt)
   779  	}
   780  }
   781  
   782  func (self *_Compiler) compileStructBody(p *_Program, sp int, vt reflect.Type) {
   783  	p.tag(sp)
   784  	p.int(_OP_byte, '{')
   785  	p.add(_OP_save)
   786  	p.add(_OP_cond_set)
   787  
   788  	/* compile each field */
   789  	for _, fv := range resolver.ResolveStruct(vt) {
   790  		var s []int
   791  		var o resolver.Offset
   792  
   793  		/* "omitempty" for arrays */
   794  		if fv.Type.Kind() == reflect.Array {
   795  			if fv.Type.Len() == 0 && (fv.Opts&resolver.F_omitempty) != 0 {
   796  				continue
   797  			}
   798  		}
   799  
   800  		/* index to the field */
   801  		for _, o = range fv.Path {
   802  			if p.int(_OP_index, int(o.Size)); o.Kind == resolver.F_deref {
   803  				s = append(s, p.pc())
   804  				p.add(_OP_is_nil)
   805  				p.add(_OP_deref)
   806  			}
   807  		}
   808  
   809  		/* check for "omitempty" option */
   810  		if fv.Type.Kind() != reflect.Struct && fv.Type.Kind() != reflect.Array && (fv.Opts&resolver.F_omitempty) != 0 {
   811  			s = append(s, p.pc())
   812  			self.compileStructFieldZero(p, fv.Type)
   813  		}
   814  
   815  		/* add the comma if not the first element */
   816  		i := p.pc()
   817  		p.add(_OP_cond_testc)
   818  		p.int(_OP_byte, ',')
   819  		p.pin(i)
   820  
   821  		/* compile the key and value */
   822  		ft := fv.Type
   823  		p.str(_OP_text, Quote(fv.Name)+":")
   824  
   825  		/* check for "stringnize" option */
   826  		if (fv.Opts & resolver.F_stringize) == 0 {
   827  			self.compileOne(p, sp+1, ft, self.pv)
   828  		} else {
   829  			self.compileStructFieldStr(p, sp+1, ft)
   830  		}
   831  
   832  		/* patch the skipping jumps and reload the struct pointer */
   833  		p.rel(s)
   834  		p.add(_OP_load)
   835  	}
   836  
   837  	/* end of object */
   838  	p.add(_OP_drop)
   839  	p.int(_OP_byte, '}')
   840  }
   841  
   842  func (self *_Compiler) compileStructFieldStr(p *_Program, sp int, vt reflect.Type) {
   843  	pc := -1
   844  	ft := vt
   845  	sv := false
   846  
   847  	/* dereference the pointer if needed */
   848  	if ft.Kind() == reflect.Ptr {
   849  		ft = ft.Elem()
   850  	}
   851  
   852  	/* check if it can be stringized */
   853  	switch ft.Kind() {
   854  	case reflect.Bool:
   855  		sv = true
   856  	case reflect.Int:
   857  		sv = true
   858  	case reflect.Int8:
   859  		sv = true
   860  	case reflect.Int16:
   861  		sv = true
   862  	case reflect.Int32:
   863  		sv = true
   864  	case reflect.Int64:
   865  		sv = true
   866  	case reflect.Uint:
   867  		sv = true
   868  	case reflect.Uint8:
   869  		sv = true
   870  	case reflect.Uint16:
   871  		sv = true
   872  	case reflect.Uint32:
   873  		sv = true
   874  	case reflect.Uint64:
   875  		sv = true
   876  	case reflect.Uintptr:
   877  		sv = true
   878  	case reflect.Float32:
   879  		sv = true
   880  	case reflect.Float64:
   881  		sv = true
   882  	case reflect.String:
   883  		sv = true
   884  	}
   885  
   886  	/* if it's not, ignore the "string" and follow the regular path */
   887  	if !sv {
   888  		self.compileOne(p, sp, vt, self.pv)
   889  		return
   890  	}
   891  
   892  	/* dereference the pointer */
   893  	if vt.Kind() == reflect.Ptr {
   894  		pc = p.pc()
   895  		vt = vt.Elem()
   896  		p.add(_OP_is_nil)
   897  		p.add(_OP_deref)
   898  	}
   899  
   900  	/* special case of a double-quoted string */
   901  	if ft != jsonNumberType && ft.Kind() == reflect.String {
   902  		p.add(_OP_quote)
   903  	} else {
   904  		self.compileStructFieldQuoted(p, sp, vt)
   905  	}
   906  
   907  	/* the "null" case of the pointer */
   908  	if pc != -1 {
   909  		e := p.pc()
   910  		p.add(_OP_goto)
   911  		p.pin(pc)
   912  		p.add(_OP_null)
   913  		p.pin(e)
   914  	}
   915  }
   916  
   917  func (self *_Compiler) compileStructFieldZero(p *_Program, vt reflect.Type) {
   918  	switch vt.Kind() {
   919  	case reflect.Bool:
   920  		p.add(_OP_is_zero_1)
   921  	case reflect.Int:
   922  		p.add(_OP_is_zero_ints())
   923  	case reflect.Int8:
   924  		p.add(_OP_is_zero_1)
   925  	case reflect.Int16:
   926  		p.add(_OP_is_zero_2)
   927  	case reflect.Int32:
   928  		p.add(_OP_is_zero_4)
   929  	case reflect.Int64:
   930  		p.add(_OP_is_zero_8)
   931  	case reflect.Uint:
   932  		p.add(_OP_is_zero_ints())
   933  	case reflect.Uint8:
   934  		p.add(_OP_is_zero_1)
   935  	case reflect.Uint16:
   936  		p.add(_OP_is_zero_2)
   937  	case reflect.Uint32:
   938  		p.add(_OP_is_zero_4)
   939  	case reflect.Uint64:
   940  		p.add(_OP_is_zero_8)
   941  	case reflect.Uintptr:
   942  		p.add(_OP_is_nil)
   943  	case reflect.Float32:
   944  		p.add(_OP_is_zero_4)
   945  	case reflect.Float64:
   946  		p.add(_OP_is_zero_8)
   947  	case reflect.String:
   948  		p.add(_OP_is_nil_p1)
   949  	case reflect.Interface:
   950  		p.add(_OP_is_nil)
   951  	case reflect.Map:
   952  		p.add(_OP_is_zero_map)
   953  	case reflect.Ptr:
   954  		p.add(_OP_is_nil)
   955  	case reflect.Slice:
   956  		p.add(_OP_is_nil_p1)
   957  	default:
   958  		panic(error_type(vt))
   959  	}
   960  }
   961  
   962  func (self *_Compiler) compileStructFieldQuoted(p *_Program, sp int, vt reflect.Type) {
   963  	p.int(_OP_byte, '"')
   964  	self.compileOne(p, sp, vt, self.pv)
   965  	p.int(_OP_byte, '"')
   966  }
   967  
   968  func (self *_Compiler) compileInterface(p *_Program, vt reflect.Type) {
   969  	x := p.pc()
   970  	p.add(_OP_is_nil_p1)
   971  
   972  	/* iface and efaces are different */
   973  	if vt.NumMethod() == 0 {
   974  		p.add(_OP_eface)
   975  	} else {
   976  		p.add(_OP_iface)
   977  	}
   978  
   979  	/* the "null" value */
   980  	e := p.pc()
   981  	p.add(_OP_goto)
   982  	p.pin(x)
   983  	p.add(_OP_null)
   984  	p.pin(e)
   985  }
   986  
   987  func (self *_Compiler) compileMarshaler(p *_Program, op _Op, vt reflect.Type, mt reflect.Type) {
   988  	pc := p.pc()
   989  	vk := vt.Kind()
   990  
   991  	/* direct receiver */
   992  	if vk != reflect.Ptr {
   993  		p.rtt(op, vt)
   994  		return
   995  	}
   996  
   997  	/* value receiver with a pointer type, check for nil before calling the marshaler */
   998  	p.add(_OP_is_nil)
   999  	p.rtt(op, vt)
  1000  	i := p.pc()
  1001  	p.add(_OP_goto)
  1002  	p.pin(pc)
  1003  	p.add(_OP_null)
  1004  	p.pin(i)
  1005  }