compiler.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 encoder
  18  
  19  import (
  20  	"reflect"
  21  	"unsafe"
  22  
  23  	"github.com/bytedance/sonic/internal/encoder/ir"
  24  	"github.com/bytedance/sonic/internal/encoder/vars"
  25  	"github.com/bytedance/sonic/internal/encoder/vm"
  26  	"github.com/bytedance/sonic/internal/resolver"
  27  	"github.com/bytedance/sonic/internal/rt"
  28  	"github.com/bytedance/sonic/option"
  29  )
  30  
  31  func ForceUseVM() {
  32  	vm.SetCompiler(makeEncoderVM)
  33  	pretouchType = pretouchTypeVM
  34  	encodeTypedPointer = vm.EncodeTypedPointer
  35  	vars.UseVM = true
  36  }
  37  
  38  var encodeTypedPointer func(buf *[]byte, vt *rt.GoType, vp *unsafe.Pointer, sb *vars.Stack, fv uint64) error
  39  
  40  func makeEncoderVM(vt *rt.GoType, ex ...interface{}) (interface{}, error) {
  41  	pp, err := NewCompiler().Compile(vt.Pack(), ex[0].(bool))
  42  	if err != nil {
  43  		return nil, err
  44  	}
  45  	return &pp, nil
  46  }
  47  
  48  var pretouchType func(_vt reflect.Type, opts option.CompileOptions, v uint8) (map[reflect.Type]uint8, error)
  49  
  50  func pretouchTypeVM(_vt reflect.Type, opts option.CompileOptions, v uint8) (map[reflect.Type]uint8, error) {
  51  	/* compile function */
  52  	compiler := NewCompiler().apply(opts)
  53  
  54  	/* find or compile */
  55  	vt := rt.UnpackType(_vt)
  56  	if val := vars.GetProgram(vt); val != nil {
  57  		return nil, nil
  58  	} else if _, err := vars.ComputeProgram(vt, makeEncoderVM, v == 1); err == nil {
  59  		return compiler.rec, nil
  60  	} else {
  61  		return nil, err
  62  	}
  63  }
  64  
  65  func pretouchRec(vtm map[reflect.Type]uint8, opts option.CompileOptions) error {
  66  	if opts.RecursiveDepth < 0 || len(vtm) == 0 {
  67  		return nil
  68  	}
  69  	next := make(map[reflect.Type]uint8)
  70  	for vt, v := range vtm {
  71  		sub, err := pretouchType(vt, opts, v)
  72  		if err != nil {
  73  			return err
  74  		}
  75  		for svt, v := range sub {
  76  			next[svt] = v
  77  		}
  78  	}
  79  	opts.RecursiveDepth -= 1
  80  	return pretouchRec(next, opts)
  81  }
  82  
  83  type Compiler struct {
  84  	opts option.CompileOptions
  85  	pv   bool
  86  	tab  map[reflect.Type]bool
  87  	rec  map[reflect.Type]uint8
  88  }
  89  
  90  func NewCompiler() *Compiler {
  91  	return &Compiler{
  92  		opts: option.DefaultCompileOptions(),
  93  		tab:  map[reflect.Type]bool{},
  94  		rec:  map[reflect.Type]uint8{},
  95  	}
  96  }
  97  
  98  func (self *Compiler) apply(opts option.CompileOptions) *Compiler {
  99  	self.opts = opts
 100  	if self.opts.RecursiveDepth > 0 {
 101  		self.rec = map[reflect.Type]uint8{}
 102  	}
 103  	return self
 104  }
 105  
 106  func (self *Compiler) rescue(ep *error) {
 107  	if val := recover(); val != nil {
 108  		if err, ok := val.(error); ok {
 109  			*ep = err
 110  		} else {
 111  			panic(val)
 112  		}
 113  	}
 114  }
 115  
 116  func (self *Compiler) Compile(vt reflect.Type, pv bool) (ret ir.Program, err error) {
 117  	defer self.rescue(&err)
 118  	self.compileOne(&ret, 0, vt, pv)
 119  	return
 120  }
 121  
 122  func (self *Compiler) compileOne(p *ir.Program, sp int, vt reflect.Type, pv bool) {
 123  	if self.tab[vt] {
 124  		p.Vp(ir.OP_recurse, vt, pv)
 125  	} else {
 126  		self.compileRec(p, sp, vt, pv)
 127  	}
 128  }
 129  
 130  func (self *Compiler) tryCompileMarshaler(p *ir.Program, vt reflect.Type, pv bool) bool {
 131  	pt := reflect.PtrTo(vt)
 132  
 133  	/* check for addressable `json.Marshaler` with pointer receiver */
 134  	if pv && pt.Implements(vars.JsonMarshalerType) {
 135  		addMarshalerOp(p, ir.OP_marshal_p, pt, vars.JsonMarshalerType)
 136  		return true
 137  	}
 138  
 139  	/* check for `json.Marshaler` */
 140  	if vt.Implements(vars.JsonMarshalerType) {
 141  		self.compileMarshaler(p, ir.OP_marshal, vt, vars.JsonMarshalerType)
 142  		return true
 143  	}
 144  
 145  	/* check for addressable `encoding.TextMarshaler` with pointer receiver */
 146  	if pv && pt.Implements(vars.EncodingTextMarshalerType) {
 147  		addMarshalerOp(p, ir.OP_marshal_text_p, pt, vars.EncodingTextMarshalerType)
 148  		return true
 149  	}
 150  
 151  	/* check for `encoding.TextMarshaler` */
 152  	if vt.Implements(vars.EncodingTextMarshalerType) {
 153  		self.compileMarshaler(p, ir.OP_marshal_text, vt, vars.EncodingTextMarshalerType)
 154  		return true
 155  	}
 156  
 157  	return false
 158  }
 159  
 160  func (self *Compiler) compileRec(p *ir.Program, sp int, vt reflect.Type, pv bool) {
 161  	pr := self.pv
 162  
 163  	if self.tryCompileMarshaler(p, vt, pv) {
 164  		return
 165  	}
 166  
 167  	/* enter the recursion, and compile the type */
 168  	self.pv = pv
 169  	self.tab[vt] = true
 170  	self.compileOps(p, sp, vt)
 171  
 172  	/* exit the recursion */
 173  	self.pv = pr
 174  	delete(self.tab, vt)
 175  }
 176  
 177  func (self *Compiler) compileOps(p *ir.Program, sp int, vt reflect.Type) {
 178  	switch vt.Kind() {
 179  	case reflect.Bool:
 180  		p.Add(ir.OP_bool)
 181  	case reflect.Int:
 182  		p.Add(ir.OP_int())
 183  	case reflect.Int8:
 184  		p.Add(ir.OP_i8)
 185  	case reflect.Int16:
 186  		p.Add(ir.OP_i16)
 187  	case reflect.Int32:
 188  		p.Add(ir.OP_i32)
 189  	case reflect.Int64:
 190  		p.Add(ir.OP_i64)
 191  	case reflect.Uint:
 192  		p.Add(ir.OP_uint())
 193  	case reflect.Uint8:
 194  		p.Add(ir.OP_u8)
 195  	case reflect.Uint16:
 196  		p.Add(ir.OP_u16)
 197  	case reflect.Uint32:
 198  		p.Add(ir.OP_u32)
 199  	case reflect.Uint64:
 200  		p.Add(ir.OP_u64)
 201  	case reflect.Uintptr:
 202  		p.Add(ir.OP_uintptr())
 203  	case reflect.Float32:
 204  		p.Add(ir.OP_f32)
 205  	case reflect.Float64:
 206  		p.Add(ir.OP_f64)
 207  	case reflect.String:
 208  		self.compileString(p, vt)
 209  	case reflect.Array:
 210  		self.compileArray(p, sp, vt.Elem(), vt.Len())
 211  	case reflect.Interface:
 212  		self.compileInterface(p, vt)
 213  	case reflect.Map:
 214  		self.compileMap(p, sp, vt)
 215  	case reflect.Ptr:
 216  		self.compilePtr(p, sp, vt.Elem())
 217  	case reflect.Slice:
 218  		self.compileSlice(p, sp, vt.Elem())
 219  	case reflect.Struct:
 220  		self.compileStruct(p, sp, vt)
 221  	default:
 222  		self.compileUnsupportedType(p, vt)
 223  	}
 224  }
 225  
 226  func (self *Compiler) compileNil(p *ir.Program, sp int, vt reflect.Type, nil_op ir.Op, fn func(*ir.Program, int, reflect.Type)) {
 227  	x := p.PC()
 228  	p.Add(ir.OP_is_nil)
 229  	fn(p, sp, vt)
 230  	e := p.PC()
 231  	p.Add(ir.OP_goto)
 232  	p.Pin(x)
 233  	p.Add(nil_op)
 234  	p.Pin(e)
 235  }
 236  
 237  func (self *Compiler) compilePtr(p *ir.Program, sp int, vt reflect.Type) {
 238  	self.compileNil(p, sp, vt, ir.OP_null, self.compilePtrBody)
 239  }
 240  
 241  func (self *Compiler) compilePtrBody(p *ir.Program, sp int, vt reflect.Type) {
 242  	p.Tag(sp)
 243  	p.Add(ir.OP_save)
 244  	p.Add(ir.OP_deref)
 245  	self.compileOne(p, sp+1, vt, true)
 246  	p.Add(ir.OP_drop)
 247  }
 248  
 249  func (self *Compiler) compileMap(p *ir.Program, sp int, vt reflect.Type) {
 250  	self.compileNil(p, sp, vt, ir.OP_empty_obj, self.compileMapBody)
 251  }
 252  
 253  func (self *Compiler) compileMapBody(p *ir.Program, sp int, vt reflect.Type) {
 254  	p.Tag(sp + 1)
 255  	p.Int(ir.OP_byte, '{')
 256  	e := p.PC()
 257  	p.Add(ir.OP_is_zero_map)
 258  	p.Add(ir.OP_save)
 259  	p.Rtt(ir.OP_map_iter, vt)
 260  	p.Add(ir.OP_save)
 261  	i := p.PC()
 262  	p.Add(ir.OP_map_check_key)
 263  	u := p.PC()
 264  	p.Add(ir.OP_map_write_key)
 265  	self.compileMapBodyKey(p, vt.Key())
 266  	p.Pin(u)
 267  	p.Int(ir.OP_byte, ':')
 268  	p.Add(ir.OP_map_value_next)
 269  	self.compileOne(p, sp+2, vt.Elem(), false)
 270  	j := p.PC()
 271  	p.Add(ir.OP_map_check_key)
 272  	p.Int(ir.OP_byte, ',')
 273  	v := p.PC()
 274  	p.Add(ir.OP_map_write_key)
 275  	self.compileMapBodyKey(p, vt.Key())
 276  	p.Pin(v)
 277  	p.Int(ir.OP_byte, ':')
 278  	p.Add(ir.OP_map_value_next)
 279  	self.compileOne(p, sp+2, vt.Elem(), false)
 280  	p.Int(ir.OP_goto, j)
 281  	p.Pin(i)
 282  	p.Pin(j)
 283  	p.Add(ir.OP_map_stop)
 284  	p.Add(ir.OP_drop_2)
 285  	p.Pin(e)
 286  	p.Int(ir.OP_byte, '}')
 287  }
 288  
 289  func (self *Compiler) compileMapBodyKey(p *ir.Program, vk reflect.Type) {
 290  	if !vk.Implements(vars.EncodingTextMarshalerType) {
 291  		self.compileMapBodyTextKey(p, vk)
 292  	} else {
 293  		self.compileMapBodyUtextKey(p, vk)
 294  	}
 295  }
 296  
 297  func (self *Compiler) compileMapBodyTextKey(p *ir.Program, vk reflect.Type) {
 298  	switch vk.Kind() {
 299  	case reflect.Invalid:
 300  		panic("map key is nil")
 301  	case reflect.Bool:
 302  		p.Key(ir.OP_bool)
 303  	case reflect.Int:
 304  		p.Key(ir.OP_int())
 305  	case reflect.Int8:
 306  		p.Key(ir.OP_i8)
 307  	case reflect.Int16:
 308  		p.Key(ir.OP_i16)
 309  	case reflect.Int32:
 310  		p.Key(ir.OP_i32)
 311  	case reflect.Int64:
 312  		p.Key(ir.OP_i64)
 313  	case reflect.Uint:
 314  		p.Key(ir.OP_uint())
 315  	case reflect.Uint8:
 316  		p.Key(ir.OP_u8)
 317  	case reflect.Uint16:
 318  		p.Key(ir.OP_u16)
 319  	case reflect.Uint32:
 320  		p.Key(ir.OP_u32)
 321  	case reflect.Uint64:
 322  		p.Key(ir.OP_u64)
 323  	case reflect.Uintptr:
 324  		p.Key(ir.OP_uintptr())
 325  	case reflect.Float32:
 326  		p.Key(ir.OP_f32)
 327  	case reflect.Float64:
 328  		p.Key(ir.OP_f64)
 329  	case reflect.String:
 330  		self.compileString(p, vk)
 331  	default:
 332  		panic(vars.Error_type(vk))
 333  	}
 334  }
 335  
 336  func (self *Compiler) compileMapBodyUtextKey(p *ir.Program, vk reflect.Type) {
 337  	if vk.Kind() != reflect.Ptr {
 338  		addMarshalerOp(p, ir.OP_marshal_text, vk, vars.EncodingTextMarshalerType)
 339  	} else {
 340  		self.compileMapBodyUtextPtr(p, vk)
 341  	}
 342  }
 343  
 344  func (self *Compiler) compileMapBodyUtextPtr(p *ir.Program, vk reflect.Type) {
 345  	i := p.PC()
 346  	p.Add(ir.OP_is_nil)
 347  	addMarshalerOp(p, ir.OP_marshal_text, vk, vars.EncodingTextMarshalerType)
 348  	j := p.PC()
 349  	p.Add(ir.OP_goto)
 350  	p.Pin(i)
 351  	p.Str(ir.OP_text, "\"\"")
 352  	p.Pin(j)
 353  }
 354  
 355  func (self *Compiler) compileSlice(p *ir.Program, sp int, vt reflect.Type) {
 356  	self.compileNil(p, sp, vt, ir.OP_empty_arr, self.compileSliceBody)
 357  }
 358  
 359  func (self *Compiler) compileSliceBody(p *ir.Program, sp int, vt reflect.Type) {
 360  	if vars.IsSimpleByte(vt) {
 361  		p.Add(ir.OP_bin)
 362  	} else {
 363  		self.compileSliceArray(p, sp, vt)
 364  	}
 365  }
 366  
 367  func (self *Compiler) compileSliceArray(p *ir.Program, sp int, vt reflect.Type) {
 368  	p.Tag(sp)
 369  	p.Int(ir.OP_byte, '[')
 370  	e := p.PC()
 371  	p.Add(ir.OP_is_nil)
 372  	p.Add(ir.OP_save)
 373  	p.Add(ir.OP_slice_len)
 374  	i := p.PC()
 375  	p.Rtt(ir.OP_slice_next, vt)
 376  	self.compileOne(p, sp+1, vt, true)
 377  	j := p.PC()
 378  	p.Rtt(ir.OP_slice_next, vt)
 379  	p.Int(ir.OP_byte, ',')
 380  	self.compileOne(p, sp+1, vt, true)
 381  	p.Int(ir.OP_goto, j)
 382  	p.Pin(i)
 383  	p.Pin(j)
 384  	p.Add(ir.OP_drop)
 385  	p.Pin(e)
 386  	p.Int(ir.OP_byte, ']')
 387  }
 388  
 389  func (self *Compiler) compileArray(p *ir.Program, sp int, vt reflect.Type, nb int) {
 390  	p.Tag(sp)
 391  	p.Int(ir.OP_byte, '[')
 392  	p.Add(ir.OP_save)
 393  
 394  	/* first item */
 395  	if nb != 0 {
 396  		self.compileOne(p, sp+1, vt, self.pv)
 397  		p.Add(ir.OP_load)
 398  	}
 399  
 400  	/* remaining items */
 401  	for i := 1; i < nb; i++ {
 402  		p.Int(ir.OP_byte, ',')
 403  		p.Int(ir.OP_index, i*int(vt.Size()))
 404  		self.compileOne(p, sp+1, vt, self.pv)
 405  		p.Add(ir.OP_load)
 406  	}
 407  
 408  	/* end of array */
 409  	p.Add(ir.OP_drop)
 410  	p.Int(ir.OP_byte, ']')
 411  }
 412  
 413  func (self *Compiler) compileString(p *ir.Program, vt reflect.Type) {
 414  	if vt != vars.JsonNumberType {
 415  		p.Add(ir.OP_str)
 416  	} else {
 417  		p.Add(ir.OP_number)
 418  	}
 419  }
 420  
 421  func (self *Compiler) compileStruct(p *ir.Program, sp int, vt reflect.Type) {
 422  	if sp >= self.opts.MaxInlineDepth || p.PC() >= vars.MAX_ILBUF || (sp > 0 && vt.NumField() >= vars.MAX_FIELDS) {
 423  		p.Vp(ir.OP_recurse, vt, self.pv)
 424  		if self.opts.RecursiveDepth > 0 {
 425  			if self.pv {
 426  				self.rec[vt] = 1
 427  			} else {
 428  				self.rec[vt] = 0
 429  			}
 430  		}
 431  	} else {
 432  		self.compileStructBody(p, sp, vt)
 433  	}
 434  }
 435  
 436  func (self *Compiler) compileStructBody(p *ir.Program, sp int, vt reflect.Type) {
 437  	p.Tag(sp)
 438  	p.Int(ir.OP_byte, '{')
 439  	p.Add(ir.OP_save)
 440  	p.Add(ir.OP_cond_set)
 441  
 442  	/* compile each field */
 443  	fvs := resolver.ResolveStruct(vt)
 444  	for i, fv := range fvs {
 445  		var s []int
 446  		var o resolver.Offset
 447  
 448  		/* "omitempty" for arrays */
 449  		if fv.Type.Kind() == reflect.Array {
 450  			if fv.Type.Len() == 0 && (fv.Opts&resolver.F_omitempty) != 0 {
 451  				continue
 452  			}
 453  		}
 454  
 455  		/* index to the field */
 456  		for _, o = range fv.Path {
 457  			if p.Int(ir.OP_index, int(o.Size)); o.Kind == resolver.F_deref {
 458  				s = append(s, p.PC())
 459  				p.Add(ir.OP_is_nil)
 460  				p.Add(ir.OP_deref)
 461  			}
 462  		}
 463  
 464  		/* check for "omitempty" option */
 465  		if fv.Type.Kind() != reflect.Struct && fv.Type.Kind() != reflect.Array && (fv.Opts&resolver.F_omitempty) != 0 {
 466  			s = append(s, p.PC())
 467  			self.compileStructFieldEmpty(p, fv.Type)
 468  		}
 469  		/* check for "omitzero" option */
 470  		if fv.Opts&resolver.F_omitzero != 0 {
 471  			s = append(s, p.PC())
 472  			p.VField(ir.OP_is_zero, &fvs[i])
 473  		}
 474  
 475  		/* add the comma if not the first element */
 476  		i := p.PC()
 477  		p.Add(ir.OP_cond_testc)
 478  		p.Int(ir.OP_byte, ',')
 479  		p.Pin(i)
 480  
 481  		/* compile the key and value */
 482  		ft := fv.Type
 483  		p.Str(ir.OP_text, Quote(fv.Name)+":")
 484  
 485  		/* check for "stringnize" option */
 486  		if (fv.Opts & resolver.F_stringize) == 0 {
 487  			self.compileOne(p, sp+1, ft, self.pv)
 488  		} else {
 489  			self.compileStructFieldStr(p, sp+1, ft)
 490  		}
 491  
 492  		/* patch the skipping jumps and reload the struct pointer */
 493  		p.Rel(s)
 494  		p.Add(ir.OP_load)
 495  	}
 496  
 497  	/* end of object */
 498  	p.Add(ir.OP_drop)
 499  	p.Int(ir.OP_byte, '}')
 500  }
 501  
 502  func (self *Compiler) compileStructFieldStr(p *ir.Program, sp int, vt reflect.Type) {
 503  	// NOTICE: according to encoding/json, Marshaler type has higher priority than string option
 504  	// see issue: 
 505  	if self.tryCompileMarshaler(p, vt, self.pv) {
 506  		return
 507  	}
 508  
 509  	pc := -1
 510  	ft := vt
 511  	sv := false
 512  
 513  	/* dereference the pointer if needed */
 514  	if ft.Kind() == reflect.Ptr {
 515  		ft = ft.Elem()
 516  	}
 517  
 518  	/* check if it can be stringized */
 519  	switch ft.Kind() {
 520  	case reflect.Bool:
 521  		sv = true
 522  	case reflect.Int:
 523  		sv = true
 524  	case reflect.Int8:
 525  		sv = true
 526  	case reflect.Int16:
 527  		sv = true
 528  	case reflect.Int32:
 529  		sv = true
 530  	case reflect.Int64:
 531  		sv = true
 532  	case reflect.Uint:
 533  		sv = true
 534  	case reflect.Uint8:
 535  		sv = true
 536  	case reflect.Uint16:
 537  		sv = true
 538  	case reflect.Uint32:
 539  		sv = true
 540  	case reflect.Uint64:
 541  		sv = true
 542  	case reflect.Uintptr:
 543  		sv = true
 544  	case reflect.Float32:
 545  		sv = true
 546  	case reflect.Float64:
 547  		sv = true
 548  	case reflect.String:
 549  		sv = true
 550  	}
 551  
 552  	/* if it's not, ignore the "string" and follow the regular path */
 553  	if !sv {
 554  		self.compileOne(p, sp, vt, self.pv)
 555  		return
 556  	}
 557  
 558  	/* dereference the pointer */
 559  	if vt.Kind() == reflect.Ptr {
 560  		pc = p.PC()
 561  		vt = vt.Elem()
 562  		p.Add(ir.OP_is_nil)
 563  		p.Add(ir.OP_deref)
 564  	}
 565  
 566  	/* special case of a double-quoted string */
 567  	if ft != vars.JsonNumberType && ft.Kind() == reflect.String {
 568  		p.Add(ir.OP_quote)
 569  	} else {
 570  		self.compileStructFieldQuoted(p, sp, vt)
 571  	}
 572  
 573  	/* the "null" case of the pointer */
 574  	if pc != -1 {
 575  		e := p.PC()
 576  		p.Add(ir.OP_goto)
 577  		p.Pin(pc)
 578  		p.Add(ir.OP_null)
 579  		p.Pin(e)
 580  	}
 581  }
 582  
 583  func (self *Compiler) compileStructFieldEmpty(p *ir.Program, vt reflect.Type) {
 584  	switch vt.Kind() {
 585  	case reflect.Bool:
 586  		p.Add(ir.OP_is_zero_1)
 587  	case reflect.Int:
 588  		p.Add(ir.OP_is_zero_ints())
 589  	case reflect.Int8:
 590  		p.Add(ir.OP_is_zero_1)
 591  	case reflect.Int16:
 592  		p.Add(ir.OP_is_zero_2)
 593  	case reflect.Int32:
 594  		p.Add(ir.OP_is_zero_4)
 595  	case reflect.Int64:
 596  		p.Add(ir.OP_is_zero_8)
 597  	case reflect.Uint:
 598  		p.Add(ir.OP_is_zero_ints())
 599  	case reflect.Uint8:
 600  		p.Add(ir.OP_is_zero_1)
 601  	case reflect.Uint16:
 602  		p.Add(ir.OP_is_zero_2)
 603  	case reflect.Uint32:
 604  		p.Add(ir.OP_is_zero_4)
 605  	case reflect.Uint64:
 606  		p.Add(ir.OP_is_zero_8)
 607  	case reflect.Uintptr:
 608  		p.Add(ir.OP_is_nil)
 609  	case reflect.Float32:
 610  		p.Add(ir.OP_is_zero_4)
 611  	case reflect.Float64:
 612  		p.Add(ir.OP_is_zero_8)
 613  	case reflect.String:
 614  		p.Add(ir.OP_is_nil_p1)
 615  	case reflect.Interface:
 616  		p.Add(ir.OP_is_nil)
 617  	case reflect.Map:
 618  		p.Add(ir.OP_is_zero_map)
 619  	case reflect.Ptr:
 620  		p.Add(ir.OP_is_nil)
 621  	case reflect.Slice:
 622  		p.Add(ir.OP_is_nil_p1)
 623  	default:
 624  		panic(vars.Error_type(vt))
 625  	}
 626  }
 627  
 628  func (self *Compiler) compileStructFieldQuoted(p *ir.Program, sp int, vt reflect.Type) {
 629  	p.Int(ir.OP_byte, '"')
 630  	self.compileOne(p, sp, vt, self.pv)
 631  	p.Int(ir.OP_byte, '"')
 632  }
 633  
 634  func (self *Compiler) compileInterface(p *ir.Program, vt reflect.Type) {
 635  	/* iface and efaces are different */
 636  	if vt.NumMethod() == 0 {
 637  		p.Add(ir.OP_eface)
 638  		return
 639  	}
 640  
 641  	x := p.PC()
 642  	p.Add(ir.OP_is_nil_p1)
 643  	p.Add(ir.OP_iface)
 644  
 645  	/* the "null" value */
 646  	e := p.PC()
 647  	p.Add(ir.OP_goto)
 648  	p.Pin(x)
 649  	p.Add(ir.OP_null)
 650  	p.Pin(e)
 651  }
 652  
 653  func (self *Compiler) compileUnsupportedType(p *ir.Program, vt reflect.Type) {
 654  	p.Rtt(ir.OP_unsupported, vt)
 655  }
 656  
 657  
 658  func (self *Compiler) compileMarshaler(p *ir.Program, op ir.Op, vt reflect.Type, mt reflect.Type) {
 659  	pc := p.PC()
 660  	vk := vt.Kind()
 661  
 662  	/* direct receiver */
 663  	if vk != reflect.Ptr {
 664  		addMarshalerOp(p, op, vt, mt)
 665  		return
 666  	}
 667  	/* value receiver with a pointer type, check for nil before calling the marshaler */
 668  	p.Add(ir.OP_is_nil)
 669  
 670  	addMarshalerOp(p, op, vt, mt)
 671  
 672  	i := p.PC()
 673  	p.Add(ir.OP_goto)
 674  	p.Pin(pc)
 675  	p.Add(ir.OP_null)
 676  	p.Pin(i)
 677  }
 678  
 679  func addMarshalerOp(p *ir.Program, op ir.Op, vt reflect.Type, mt reflect.Type) {
 680  	if vars.UseVM {
 681  		itab := rt.GetItab(rt.IfaceType(rt.UnpackType(mt)), rt.UnpackType(vt), true)
 682  		p.Vtab(op, vt, itab)
 683  	} else {
 684  		// OPT: get itab here 
 685  		p.Rtt(op, vt)
 686  	}
 687  }
 688