github.com/goshafaq/sonic@v0.0.0-20231026082336-871835fb94c6/internal/decoder/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 decoder
    18  
    19  import (
    20  	"encoding/json"
    21  	"fmt"
    22  	"reflect"
    23  	"sort"
    24  	"strconv"
    25  	"strings"
    26  	"unsafe"
    27  
    28  	"github.com/goshafaq/sonic/internal/caching"
    29  	"github.com/goshafaq/sonic/internal/resolver"
    30  	"github.com/goshafaq/sonic/internal/rt"
    31  	"github.com/goshafaq/sonic/option"
    32  )
    33  
    34  type _Op uint8
    35  
    36  const (
    37  	_OP_any _Op = iota + 1
    38  	_OP_dyn
    39  	_OP_str
    40  	_OP_bin
    41  	_OP_bool
    42  	_OP_num
    43  	_OP_i8
    44  	_OP_i16
    45  	_OP_i32
    46  	_OP_i64
    47  	_OP_u8
    48  	_OP_u16
    49  	_OP_u32
    50  	_OP_u64
    51  	_OP_f32
    52  	_OP_f64
    53  	_OP_unquote
    54  	_OP_nil_1
    55  	_OP_nil_2
    56  	_OP_nil_3
    57  	_OP_deref
    58  	_OP_index
    59  	_OP_is_null
    60  	_OP_is_null_quote
    61  	_OP_map_init
    62  	_OP_map_key_i8
    63  	_OP_map_key_i16
    64  	_OP_map_key_i32
    65  	_OP_map_key_i64
    66  	_OP_map_key_u8
    67  	_OP_map_key_u16
    68  	_OP_map_key_u32
    69  	_OP_map_key_u64
    70  	_OP_map_key_f32
    71  	_OP_map_key_f64
    72  	_OP_map_key_str
    73  	_OP_map_key_utext
    74  	_OP_map_key_utext_p
    75  	_OP_array_skip
    76  	_OP_array_clear
    77  	_OP_array_clear_p
    78  	_OP_slice_init
    79  	_OP_slice_append
    80  	_OP_object_skip
    81  	_OP_object_next
    82  	_OP_struct_field
    83  	_OP_unmarshal
    84  	_OP_unmarshal_p
    85  	_OP_unmarshal_text
    86  	_OP_unmarshal_text_p
    87  	_OP_lspace
    88  	_OP_match_char
    89  	_OP_check_char
    90  	_OP_load
    91  	_OP_save
    92  	_OP_drop
    93  	_OP_drop_2
    94  	_OP_recurse
    95  	_OP_goto
    96  	_OP_switch
    97  	_OP_check_char_0
    98  	_OP_dismatch_err
    99  	_OP_go_skip
   100  	_OP_add
   101  	_OP_check_empty
   102  	_OP_debug
   103  )
   104  
   105  const (
   106  	_INT_SIZE = 32 << (^uint(0) >> 63)
   107  	_PTR_SIZE = 32 << (^uintptr(0) >> 63)
   108  	_PTR_BYTE = unsafe.Sizeof(uintptr(0))
   109  )
   110  
   111  const (
   112  	_MAX_ILBUF  = 100000 // cutoff at 100k of IL instructions
   113  	_MAX_FIELDS = 50     // cutoff at 50 fields struct
   114  )
   115  
   116  var _OpNames = [256]string{
   117  	_OP_any:              "any",
   118  	_OP_dyn:              "dyn",
   119  	_OP_str:              "str",
   120  	_OP_bin:              "bin",
   121  	_OP_bool:             "bool",
   122  	_OP_num:              "num",
   123  	_OP_i8:               "i8",
   124  	_OP_i16:              "i16",
   125  	_OP_i32:              "i32",
   126  	_OP_i64:              "i64",
   127  	_OP_u8:               "u8",
   128  	_OP_u16:              "u16",
   129  	_OP_u32:              "u32",
   130  	_OP_u64:              "u64",
   131  	_OP_f32:              "f32",
   132  	_OP_f64:              "f64",
   133  	_OP_unquote:          "unquote",
   134  	_OP_nil_1:            "nil_1",
   135  	_OP_nil_2:            "nil_2",
   136  	_OP_nil_3:            "nil_3",
   137  	_OP_deref:            "deref",
   138  	_OP_index:            "index",
   139  	_OP_is_null:          "is_null",
   140  	_OP_is_null_quote:    "is_null_quote",
   141  	_OP_map_init:         "map_init",
   142  	_OP_map_key_i8:       "map_key_i8",
   143  	_OP_map_key_i16:      "map_key_i16",
   144  	_OP_map_key_i32:      "map_key_i32",
   145  	_OP_map_key_i64:      "map_key_i64",
   146  	_OP_map_key_u8:       "map_key_u8",
   147  	_OP_map_key_u16:      "map_key_u16",
   148  	_OP_map_key_u32:      "map_key_u32",
   149  	_OP_map_key_u64:      "map_key_u64",
   150  	_OP_map_key_f32:      "map_key_f32",
   151  	_OP_map_key_f64:      "map_key_f64",
   152  	_OP_map_key_str:      "map_key_str",
   153  	_OP_map_key_utext:    "map_key_utext",
   154  	_OP_map_key_utext_p:  "map_key_utext_p",
   155  	_OP_array_skip:       "array_skip",
   156  	_OP_slice_init:       "slice_init",
   157  	_OP_slice_append:     "slice_append",
   158  	_OP_object_skip:      "object_skip",
   159  	_OP_object_next:      "object_next",
   160  	_OP_struct_field:     "struct_field",
   161  	_OP_unmarshal:        "unmarshal",
   162  	_OP_unmarshal_p:      "unmarshal_p",
   163  	_OP_unmarshal_text:   "unmarshal_text",
   164  	_OP_unmarshal_text_p: "unmarshal_text_p",
   165  	_OP_lspace:           "lspace",
   166  	_OP_match_char:       "match_char",
   167  	_OP_check_char:       "check_char",
   168  	_OP_load:             "load",
   169  	_OP_save:             "save",
   170  	_OP_drop:             "drop",
   171  	_OP_drop_2:           "drop_2",
   172  	_OP_recurse:          "recurse",
   173  	_OP_goto:             "goto",
   174  	_OP_switch:           "switch",
   175  	_OP_check_char_0:     "check_char_0",
   176  	_OP_dismatch_err:     "dismatch_err",
   177  	_OP_add:              "add",
   178  	_OP_go_skip:          "go_skip",
   179  	_OP_check_empty:      "check_empty",
   180  	_OP_debug:            "debug",
   181  }
   182  
   183  func (self _Op) String() string {
   184  	if ret := _OpNames[self]; ret != "" {
   185  		return ret
   186  	} else {
   187  		return "<invalid>"
   188  	}
   189  }
   190  
   191  func _OP_int() _Op {
   192  	switch _INT_SIZE {
   193  	case 32:
   194  		return _OP_i32
   195  	case 64:
   196  		return _OP_i64
   197  	default:
   198  		panic("unsupported int size")
   199  	}
   200  }
   201  
   202  func _OP_uint() _Op {
   203  	switch _INT_SIZE {
   204  	case 32:
   205  		return _OP_u32
   206  	case 64:
   207  		return _OP_u64
   208  	default:
   209  		panic("unsupported uint size")
   210  	}
   211  }
   212  
   213  func _OP_uintptr() _Op {
   214  	switch _PTR_SIZE {
   215  	case 32:
   216  		return _OP_u32
   217  	case 64:
   218  		return _OP_u64
   219  	default:
   220  		panic("unsupported pointer size")
   221  	}
   222  }
   223  
   224  func _OP_map_key_int() _Op {
   225  	switch _INT_SIZE {
   226  	case 32:
   227  		return _OP_map_key_i32
   228  	case 64:
   229  		return _OP_map_key_i64
   230  	default:
   231  		panic("unsupported int size")
   232  	}
   233  }
   234  
   235  func _OP_map_key_uint() _Op {
   236  	switch _INT_SIZE {
   237  	case 32:
   238  		return _OP_map_key_u32
   239  	case 64:
   240  		return _OP_map_key_u64
   241  	default:
   242  		panic("unsupported uint size")
   243  	}
   244  }
   245  
   246  func _OP_map_key_uintptr() _Op {
   247  	switch _PTR_SIZE {
   248  	case 32:
   249  		return _OP_map_key_u32
   250  	case 64:
   251  		return _OP_map_key_u64
   252  	default:
   253  		panic("unsupported pointer size")
   254  	}
   255  }
   256  
   257  type _Instr struct {
   258  	u uint64         // union {op: 8, vb: 8, vi: 48}, iv maybe int or len([]int)
   259  	p unsafe.Pointer // maybe GoSlice.Data, *GoType or *caching.FieldMap
   260  }
   261  
   262  func packOp(op _Op) uint64 {
   263  	return uint64(op) << 56
   264  }
   265  
   266  func newInsOp(op _Op) _Instr {
   267  	return _Instr{u: packOp(op)}
   268  }
   269  
   270  func newInsVi(op _Op, vi int) _Instr {
   271  	return _Instr{u: packOp(op) | rt.PackInt(vi)}
   272  }
   273  
   274  func newInsVb(op _Op, vb byte) _Instr {
   275  	return _Instr{u: packOp(op) | (uint64(vb) << 48)}
   276  }
   277  
   278  func newInsVs(op _Op, vs []int) _Instr {
   279  	return _Instr{
   280  		u: packOp(op) | rt.PackInt(len(vs)),
   281  		p: (*rt.GoSlice)(unsafe.Pointer(&vs)).Ptr,
   282  	}
   283  }
   284  
   285  func newInsVt(op _Op, vt reflect.Type) _Instr {
   286  	return _Instr{
   287  		u: packOp(op),
   288  		p: unsafe.Pointer(rt.UnpackType(vt)),
   289  	}
   290  }
   291  
   292  func newInsVf(op _Op, vf *caching.FieldMap) _Instr {
   293  	return _Instr{
   294  		u: packOp(op),
   295  		p: unsafe.Pointer(vf),
   296  	}
   297  }
   298  
   299  func (self _Instr) op() _Op {
   300  	return _Op(self.u >> 56)
   301  }
   302  
   303  func (self _Instr) vi() int {
   304  	return rt.UnpackInt(self.u)
   305  }
   306  
   307  func (self _Instr) vb() byte {
   308  	return byte(self.u >> 48)
   309  }
   310  
   311  func (self _Instr) vs() (v []int) {
   312  	(*rt.GoSlice)(unsafe.Pointer(&v)).Ptr = self.p
   313  	(*rt.GoSlice)(unsafe.Pointer(&v)).Cap = self.vi()
   314  	(*rt.GoSlice)(unsafe.Pointer(&v)).Len = self.vi()
   315  	return
   316  }
   317  
   318  func (self _Instr) vf() *caching.FieldMap {
   319  	return (*caching.FieldMap)(self.p)
   320  }
   321  
   322  func (self _Instr) vk() reflect.Kind {
   323  	return (*rt.GoType)(self.p).Kind()
   324  }
   325  
   326  func (self _Instr) vt() reflect.Type {
   327  	return (*rt.GoType)(self.p).Pack()
   328  }
   329  
   330  func (self _Instr) i64() int64 {
   331  	return int64(self.vi())
   332  }
   333  
   334  func (self _Instr) vlen() int {
   335  	return int((*rt.GoType)(self.p).Size)
   336  }
   337  
   338  func (self _Instr) isBranch() bool {
   339  	switch self.op() {
   340  	case _OP_goto:
   341  		fallthrough
   342  	case _OP_switch:
   343  		fallthrough
   344  	case _OP_is_null:
   345  		fallthrough
   346  	case _OP_is_null_quote:
   347  		fallthrough
   348  	case _OP_check_char:
   349  		return true
   350  	default:
   351  		return false
   352  	}
   353  }
   354  
   355  func (self _Instr) disassemble() string {
   356  	switch self.op() {
   357  	case _OP_dyn:
   358  		fallthrough
   359  	case _OP_deref:
   360  		fallthrough
   361  	case _OP_map_key_i8:
   362  		fallthrough
   363  	case _OP_map_key_i16:
   364  		fallthrough
   365  	case _OP_map_key_i32:
   366  		fallthrough
   367  	case _OP_map_key_i64:
   368  		fallthrough
   369  	case _OP_map_key_u8:
   370  		fallthrough
   371  	case _OP_map_key_u16:
   372  		fallthrough
   373  	case _OP_map_key_u32:
   374  		fallthrough
   375  	case _OP_map_key_u64:
   376  		fallthrough
   377  	case _OP_map_key_f32:
   378  		fallthrough
   379  	case _OP_map_key_f64:
   380  		fallthrough
   381  	case _OP_map_key_str:
   382  		fallthrough
   383  	case _OP_map_key_utext:
   384  		fallthrough
   385  	case _OP_map_key_utext_p:
   386  		fallthrough
   387  	case _OP_slice_init:
   388  		fallthrough
   389  	case _OP_slice_append:
   390  		fallthrough
   391  	case _OP_unmarshal:
   392  		fallthrough
   393  	case _OP_unmarshal_p:
   394  		fallthrough
   395  	case _OP_unmarshal_text:
   396  		fallthrough
   397  	case _OP_unmarshal_text_p:
   398  		fallthrough
   399  	case _OP_recurse:
   400  		return fmt.Sprintf("%-18s%s", self.op(), self.vt())
   401  	case _OP_goto:
   402  		fallthrough
   403  	case _OP_is_null_quote:
   404  		fallthrough
   405  	case _OP_is_null:
   406  		return fmt.Sprintf("%-18sL_%d", self.op(), self.vi())
   407  	case _OP_index:
   408  		fallthrough
   409  	case _OP_array_clear:
   410  		fallthrough
   411  	case _OP_array_clear_p:
   412  		return fmt.Sprintf("%-18s%d", self.op(), self.vi())
   413  	case _OP_switch:
   414  		return fmt.Sprintf("%-18s%s", self.op(), self.formatSwitchLabels())
   415  	case _OP_struct_field:
   416  		return fmt.Sprintf("%-18s%s", self.op(), self.formatStructFields())
   417  	case _OP_match_char:
   418  		return fmt.Sprintf("%-18s%s", self.op(), strconv.QuoteRune(rune(self.vb())))
   419  	case _OP_check_char:
   420  		return fmt.Sprintf("%-18sL_%d, %s", self.op(), self.vi(), strconv.QuoteRune(rune(self.vb())))
   421  	default:
   422  		return self.op().String()
   423  	}
   424  }
   425  
   426  func (self _Instr) formatSwitchLabels() string {
   427  	var i int
   428  	var v int
   429  	var m []string
   430  
   431  	/* format each label */
   432  	for i, v = range self.vs() {
   433  		m = append(m, fmt.Sprintf("%d=L_%d", i, v))
   434  	}
   435  
   436  	/* join them with "," */
   437  	return strings.Join(m, ", ")
   438  }
   439  
   440  func (self _Instr) formatStructFields() string {
   441  	var i uint64
   442  	var r []string
   443  	var m []struct {
   444  		i int
   445  		n string
   446  	}
   447  
   448  	/* extract all the fields */
   449  	for i = 0; i < self.vf().N; i++ {
   450  		if v := self.vf().At(i); v.Hash != 0 {
   451  			m = append(m, struct {
   452  				i int
   453  				n string
   454  			}{i: v.ID, n: v.Name})
   455  		}
   456  	}
   457  
   458  	/* sort by field name */
   459  	sort.Slice(m, func(i, j int) bool {
   460  		return m[i].n < m[j].n
   461  	})
   462  
   463  	/* format each field */
   464  	for _, v := range m {
   465  		r = append(r, fmt.Sprintf("%s=%d", v.n, v.i))
   466  	}
   467  
   468  	/* join them with "," */
   469  	return strings.Join(r, ", ")
   470  }
   471  
   472  type (
   473  	_Program []_Instr
   474  )
   475  
   476  func (self _Program) pc() int {
   477  	return len(self)
   478  }
   479  
   480  func (self _Program) tag(n int) {
   481  	if n >= _MaxStack {
   482  		panic("type nesting too deep")
   483  	}
   484  }
   485  
   486  func (self _Program) pin(i int) {
   487  	v := &self[i]
   488  	v.u &= 0xffff000000000000
   489  	v.u |= rt.PackInt(self.pc())
   490  }
   491  
   492  func (self _Program) rel(v []int) {
   493  	for _, i := range v {
   494  		self.pin(i)
   495  	}
   496  }
   497  
   498  func (self *_Program) add(op _Op) {
   499  	*self = append(*self, newInsOp(op))
   500  }
   501  
   502  func (self *_Program) int(op _Op, vi int) {
   503  	*self = append(*self, newInsVi(op, vi))
   504  }
   505  
   506  func (self *_Program) chr(op _Op, vb byte) {
   507  	*self = append(*self, newInsVb(op, vb))
   508  }
   509  
   510  func (self *_Program) tab(op _Op, vs []int) {
   511  	*self = append(*self, newInsVs(op, vs))
   512  }
   513  
   514  func (self *_Program) rtt(op _Op, vt reflect.Type) {
   515  	*self = append(*self, newInsVt(op, vt))
   516  }
   517  
   518  func (self *_Program) fmv(op _Op, vf *caching.FieldMap) {
   519  	*self = append(*self, newInsVf(op, vf))
   520  }
   521  
   522  func (self _Program) disassemble() string {
   523  	nb := len(self)
   524  	tab := make([]bool, nb+1)
   525  	ret := make([]string, 0, nb+1)
   526  
   527  	/* prescan to get all the labels */
   528  	for _, ins := range self {
   529  		if ins.isBranch() {
   530  			if ins.op() != _OP_switch {
   531  				tab[ins.vi()] = true
   532  			} else {
   533  				for _, v := range ins.vs() {
   534  					tab[v] = true
   535  				}
   536  			}
   537  		}
   538  	}
   539  
   540  	/* disassemble each instruction */
   541  	for i, ins := range self {
   542  		if !tab[i] {
   543  			ret = append(ret, "\t"+ins.disassemble())
   544  		} else {
   545  			ret = append(ret, fmt.Sprintf("L_%d:\n\t%s", i, ins.disassemble()))
   546  		}
   547  	}
   548  
   549  	/* add the last label, if needed */
   550  	if tab[nb] {
   551  		ret = append(ret, fmt.Sprintf("L_%d:", nb))
   552  	}
   553  
   554  	/* add an "end" indicator, and join all the strings */
   555  	return strings.Join(append(ret, "\tend"), "\n")
   556  }
   557  
   558  type _Compiler struct {
   559  	opts option.CompileOptions
   560  	tab  map[reflect.Type]bool
   561  	rec  map[reflect.Type]bool
   562  }
   563  
   564  func newCompiler() *_Compiler {
   565  	return &_Compiler{
   566  		opts: option.DefaultCompileOptions(),
   567  		tab:  map[reflect.Type]bool{},
   568  		rec:  map[reflect.Type]bool{},
   569  	}
   570  }
   571  
   572  func (self *_Compiler) apply(opts option.CompileOptions) *_Compiler {
   573  	self.opts = opts
   574  	return self
   575  }
   576  
   577  func (self *_Compiler) rescue(ep *error) {
   578  	if val := recover(); val != nil {
   579  		if err, ok := val.(error); ok {
   580  			*ep = err
   581  		} else {
   582  			panic(val)
   583  		}
   584  	}
   585  }
   586  
   587  func (self *_Compiler) compile(vt reflect.Type) (ret _Program, err error) {
   588  	defer self.rescue(&err)
   589  	self.compileOne(&ret, 0, vt)
   590  	return
   591  }
   592  
   593  func (self *_Compiler) checkMarshaler(p *_Program, vt reflect.Type) bool {
   594  	pt := reflect.PtrTo(vt)
   595  
   596  	/* check for `json.Unmarshaler` with pointer receiver */
   597  	if pt.Implements(jsonUnmarshalerType) {
   598  		p.rtt(_OP_unmarshal_p, pt)
   599  		return true
   600  	}
   601  
   602  	/* check for `json.Unmarshaler` */
   603  	if vt.Implements(jsonUnmarshalerType) {
   604  		p.add(_OP_lspace)
   605  		self.compileUnmarshalJson(p, vt)
   606  		return true
   607  	}
   608  
   609  	/* check for `encoding.TextMarshaler` with pointer receiver */
   610  	if pt.Implements(encodingTextUnmarshalerType) {
   611  		p.add(_OP_lspace)
   612  		self.compileUnmarshalTextPtr(p, pt)
   613  		return true
   614  	}
   615  
   616  	/* check for `encoding.TextUnmarshaler` */
   617  	if vt.Implements(encodingTextUnmarshalerType) {
   618  		p.add(_OP_lspace)
   619  		self.compileUnmarshalText(p, vt)
   620  		return true
   621  	}
   622  	return false
   623  }
   624  
   625  func (self *_Compiler) compileOne(p *_Program, sp int, vt reflect.Type) {
   626  	/* check for recursive nesting */
   627  	ok := self.tab[vt]
   628  	if ok {
   629  		p.rtt(_OP_recurse, vt)
   630  		return
   631  	}
   632  
   633  	if self.checkMarshaler(p, vt) {
   634  		return
   635  	}
   636  
   637  	/* enter the recursion */
   638  	p.add(_OP_lspace)
   639  	self.tab[vt] = true
   640  	self.compileOps(p, sp, vt)
   641  	delete(self.tab, vt)
   642  }
   643  
   644  func (self *_Compiler) compileOps(p *_Program, sp int, vt reflect.Type) {
   645  	switch vt.Kind() {
   646  	case reflect.Bool:
   647  		self.compilePrimitive(vt, p, _OP_bool)
   648  	case reflect.Int:
   649  		self.compilePrimitive(vt, p, _OP_int())
   650  	case reflect.Int8:
   651  		self.compilePrimitive(vt, p, _OP_i8)
   652  	case reflect.Int16:
   653  		self.compilePrimitive(vt, p, _OP_i16)
   654  	case reflect.Int32:
   655  		self.compilePrimitive(vt, p, _OP_i32)
   656  	case reflect.Int64:
   657  		self.compilePrimitive(vt, p, _OP_i64)
   658  	case reflect.Uint:
   659  		self.compilePrimitive(vt, p, _OP_uint())
   660  	case reflect.Uint8:
   661  		self.compilePrimitive(vt, p, _OP_u8)
   662  	case reflect.Uint16:
   663  		self.compilePrimitive(vt, p, _OP_u16)
   664  	case reflect.Uint32:
   665  		self.compilePrimitive(vt, p, _OP_u32)
   666  	case reflect.Uint64:
   667  		self.compilePrimitive(vt, p, _OP_u64)
   668  	case reflect.Uintptr:
   669  		self.compilePrimitive(vt, p, _OP_uintptr())
   670  	case reflect.Float32:
   671  		self.compilePrimitive(vt, p, _OP_f32)
   672  	case reflect.Float64:
   673  		self.compilePrimitive(vt, p, _OP_f64)
   674  	case reflect.String:
   675  		self.compileString(p, vt)
   676  	case reflect.Array:
   677  		self.compileArray(p, sp, vt)
   678  	case reflect.Interface:
   679  		self.compileInterface(p, vt)
   680  	case reflect.Map:
   681  		self.compileMap(p, sp, vt)
   682  	case reflect.Ptr:
   683  		self.compilePtr(p, sp, vt)
   684  	case reflect.Slice:
   685  		self.compileSlice(p, sp, vt)
   686  	case reflect.Struct:
   687  		self.compileStruct(p, sp, vt)
   688  	default:
   689  		panic(&json.UnmarshalTypeError{Type: vt})
   690  	}
   691  }
   692  
   693  func (self *_Compiler) compileMap(p *_Program, sp int, vt reflect.Type) {
   694  	if reflect.PtrTo(vt.Key()).Implements(encodingTextUnmarshalerType) {
   695  		self.compileMapOp(p, sp, vt, _OP_map_key_utext_p)
   696  	} else if vt.Key().Implements(encodingTextUnmarshalerType) {
   697  		self.compileMapOp(p, sp, vt, _OP_map_key_utext)
   698  	} else {
   699  		self.compileMapUt(p, sp, vt)
   700  	}
   701  }
   702  
   703  func (self *_Compiler) compileMapUt(p *_Program, sp int, vt reflect.Type) {
   704  	switch vt.Key().Kind() {
   705  	case reflect.Int:
   706  		self.compileMapOp(p, sp, vt, _OP_map_key_int())
   707  	case reflect.Int8:
   708  		self.compileMapOp(p, sp, vt, _OP_map_key_i8)
   709  	case reflect.Int16:
   710  		self.compileMapOp(p, sp, vt, _OP_map_key_i16)
   711  	case reflect.Int32:
   712  		self.compileMapOp(p, sp, vt, _OP_map_key_i32)
   713  	case reflect.Int64:
   714  		self.compileMapOp(p, sp, vt, _OP_map_key_i64)
   715  	case reflect.Uint:
   716  		self.compileMapOp(p, sp, vt, _OP_map_key_uint())
   717  	case reflect.Uint8:
   718  		self.compileMapOp(p, sp, vt, _OP_map_key_u8)
   719  	case reflect.Uint16:
   720  		self.compileMapOp(p, sp, vt, _OP_map_key_u16)
   721  	case reflect.Uint32:
   722  		self.compileMapOp(p, sp, vt, _OP_map_key_u32)
   723  	case reflect.Uint64:
   724  		self.compileMapOp(p, sp, vt, _OP_map_key_u64)
   725  	case reflect.Uintptr:
   726  		self.compileMapOp(p, sp, vt, _OP_map_key_uintptr())
   727  	case reflect.Float32:
   728  		self.compileMapOp(p, sp, vt, _OP_map_key_f32)
   729  	case reflect.Float64:
   730  		self.compileMapOp(p, sp, vt, _OP_map_key_f64)
   731  	case reflect.String:
   732  		self.compileMapOp(p, sp, vt, _OP_map_key_str)
   733  	default:
   734  		panic(&json.UnmarshalTypeError{Type: vt})
   735  	}
   736  }
   737  
   738  func (self *_Compiler) compileMapOp(p *_Program, sp int, vt reflect.Type, op _Op) {
   739  	i := p.pc()
   740  	p.add(_OP_is_null)
   741  	p.tag(sp + 1)
   742  	skip := self.checkIfSkip(p, vt, '{')
   743  	p.add(_OP_save)
   744  	p.add(_OP_map_init)
   745  	p.add(_OP_save)
   746  	p.add(_OP_lspace)
   747  	j := p.pc()
   748  	p.chr(_OP_check_char, '}')
   749  	p.chr(_OP_match_char, '"')
   750  	skip2 := p.pc()
   751  	p.rtt(op, vt)
   752  
   753  	/* match the value separator */
   754  	p.add(_OP_lspace)
   755  	p.chr(_OP_match_char, ':')
   756  	self.compileOne(p, sp+2, vt.Elem())
   757  	p.pin(skip2)
   758  	p.add(_OP_load)
   759  	k0 := p.pc()
   760  	p.add(_OP_lspace)
   761  	k1 := p.pc()
   762  	p.chr(_OP_check_char, '}')
   763  	p.chr(_OP_match_char, ',')
   764  	p.add(_OP_lspace)
   765  	p.chr(_OP_match_char, '"')
   766  	skip3 := p.pc()
   767  	p.rtt(op, vt)
   768  
   769  	/* match the value separator */
   770  	p.add(_OP_lspace)
   771  	p.chr(_OP_match_char, ':')
   772  	self.compileOne(p, sp+2, vt.Elem())
   773  	p.pin(skip3)
   774  	p.add(_OP_load)
   775  	p.int(_OP_goto, k0)
   776  	p.pin(j)
   777  	p.pin(k1)
   778  	p.add(_OP_drop_2)
   779  	x := p.pc()
   780  	p.add(_OP_goto)
   781  	p.pin(i)
   782  	p.add(_OP_nil_1)
   783  	p.pin(skip)
   784  	p.pin(x)
   785  }
   786  
   787  func (self *_Compiler) compilePtr(p *_Program, sp int, et reflect.Type) {
   788  	i := p.pc()
   789  	p.add(_OP_is_null)
   790  
   791  	/* dereference all the way down */
   792  	for et.Kind() == reflect.Ptr {
   793  		if self.checkMarshaler(p, et) {
   794  			return
   795  		}
   796  		et = et.Elem()
   797  		p.rtt(_OP_deref, et)
   798  	}
   799  
   800  	/* check for recursive nesting */
   801  	ok := self.tab[et]
   802  	if ok {
   803  		p.rtt(_OP_recurse, et)
   804  	} else {
   805  		/* enter the recursion */
   806  		p.add(_OP_lspace)
   807  		self.tab[et] = true
   808  
   809  		/* not inline the pointer type
   810  		 * recursing the defined pointer type's elem will casue issue379.
   811  		 */
   812  		self.compileOps(p, sp, et)
   813  	}
   814  	delete(self.tab, et)
   815  
   816  	j := p.pc()
   817  	p.add(_OP_goto)
   818  
   819  	// set val pointer as nil
   820  	p.pin(i)
   821  	p.add(_OP_nil_1)
   822  
   823  	// nothing todo
   824  	p.pin(j)
   825  }
   826  
   827  func (self *_Compiler) compileArray(p *_Program, sp int, vt reflect.Type) {
   828  	x := p.pc()
   829  	p.add(_OP_is_null)
   830  	p.tag(sp)
   831  	skip := self.checkIfSkip(p, vt, '[')
   832  
   833  	p.add(_OP_save)
   834  	p.add(_OP_lspace)
   835  	v := []int{p.pc()}
   836  	p.chr(_OP_check_char, ']')
   837  
   838  	/* decode every item */
   839  	for i := 1; i <= vt.Len(); i++ {
   840  		self.compileOne(p, sp+1, vt.Elem())
   841  		p.add(_OP_load)
   842  		p.int(_OP_index, i*int(vt.Elem().Size()))
   843  		p.add(_OP_lspace)
   844  		v = append(v, p.pc())
   845  		p.chr(_OP_check_char, ']')
   846  		p.chr(_OP_match_char, ',')
   847  	}
   848  
   849  	/* drop rest of the array */
   850  	p.add(_OP_array_skip)
   851  	w := p.pc()
   852  	p.add(_OP_goto)
   853  	p.rel(v)
   854  
   855  	/* check for pointer data */
   856  	if rt.UnpackType(vt.Elem()).PtrData == 0 {
   857  		p.int(_OP_array_clear, int(vt.Size()))
   858  	} else {
   859  		p.int(_OP_array_clear_p, int(vt.Size()))
   860  	}
   861  
   862  	/* restore the stack */
   863  	p.pin(w)
   864  	p.add(_OP_drop)
   865  
   866  	p.pin(skip)
   867  	p.pin(x)
   868  }
   869  
   870  func (self *_Compiler) compileSlice(p *_Program, sp int, vt reflect.Type) {
   871  	if vt.Elem().Kind() == byteType.Kind() {
   872  		self.compileSliceBin(p, sp, vt)
   873  	} else {
   874  		self.compileSliceList(p, sp, vt)
   875  	}
   876  }
   877  
   878  func (self *_Compiler) compileSliceBin(p *_Program, sp int, vt reflect.Type) {
   879  	i := p.pc()
   880  	p.add(_OP_is_null)
   881  	j := p.pc()
   882  	p.chr(_OP_check_char, '[')
   883  	skip := self.checkIfSkip(p, vt, '"')
   884  	k := p.pc()
   885  	p.chr(_OP_check_char, '"')
   886  	p.add(_OP_bin)
   887  	x := p.pc()
   888  	p.add(_OP_goto)
   889  	p.pin(j)
   890  	self.compileSliceBody(p, sp, vt.Elem())
   891  	y := p.pc()
   892  	p.add(_OP_goto)
   893  	p.pin(i)
   894  	p.pin(k)
   895  	p.add(_OP_nil_3)
   896  	p.pin(x)
   897  	p.pin(skip)
   898  	p.pin(y)
   899  }
   900  
   901  func (self *_Compiler) compileSliceList(p *_Program, sp int, vt reflect.Type) {
   902  	i := p.pc()
   903  	p.add(_OP_is_null)
   904  	p.tag(sp)
   905  	skip := self.checkIfSkip(p, vt, '[')
   906  	self.compileSliceBody(p, sp, vt.Elem())
   907  	x := p.pc()
   908  	p.add(_OP_goto)
   909  	p.pin(i)
   910  	p.add(_OP_nil_3)
   911  	p.pin(x)
   912  	p.pin(skip)
   913  }
   914  
   915  func (self *_Compiler) compileSliceBody(p *_Program, sp int, et reflect.Type) {
   916  	p.add(_OP_lspace)
   917  	j := p.pc()
   918  	p.chr(_OP_check_empty, ']')
   919  	p.rtt(_OP_slice_init, et)
   920  	p.add(_OP_save)
   921  	p.rtt(_OP_slice_append, et)
   922  	self.compileOne(p, sp+1, et)
   923  	p.add(_OP_load)
   924  	k0 := p.pc()
   925  	p.add(_OP_lspace)
   926  	k1 := p.pc()
   927  	p.chr(_OP_check_char, ']')
   928  	p.chr(_OP_match_char, ',')
   929  	p.rtt(_OP_slice_append, et)
   930  	self.compileOne(p, sp+1, et)
   931  	p.add(_OP_load)
   932  	p.int(_OP_goto, k0)
   933  	p.pin(k1)
   934  	p.add(_OP_drop)
   935  	p.pin(j)
   936  }
   937  
   938  func (self *_Compiler) compileString(p *_Program, vt reflect.Type) {
   939  	if vt == jsonNumberType {
   940  		self.compilePrimitive(vt, p, _OP_num)
   941  	} else {
   942  		self.compileStringBody(vt, p)
   943  	}
   944  }
   945  
   946  func (self *_Compiler) compileStringBody(vt reflect.Type, p *_Program) {
   947  	i := p.pc()
   948  	p.add(_OP_is_null)
   949  	skip := self.checkIfSkip(p, vt, '"')
   950  	p.add(_OP_str)
   951  	p.pin(i)
   952  	p.pin(skip)
   953  }
   954  
   955  func (self *_Compiler) compileStruct(p *_Program, sp int, vt reflect.Type) {
   956  	if sp >= self.opts.MaxInlineDepth || p.pc() >= _MAX_ILBUF || (sp > 0 && vt.NumField() >= _MAX_FIELDS) {
   957  		p.rtt(_OP_recurse, vt)
   958  		if self.opts.RecursiveDepth > 0 {
   959  			self.rec[vt] = true
   960  		}
   961  	} else {
   962  		self.compileStructBody(p, sp, vt)
   963  	}
   964  }
   965  
   966  func (self *_Compiler) compileStructBody(p *_Program, sp int, vt reflect.Type) {
   967  	fv := resolver.ResolveStruct(vt)
   968  	fm, sw := caching.CreateFieldMap(len(fv)), make([]int, len(fv))
   969  
   970  	/* start of object */
   971  	p.tag(sp)
   972  	n := p.pc()
   973  	p.add(_OP_is_null)
   974  
   975  	skip := self.checkIfSkip(p, vt, '{')
   976  
   977  	p.add(_OP_save)
   978  	p.add(_OP_lspace)
   979  	x := p.pc()
   980  	p.chr(_OP_check_char, '}')
   981  	p.chr(_OP_match_char, '"')
   982  	p.fmv(_OP_struct_field, fm)
   983  	p.add(_OP_lspace)
   984  	p.chr(_OP_match_char, ':')
   985  	p.tab(_OP_switch, sw)
   986  	p.add(_OP_object_next)
   987  	y0 := p.pc()
   988  	p.add(_OP_lspace)
   989  	y1 := p.pc()
   990  	p.chr(_OP_check_char, '}')
   991  	p.chr(_OP_match_char, ',')
   992  
   993  	/* special case of an empty struct */
   994  	if len(fv) == 0 {
   995  		p.add(_OP_object_skip)
   996  		goto end_of_object
   997  	}
   998  
   999  	/* match the remaining fields */
  1000  	p.add(_OP_lspace)
  1001  	p.chr(_OP_match_char, '"')
  1002  	p.fmv(_OP_struct_field, fm)
  1003  	p.add(_OP_lspace)
  1004  	p.chr(_OP_match_char, ':')
  1005  	p.tab(_OP_switch, sw)
  1006  	p.add(_OP_object_next)
  1007  	p.int(_OP_goto, y0)
  1008  
  1009  	/* process each field */
  1010  	for i, f := range fv {
  1011  		sw[i] = p.pc()
  1012  		fm.Set(f.Name, i)
  1013  
  1014  		/* index to the field */
  1015  		for _, o := range f.Path {
  1016  			if p.int(_OP_index, int(o.Size)); o.Kind == resolver.F_deref {
  1017  				p.rtt(_OP_deref, o.Type)
  1018  			}
  1019  		}
  1020  
  1021  		/* check for "stringnize" option */
  1022  		if (f.Opts & resolver.F_stringize) == 0 {
  1023  			self.compileOne(p, sp+1, f.Type)
  1024  		} else {
  1025  			self.compileStructFieldStr(p, sp+1, f.Type)
  1026  		}
  1027  
  1028  		/* load the state, and try next field */
  1029  		p.add(_OP_load)
  1030  		p.int(_OP_goto, y0)
  1031  	}
  1032  
  1033  end_of_object:
  1034  	p.pin(x)
  1035  	p.pin(y1)
  1036  	p.add(_OP_drop)
  1037  	p.pin(n)
  1038  	p.pin(skip)
  1039  }
  1040  
  1041  func (self *_Compiler) compileStructFieldStr(p *_Program, sp int, vt reflect.Type) {
  1042  	n1 := -1
  1043  	ft := vt
  1044  	sv := false
  1045  
  1046  	/* dereference the pointer if needed */
  1047  	if ft.Kind() == reflect.Ptr {
  1048  		ft = ft.Elem()
  1049  	}
  1050  
  1051  	/* check if it can be stringized */
  1052  	switch ft.Kind() {
  1053  	case reflect.Bool:
  1054  		sv = true
  1055  	case reflect.Int:
  1056  		sv = true
  1057  	case reflect.Int8:
  1058  		sv = true
  1059  	case reflect.Int16:
  1060  		sv = true
  1061  	case reflect.Int32:
  1062  		sv = true
  1063  	case reflect.Int64:
  1064  		sv = true
  1065  	case reflect.Uint:
  1066  		sv = true
  1067  	case reflect.Uint8:
  1068  		sv = true
  1069  	case reflect.Uint16:
  1070  		sv = true
  1071  	case reflect.Uint32:
  1072  		sv = true
  1073  	case reflect.Uint64:
  1074  		sv = true
  1075  	case reflect.Uintptr:
  1076  		sv = true
  1077  	case reflect.Float32:
  1078  		sv = true
  1079  	case reflect.Float64:
  1080  		sv = true
  1081  	case reflect.String:
  1082  		sv = true
  1083  	}
  1084  
  1085  	/* if it's not, ignore the "string" and follow the regular path */
  1086  	if !sv {
  1087  		self.compileOne(p, sp, vt)
  1088  		return
  1089  	}
  1090  
  1091  	/* remove the leading space, and match the leading quote */
  1092  	vk := vt.Kind()
  1093  	p.add(_OP_lspace)
  1094  	n0 := p.pc()
  1095  	p.add(_OP_is_null)
  1096  
  1097  	skip := self.checkIfSkip(p, stringType, '"')
  1098  
  1099  	/* also check for inner "null" */
  1100  	n1 = p.pc()
  1101  	p.add(_OP_is_null_quote)
  1102  
  1103  	/* dereference the pointer only when it is not null */
  1104  	if vk == reflect.Ptr {
  1105  		vt = vt.Elem()
  1106  		p.rtt(_OP_deref, vt)
  1107  	}
  1108  
  1109  	n2 := p.pc()
  1110  	p.chr(_OP_check_char_0, '"')
  1111  
  1112  	/* string opcode selector */
  1113  	_OP_string := func() _Op {
  1114  		if ft == jsonNumberType {
  1115  			return _OP_num
  1116  		} else {
  1117  			return _OP_unquote
  1118  		}
  1119  	}
  1120  
  1121  	/* compile for each type */
  1122  	switch vt.Kind() {
  1123  	case reflect.Bool:
  1124  		p.add(_OP_bool)
  1125  	case reflect.Int:
  1126  		p.add(_OP_int())
  1127  	case reflect.Int8:
  1128  		p.add(_OP_i8)
  1129  	case reflect.Int16:
  1130  		p.add(_OP_i16)
  1131  	case reflect.Int32:
  1132  		p.add(_OP_i32)
  1133  	case reflect.Int64:
  1134  		p.add(_OP_i64)
  1135  	case reflect.Uint:
  1136  		p.add(_OP_uint())
  1137  	case reflect.Uint8:
  1138  		p.add(_OP_u8)
  1139  	case reflect.Uint16:
  1140  		p.add(_OP_u16)
  1141  	case reflect.Uint32:
  1142  		p.add(_OP_u32)
  1143  	case reflect.Uint64:
  1144  		p.add(_OP_u64)
  1145  	case reflect.Uintptr:
  1146  		p.add(_OP_uintptr())
  1147  	case reflect.Float32:
  1148  		p.add(_OP_f32)
  1149  	case reflect.Float64:
  1150  		p.add(_OP_f64)
  1151  	case reflect.String:
  1152  		p.add(_OP_string())
  1153  	default:
  1154  		panic("not reachable")
  1155  	}
  1156  
  1157  	/* the closing quote is not needed when parsing a pure string */
  1158  	if vt == jsonNumberType || vt.Kind() != reflect.String {
  1159  		p.chr(_OP_match_char, '"')
  1160  	}
  1161  
  1162  	/* pin the `is_null_quote` jump location */
  1163  	if n1 != -1 && vk != reflect.Ptr {
  1164  		p.pin(n1)
  1165  	}
  1166  
  1167  	/* "null" but not a pointer, act as if the field is not present */
  1168  	if vk != reflect.Ptr {
  1169  		pc2 := p.pc()
  1170  		p.add(_OP_goto)
  1171  		p.pin(n2)
  1172  		p.rtt(_OP_dismatch_err, vt)
  1173  		p.int(_OP_add, 1)
  1174  		p.pin(pc2)
  1175  		p.pin(n0)
  1176  		return
  1177  	}
  1178  
  1179  	/* the "null" case of the pointer */
  1180  	pc := p.pc()
  1181  	p.add(_OP_goto)
  1182  	p.pin(n0) // `is_null` jump location
  1183  	p.pin(n1) // `is_null_quote` jump location
  1184  	p.add(_OP_nil_1)
  1185  	pc2 := p.pc()
  1186  	p.add(_OP_goto)
  1187  	p.pin(n2)
  1188  	p.rtt(_OP_dismatch_err, vt)
  1189  	p.int(_OP_add, 1)
  1190  	p.pin(pc)
  1191  	p.pin(pc2)
  1192  	p.pin(skip)
  1193  }
  1194  
  1195  func (self *_Compiler) compileInterface(p *_Program, vt reflect.Type) {
  1196  	i := p.pc()
  1197  	p.add(_OP_is_null)
  1198  
  1199  	/* check for empty interface */
  1200  	if vt.NumMethod() == 0 {
  1201  		p.add(_OP_any)
  1202  	} else {
  1203  		p.rtt(_OP_dyn, vt)
  1204  	}
  1205  
  1206  	/* finish the OpCode */
  1207  	j := p.pc()
  1208  	p.add(_OP_goto)
  1209  	p.pin(i)
  1210  	p.add(_OP_nil_2)
  1211  	p.pin(j)
  1212  }
  1213  
  1214  func (self *_Compiler) compilePrimitive(vt reflect.Type, p *_Program, op _Op) {
  1215  	i := p.pc()
  1216  	p.add(_OP_is_null)
  1217  	// skip := self.checkPrimitive(p, vt)
  1218  	p.add(op)
  1219  	p.pin(i)
  1220  	// p.pin(skip)
  1221  }
  1222  
  1223  func (self *_Compiler) compileUnmarshalEnd(p *_Program, vt reflect.Type, i int) {
  1224  	j := p.pc()
  1225  	k := vt.Kind()
  1226  
  1227  	/* not a pointer */
  1228  	if k != reflect.Ptr {
  1229  		p.pin(i)
  1230  		return
  1231  	}
  1232  
  1233  	/* it seems that in Go JSON library, "null" takes priority over any kind of unmarshaler */
  1234  	p.add(_OP_goto)
  1235  	p.pin(i)
  1236  	p.add(_OP_nil_1)
  1237  	p.pin(j)
  1238  }
  1239  
  1240  func (self *_Compiler) compileUnmarshalJson(p *_Program, vt reflect.Type) {
  1241  	i := p.pc()
  1242  	v := _OP_unmarshal
  1243  	p.add(_OP_is_null)
  1244  
  1245  	/* check for dynamic interface */
  1246  	if vt.Kind() == reflect.Interface {
  1247  		v = _OP_dyn
  1248  	}
  1249  
  1250  	/* call the unmarshaler */
  1251  	p.rtt(v, vt)
  1252  	self.compileUnmarshalEnd(p, vt, i)
  1253  }
  1254  
  1255  func (self *_Compiler) compileUnmarshalText(p *_Program, vt reflect.Type) {
  1256  	i := p.pc()
  1257  	v := _OP_unmarshal_text
  1258  	p.add(_OP_is_null)
  1259  
  1260  	/* check for dynamic interface */
  1261  	if vt.Kind() == reflect.Interface {
  1262  		v = _OP_dyn
  1263  	} else {
  1264  		p.chr(_OP_match_char, '"')
  1265  	}
  1266  
  1267  	/* call the unmarshaler */
  1268  	p.rtt(v, vt)
  1269  	self.compileUnmarshalEnd(p, vt, i)
  1270  }
  1271  
  1272  func (self *_Compiler) compileUnmarshalTextPtr(p *_Program, vt reflect.Type) {
  1273  	i := p.pc()
  1274  	p.add(_OP_is_null)
  1275  	p.chr(_OP_match_char, '"')
  1276  	p.rtt(_OP_unmarshal_text_p, vt)
  1277  	p.pin(i)
  1278  }
  1279  
  1280  func (self *_Compiler) checkIfSkip(p *_Program, vt reflect.Type, c byte) int {
  1281  	j := p.pc()
  1282  	p.chr(_OP_check_char_0, c)
  1283  	p.rtt(_OP_dismatch_err, vt)
  1284  	s := p.pc()
  1285  	p.add(_OP_go_skip)
  1286  	p.pin(j)
  1287  	p.int(_OP_add, 1)
  1288  	return s
  1289  }