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 }