op.go raw

   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 ir
  18  
  19  import (
  20  	"fmt"
  21  	"reflect"
  22  	"strconv"
  23  	"strings"
  24  	"unsafe"
  25  
  26  	"github.com/bytedance/sonic/internal/encoder/vars"
  27  	"github.com/bytedance/sonic/internal/resolver"
  28  	"github.com/bytedance/sonic/internal/rt"
  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  	OP_unsupported
  85  	OP_is_zero
  86  )
  87  
  88  const (
  89  	_INT_SIZE = 32 << (^uint(0) >> 63)
  90  	_PTR_SIZE = 32 << (^uintptr(0) >> 63)
  91  	_PTR_BYTE = unsafe.Sizeof(uintptr(0))
  92  )
  93  
  94  const OpSize = unsafe.Sizeof(NewInsOp(0))
  95  
  96  var OpNames = [256]string{
  97  	OP_null:           "null",
  98  	OP_empty_arr:      "empty_arr",
  99  	OP_empty_obj:      "empty_obj",
 100  	OP_bool:           "bool",
 101  	OP_i8:             "i8",
 102  	OP_i16:            "i16",
 103  	OP_i32:            "i32",
 104  	OP_i64:            "i64",
 105  	OP_u8:             "u8",
 106  	OP_u16:            "u16",
 107  	OP_u32:            "u32",
 108  	OP_u64:            "u64",
 109  	OP_f32:            "f32",
 110  	OP_f64:            "f64",
 111  	OP_str:            "str",
 112  	OP_bin:            "bin",
 113  	OP_quote:          "quote",
 114  	OP_number:         "number",
 115  	OP_eface:          "eface",
 116  	OP_iface:          "iface",
 117  	OP_byte:           "byte",
 118  	OP_text:           "text",
 119  	OP_deref:          "deref",
 120  	OP_index:          "index",
 121  	OP_load:           "load",
 122  	OP_save:           "save",
 123  	OP_drop:           "drop",
 124  	OP_drop_2:         "drop_2",
 125  	OP_recurse:        "recurse",
 126  	OP_is_nil:         "is_nil",
 127  	OP_is_nil_p1:      "is_nil_p1",
 128  	OP_is_zero_1:      "is_zero_1",
 129  	OP_is_zero_2:      "is_zero_2",
 130  	OP_is_zero_4:      "is_zero_4",
 131  	OP_is_zero_8:      "is_zero_8",
 132  	OP_is_zero_map:    "is_zero_map",
 133  	OP_goto:           "goto",
 134  	OP_map_iter:       "map_iter",
 135  	OP_map_stop:       "map_stop",
 136  	OP_map_check_key:  "map_check_key",
 137  	OP_map_write_key:  "map_write_key",
 138  	OP_map_value_next: "map_value_next",
 139  	OP_slice_len:      "slice_len",
 140  	OP_slice_next:     "slice_next",
 141  	OP_marshal:        "marshal",
 142  	OP_marshal_p:      "marshal_p",
 143  	OP_marshal_text:   "marshal_text",
 144  	OP_marshal_text_p: "marshal_text_p",
 145  	OP_cond_set:       "cond_set",
 146  	OP_cond_testc:     "cond_testc",
 147  	OP_unsupported:    "unsupported type",
 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  	o Op
 204  	u int            // union {op: 8, _: 8, vi: 48}, vi maybe int or len(str)
 205  	p unsafe.Pointer // maybe GoString.Ptr, or *GoType
 206  }
 207  
 208  func NewInsOp(op Op) Instr {
 209  	return Instr{o: op}
 210  }
 211  
 212  func NewInsVi(op Op, vi int) Instr {
 213  	return Instr{o: op, u: vi}
 214  }
 215  
 216  func NewInsVs(op Op, vs string) Instr {
 217  	return Instr{
 218  		o: op,
 219  		u: len(vs),
 220  		p: (*rt.GoString)(unsafe.Pointer(&vs)).Ptr,
 221  	}
 222  }
 223  
 224  func NewInsVt(op Op, vt reflect.Type) Instr {
 225  	return Instr{
 226  		o: op,
 227  		p: unsafe.Pointer(rt.UnpackType(vt)),
 228  	}
 229  }
 230  
 231  type typAndTab struct {
 232  	vt *rt.GoType
 233  	itab *rt.GoItab
 234  }
 235  
 236  type typAndField struct {
 237  	vt reflect.Type
 238  	fv *resolver.FieldMeta
 239  }
 240  
 241  func NewInsVtab(op Op, vt reflect.Type, itab *rt.GoItab) Instr {
 242  	return Instr{
 243  		o: op,
 244  		p: unsafe.Pointer(&typAndTab{
 245  			vt: rt.UnpackType(vt),
 246  			itab: itab,
 247  		}),
 248  	}
 249  }
 250  
 251  func NewInsField(op Op, fv *resolver.FieldMeta) Instr {
 252  	return Instr{
 253  		o: op,
 254  		p: unsafe.Pointer(fv),
 255  	}
 256  }
 257  
 258  func NewInsVp(op Op, vt reflect.Type, pv bool) Instr {
 259  	i := 0
 260  	if pv {
 261  		i = 1
 262  	}
 263  	return Instr{
 264  		o: op,
 265  		u: i,
 266  		p: unsafe.Pointer(rt.UnpackType(vt)),
 267  	}
 268  }
 269  
 270  func (self Instr) Op() Op {
 271  	return Op(self.o)
 272  }
 273  
 274  func (self Instr) Vi() int {
 275  	return self.u
 276  }
 277  
 278  func (self Instr) Vf() uint8 {
 279  	return (*rt.GoType)(self.p).KindFlags
 280  }
 281  
 282  func (self Instr) VField() (*resolver.FieldMeta) {
 283  	return (*resolver.FieldMeta)(self.p)
 284  }
 285  
 286  func (self Instr) Vs() (v string) {
 287  	(*rt.GoString)(unsafe.Pointer(&v)).Ptr = self.p
 288  	(*rt.GoString)(unsafe.Pointer(&v)).Len = self.Vi()
 289  	return
 290  }
 291  
 292  func (self Instr) Vk() reflect.Kind {
 293  	return (*rt.GoType)(self.p).Kind()
 294  }
 295  
 296  func (self Instr) GoType() *rt.GoType {
 297  	return (*rt.GoType)(self.p)
 298  }
 299  
 300  func (self Instr) Vt() reflect.Type {
 301  	return (*rt.GoType)(self.p).Pack()
 302  }
 303  
 304  func (self Instr) Vr() *rt.GoType {
 305  	return (*rt.GoType)(self.p)
 306  }
 307  
 308  func (self Instr) Vp() (vt reflect.Type, pv bool) {
 309  	return (*rt.GoType)(self.p).Pack(), self.u == 1
 310  }
 311  
 312  func (self Instr) Vtab() (vt *rt.GoType, itab *rt.GoItab) {
 313  	tt := (*typAndTab)(self.p)
 314  	return tt.vt, tt.itab
 315  }
 316  
 317  func (self Instr) Vp2() (vt *rt.GoType, pv bool) {
 318  	return (*rt.GoType)(self.p), self.u == 1
 319  }
 320  
 321  func (self Instr) I64() int64 {
 322  	return int64(self.Vi())
 323  }
 324  
 325  func (self Instr) Byte() byte {
 326  	return byte(self.Vi())
 327  }
 328  
 329  func (self Instr) Vlen() int {
 330  	return int((*rt.GoType)(self.p).Size)
 331  }
 332  
 333  func (self Instr) isBranch() bool {
 334  	switch self.Op() {
 335  	case OP_goto:
 336  		fallthrough
 337  	case OP_is_nil:
 338  		fallthrough
 339  	case OP_is_nil_p1:
 340  		fallthrough
 341  	case OP_is_zero_1:
 342  		fallthrough
 343  	case OP_is_zero_2:
 344  		fallthrough
 345  	case OP_is_zero_4:
 346  		fallthrough
 347  	case OP_is_zero_8:
 348  		fallthrough
 349  	case OP_map_check_key:
 350  		fallthrough
 351  	case OP_map_write_key:
 352  		fallthrough
 353  	case OP_slice_next:
 354  		fallthrough
 355  	case OP_cond_testc:
 356  		return true
 357  	default:
 358  		return false
 359  	}
 360  }
 361  
 362  func (self Instr) Disassemble() string {
 363  	switch self.Op() {
 364  	case OP_byte:
 365  		return fmt.Sprintf("%-18s%s", self.Op().String(), strconv.QuoteRune(rune(self.Vi())))
 366  	case OP_text:
 367  		return fmt.Sprintf("%-18s%s", self.Op().String(), strconv.Quote(self.Vs()))
 368  	case OP_index:
 369  		return fmt.Sprintf("%-18s%d", self.Op().String(), self.Vi())
 370  	case OP_recurse:
 371  		fallthrough
 372  	case OP_map_iter:
 373  		return fmt.Sprintf("%-18s%s", self.Op().String(), self.Vt())
 374  	case OP_marshal:
 375  		fallthrough
 376  	case OP_marshal_p:
 377  		fallthrough
 378  	case OP_marshal_text:
 379  		fallthrough
 380  	case OP_marshal_text_p:
 381  		vt, _ := self.Vtab()
 382  		return fmt.Sprintf("%-18s%s", self.Op().String(), vt.Pack())
 383  	case OP_goto:
 384  		fallthrough
 385  	case OP_is_nil:
 386  		fallthrough
 387  	case OP_is_nil_p1:
 388  		fallthrough
 389  	case OP_is_zero_1:
 390  		fallthrough
 391  	case OP_is_zero_2:
 392  		fallthrough
 393  	case OP_is_zero_4:
 394  		fallthrough
 395  	case OP_is_zero_8:
 396  		fallthrough
 397  	case OP_is_zero_map:
 398  		fallthrough
 399  	case OP_cond_testc:
 400  		fallthrough
 401  	case OP_map_check_key:
 402  		fallthrough
 403  	case OP_map_write_key:
 404  		return fmt.Sprintf("%-18sL_%d", self.Op().String(), self.Vi())
 405  	case OP_slice_next:
 406  		return fmt.Sprintf("%-18sL_%d, %s", self.Op().String(), self.Vi(), self.Vt())
 407  	default:
 408  		return fmt.Sprintf("%#v", self) 
 409  	}
 410  }
 411  
 412  type (
 413  	Program []Instr
 414  )
 415  
 416  func (self Program) PC() int {
 417  	return len(self)
 418  }
 419  
 420  func (self Program) Tag(n int) {
 421  	if n >= vars.MaxStack {
 422  		panic("type nesting too deep")
 423  	}
 424  }
 425  
 426  func (self Program) Pin(i int) {
 427  	v := &self[i]
 428  	v.u = self.PC()
 429  }
 430  
 431  func (self Program) Rel(v []int) {
 432  	for _, i := range v {
 433  		self.Pin(i)
 434  	}
 435  }
 436  
 437  func (self *Program) Add(op Op) {
 438  	*self = append(*self, NewInsOp(op))
 439  }
 440  
 441  func (self *Program) Key(op Op) {
 442  	*self = append(*self,
 443  		NewInsVi(OP_byte, '"'),
 444  		NewInsOp(op),
 445  		NewInsVi(OP_byte, '"'),
 446  	)
 447  }
 448  
 449  func (self *Program) Int(op Op, vi int) {
 450  	*self = append(*self, NewInsVi(op, vi))
 451  }
 452  
 453  func (self *Program) Str(op Op, vs string) {
 454  	*self = append(*self, NewInsVs(op, vs))
 455  }
 456  
 457  func (self *Program) Rtt(op Op, vt reflect.Type) {
 458  	*self = append(*self, NewInsVt(op, vt))
 459  }
 460  
 461  func (self *Program) Vp(op Op, vt reflect.Type, pv bool) {
 462  	*self = append(*self, NewInsVp(op, vt, pv))
 463  }
 464  
 465  func (self *Program) Vtab(op Op, vt reflect.Type, itab *rt.GoItab) {
 466  	*self = append(*self, NewInsVtab(op, vt, itab))
 467  }
 468  
 469  func (self *Program) VField(op Op, fv *resolver.FieldMeta) {
 470  	*self = append(*self, NewInsField(op, fv))
 471  }
 472  
 473  func (self Program) Disassemble() string {
 474  	nb := len(self)
 475  	tab := make([]bool, nb+1)
 476  	ret := make([]string, 0, nb+1)
 477  
 478  	/* prescan to get all the labels */
 479  	for _, ins := range self {
 480  		if ins.isBranch() {
 481  			tab[ins.Vi()] = true
 482  		}
 483  	}
 484  
 485  	/* disassemble each instruction */
 486  	for i, ins := range self {
 487  		if !tab[i] {
 488  			ret = append(ret, "\t"+ins.Disassemble())
 489  		} else {
 490  			ret = append(ret, fmt.Sprintf("L_%d:\n\t%s", i, ins.Disassemble()))
 491  		}
 492  	}
 493  
 494  	/* add the last label, if needed */
 495  	if tab[nb] {
 496  		ret = append(ret, fmt.Sprintf("L_%d:", nb))
 497  	}
 498  
 499  	/* add an "end" indicator, and join all the strings */
 500  	return strings.Join(append(ret, "\tend"), "\n")
 501  }
 502