gtsocial-umbx

Unnamed repository; edit this file 'description' to name the repository.
Log | Files | Refs | README | LICENSE

compiler.go (31062B)


      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/bytedance/sonic/internal/caching`
     29     `github.com/bytedance/sonic/internal/resolver`
     30     `github.com/bytedance/sonic/internal/rt`
     31     `github.com/bytedance/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: return _OP_i32
    194         case 64: return _OP_i64
    195         default: panic("unsupported int size")
    196     }
    197 }
    198 
    199 func _OP_uint() _Op {
    200     switch _INT_SIZE {
    201         case 32: return _OP_u32
    202         case 64: return _OP_u64
    203         default: panic("unsupported uint size")
    204     }
    205 }
    206 
    207 func _OP_uintptr() _Op {
    208     switch _PTR_SIZE {
    209         case 32: return _OP_u32
    210         case 64: return _OP_u64
    211         default: panic("unsupported pointer size")
    212     }
    213 }
    214 
    215 func _OP_map_key_int() _Op {
    216     switch _INT_SIZE {
    217         case 32: return _OP_map_key_i32
    218         case 64: return _OP_map_key_i64
    219         default: panic("unsupported int size")
    220     }
    221 }
    222 
    223 func _OP_map_key_uint() _Op {
    224     switch _INT_SIZE {
    225         case 32: return _OP_map_key_u32
    226         case 64: return _OP_map_key_u64
    227         default: panic("unsupported uint size")
    228     }
    229 }
    230 
    231 func _OP_map_key_uintptr() _Op {
    232     switch _PTR_SIZE {
    233         case 32: return _OP_map_key_u32
    234         case 64: return _OP_map_key_u64
    235         default: panic("unsupported pointer size")
    236     }
    237 }
    238 
    239 type _Instr struct {
    240     u uint64            // union {op: 8, vb: 8, vi: 48}, iv maybe int or len([]int)
    241     p unsafe.Pointer    // maybe GoSlice.Data, *GoType or *caching.FieldMap
    242 }
    243 
    244 func packOp(op _Op) uint64 {
    245     return uint64(op) << 56
    246 }
    247 
    248 func newInsOp(op _Op) _Instr {
    249     return _Instr{u: packOp(op)}
    250 }
    251 
    252 func newInsVi(op _Op, vi int) _Instr {
    253     return _Instr{u: packOp(op) | rt.PackInt(vi)}
    254 }
    255 
    256 func newInsVb(op _Op, vb byte) _Instr {
    257     return _Instr{u: packOp(op) | (uint64(vb) << 48)}
    258 }
    259 
    260 func newInsVs(op _Op, vs []int) _Instr {
    261     return _Instr {
    262         u: packOp(op) | rt.PackInt(len(vs)),
    263         p: (*rt.GoSlice)(unsafe.Pointer(&vs)).Ptr,
    264     }
    265 }
    266 
    267 func newInsVt(op _Op, vt reflect.Type) _Instr {
    268     return _Instr {
    269         u: packOp(op),
    270         p: unsafe.Pointer(rt.UnpackType(vt)),
    271     }
    272 }
    273 
    274 func newInsVf(op _Op, vf *caching.FieldMap) _Instr {
    275     return _Instr {
    276         u: packOp(op),
    277         p: unsafe.Pointer(vf),
    278     }
    279 }
    280 
    281 func (self _Instr) op() _Op {
    282     return _Op(self.u >> 56)
    283 }
    284 
    285 func (self _Instr) vi() int {
    286     return rt.UnpackInt(self.u)
    287 }
    288 
    289 func (self _Instr) vb() byte {
    290     return byte(self.u >> 48)
    291 }
    292 
    293 func (self _Instr) vs() (v []int) {
    294     (*rt.GoSlice)(unsafe.Pointer(&v)).Ptr = self.p
    295     (*rt.GoSlice)(unsafe.Pointer(&v)).Cap = self.vi()
    296     (*rt.GoSlice)(unsafe.Pointer(&v)).Len = self.vi()
    297     return
    298 }
    299 
    300 func (self _Instr) vf() *caching.FieldMap {
    301     return (*caching.FieldMap)(self.p)
    302 }
    303 
    304 func (self _Instr) vk() reflect.Kind {
    305     return (*rt.GoType)(self.p).Kind()
    306 }
    307 
    308 func (self _Instr) vt() reflect.Type {
    309     return (*rt.GoType)(self.p).Pack()
    310 }
    311 
    312 func (self _Instr) i64() int64 {
    313     return int64(self.vi())
    314 }
    315 
    316 func (self _Instr) vlen() int {
    317     return int((*rt.GoType)(self.p).Size)
    318 }
    319 
    320 func (self _Instr) isBranch() bool {
    321     switch self.op() {
    322         case _OP_goto          : fallthrough
    323         case _OP_switch        : fallthrough
    324         case _OP_is_null       : fallthrough
    325         case _OP_is_null_quote : fallthrough
    326         case _OP_check_char    : return true
    327         default                : return false
    328     }
    329 }
    330 
    331 func (self _Instr) disassemble() string {
    332     switch self.op() {
    333         case _OP_dyn              : fallthrough
    334         case _OP_deref            : fallthrough
    335         case _OP_map_key_i8       : fallthrough
    336         case _OP_map_key_i16      : fallthrough
    337         case _OP_map_key_i32      : fallthrough
    338         case _OP_map_key_i64      : fallthrough
    339         case _OP_map_key_u8       : fallthrough
    340         case _OP_map_key_u16      : fallthrough
    341         case _OP_map_key_u32      : fallthrough
    342         case _OP_map_key_u64      : fallthrough
    343         case _OP_map_key_f32      : fallthrough
    344         case _OP_map_key_f64      : fallthrough
    345         case _OP_map_key_str      : fallthrough
    346         case _OP_map_key_utext    : fallthrough
    347         case _OP_map_key_utext_p  : fallthrough
    348         case _OP_slice_init       : fallthrough
    349         case _OP_slice_append     : fallthrough
    350         case _OP_unmarshal        : fallthrough
    351         case _OP_unmarshal_p      : fallthrough
    352         case _OP_unmarshal_text   : fallthrough
    353         case _OP_unmarshal_text_p : fallthrough
    354         case _OP_recurse          : return fmt.Sprintf("%-18s%s", self.op(), self.vt())
    355         case _OP_goto             : fallthrough
    356         case _OP_is_null_quote    : fallthrough
    357         case _OP_is_null          : return fmt.Sprintf("%-18sL_%d", self.op(), self.vi())
    358         case _OP_index            : fallthrough
    359         case _OP_array_clear      : fallthrough
    360         case _OP_array_clear_p    : return fmt.Sprintf("%-18s%d", self.op(), self.vi())
    361         case _OP_switch           : return fmt.Sprintf("%-18s%s", self.op(), self.formatSwitchLabels())
    362         case _OP_struct_field     : return fmt.Sprintf("%-18s%s", self.op(), self.formatStructFields())
    363         case _OP_match_char       : return fmt.Sprintf("%-18s%s", self.op(), strconv.QuoteRune(rune(self.vb())))
    364         case _OP_check_char       : return fmt.Sprintf("%-18sL_%d, %s", self.op(), self.vi(), strconv.QuoteRune(rune(self.vb())))
    365         default                   : return self.op().String()
    366     }
    367 }
    368 
    369 func (self _Instr) formatSwitchLabels() string {
    370     var i int
    371     var v int
    372     var m []string
    373 
    374     /* format each label */
    375     for i, v = range self.vs() {
    376         m = append(m, fmt.Sprintf("%d=L_%d", i, v))
    377     }
    378 
    379     /* join them with "," */
    380     return strings.Join(m, ", ")
    381 }
    382 
    383 func (self _Instr) formatStructFields() string {
    384     var i uint64
    385     var r []string
    386     var m []struct{i int; n string}
    387 
    388     /* extract all the fields */
    389     for i = 0; i < self.vf().N; i++ {
    390         if v := self.vf().At(i); v.Hash != 0 {
    391             m = append(m, struct{i int; n string}{i: v.ID, n: v.Name})
    392         }
    393     }
    394 
    395     /* sort by field name */
    396     sort.Slice(m, func(i, j int) bool {
    397         return m[i].n < m[j].n
    398     })
    399 
    400     /* format each field */
    401     for _, v := range m {
    402         r = append(r, fmt.Sprintf("%s=%d", v.n, v.i))
    403     }
    404 
    405     /* join them with "," */
    406     return strings.Join(r, ", ")
    407 }
    408 
    409 type (
    410     _Program []_Instr
    411 )
    412 
    413 func (self _Program) pc() int {
    414     return len(self)
    415 }
    416 
    417 func (self _Program) tag(n int) {
    418     if n >= _MaxStack {
    419         panic("type nesting too deep")
    420     }
    421 }
    422 
    423 func (self _Program) pin(i int) {
    424     v := &self[i]
    425     v.u &= 0xffff000000000000
    426     v.u |= rt.PackInt(self.pc())
    427 }
    428 
    429 func (self _Program) rel(v []int) {
    430     for _, i := range v {
    431         self.pin(i)
    432     }
    433 }
    434 
    435 func (self *_Program) add(op _Op) {
    436     *self = append(*self, newInsOp(op))
    437 }
    438 
    439 func (self *_Program) int(op _Op, vi int) {
    440     *self = append(*self, newInsVi(op, vi))
    441 }
    442 
    443 func (self *_Program) chr(op _Op, vb byte) {
    444     *self = append(*self, newInsVb(op, vb))
    445 }
    446 
    447 func (self *_Program) tab(op _Op, vs []int) {
    448     *self = append(*self, newInsVs(op, vs))
    449 }
    450 
    451 func (self *_Program) rtt(op _Op, vt reflect.Type) {
    452     *self = append(*self, newInsVt(op, vt))
    453 }
    454 
    455 func (self *_Program) fmv(op _Op, vf *caching.FieldMap) {
    456     *self = append(*self, newInsVf(op, vf))
    457 }
    458 
    459 func (self _Program) disassemble() string {
    460     nb  := len(self)
    461     tab := make([]bool, nb + 1)
    462     ret := make([]string, 0, nb + 1)
    463 
    464     /* prescan to get all the labels */
    465     for _, ins := range self {
    466         if ins.isBranch() {
    467             if ins.op() != _OP_switch {
    468                 tab[ins.vi()] = true
    469             } else {
    470                 for _, v := range ins.vs() {
    471                     tab[v] = true
    472                 }
    473             }
    474         }
    475     }
    476 
    477     /* disassemble each instruction */
    478     for i, ins := range self {
    479         if !tab[i] {
    480             ret = append(ret, "\t" + ins.disassemble())
    481         } else {
    482             ret = append(ret, fmt.Sprintf("L_%d:\n\t%s", i, ins.disassemble()))
    483         }
    484     }
    485 
    486     /* add the last label, if needed */
    487     if tab[nb] {
    488         ret = append(ret, fmt.Sprintf("L_%d:", nb))
    489     }
    490 
    491     /* add an "end" indicator, and join all the strings */
    492     return strings.Join(append(ret, "\tend"), "\n")
    493 }
    494 
    495 type _Compiler struct {
    496     opts option.CompileOptions
    497     tab  map[reflect.Type]bool
    498     rec  map[reflect.Type]bool
    499 }
    500 
    501 func newCompiler() *_Compiler {
    502     return &_Compiler {
    503         opts: option.DefaultCompileOptions(),
    504         tab: map[reflect.Type]bool{},
    505         rec: map[reflect.Type]bool{},
    506     }
    507 }
    508 
    509 func (self *_Compiler) apply(opts option.CompileOptions) *_Compiler {
    510     self.opts = opts
    511     return self
    512 }
    513 
    514 func (self *_Compiler) rescue(ep *error) {
    515     if val := recover(); val != nil {
    516         if err, ok := val.(error); ok {
    517             *ep = err
    518         } else {
    519             panic(val)
    520         }
    521     }
    522 }
    523 
    524 func (self *_Compiler) compile(vt reflect.Type) (ret _Program, err error) {
    525     defer self.rescue(&err)
    526     self.compileOne(&ret, 0, vt)
    527     return
    528 }
    529 
    530 func (self *_Compiler) compileOne(p *_Program, sp int, vt reflect.Type) {
    531     /* check for recursive nesting */
    532     ok := self.tab[vt]
    533     if ok {
    534         p.rtt(_OP_recurse, vt)
    535         return
    536     }
    537 
    538     pt := reflect.PtrTo(vt)
    539 
    540     /* check for `json.Unmarshaler` with pointer receiver */
    541     if pt.Implements(jsonUnmarshalerType) {
    542         p.rtt(_OP_unmarshal_p, pt)
    543         return
    544     }
    545 
    546     /* check for `json.Unmarshaler` */
    547     if vt.Implements(jsonUnmarshalerType) {
    548         p.add(_OP_lspace)
    549         self.compileUnmarshalJson(p, vt)
    550         return
    551     }
    552 
    553     /* check for `encoding.TextMarshaler` with pointer receiver */
    554     if pt.Implements(encodingTextUnmarshalerType) {
    555         p.add(_OP_lspace)
    556         self.compileUnmarshalTextPtr(p, pt)
    557         return
    558     }
    559 
    560     /* check for `encoding.TextUnmarshaler` */
    561     if vt.Implements(encodingTextUnmarshalerType) {
    562         p.add(_OP_lspace)
    563         self.compileUnmarshalText(p, vt)
    564         return
    565     }
    566 
    567     /* enter the recursion */
    568     p.add(_OP_lspace)
    569     self.tab[vt] = true
    570     self.compileOps(p, sp, vt)
    571     delete(self.tab, vt)
    572 }
    573 
    574 func (self *_Compiler) compileOps(p *_Program, sp int, vt reflect.Type) {
    575     switch vt.Kind() {
    576         case reflect.Bool      : self.compilePrimitive (vt, p, _OP_bool)
    577         case reflect.Int       : self.compilePrimitive (vt, p, _OP_int())
    578         case reflect.Int8      : self.compilePrimitive (vt, p, _OP_i8)
    579         case reflect.Int16     : self.compilePrimitive (vt, p, _OP_i16)
    580         case reflect.Int32     : self.compilePrimitive (vt, p, _OP_i32)
    581         case reflect.Int64     : self.compilePrimitive (vt, p, _OP_i64)
    582         case reflect.Uint      : self.compilePrimitive (vt, p, _OP_uint())
    583         case reflect.Uint8     : self.compilePrimitive (vt, p, _OP_u8)
    584         case reflect.Uint16    : self.compilePrimitive (vt, p, _OP_u16)
    585         case reflect.Uint32    : self.compilePrimitive (vt, p, _OP_u32)
    586         case reflect.Uint64    : self.compilePrimitive (vt, p, _OP_u64)
    587         case reflect.Uintptr   : self.compilePrimitive (vt, p, _OP_uintptr())
    588         case reflect.Float32   : self.compilePrimitive (vt, p, _OP_f32)
    589         case reflect.Float64   : self.compilePrimitive (vt, p, _OP_f64)
    590         case reflect.String    : self.compileString    (p, vt)
    591         case reflect.Array     : self.compileArray     (p, sp, vt)
    592         case reflect.Interface : self.compileInterface (p, vt)
    593         case reflect.Map       : self.compileMap       (p, sp, vt)
    594         case reflect.Ptr       : self.compilePtr       (p, sp, vt)
    595         case reflect.Slice     : self.compileSlice     (p, sp, vt)
    596         case reflect.Struct    : self.compileStruct    (p, sp, vt)
    597         default                : panic                 (&json.UnmarshalTypeError{Type: vt})
    598     }
    599 }
    600 
    601 func (self *_Compiler) compileMap(p *_Program, sp int, vt reflect.Type) {
    602     if reflect.PtrTo(vt.Key()).Implements(encodingTextUnmarshalerType) {
    603         self.compileMapOp(p, sp, vt, _OP_map_key_utext_p)
    604     } else if vt.Key().Implements(encodingTextUnmarshalerType) {
    605         self.compileMapOp(p, sp, vt, _OP_map_key_utext)
    606     } else {
    607         self.compileMapUt(p, sp, vt)
    608     }
    609 }
    610 
    611 func (self *_Compiler) compileMapUt(p *_Program, sp int, vt reflect.Type) {
    612     switch vt.Key().Kind() {
    613         case reflect.Int     : self.compileMapOp(p, sp, vt, _OP_map_key_int())
    614         case reflect.Int8    : self.compileMapOp(p, sp, vt, _OP_map_key_i8)
    615         case reflect.Int16   : self.compileMapOp(p, sp, vt, _OP_map_key_i16)
    616         case reflect.Int32   : self.compileMapOp(p, sp, vt, _OP_map_key_i32)
    617         case reflect.Int64   : self.compileMapOp(p, sp, vt, _OP_map_key_i64)
    618         case reflect.Uint    : self.compileMapOp(p, sp, vt, _OP_map_key_uint())
    619         case reflect.Uint8   : self.compileMapOp(p, sp, vt, _OP_map_key_u8)
    620         case reflect.Uint16  : self.compileMapOp(p, sp, vt, _OP_map_key_u16)
    621         case reflect.Uint32  : self.compileMapOp(p, sp, vt, _OP_map_key_u32)
    622         case reflect.Uint64  : self.compileMapOp(p, sp, vt, _OP_map_key_u64)
    623         case reflect.Uintptr : self.compileMapOp(p, sp, vt, _OP_map_key_uintptr())
    624         case reflect.Float32 : self.compileMapOp(p, sp, vt, _OP_map_key_f32)
    625         case reflect.Float64 : self.compileMapOp(p, sp, vt, _OP_map_key_f64)
    626         case reflect.String  : self.compileMapOp(p, sp, vt, _OP_map_key_str)
    627         default              : panic(&json.UnmarshalTypeError{Type: vt})
    628     }
    629 }
    630 
    631 func (self *_Compiler) compileMapOp(p *_Program, sp int, vt reflect.Type, op _Op) {
    632     i := p.pc()
    633     p.add(_OP_is_null)
    634     p.tag(sp + 1)
    635     skip := self.checkIfSkip(p, vt, '{')
    636     p.add(_OP_save)
    637     p.add(_OP_map_init)
    638     p.add(_OP_save)
    639     p.add(_OP_lspace)
    640     j := p.pc()
    641     p.chr(_OP_check_char, '}')
    642     p.chr(_OP_match_char, '"')
    643     skip2 := p.pc()
    644     p.rtt(op, vt)
    645 
    646     /* match the value separator */
    647     p.add(_OP_lspace)
    648     p.chr(_OP_match_char, ':')
    649     self.compileOne(p, sp + 2, vt.Elem())
    650     p.pin(skip2)
    651     p.add(_OP_load)
    652     k0 := p.pc()
    653     p.add(_OP_lspace)
    654     k1 := p.pc()
    655     p.chr(_OP_check_char, '}')
    656     p.chr(_OP_match_char, ',')
    657     p.add(_OP_lspace)
    658     p.chr(_OP_match_char, '"')
    659     skip3 := p.pc()
    660     p.rtt(op, vt)
    661 
    662     /* match the value separator */
    663     p.add(_OP_lspace)
    664     p.chr(_OP_match_char, ':')
    665     self.compileOne(p, sp + 2, vt.Elem())
    666     p.pin(skip3)
    667     p.add(_OP_load)
    668     p.int(_OP_goto, k0)
    669     p.pin(j)
    670     p.pin(k1)
    671     p.add(_OP_drop_2)
    672     x := p.pc()
    673     p.add(_OP_goto)
    674     p.pin(i)
    675     p.add(_OP_nil_1)
    676     p.pin(skip)
    677     p.pin(x)
    678 }
    679 
    680 func (self *_Compiler) compilePtr(p *_Program, sp int, et reflect.Type) {
    681     i := p.pc()
    682     p.add(_OP_is_null)
    683 
    684     /* dereference all the way down */
    685     for et.Kind() == reflect.Ptr {
    686         if et.Implements(jsonUnmarshalerType) {
    687             p.rtt(_OP_unmarshal_p, et)
    688             return
    689         }
    690 
    691         if et.Implements(encodingTextUnmarshalerType) {
    692             p.add(_OP_lspace)
    693             self.compileUnmarshalTextPtr(p, et)
    694             return
    695         }
    696 
    697         et = et.Elem()
    698         p.rtt(_OP_deref, et)
    699     }
    700 
    701     /* check for recursive nesting */
    702     ok := self.tab[et]
    703     if ok {
    704         p.rtt(_OP_recurse, et)
    705     } else {
    706         /* enter the recursion */
    707         p.add(_OP_lspace)
    708         self.tab[et] = true
    709         
    710         /* not inline the pointer type
    711         * recursing the defined pointer type's elem will casue issue379.
    712         */
    713         self.compileOps(p, sp, et)
    714     }
    715     delete(self.tab, et)
    716 
    717     j := p.pc()
    718     p.add(_OP_goto)
    719     p.pin(i)
    720     p.add(_OP_nil_1)
    721     p.pin(j)
    722 }
    723 
    724 func (self *_Compiler) compileArray(p *_Program, sp int, vt reflect.Type) {
    725     x := p.pc()
    726     p.add(_OP_is_null)
    727     p.tag(sp)
    728     skip := self.checkIfSkip(p, vt, '[')
    729     
    730     p.add(_OP_save)
    731     p.add(_OP_lspace)
    732     v := []int{p.pc()}
    733     p.chr(_OP_check_char, ']')
    734 
    735     /* decode every item */
    736     for i := 1; i <= vt.Len(); i++ {
    737         self.compileOne(p, sp + 1, vt.Elem())
    738         p.add(_OP_load)
    739         p.int(_OP_index, i * int(vt.Elem().Size()))
    740         p.add(_OP_lspace)
    741         v = append(v, p.pc())
    742         p.chr(_OP_check_char, ']')
    743         p.chr(_OP_match_char, ',')
    744     }
    745 
    746     /* drop rest of the array */
    747     p.add(_OP_array_skip)
    748     w := p.pc()
    749     p.add(_OP_goto)
    750     p.rel(v)
    751 
    752     /* check for pointer data */
    753     if rt.UnpackType(vt.Elem()).PtrData == 0 {
    754         p.int(_OP_array_clear, int(vt.Size()))
    755     } else {
    756         p.int(_OP_array_clear_p, int(vt.Size()))
    757     }
    758 
    759     /* restore the stack */
    760     p.pin(w)
    761     p.add(_OP_drop)
    762 
    763     p.pin(skip)
    764     p.pin(x)
    765 }
    766 
    767 func (self *_Compiler) compileSlice(p *_Program, sp int, vt reflect.Type) {
    768     if vt.Elem().Kind() == byteType.Kind() {
    769         self.compileSliceBin(p, sp, vt)
    770     } else {
    771         self.compileSliceList(p, sp, vt)
    772     }
    773 }
    774 
    775 func (self *_Compiler) compileSliceBin(p *_Program, sp int, vt reflect.Type) {
    776     i := p.pc()
    777     p.add(_OP_is_null)
    778     j := p.pc()
    779     p.chr(_OP_check_char, '[')
    780     skip := self.checkIfSkip(p, vt, '"')
    781     k := p.pc()
    782     p.chr(_OP_check_char, '"')
    783     p.add(_OP_bin)
    784     x := p.pc()
    785     p.add(_OP_goto)
    786     p.pin(j)
    787     self.compileSliceBody(p, sp, vt.Elem())
    788     y := p.pc()
    789     p.add(_OP_goto)
    790     p.pin(i)
    791     p.pin(k)
    792     p.add(_OP_nil_3)
    793     p.pin(x)
    794     p.pin(skip)
    795     p.pin(y)
    796 }
    797 
    798 func (self *_Compiler) compileSliceList(p *_Program, sp int, vt reflect.Type) {
    799     i := p.pc()
    800     p.add(_OP_is_null)
    801     p.tag(sp)
    802     skip := self.checkIfSkip(p, vt, '[')
    803     self.compileSliceBody(p, sp, vt.Elem())
    804     x := p.pc()
    805     p.add(_OP_goto)
    806     p.pin(i)
    807     p.add(_OP_nil_3)
    808     p.pin(x)
    809     p.pin(skip)
    810 }
    811 
    812 func (self *_Compiler) compileSliceBody(p *_Program, sp int, et reflect.Type) {
    813     p.add(_OP_lspace)
    814     j := p.pc()
    815     p.chr(_OP_check_empty, ']')
    816     p.rtt(_OP_slice_init, et)
    817     p.add(_OP_save)
    818     p.rtt(_OP_slice_append, et)
    819     self.compileOne(p, sp + 1, et)
    820     p.add(_OP_load)
    821     k0 := p.pc()
    822     p.add(_OP_lspace)
    823     k1 := p.pc()
    824     p.chr(_OP_check_char, ']')
    825     p.chr(_OP_match_char, ',')
    826     p.rtt(_OP_slice_append, et)
    827     self.compileOne(p, sp + 1, et)
    828     p.add(_OP_load)
    829     p.int(_OP_goto, k0)
    830     p.pin(k1)
    831     p.add(_OP_drop)
    832     p.pin(j)
    833 }
    834 
    835 func (self *_Compiler) compileString(p *_Program, vt reflect.Type) {
    836     if vt == jsonNumberType {
    837         self.compilePrimitive(vt, p, _OP_num)
    838     } else {
    839         self.compileStringBody(vt, p)
    840     }
    841 }
    842 
    843 func (self *_Compiler) compileStringBody(vt reflect.Type, p *_Program) {
    844     i := p.pc()
    845     p.add(_OP_is_null)
    846     skip := self.checkIfSkip(p, vt, '"')
    847     p.add(_OP_str)
    848     p.pin(i)
    849     p.pin(skip)
    850 }
    851 
    852 func (self *_Compiler) compileStruct(p *_Program, sp int, vt reflect.Type) {
    853     if sp >= self.opts.MaxInlineDepth || p.pc() >= _MAX_ILBUF || (sp > 0 && vt.NumField() >= _MAX_FIELDS) {
    854         p.rtt(_OP_recurse, vt)
    855         if self.opts.RecursiveDepth > 0 {
    856             self.rec[vt] = true
    857         }
    858     } else {
    859         self.compileStructBody(p, sp, vt)
    860     }
    861 }
    862 
    863 func (self *_Compiler) compileStructBody(p *_Program, sp int, vt reflect.Type) {
    864     fv := resolver.ResolveStruct(vt)
    865     fm, sw := caching.CreateFieldMap(len(fv)), make([]int, len(fv))
    866 
    867     /* start of object */
    868     p.tag(sp)
    869     n := p.pc()
    870     p.add(_OP_is_null)
    871 
    872     skip := self.checkIfSkip(p, vt, '{')
    873     
    874     p.add(_OP_save)
    875     p.add(_OP_lspace)
    876     x := p.pc()
    877     p.chr(_OP_check_char, '}')
    878     p.chr(_OP_match_char, '"')
    879     p.fmv(_OP_struct_field, fm)
    880     p.add(_OP_lspace)
    881     p.chr(_OP_match_char, ':')
    882     p.tab(_OP_switch, sw)
    883     p.add(_OP_object_next)
    884     y0 := p.pc()
    885     p.add(_OP_lspace)
    886     y1 := p.pc()
    887     p.chr(_OP_check_char, '}')
    888     p.chr(_OP_match_char, ',')
    889 
    890     /* special case of an empty struct */
    891     if len(fv) == 0 {
    892         p.add(_OP_object_skip)
    893         goto end_of_object
    894     }
    895 
    896     /* match the remaining fields */
    897     p.add(_OP_lspace)
    898     p.chr(_OP_match_char, '"')
    899     p.fmv(_OP_struct_field, fm)
    900     p.add(_OP_lspace)
    901     p.chr(_OP_match_char, ':')
    902     p.tab(_OP_switch, sw)
    903     p.add(_OP_object_next)
    904     p.int(_OP_goto, y0)
    905 
    906     /* process each field */
    907     for i, f := range fv {
    908         sw[i] = p.pc()
    909         fm.Set(f.Name, i)
    910 
    911         /* index to the field */
    912         for _, o := range f.Path {
    913             if p.int(_OP_index, int(o.Size)); o.Kind == resolver.F_deref {
    914                 p.rtt(_OP_deref, o.Type)
    915             }
    916         }
    917 
    918         /* check for "stringnize" option */
    919         if (f.Opts & resolver.F_stringize) == 0 {
    920             self.compileOne(p, sp + 1, f.Type)
    921         } else {
    922             self.compileStructFieldStr(p, sp + 1, f.Type)
    923         }
    924 
    925         /* load the state, and try next field */
    926         p.add(_OP_load)
    927         p.int(_OP_goto, y0)
    928     }
    929 
    930 end_of_object:
    931     p.pin(x)
    932     p.pin(y1)
    933     p.add(_OP_drop)
    934     p.pin(n)
    935     p.pin(skip)
    936 }
    937 
    938 func (self *_Compiler) compileStructFieldStr(p *_Program, sp int, vt reflect.Type) {
    939     n1 := -1
    940     ft := vt
    941     sv := false
    942 
    943     /* dereference the pointer if needed */
    944     if ft.Kind() == reflect.Ptr {
    945         ft = ft.Elem()
    946     }
    947 
    948     /* check if it can be stringized */
    949     switch ft.Kind() {
    950         case reflect.Bool    : sv = true
    951         case reflect.Int     : sv = true
    952         case reflect.Int8    : sv = true
    953         case reflect.Int16   : sv = true
    954         case reflect.Int32   : sv = true
    955         case reflect.Int64   : sv = true
    956         case reflect.Uint    : sv = true
    957         case reflect.Uint8   : sv = true
    958         case reflect.Uint16  : sv = true
    959         case reflect.Uint32  : sv = true
    960         case reflect.Uint64  : sv = true
    961         case reflect.Uintptr : sv = true
    962         case reflect.Float32 : sv = true
    963         case reflect.Float64 : sv = true
    964         case reflect.String  : sv = true
    965     }
    966 
    967     /* if it's not, ignore the "string" and follow the regular path */
    968     if !sv {
    969         self.compileOne(p, sp, vt)
    970         return
    971     }
    972 
    973     /* remove the leading space, and match the leading quote */
    974     vk := vt.Kind()
    975     p.add(_OP_lspace)
    976     n0 := p.pc()
    977     p.add(_OP_is_null)
    978     
    979     skip := self.checkIfSkip(p, stringType, '"')
    980 
    981     /* also check for inner "null" */
    982     n1 = p.pc()
    983     p.add(_OP_is_null_quote)
    984 
    985     /* dereference the pointer only when it is not null */
    986     if vk == reflect.Ptr {
    987         vt = vt.Elem()
    988         p.rtt(_OP_deref, vt)
    989     }
    990 
    991     n2 := p.pc()
    992     p.chr(_OP_check_char_0, '"')
    993 
    994     /* string opcode selector */
    995     _OP_string := func() _Op {
    996         if ft == jsonNumberType {
    997             return _OP_num
    998         } else {
    999             return _OP_unquote
   1000         }
   1001     }
   1002 
   1003     /* compile for each type */
   1004     switch vt.Kind() {
   1005         case reflect.Bool    : p.add(_OP_bool)
   1006         case reflect.Int     : p.add(_OP_int())
   1007         case reflect.Int8    : p.add(_OP_i8)
   1008         case reflect.Int16   : p.add(_OP_i16)
   1009         case reflect.Int32   : p.add(_OP_i32)
   1010         case reflect.Int64   : p.add(_OP_i64)
   1011         case reflect.Uint    : p.add(_OP_uint())
   1012         case reflect.Uint8   : p.add(_OP_u8)
   1013         case reflect.Uint16  : p.add(_OP_u16)
   1014         case reflect.Uint32  : p.add(_OP_u32)
   1015         case reflect.Uint64  : p.add(_OP_u64)
   1016         case reflect.Uintptr : p.add(_OP_uintptr())
   1017         case reflect.Float32 : p.add(_OP_f32)
   1018         case reflect.Float64 : p.add(_OP_f64)
   1019         case reflect.String  : p.add(_OP_string())
   1020         default              : panic("not reachable")
   1021     }
   1022 
   1023     /* the closing quote is not needed when parsing a pure string */
   1024     if vt == jsonNumberType || vt.Kind() != reflect.String {
   1025         p.chr(_OP_match_char, '"')
   1026     }
   1027 
   1028     /* pin the `is_null_quote` jump location */
   1029     if n1 != -1 && vk != reflect.Ptr {
   1030         p.pin(n1)
   1031     }
   1032 
   1033     /* "null" but not a pointer, act as if the field is not present */
   1034     if vk != reflect.Ptr {
   1035         pc2 := p.pc()
   1036         p.add(_OP_goto)
   1037         p.pin(n2)
   1038         p.rtt(_OP_dismatch_err, vt)
   1039         p.int(_OP_add, 1)
   1040         p.pin(pc2)
   1041         p.pin(n0)
   1042         return
   1043     }
   1044 
   1045     /* the "null" case of the pointer */
   1046     pc := p.pc()
   1047     p.add(_OP_goto)
   1048     p.pin(n0) // `is_null` jump location
   1049     p.pin(n1) // `is_null_quote` jump location
   1050     p.add(_OP_nil_1)
   1051     pc2 := p.pc()
   1052     p.add(_OP_goto)
   1053     p.pin(n2)
   1054     p.rtt(_OP_dismatch_err, vt)
   1055     p.int(_OP_add, 1)
   1056     p.pin(pc)
   1057     p.pin(pc2)
   1058     p.pin(skip)
   1059 }
   1060 
   1061 func (self *_Compiler) compileInterface(p *_Program, vt reflect.Type) {
   1062     i := p.pc()
   1063     p.add(_OP_is_null)
   1064 
   1065     /* check for empty interface */
   1066     if vt.NumMethod() == 0 {
   1067         p.add(_OP_any)
   1068     } else {
   1069         p.rtt(_OP_dyn, vt)
   1070     }
   1071 
   1072     /* finish the OpCode */
   1073     j := p.pc()
   1074     p.add(_OP_goto)
   1075     p.pin(i)
   1076     p.add(_OP_nil_2)
   1077     p.pin(j)
   1078 }
   1079 
   1080 func (self *_Compiler) compilePrimitive(vt reflect.Type, p *_Program, op _Op) {
   1081     i := p.pc()
   1082     p.add(_OP_is_null)
   1083     // skip := self.checkPrimitive(p, vt)
   1084     p.add(op)
   1085     p.pin(i)
   1086     // p.pin(skip)
   1087 }
   1088 
   1089 func (self *_Compiler) compileUnmarshalEnd(p *_Program, vt reflect.Type, i int) {
   1090     j := p.pc()
   1091     k := vt.Kind()
   1092 
   1093     /* not a pointer */
   1094     if k != reflect.Ptr {
   1095         p.pin(i)
   1096         return
   1097     }
   1098 
   1099     /* it seems that in Go JSON library, "null" takes priority over any kind of unmarshaler */
   1100     p.add(_OP_goto)
   1101     p.pin(i)
   1102     p.add(_OP_nil_1)
   1103     p.pin(j)
   1104 }
   1105 
   1106 func (self *_Compiler) compileUnmarshalJson(p *_Program, vt reflect.Type) {
   1107     i := p.pc()
   1108     v := _OP_unmarshal
   1109     p.add(_OP_is_null)
   1110 
   1111     /* check for dynamic interface */
   1112     if vt.Kind() == reflect.Interface {
   1113         v = _OP_dyn
   1114     }
   1115 
   1116     /* call the unmarshaler */
   1117     p.rtt(v, vt)
   1118     self.compileUnmarshalEnd(p, vt, i)
   1119 }
   1120 
   1121 func (self *_Compiler) compileUnmarshalText(p *_Program, vt reflect.Type) {
   1122     i := p.pc()
   1123     v := _OP_unmarshal_text
   1124     p.add(_OP_is_null)
   1125 
   1126     /* check for dynamic interface */
   1127     if vt.Kind() == reflect.Interface {
   1128         v = _OP_dyn
   1129     } else {
   1130         p.chr(_OP_match_char, '"')
   1131     }
   1132 
   1133     /* call the unmarshaler */
   1134     p.rtt(v, vt)
   1135     self.compileUnmarshalEnd(p, vt, i)
   1136 }
   1137 
   1138 func (self *_Compiler) compileUnmarshalTextPtr(p *_Program, vt reflect.Type) {
   1139     i := p.pc()
   1140     p.add(_OP_is_null)
   1141     p.chr(_OP_match_char, '"')
   1142     p.rtt(_OP_unmarshal_text_p, vt)
   1143     p.pin(i)
   1144 }
   1145 
   1146 func (self *_Compiler) checkIfSkip(p *_Program, vt reflect.Type, c byte) int {
   1147     j := p.pc()
   1148     p.chr(_OP_check_char_0, c)
   1149     p.rtt(_OP_dismatch_err, vt)
   1150     s := p.pc()
   1151     p.add(_OP_go_skip)
   1152     p.pin(j)
   1153     p.int(_OP_add, 1)
   1154     return s
   1155 }