github.com/nuvolaris/goja@v0.0.0-20230825100449-967811910c6d/vm.go (about)

     1  package goja
     2  
     3  import (
     4  	"fmt"
     5  	"math"
     6  	"strconv"
     7  	"strings"
     8  	"sync"
     9  	"sync/atomic"
    10  	"time"
    11  
    12  	"github.com/nuvolaris/goja/unistring"
    13  )
    14  
    15  const (
    16  	maxInt = 1 << 53
    17  
    18  	tryPanicMarker = -2
    19  )
    20  
    21  type valueStack []Value
    22  
    23  type stash struct {
    24  	values    []Value
    25  	extraArgs []Value
    26  	names     map[unistring.String]uint32
    27  	obj       *Object
    28  
    29  	outer *stash
    30  
    31  	// If this is a top-level function stash, sets the type of the function. If set, dynamic var declarations
    32  	// created by direct eval go here.
    33  	funcType funcType
    34  }
    35  
    36  type context struct {
    37  	prg       *Program
    38  	stash     *stash
    39  	privEnv   *privateEnv
    40  	newTarget Value
    41  	result    Value
    42  	pc, sb    int
    43  	args      int
    44  }
    45  
    46  type tryFrame struct {
    47  	// holds an uncaught exception for the 'finally' block
    48  	exception *Exception
    49  
    50  	callStackLen, iterLen, refLen uint32
    51  
    52  	sp      int32
    53  	stash   *stash
    54  	privEnv *privateEnv
    55  
    56  	catchPos, finallyPos, finallyRet int32
    57  }
    58  
    59  type execCtx struct {
    60  	context
    61  	stack     []Value
    62  	tryStack  []tryFrame
    63  	iterStack []iterStackItem
    64  	refStack  []ref
    65  }
    66  
    67  func (vm *vm) suspend(ectx *execCtx, tryStackLen, iterStackLen, refStackLen uint32) {
    68  	vm.saveCtx(&ectx.context)
    69  	ectx.stack = append(ectx.stack[:0], vm.stack[vm.sb-1:vm.sp]...)
    70  	if len(vm.tryStack) > int(tryStackLen) {
    71  		ectx.tryStack = append(ectx.tryStack[:0], vm.tryStack[tryStackLen:]...)
    72  		vm.tryStack = vm.tryStack[:tryStackLen]
    73  		sp := int32(vm.sb - 1)
    74  		for i := range ectx.tryStack {
    75  			tf := &ectx.tryStack[i]
    76  			tf.iterLen -= iterStackLen
    77  			tf.refLen -= refStackLen
    78  			tf.sp -= sp
    79  		}
    80  	}
    81  	if len(vm.iterStack) > int(iterStackLen) {
    82  		ectx.iterStack = append(ectx.iterStack[:0], vm.iterStack[iterStackLen:]...)
    83  		vm.iterStack = vm.iterStack[:iterStackLen]
    84  	}
    85  	if len(vm.refStack) > int(refStackLen) {
    86  		ectx.refStack = append(ectx.refStack[:0], vm.refStack[refStackLen:]...)
    87  		vm.refStack = vm.refStack[:refStackLen]
    88  	}
    89  }
    90  
    91  func (vm *vm) resume(ctx *execCtx) {
    92  	vm.restoreCtx(&ctx.context)
    93  	sp := vm.sp
    94  	vm.sb = sp + 1
    95  	vm.stack.expand(sp + len(ctx.stack))
    96  	copy(vm.stack[sp:], ctx.stack)
    97  	vm.sp += len(ctx.stack)
    98  	for i := range ctx.tryStack {
    99  		tf := &ctx.tryStack[i]
   100  		tf.callStackLen = uint32(len(vm.callStack))
   101  		tf.iterLen += uint32(len(vm.iterStack))
   102  		tf.refLen += uint32(len(vm.refStack))
   103  		tf.sp += int32(sp)
   104  	}
   105  	vm.tryStack = append(vm.tryStack, ctx.tryStack...)
   106  	vm.iterStack = append(vm.iterStack, ctx.iterStack...)
   107  	vm.refStack = append(vm.refStack, ctx.refStack...)
   108  }
   109  
   110  type iterStackItem struct {
   111  	val  Value
   112  	f    iterNextFunc
   113  	iter *iteratorRecord
   114  }
   115  
   116  type ref interface {
   117  	get() Value
   118  	set(Value)
   119  	init(Value)
   120  	refname() unistring.String
   121  }
   122  
   123  type stashRef struct {
   124  	n   unistring.String
   125  	v   *[]Value
   126  	idx int
   127  }
   128  
   129  func (r *stashRef) get() Value {
   130  	return nilSafe((*r.v)[r.idx])
   131  }
   132  
   133  func (r *stashRef) set(v Value) {
   134  	(*r.v)[r.idx] = v
   135  }
   136  
   137  func (r *stashRef) init(v Value) {
   138  	r.set(v)
   139  }
   140  
   141  func (r *stashRef) refname() unistring.String {
   142  	return r.n
   143  }
   144  
   145  type thisRef struct {
   146  	v   *[]Value
   147  	idx int
   148  }
   149  
   150  func (r *thisRef) get() Value {
   151  	v := (*r.v)[r.idx]
   152  	if v == nil {
   153  		panic(referenceError("Must call super constructor in derived class before accessing 'this'"))
   154  	}
   155  
   156  	return v
   157  }
   158  
   159  func (r *thisRef) set(v Value) {
   160  	ptr := &(*r.v)[r.idx]
   161  	if *ptr != nil {
   162  		panic(referenceError("Super constructor may only be called once"))
   163  	}
   164  	*ptr = v
   165  }
   166  
   167  func (r *thisRef) init(v Value) {
   168  	r.set(v)
   169  }
   170  
   171  func (r *thisRef) refname() unistring.String {
   172  	return thisBindingName
   173  }
   174  
   175  type stashRefLex struct {
   176  	stashRef
   177  }
   178  
   179  func (r *stashRefLex) get() Value {
   180  	v := (*r.v)[r.idx]
   181  	if v == nil {
   182  		panic(errAccessBeforeInit)
   183  	}
   184  	return v
   185  }
   186  
   187  func (r *stashRefLex) set(v Value) {
   188  	p := &(*r.v)[r.idx]
   189  	if *p == nil {
   190  		panic(errAccessBeforeInit)
   191  	}
   192  	*p = v
   193  }
   194  
   195  func (r *stashRefLex) init(v Value) {
   196  	(*r.v)[r.idx] = v
   197  }
   198  
   199  type stashRefConst struct {
   200  	stashRefLex
   201  	strictConst bool
   202  }
   203  
   204  func (r *stashRefConst) set(v Value) {
   205  	if r.strictConst {
   206  		panic(errAssignToConst)
   207  	}
   208  }
   209  
   210  type objRef struct {
   211  	base    *Object
   212  	name    unistring.String
   213  	this    Value
   214  	strict  bool
   215  	binding bool
   216  }
   217  
   218  func (r *objRef) get() Value {
   219  	return r.base.self.getStr(r.name, r.this)
   220  }
   221  
   222  func (r *objRef) set(v Value) {
   223  	if r.strict && r.binding && !r.base.self.hasOwnPropertyStr(r.name) {
   224  		panic(referenceError(fmt.Sprintf("%s is not defined", r.name)))
   225  	}
   226  	if r.this != nil {
   227  		r.base.setStr(r.name, v, r.this, r.strict)
   228  	} else {
   229  		r.base.self.setOwnStr(r.name, v, r.strict)
   230  	}
   231  }
   232  
   233  func (r *objRef) init(v Value) {
   234  	if r.this != nil {
   235  		r.base.setStr(r.name, v, r.this, r.strict)
   236  	} else {
   237  		r.base.self.setOwnStr(r.name, v, r.strict)
   238  	}
   239  }
   240  
   241  func (r *objRef) refname() unistring.String {
   242  	return r.name
   243  }
   244  
   245  type privateRefRes struct {
   246  	base *Object
   247  	name *resolvedPrivateName
   248  }
   249  
   250  func (p *privateRefRes) get() Value {
   251  	return (*getPrivatePropRes)(p.name)._get(p.base, p.base.runtime.vm)
   252  }
   253  
   254  func (p *privateRefRes) set(value Value) {
   255  	(*setPrivatePropRes)(p.name)._set(p.base, value, p.base.runtime.vm)
   256  }
   257  
   258  func (p *privateRefRes) init(value Value) {
   259  	panic("not supported")
   260  }
   261  
   262  func (p *privateRefRes) refname() unistring.String {
   263  	return p.name.string()
   264  }
   265  
   266  type privateRefId struct {
   267  	base *Object
   268  	id   *privateId
   269  }
   270  
   271  func (p *privateRefId) get() Value {
   272  	return p.base.runtime.vm.getPrivateProp(p.base, p.id.name, p.id.typ, p.id.idx, p.id.isMethod)
   273  }
   274  
   275  func (p *privateRefId) set(value Value) {
   276  	p.base.runtime.vm.setPrivateProp(p.base, p.id.name, p.id.typ, p.id.idx, p.id.isMethod, value)
   277  }
   278  
   279  func (p *privateRefId) init(value Value) {
   280  	panic("not supported")
   281  }
   282  
   283  func (p *privateRefId) refname() unistring.String {
   284  	return p.id.string()
   285  }
   286  
   287  type unresolvedRef struct {
   288  	runtime *Runtime
   289  	name    unistring.String
   290  }
   291  
   292  func (r *unresolvedRef) get() Value {
   293  	r.runtime.throwReferenceError(r.name)
   294  	panic("Unreachable")
   295  }
   296  
   297  func (r *unresolvedRef) set(Value) {
   298  	r.get()
   299  }
   300  
   301  func (r *unresolvedRef) init(Value) {
   302  	r.get()
   303  }
   304  
   305  func (r *unresolvedRef) refname() unistring.String {
   306  	return r.name
   307  }
   308  
   309  type vm struct {
   310  	r            *Runtime
   311  	prg          *Program
   312  	pc           int
   313  	stack        valueStack
   314  	sp, sb, args int
   315  
   316  	stash     *stash
   317  	privEnv   *privateEnv
   318  	callStack []context
   319  	iterStack []iterStackItem
   320  	refStack  []ref
   321  	tryStack  []tryFrame
   322  	newTarget Value
   323  	result    Value
   324  
   325  	maxCallStackSize int
   326  
   327  	stashAllocs int
   328  
   329  	interrupted   uint32
   330  	interruptVal  interface{}
   331  	interruptLock sync.Mutex
   332  
   333  	curAsyncRunner *asyncRunner
   334  
   335  	profTracker *profTracker
   336  }
   337  
   338  type instruction interface {
   339  	exec(*vm)
   340  }
   341  
   342  func intToValue(i int64) Value {
   343  	if idx := 256 + i; idx >= 0 && idx < 256 {
   344  		return intCache[idx]
   345  	}
   346  	if i >= -maxInt && i <= maxInt {
   347  		return valueInt(i)
   348  	}
   349  	return valueFloat(i)
   350  }
   351  
   352  func floatToInt(f float64) (result int64, ok bool) {
   353  	if (f != 0 || !math.Signbit(f)) && !math.IsInf(f, 0) && f == math.Trunc(f) && f >= -maxInt && f <= maxInt {
   354  		return int64(f), true
   355  	}
   356  	return 0, false
   357  }
   358  
   359  func floatToValue(f float64) (result Value) {
   360  	if i, ok := floatToInt(f); ok {
   361  		return intToValue(i)
   362  	}
   363  	switch {
   364  	case f == 0:
   365  		return _negativeZero
   366  	case math.IsNaN(f):
   367  		return _NaN
   368  	case math.IsInf(f, 1):
   369  		return _positiveInf
   370  	case math.IsInf(f, -1):
   371  		return _negativeInf
   372  	}
   373  	return valueFloat(f)
   374  }
   375  
   376  func assertInt64(v Value) (int64, bool) {
   377  	num := v.ToNumber()
   378  	if i, ok := num.(valueInt); ok {
   379  		return int64(i), true
   380  	}
   381  	if f, ok := num.(valueFloat); ok {
   382  		if i, ok := floatToInt(float64(f)); ok {
   383  			return i, true
   384  		}
   385  	}
   386  	return 0, false
   387  }
   388  
   389  func (s *valueStack) expand(idx int) {
   390  	if idx < len(*s) {
   391  		return
   392  	}
   393  	idx++
   394  	if idx < cap(*s) {
   395  		*s = (*s)[:idx]
   396  	} else {
   397  		var newCap int
   398  		if idx < 1024 {
   399  			newCap = idx * 2
   400  		} else {
   401  			newCap = (idx + 1025) &^ 1023
   402  		}
   403  		n := make([]Value, idx, newCap)
   404  		copy(n, *s)
   405  		*s = n
   406  	}
   407  }
   408  
   409  func stashObjHas(obj *Object, name unistring.String) bool {
   410  	if obj.self.hasPropertyStr(name) {
   411  		if unscopables, ok := obj.self.getSym(SymUnscopables, nil).(*Object); ok {
   412  			if b := unscopables.self.getStr(name, nil); b != nil {
   413  				return !b.ToBoolean()
   414  			}
   415  		}
   416  		return true
   417  	}
   418  	return false
   419  }
   420  
   421  func (s *stash) isVariable() bool {
   422  	return s.funcType != funcNone
   423  }
   424  
   425  func (s *stash) initByIdx(idx uint32, v Value) {
   426  	if s.obj != nil {
   427  		panic("Attempt to init by idx into an object scope")
   428  	}
   429  	s.values[idx] = v
   430  }
   431  
   432  func (s *stash) initByName(name unistring.String, v Value) {
   433  	if idx, exists := s.names[name]; exists {
   434  		s.values[idx&^maskTyp] = v
   435  	} else {
   436  		panic(referenceError(fmt.Sprintf("%s is not defined", name)))
   437  	}
   438  }
   439  
   440  func (s *stash) getByIdx(idx uint32) Value {
   441  	return s.values[idx]
   442  }
   443  
   444  func (s *stash) getByName(name unistring.String) (v Value, exists bool) {
   445  	if s.obj != nil {
   446  		if stashObjHas(s.obj, name) {
   447  			return nilSafe(s.obj.self.getStr(name, nil)), true
   448  		}
   449  		return nil, false
   450  	}
   451  	if idx, exists := s.names[name]; exists {
   452  		v := s.values[idx&^maskTyp]
   453  		if v == nil {
   454  			if idx&maskVar == 0 {
   455  				panic(errAccessBeforeInit)
   456  			} else {
   457  				v = _undefined
   458  			}
   459  		}
   460  		return v, true
   461  	}
   462  	return nil, false
   463  }
   464  
   465  func (s *stash) getRefByName(name unistring.String, strict bool) ref {
   466  	if obj := s.obj; obj != nil {
   467  		if stashObjHas(obj, name) {
   468  			return &objRef{
   469  				base:    obj,
   470  				name:    name,
   471  				strict:  strict,
   472  				binding: true,
   473  			}
   474  		}
   475  	} else {
   476  		if idx, exists := s.names[name]; exists {
   477  			if idx&maskVar == 0 {
   478  				if idx&maskConst == 0 {
   479  					return &stashRefLex{
   480  						stashRef: stashRef{
   481  							n:   name,
   482  							v:   &s.values,
   483  							idx: int(idx &^ maskTyp),
   484  						},
   485  					}
   486  				} else {
   487  					return &stashRefConst{
   488  						stashRefLex: stashRefLex{
   489  							stashRef: stashRef{
   490  								n:   name,
   491  								v:   &s.values,
   492  								idx: int(idx &^ maskTyp),
   493  							},
   494  						},
   495  						strictConst: strict || (idx&maskStrict != 0),
   496  					}
   497  				}
   498  			} else {
   499  				return &stashRef{
   500  					n:   name,
   501  					v:   &s.values,
   502  					idx: int(idx &^ maskTyp),
   503  				}
   504  			}
   505  		}
   506  	}
   507  	return nil
   508  }
   509  
   510  func (s *stash) createBinding(name unistring.String, deletable bool) {
   511  	if s.names == nil {
   512  		s.names = make(map[unistring.String]uint32)
   513  	}
   514  	if _, exists := s.names[name]; !exists {
   515  		idx := uint32(len(s.names)) | maskVar
   516  		if deletable {
   517  			idx |= maskDeletable
   518  		}
   519  		s.names[name] = idx
   520  		s.values = append(s.values, _undefined)
   521  	}
   522  }
   523  
   524  func (s *stash) createLexBinding(name unistring.String, isConst bool) {
   525  	if s.names == nil {
   526  		s.names = make(map[unistring.String]uint32)
   527  	}
   528  	if _, exists := s.names[name]; !exists {
   529  		idx := uint32(len(s.names))
   530  		if isConst {
   531  			idx |= maskConst | maskStrict
   532  		}
   533  		s.names[name] = idx
   534  		s.values = append(s.values, nil)
   535  	}
   536  }
   537  
   538  func (s *stash) deleteBinding(name unistring.String) {
   539  	delete(s.names, name)
   540  }
   541  
   542  func (vm *vm) newStash() {
   543  	vm.stash = &stash{
   544  		outer: vm.stash,
   545  	}
   546  	vm.stashAllocs++
   547  }
   548  
   549  func (vm *vm) init() {
   550  	vm.sb = -1
   551  	vm.stash = &vm.r.global.stash
   552  	vm.maxCallStackSize = math.MaxInt32
   553  }
   554  
   555  func (vm *vm) halted() bool {
   556  	pc := vm.pc
   557  	return pc < 0 || pc >= len(vm.prg.code)
   558  }
   559  
   560  func (vm *vm) run() {
   561  	if vm.profTracker != nil && !vm.runWithProfiler() {
   562  		return
   563  	}
   564  	count := 0
   565  	interrupted := false
   566  	for {
   567  		if count == 0 {
   568  			if atomic.LoadInt32(&globalProfiler.enabled) == 1 && !vm.runWithProfiler() {
   569  				return
   570  			}
   571  			count = 100
   572  		} else {
   573  			count--
   574  		}
   575  		if interrupted = atomic.LoadUint32(&vm.interrupted) != 0; interrupted {
   576  			break
   577  		}
   578  		pc := vm.pc
   579  		if pc < 0 || pc >= len(vm.prg.code) {
   580  			break
   581  		}
   582  		vm.prg.code[pc].exec(vm)
   583  	}
   584  
   585  	if interrupted {
   586  		vm.interruptLock.Lock()
   587  		v := &InterruptedError{
   588  			iface: vm.interruptVal,
   589  		}
   590  		v.stack = vm.captureStack(nil, 0)
   591  		vm.interruptLock.Unlock()
   592  		panic(v)
   593  	}
   594  }
   595  
   596  func (vm *vm) runWithProfiler() bool {
   597  	pt := vm.profTracker
   598  	if pt == nil {
   599  		pt = globalProfiler.p.registerVm()
   600  		vm.profTracker = pt
   601  		defer func() {
   602  			atomic.StoreInt32(&vm.profTracker.finished, 1)
   603  			vm.profTracker = nil
   604  		}()
   605  	}
   606  	interrupted := false
   607  	for {
   608  		if interrupted = atomic.LoadUint32(&vm.interrupted) != 0; interrupted {
   609  			return true
   610  		}
   611  		pc := vm.pc
   612  		if pc < 0 || pc >= len(vm.prg.code) {
   613  			break
   614  		}
   615  		vm.prg.code[pc].exec(vm)
   616  		req := atomic.LoadInt32(&pt.req)
   617  		if req == profReqStop {
   618  			return true
   619  		}
   620  		if req == profReqDoSample {
   621  			pt.stop = time.Now()
   622  
   623  			pt.numFrames = len(vm.r.CaptureCallStack(len(pt.frames), pt.frames[:0]))
   624  			pt.frames[0].pc = pc
   625  			atomic.StoreInt32(&pt.req, profReqSampleReady)
   626  		}
   627  	}
   628  
   629  	return false
   630  }
   631  
   632  func (vm *vm) Interrupt(v interface{}) {
   633  	vm.interruptLock.Lock()
   634  	vm.interruptVal = v
   635  	atomic.StoreUint32(&vm.interrupted, 1)
   636  	vm.interruptLock.Unlock()
   637  }
   638  
   639  func (vm *vm) ClearInterrupt() {
   640  	atomic.StoreUint32(&vm.interrupted, 0)
   641  }
   642  
   643  func getFuncName(stack []Value, sb int) unistring.String {
   644  	if sb > 0 {
   645  		if f, ok := stack[sb-1].(*Object); ok {
   646  			if _, isProxy := f.self.(*proxyObject); isProxy {
   647  				return "proxy"
   648  			}
   649  			return nilSafe(f.self.getStr("name", nil)).string()
   650  		}
   651  	}
   652  	return ""
   653  }
   654  
   655  func (vm *vm) captureStack(stack []StackFrame, ctxOffset int) []StackFrame {
   656  	// Unroll the context stack
   657  	if vm.prg != nil || vm.sb > 0 {
   658  		var funcName unistring.String
   659  		if vm.prg != nil {
   660  			funcName = vm.prg.funcName
   661  		} else {
   662  			funcName = getFuncName(vm.stack, vm.sb)
   663  		}
   664  		stack = append(stack, StackFrame{prg: vm.prg, pc: vm.pc, funcName: funcName})
   665  	}
   666  	for i := len(vm.callStack) - 1; i > ctxOffset-1; i-- {
   667  		frame := &vm.callStack[i]
   668  		if frame.prg != nil || frame.sb > 0 {
   669  			var funcName unistring.String
   670  			if prg := frame.prg; prg != nil {
   671  				funcName = prg.funcName
   672  			} else {
   673  				funcName = getFuncName(vm.stack, frame.sb)
   674  			}
   675  			stack = append(stack, StackFrame{prg: vm.callStack[i].prg, pc: frame.pc, funcName: funcName})
   676  		}
   677  	}
   678  	if ctxOffset == 0 && vm.curAsyncRunner != nil {
   679  		stack = vm.captureAsyncStack(stack, vm.curAsyncRunner)
   680  	}
   681  	return stack
   682  }
   683  
   684  func (vm *vm) captureAsyncStack(stack []StackFrame, runner *asyncRunner) []StackFrame {
   685  	if promise, _ := runner.promiseCap.promise.self.(*Promise); promise != nil {
   686  		if len(promise.fulfillReactions) == 1 {
   687  			if r := promise.fulfillReactions[0].asyncRunner; r != nil {
   688  				ctx := &r.gen.ctx
   689  				if ctx.prg != nil || ctx.sb > 0 {
   690  					var funcName unistring.String
   691  					if prg := ctx.prg; prg != nil {
   692  						funcName = prg.funcName
   693  					} else {
   694  						funcName = getFuncName(ctx.stack, 1)
   695  					}
   696  					stack = append(stack, StackFrame{prg: ctx.prg, pc: ctx.pc, funcName: funcName})
   697  				}
   698  				stack = vm.captureAsyncStack(stack, r)
   699  			}
   700  		}
   701  	}
   702  
   703  	return stack
   704  }
   705  
   706  func (vm *vm) pushTryFrame(catchPos, finallyPos int32) {
   707  	vm.tryStack = append(vm.tryStack, tryFrame{
   708  		callStackLen: uint32(len(vm.callStack)),
   709  		iterLen:      uint32(len(vm.iterStack)),
   710  		refLen:       uint32(len(vm.refStack)),
   711  		sp:           int32(vm.sp),
   712  		stash:        vm.stash,
   713  		privEnv:      vm.privEnv,
   714  		catchPos:     catchPos,
   715  		finallyPos:   finallyPos,
   716  		finallyRet:   -1,
   717  	})
   718  }
   719  
   720  func (vm *vm) popTryFrame() {
   721  	vm.tryStack = vm.tryStack[:len(vm.tryStack)-1]
   722  }
   723  
   724  func (vm *vm) restoreStacks(iterLen, refLen uint32) (ex *Exception) {
   725  	// Restore other stacks
   726  	iterTail := vm.iterStack[iterLen:]
   727  	for i := len(iterTail) - 1; i >= 0; i-- {
   728  		if iter := iterTail[i].iter; iter != nil {
   729  			ex1 := vm.try(func() {
   730  				iter.returnIter()
   731  			})
   732  			if ex1 != nil && ex == nil {
   733  				ex = ex1
   734  			}
   735  		}
   736  		iterTail[i] = iterStackItem{}
   737  	}
   738  	vm.iterStack = vm.iterStack[:iterLen]
   739  	refTail := vm.refStack[refLen:]
   740  	for i := range refTail {
   741  		refTail[i] = nil
   742  	}
   743  	vm.refStack = vm.refStack[:refLen]
   744  	return
   745  }
   746  
   747  func (vm *vm) handleThrow(arg interface{}) *Exception {
   748  	ex := vm.exceptionFromValue(arg)
   749  	for len(vm.tryStack) > 0 {
   750  		tf := &vm.tryStack[len(vm.tryStack)-1]
   751  		if tf.catchPos == -1 && tf.finallyPos == -1 || ex == nil && tf.catchPos != tryPanicMarker {
   752  			tf.exception = nil
   753  			vm.popTryFrame()
   754  			continue
   755  		}
   756  		if int(tf.callStackLen) < len(vm.callStack) {
   757  			ctx := &vm.callStack[tf.callStackLen]
   758  			vm.prg, vm.newTarget, vm.result, vm.pc, vm.sb, vm.args =
   759  				ctx.prg, ctx.newTarget, ctx.result, ctx.pc, ctx.sb, ctx.args
   760  			vm.callStack = vm.callStack[:tf.callStackLen]
   761  		}
   762  		vm.sp = int(tf.sp)
   763  		vm.stash = tf.stash
   764  		vm.privEnv = tf.privEnv
   765  		_ = vm.restoreStacks(tf.iterLen, tf.refLen)
   766  
   767  		if tf.catchPos == tryPanicMarker {
   768  			break
   769  		}
   770  
   771  		if tf.catchPos >= 0 {
   772  			// exception is caught
   773  			vm.push(ex.val)
   774  			vm.pc = int(tf.catchPos)
   775  			tf.catchPos = -1
   776  			return nil
   777  		}
   778  		if tf.finallyPos >= 0 {
   779  			// no 'catch' block, but there is a 'finally' block
   780  			tf.exception = ex
   781  			vm.pc = int(tf.finallyPos)
   782  			tf.finallyPos = -1
   783  			tf.finallyRet = -1
   784  			return nil
   785  		}
   786  	}
   787  	if ex == nil {
   788  		panic(arg)
   789  	}
   790  	return ex
   791  }
   792  
   793  // Calls to this method must be made from the run() loop and must be the last statement before 'return'.
   794  // In all other cases exceptions must be thrown using panic().
   795  func (vm *vm) throw(v interface{}) {
   796  	if ex := vm.handleThrow(v); ex != nil {
   797  		panic(ex)
   798  	}
   799  }
   800  
   801  func (vm *vm) try(f func()) (ex *Exception) {
   802  	vm.pushTryFrame(tryPanicMarker, -1)
   803  	defer vm.popTryFrame()
   804  
   805  	defer func() {
   806  		if x := recover(); x != nil {
   807  			ex = vm.handleThrow(x)
   808  		}
   809  	}()
   810  
   811  	f()
   812  	return
   813  }
   814  
   815  func (vm *vm) runTry() (ex *Exception) {
   816  	vm.pushTryFrame(tryPanicMarker, -1)
   817  	defer vm.popTryFrame()
   818  
   819  	for {
   820  		ex = vm.runTryInner()
   821  		if ex != nil || vm.halted() {
   822  			return
   823  		}
   824  	}
   825  }
   826  
   827  func (vm *vm) runTryInner() (ex *Exception) {
   828  	defer func() {
   829  		if x := recover(); x != nil {
   830  			ex = vm.handleThrow(x)
   831  		}
   832  	}()
   833  
   834  	vm.run()
   835  	return
   836  }
   837  
   838  func (vm *vm) push(v Value) {
   839  	vm.stack.expand(vm.sp)
   840  	vm.stack[vm.sp] = v
   841  	vm.sp++
   842  }
   843  
   844  func (vm *vm) pop() Value {
   845  	vm.sp--
   846  	return vm.stack[vm.sp]
   847  }
   848  
   849  func (vm *vm) peek() Value {
   850  	return vm.stack[vm.sp-1]
   851  }
   852  
   853  func (vm *vm) saveCtx(ctx *context) {
   854  	ctx.prg, ctx.stash, ctx.privEnv, ctx.newTarget, ctx.result, ctx.pc, ctx.sb, ctx.args =
   855  		vm.prg, vm.stash, vm.privEnv, vm.newTarget, vm.result, vm.pc, vm.sb, vm.args
   856  }
   857  
   858  func (vm *vm) pushCtx() {
   859  	if len(vm.callStack) > vm.maxCallStackSize {
   860  		ex := &StackOverflowError{}
   861  		ex.stack = vm.captureStack(nil, 0)
   862  		panic(ex)
   863  	}
   864  	vm.callStack = append(vm.callStack, context{})
   865  	ctx := &vm.callStack[len(vm.callStack)-1]
   866  	vm.saveCtx(ctx)
   867  }
   868  
   869  func (vm *vm) restoreCtx(ctx *context) {
   870  	vm.prg, vm.stash, vm.privEnv, vm.newTarget, vm.result, vm.pc, vm.sb, vm.args =
   871  		ctx.prg, ctx.stash, ctx.privEnv, ctx.newTarget, ctx.result, ctx.pc, ctx.sb, ctx.args
   872  }
   873  
   874  func (vm *vm) popCtx() {
   875  	l := len(vm.callStack) - 1
   876  	ctx := &vm.callStack[l]
   877  	vm.restoreCtx(ctx)
   878  
   879  	if ctx.prg != nil {
   880  		*ctx = context{}
   881  	}
   882  
   883  	vm.callStack = vm.callStack[:l]
   884  }
   885  
   886  func (vm *vm) toCallee(v Value) *Object {
   887  	if obj, ok := v.(*Object); ok {
   888  		return obj
   889  	}
   890  	switch unresolved := v.(type) {
   891  	case valueUnresolved:
   892  		unresolved.throw()
   893  		panic("Unreachable")
   894  	case memberUnresolved:
   895  		panic(vm.r.NewTypeError("Object has no member '%s'", unresolved.ref))
   896  	}
   897  	panic(vm.r.NewTypeError("Value is not an object: %s", v.toString()))
   898  }
   899  
   900  type loadVal uint32
   901  
   902  func (l loadVal) exec(vm *vm) {
   903  	vm.push(vm.prg.values[l])
   904  	vm.pc++
   905  }
   906  
   907  type _loadUndef struct{}
   908  
   909  var loadUndef _loadUndef
   910  
   911  func (_loadUndef) exec(vm *vm) {
   912  	vm.push(_undefined)
   913  	vm.pc++
   914  }
   915  
   916  type _loadNil struct{}
   917  
   918  var loadNil _loadNil
   919  
   920  func (_loadNil) exec(vm *vm) {
   921  	vm.push(nil)
   922  	vm.pc++
   923  }
   924  
   925  type _saveResult struct{}
   926  
   927  var saveResult _saveResult
   928  
   929  func (_saveResult) exec(vm *vm) {
   930  	vm.sp--
   931  	vm.result = vm.stack[vm.sp]
   932  	vm.pc++
   933  }
   934  
   935  type _clearResult struct{}
   936  
   937  var clearResult _clearResult
   938  
   939  func (_clearResult) exec(vm *vm) {
   940  	vm.result = _undefined
   941  	vm.pc++
   942  }
   943  
   944  type _loadGlobalObject struct{}
   945  
   946  var loadGlobalObject _loadGlobalObject
   947  
   948  func (_loadGlobalObject) exec(vm *vm) {
   949  	vm.push(vm.r.globalObject)
   950  	vm.pc++
   951  }
   952  
   953  type loadStack int
   954  
   955  func (l loadStack) exec(vm *vm) {
   956  	// l > 0 -- var<l-1>
   957  	// l == 0 -- this
   958  
   959  	if l > 0 {
   960  		vm.push(nilSafe(vm.stack[vm.sb+vm.args+int(l)]))
   961  	} else {
   962  		vm.push(vm.stack[vm.sb])
   963  	}
   964  	vm.pc++
   965  }
   966  
   967  type loadStack1 int
   968  
   969  func (l loadStack1) exec(vm *vm) {
   970  	// args are in stash
   971  	// l > 0 -- var<l-1>
   972  	// l == 0 -- this
   973  
   974  	if l > 0 {
   975  		vm.push(nilSafe(vm.stack[vm.sb+int(l)]))
   976  	} else {
   977  		vm.push(vm.stack[vm.sb])
   978  	}
   979  	vm.pc++
   980  }
   981  
   982  type loadStackLex int
   983  
   984  func (l loadStackLex) exec(vm *vm) {
   985  	// l < 0 -- arg<-l-1>
   986  	// l > 0 -- var<l-1>
   987  	// l == 0 -- this
   988  	var p *Value
   989  	if l <= 0 {
   990  		arg := int(-l)
   991  		if arg > vm.args {
   992  			vm.push(_undefined)
   993  			vm.pc++
   994  			return
   995  		} else {
   996  			p = &vm.stack[vm.sb+arg]
   997  		}
   998  	} else {
   999  		p = &vm.stack[vm.sb+vm.args+int(l)]
  1000  	}
  1001  	if *p == nil {
  1002  		vm.throw(errAccessBeforeInit)
  1003  		return
  1004  	}
  1005  	vm.push(*p)
  1006  	vm.pc++
  1007  }
  1008  
  1009  type loadStack1Lex int
  1010  
  1011  func (l loadStack1Lex) exec(vm *vm) {
  1012  	p := &vm.stack[vm.sb+int(l)]
  1013  	if *p == nil {
  1014  		vm.throw(errAccessBeforeInit)
  1015  		return
  1016  	}
  1017  	vm.push(*p)
  1018  	vm.pc++
  1019  }
  1020  
  1021  type _loadCallee struct{}
  1022  
  1023  var loadCallee _loadCallee
  1024  
  1025  func (_loadCallee) exec(vm *vm) {
  1026  	vm.push(vm.stack[vm.sb-1])
  1027  	vm.pc++
  1028  }
  1029  
  1030  func (vm *vm) storeStack(s int) {
  1031  	// l > 0 -- var<l-1>
  1032  
  1033  	if s > 0 {
  1034  		vm.stack[vm.sb+vm.args+s] = vm.stack[vm.sp-1]
  1035  	} else {
  1036  		panic("Illegal stack var index")
  1037  	}
  1038  	vm.pc++
  1039  }
  1040  
  1041  func (vm *vm) storeStack1(s int) {
  1042  	// args are in stash
  1043  	// l > 0 -- var<l-1>
  1044  
  1045  	if s > 0 {
  1046  		vm.stack[vm.sb+s] = vm.stack[vm.sp-1]
  1047  	} else {
  1048  		panic("Illegal stack var index")
  1049  	}
  1050  	vm.pc++
  1051  }
  1052  
  1053  func (vm *vm) storeStackLex(s int) {
  1054  	// l < 0 -- arg<-l-1>
  1055  	// l > 0 -- var<l-1>
  1056  	var p *Value
  1057  	if s < 0 {
  1058  		p = &vm.stack[vm.sb-s]
  1059  	} else {
  1060  		p = &vm.stack[vm.sb+vm.args+s]
  1061  	}
  1062  
  1063  	if *p != nil {
  1064  		*p = vm.stack[vm.sp-1]
  1065  	} else {
  1066  		panic(errAccessBeforeInit)
  1067  	}
  1068  	vm.pc++
  1069  }
  1070  
  1071  func (vm *vm) storeStack1Lex(s int) {
  1072  	// args are in stash
  1073  	// s > 0 -- var<l-1>
  1074  	if s <= 0 {
  1075  		panic("Illegal stack var index")
  1076  	}
  1077  	p := &vm.stack[vm.sb+s]
  1078  	if *p != nil {
  1079  		*p = vm.stack[vm.sp-1]
  1080  	} else {
  1081  		panic(errAccessBeforeInit)
  1082  	}
  1083  	vm.pc++
  1084  }
  1085  
  1086  func (vm *vm) initStack(s int) {
  1087  	if s <= 0 {
  1088  		vm.stack[vm.sb-s] = vm.stack[vm.sp-1]
  1089  	} else {
  1090  		vm.stack[vm.sb+vm.args+s] = vm.stack[vm.sp-1]
  1091  	}
  1092  	vm.pc++
  1093  }
  1094  
  1095  func (vm *vm) initStack1(s int) {
  1096  	if s <= 0 {
  1097  		panic("Illegal stack var index")
  1098  	}
  1099  	vm.stack[vm.sb+s] = vm.stack[vm.sp-1]
  1100  	vm.pc++
  1101  }
  1102  
  1103  type storeStack int
  1104  
  1105  func (s storeStack) exec(vm *vm) {
  1106  	vm.storeStack(int(s))
  1107  }
  1108  
  1109  type storeStack1 int
  1110  
  1111  func (s storeStack1) exec(vm *vm) {
  1112  	vm.storeStack1(int(s))
  1113  }
  1114  
  1115  type storeStackLex int
  1116  
  1117  func (s storeStackLex) exec(vm *vm) {
  1118  	vm.storeStackLex(int(s))
  1119  }
  1120  
  1121  type storeStack1Lex int
  1122  
  1123  func (s storeStack1Lex) exec(vm *vm) {
  1124  	vm.storeStack1Lex(int(s))
  1125  }
  1126  
  1127  type initStack int
  1128  
  1129  func (s initStack) exec(vm *vm) {
  1130  	vm.initStack(int(s))
  1131  }
  1132  
  1133  type initStackP int
  1134  
  1135  func (s initStackP) exec(vm *vm) {
  1136  	vm.initStack(int(s))
  1137  	vm.sp--
  1138  }
  1139  
  1140  type initStack1 int
  1141  
  1142  func (s initStack1) exec(vm *vm) {
  1143  	vm.initStack1(int(s))
  1144  }
  1145  
  1146  type initStack1P int
  1147  
  1148  func (s initStack1P) exec(vm *vm) {
  1149  	vm.initStack1(int(s))
  1150  	vm.sp--
  1151  }
  1152  
  1153  type storeStackP int
  1154  
  1155  func (s storeStackP) exec(vm *vm) {
  1156  	vm.storeStack(int(s))
  1157  	vm.sp--
  1158  }
  1159  
  1160  type storeStack1P int
  1161  
  1162  func (s storeStack1P) exec(vm *vm) {
  1163  	vm.storeStack1(int(s))
  1164  	vm.sp--
  1165  }
  1166  
  1167  type storeStackLexP int
  1168  
  1169  func (s storeStackLexP) exec(vm *vm) {
  1170  	vm.storeStackLex(int(s))
  1171  	vm.sp--
  1172  }
  1173  
  1174  type storeStack1LexP int
  1175  
  1176  func (s storeStack1LexP) exec(vm *vm) {
  1177  	vm.storeStack1Lex(int(s))
  1178  	vm.sp--
  1179  }
  1180  
  1181  type _toNumber struct{}
  1182  
  1183  var toNumber _toNumber
  1184  
  1185  func (_toNumber) exec(vm *vm) {
  1186  	vm.stack[vm.sp-1] = vm.stack[vm.sp-1].ToNumber()
  1187  	vm.pc++
  1188  }
  1189  
  1190  type _add struct{}
  1191  
  1192  var add _add
  1193  
  1194  func (_add) exec(vm *vm) {
  1195  	right := vm.stack[vm.sp-1]
  1196  	left := vm.stack[vm.sp-2]
  1197  
  1198  	if o, ok := left.(*Object); ok {
  1199  		left = o.toPrimitive()
  1200  	}
  1201  
  1202  	if o, ok := right.(*Object); ok {
  1203  		right = o.toPrimitive()
  1204  	}
  1205  
  1206  	var ret Value
  1207  
  1208  	leftString, isLeftString := left.(String)
  1209  	rightString, isRightString := right.(String)
  1210  
  1211  	if isLeftString || isRightString {
  1212  		if !isLeftString {
  1213  			leftString = left.toString()
  1214  		}
  1215  		if !isRightString {
  1216  			rightString = right.toString()
  1217  		}
  1218  		ret = leftString.Concat(rightString)
  1219  	} else {
  1220  		if leftInt, ok := left.(valueInt); ok {
  1221  			if rightInt, ok := right.(valueInt); ok {
  1222  				ret = intToValue(int64(leftInt) + int64(rightInt))
  1223  			} else {
  1224  				ret = floatToValue(float64(leftInt) + right.ToFloat())
  1225  			}
  1226  		} else {
  1227  			ret = floatToValue(left.ToFloat() + right.ToFloat())
  1228  		}
  1229  	}
  1230  
  1231  	vm.stack[vm.sp-2] = ret
  1232  	vm.sp--
  1233  	vm.pc++
  1234  }
  1235  
  1236  type _sub struct{}
  1237  
  1238  var sub _sub
  1239  
  1240  func (_sub) exec(vm *vm) {
  1241  	right := vm.stack[vm.sp-1]
  1242  	left := vm.stack[vm.sp-2]
  1243  
  1244  	var result Value
  1245  
  1246  	if left, ok := left.(valueInt); ok {
  1247  		if right, ok := right.(valueInt); ok {
  1248  			result = intToValue(int64(left) - int64(right))
  1249  			goto end
  1250  		}
  1251  	}
  1252  
  1253  	result = floatToValue(left.ToFloat() - right.ToFloat())
  1254  end:
  1255  	vm.sp--
  1256  	vm.stack[vm.sp-1] = result
  1257  	vm.pc++
  1258  }
  1259  
  1260  type _mul struct{}
  1261  
  1262  var mul _mul
  1263  
  1264  func (_mul) exec(vm *vm) {
  1265  	left := vm.stack[vm.sp-2]
  1266  	right := vm.stack[vm.sp-1]
  1267  
  1268  	var result Value
  1269  
  1270  	if left, ok := assertInt64(left); ok {
  1271  		if right, ok := assertInt64(right); ok {
  1272  			if left == 0 && right == -1 || left == -1 && right == 0 {
  1273  				result = _negativeZero
  1274  				goto end
  1275  			}
  1276  			res := left * right
  1277  			// check for overflow
  1278  			if left == 0 || right == 0 || res/left == right {
  1279  				result = intToValue(res)
  1280  				goto end
  1281  			}
  1282  
  1283  		}
  1284  	}
  1285  
  1286  	result = floatToValue(left.ToFloat() * right.ToFloat())
  1287  
  1288  end:
  1289  	vm.sp--
  1290  	vm.stack[vm.sp-1] = result
  1291  	vm.pc++
  1292  }
  1293  
  1294  type _exp struct{}
  1295  
  1296  var exp _exp
  1297  
  1298  func (_exp) exec(vm *vm) {
  1299  	vm.sp--
  1300  	vm.stack[vm.sp-1] = pow(vm.stack[vm.sp-1], vm.stack[vm.sp])
  1301  	vm.pc++
  1302  }
  1303  
  1304  type _div struct{}
  1305  
  1306  var div _div
  1307  
  1308  func (_div) exec(vm *vm) {
  1309  	left := vm.stack[vm.sp-2].ToFloat()
  1310  	right := vm.stack[vm.sp-1].ToFloat()
  1311  
  1312  	var result Value
  1313  
  1314  	if math.IsNaN(left) || math.IsNaN(right) {
  1315  		result = _NaN
  1316  		goto end
  1317  	}
  1318  	if math.IsInf(left, 0) && math.IsInf(right, 0) {
  1319  		result = _NaN
  1320  		goto end
  1321  	}
  1322  	if left == 0 && right == 0 {
  1323  		result = _NaN
  1324  		goto end
  1325  	}
  1326  
  1327  	if math.IsInf(left, 0) {
  1328  		if math.Signbit(left) == math.Signbit(right) {
  1329  			result = _positiveInf
  1330  			goto end
  1331  		} else {
  1332  			result = _negativeInf
  1333  			goto end
  1334  		}
  1335  	}
  1336  	if math.IsInf(right, 0) {
  1337  		if math.Signbit(left) == math.Signbit(right) {
  1338  			result = _positiveZero
  1339  			goto end
  1340  		} else {
  1341  			result = _negativeZero
  1342  			goto end
  1343  		}
  1344  	}
  1345  	if right == 0 {
  1346  		if math.Signbit(left) == math.Signbit(right) {
  1347  			result = _positiveInf
  1348  			goto end
  1349  		} else {
  1350  			result = _negativeInf
  1351  			goto end
  1352  		}
  1353  	}
  1354  
  1355  	result = floatToValue(left / right)
  1356  
  1357  end:
  1358  	vm.sp--
  1359  	vm.stack[vm.sp-1] = result
  1360  	vm.pc++
  1361  }
  1362  
  1363  type _mod struct{}
  1364  
  1365  var mod _mod
  1366  
  1367  func (_mod) exec(vm *vm) {
  1368  	left := vm.stack[vm.sp-2]
  1369  	right := vm.stack[vm.sp-1]
  1370  
  1371  	var result Value
  1372  
  1373  	if leftInt, ok := assertInt64(left); ok {
  1374  		if rightInt, ok := assertInt64(right); ok {
  1375  			if rightInt == 0 {
  1376  				result = _NaN
  1377  				goto end
  1378  			}
  1379  			r := leftInt % rightInt
  1380  			if r == 0 && leftInt < 0 {
  1381  				result = _negativeZero
  1382  			} else {
  1383  				result = intToValue(leftInt % rightInt)
  1384  			}
  1385  			goto end
  1386  		}
  1387  	}
  1388  
  1389  	result = floatToValue(math.Mod(left.ToFloat(), right.ToFloat()))
  1390  end:
  1391  	vm.sp--
  1392  	vm.stack[vm.sp-1] = result
  1393  	vm.pc++
  1394  }
  1395  
  1396  type _neg struct{}
  1397  
  1398  var neg _neg
  1399  
  1400  func (_neg) exec(vm *vm) {
  1401  	operand := vm.stack[vm.sp-1]
  1402  
  1403  	var result Value
  1404  
  1405  	if i, ok := assertInt64(operand); ok {
  1406  		if i == 0 {
  1407  			result = _negativeZero
  1408  		} else {
  1409  			result = valueInt(-i)
  1410  		}
  1411  	} else {
  1412  		f := operand.ToFloat()
  1413  		if !math.IsNaN(f) {
  1414  			f = -f
  1415  		}
  1416  		result = valueFloat(f)
  1417  	}
  1418  
  1419  	vm.stack[vm.sp-1] = result
  1420  	vm.pc++
  1421  }
  1422  
  1423  type _plus struct{}
  1424  
  1425  var plus _plus
  1426  
  1427  func (_plus) exec(vm *vm) {
  1428  	vm.stack[vm.sp-1] = vm.stack[vm.sp-1].ToNumber()
  1429  	vm.pc++
  1430  }
  1431  
  1432  type _inc struct{}
  1433  
  1434  var inc _inc
  1435  
  1436  func (_inc) exec(vm *vm) {
  1437  	v := vm.stack[vm.sp-1]
  1438  
  1439  	if i, ok := assertInt64(v); ok {
  1440  		v = intToValue(i + 1)
  1441  		goto end
  1442  	}
  1443  
  1444  	v = valueFloat(v.ToFloat() + 1)
  1445  
  1446  end:
  1447  	vm.stack[vm.sp-1] = v
  1448  	vm.pc++
  1449  }
  1450  
  1451  type _dec struct{}
  1452  
  1453  var dec _dec
  1454  
  1455  func (_dec) exec(vm *vm) {
  1456  	v := vm.stack[vm.sp-1]
  1457  
  1458  	if i, ok := assertInt64(v); ok {
  1459  		v = intToValue(i - 1)
  1460  		goto end
  1461  	}
  1462  
  1463  	v = valueFloat(v.ToFloat() - 1)
  1464  
  1465  end:
  1466  	vm.stack[vm.sp-1] = v
  1467  	vm.pc++
  1468  }
  1469  
  1470  type _and struct{}
  1471  
  1472  var and _and
  1473  
  1474  func (_and) exec(vm *vm) {
  1475  	left := toInt32(vm.stack[vm.sp-2])
  1476  	right := toInt32(vm.stack[vm.sp-1])
  1477  	vm.stack[vm.sp-2] = intToValue(int64(left & right))
  1478  	vm.sp--
  1479  	vm.pc++
  1480  }
  1481  
  1482  type _or struct{}
  1483  
  1484  var or _or
  1485  
  1486  func (_or) exec(vm *vm) {
  1487  	left := toInt32(vm.stack[vm.sp-2])
  1488  	right := toInt32(vm.stack[vm.sp-1])
  1489  	vm.stack[vm.sp-2] = intToValue(int64(left | right))
  1490  	vm.sp--
  1491  	vm.pc++
  1492  }
  1493  
  1494  type _xor struct{}
  1495  
  1496  var xor _xor
  1497  
  1498  func (_xor) exec(vm *vm) {
  1499  	left := toInt32(vm.stack[vm.sp-2])
  1500  	right := toInt32(vm.stack[vm.sp-1])
  1501  	vm.stack[vm.sp-2] = intToValue(int64(left ^ right))
  1502  	vm.sp--
  1503  	vm.pc++
  1504  }
  1505  
  1506  type _bnot struct{}
  1507  
  1508  var bnot _bnot
  1509  
  1510  func (_bnot) exec(vm *vm) {
  1511  	op := toInt32(vm.stack[vm.sp-1])
  1512  	vm.stack[vm.sp-1] = intToValue(int64(^op))
  1513  	vm.pc++
  1514  }
  1515  
  1516  type _sal struct{}
  1517  
  1518  var sal _sal
  1519  
  1520  func (_sal) exec(vm *vm) {
  1521  	left := toInt32(vm.stack[vm.sp-2])
  1522  	right := toUint32(vm.stack[vm.sp-1])
  1523  	vm.stack[vm.sp-2] = intToValue(int64(left << (right & 0x1F)))
  1524  	vm.sp--
  1525  	vm.pc++
  1526  }
  1527  
  1528  type _sar struct{}
  1529  
  1530  var sar _sar
  1531  
  1532  func (_sar) exec(vm *vm) {
  1533  	left := toInt32(vm.stack[vm.sp-2])
  1534  	right := toUint32(vm.stack[vm.sp-1])
  1535  	vm.stack[vm.sp-2] = intToValue(int64(left >> (right & 0x1F)))
  1536  	vm.sp--
  1537  	vm.pc++
  1538  }
  1539  
  1540  type _shr struct{}
  1541  
  1542  var shr _shr
  1543  
  1544  func (_shr) exec(vm *vm) {
  1545  	left := toUint32(vm.stack[vm.sp-2])
  1546  	right := toUint32(vm.stack[vm.sp-1])
  1547  	vm.stack[vm.sp-2] = intToValue(int64(left >> (right & 0x1F)))
  1548  	vm.sp--
  1549  	vm.pc++
  1550  }
  1551  
  1552  type jump int32
  1553  
  1554  func (j jump) exec(vm *vm) {
  1555  	vm.pc += int(j)
  1556  }
  1557  
  1558  type _toPropertyKey struct{}
  1559  
  1560  func (_toPropertyKey) exec(vm *vm) {
  1561  	p := vm.sp - 1
  1562  	vm.stack[p] = toPropertyKey(vm.stack[p])
  1563  	vm.pc++
  1564  }
  1565  
  1566  type _toString struct{}
  1567  
  1568  func (_toString) exec(vm *vm) {
  1569  	p := vm.sp - 1
  1570  	vm.stack[p] = vm.stack[p].toString()
  1571  	vm.pc++
  1572  }
  1573  
  1574  type _getElemRef struct{}
  1575  
  1576  var getElemRef _getElemRef
  1577  
  1578  func (_getElemRef) exec(vm *vm) {
  1579  	obj := vm.stack[vm.sp-2].ToObject(vm.r)
  1580  	propName := toPropertyKey(vm.stack[vm.sp-1])
  1581  	vm.refStack = append(vm.refStack, &objRef{
  1582  		base: obj,
  1583  		name: propName.string(),
  1584  	})
  1585  	vm.sp -= 2
  1586  	vm.pc++
  1587  }
  1588  
  1589  type _getElemRefRecv struct{}
  1590  
  1591  var getElemRefRecv _getElemRefRecv
  1592  
  1593  func (_getElemRefRecv) exec(vm *vm) {
  1594  	obj := vm.stack[vm.sp-1].ToObject(vm.r)
  1595  	propName := toPropertyKey(vm.stack[vm.sp-2])
  1596  	vm.refStack = append(vm.refStack, &objRef{
  1597  		base: obj,
  1598  		name: propName.string(),
  1599  		this: vm.stack[vm.sp-3],
  1600  	})
  1601  	vm.sp -= 3
  1602  	vm.pc++
  1603  }
  1604  
  1605  type _getElemRefStrict struct{}
  1606  
  1607  var getElemRefStrict _getElemRefStrict
  1608  
  1609  func (_getElemRefStrict) exec(vm *vm) {
  1610  	obj := vm.stack[vm.sp-2].ToObject(vm.r)
  1611  	propName := toPropertyKey(vm.stack[vm.sp-1])
  1612  	vm.refStack = append(vm.refStack, &objRef{
  1613  		base:   obj,
  1614  		name:   propName.string(),
  1615  		strict: true,
  1616  	})
  1617  	vm.sp -= 2
  1618  	vm.pc++
  1619  }
  1620  
  1621  type _getElemRefRecvStrict struct{}
  1622  
  1623  var getElemRefRecvStrict _getElemRefRecvStrict
  1624  
  1625  func (_getElemRefRecvStrict) exec(vm *vm) {
  1626  	obj := vm.stack[vm.sp-1].ToObject(vm.r)
  1627  	propName := toPropertyKey(vm.stack[vm.sp-2])
  1628  	vm.refStack = append(vm.refStack, &objRef{
  1629  		base:   obj,
  1630  		name:   propName.string(),
  1631  		this:   vm.stack[vm.sp-3],
  1632  		strict: true,
  1633  	})
  1634  	vm.sp -= 3
  1635  	vm.pc++
  1636  }
  1637  
  1638  type _setElem struct{}
  1639  
  1640  var setElem _setElem
  1641  
  1642  func (_setElem) exec(vm *vm) {
  1643  	obj := vm.stack[vm.sp-3].ToObject(vm.r)
  1644  	propName := toPropertyKey(vm.stack[vm.sp-2])
  1645  	val := vm.stack[vm.sp-1]
  1646  
  1647  	obj.setOwn(propName, val, false)
  1648  
  1649  	vm.sp -= 2
  1650  	vm.stack[vm.sp-1] = val
  1651  	vm.pc++
  1652  }
  1653  
  1654  type _setElem1 struct{}
  1655  
  1656  var setElem1 _setElem1
  1657  
  1658  func (_setElem1) exec(vm *vm) {
  1659  	obj := vm.stack[vm.sp-3].ToObject(vm.r)
  1660  	propName := vm.stack[vm.sp-2]
  1661  	val := vm.stack[vm.sp-1]
  1662  
  1663  	obj.setOwn(propName, val, true)
  1664  
  1665  	vm.sp -= 2
  1666  	vm.pc++
  1667  }
  1668  
  1669  type _setElem1Named struct{}
  1670  
  1671  var setElem1Named _setElem1Named
  1672  
  1673  func (_setElem1Named) exec(vm *vm) {
  1674  	receiver := vm.stack[vm.sp-3]
  1675  	base := receiver.ToObject(vm.r)
  1676  	propName := vm.stack[vm.sp-2]
  1677  	val := vm.stack[vm.sp-1]
  1678  	vm.r.toObject(val).self.defineOwnPropertyStr("name", PropertyDescriptor{
  1679  		Value:        funcName("", propName),
  1680  		Configurable: FLAG_TRUE,
  1681  	}, true)
  1682  	base.set(propName, val, receiver, true)
  1683  
  1684  	vm.sp -= 2
  1685  	vm.pc++
  1686  }
  1687  
  1688  type defineMethod struct {
  1689  	enumerable bool
  1690  }
  1691  
  1692  func (d *defineMethod) exec(vm *vm) {
  1693  	obj := vm.r.toObject(vm.stack[vm.sp-3])
  1694  	propName := vm.stack[vm.sp-2]
  1695  	method := vm.r.toObject(vm.stack[vm.sp-1])
  1696  	method.self.defineOwnPropertyStr("name", PropertyDescriptor{
  1697  		Value:        funcName("", propName),
  1698  		Configurable: FLAG_TRUE,
  1699  	}, true)
  1700  	obj.defineOwnProperty(propName, PropertyDescriptor{
  1701  		Value:        method,
  1702  		Writable:     FLAG_TRUE,
  1703  		Configurable: FLAG_TRUE,
  1704  		Enumerable:   ToFlag(d.enumerable),
  1705  	}, true)
  1706  
  1707  	vm.sp -= 2
  1708  	vm.pc++
  1709  }
  1710  
  1711  type _setElemP struct{}
  1712  
  1713  var setElemP _setElemP
  1714  
  1715  func (_setElemP) exec(vm *vm) {
  1716  	obj := vm.stack[vm.sp-3].ToObject(vm.r)
  1717  	propName := toPropertyKey(vm.stack[vm.sp-2])
  1718  	val := vm.stack[vm.sp-1]
  1719  
  1720  	obj.setOwn(propName, val, false)
  1721  
  1722  	vm.sp -= 3
  1723  	vm.pc++
  1724  }
  1725  
  1726  type _setElemStrict struct{}
  1727  
  1728  var setElemStrict _setElemStrict
  1729  
  1730  func (_setElemStrict) exec(vm *vm) {
  1731  	propName := toPropertyKey(vm.stack[vm.sp-2])
  1732  	receiver := vm.stack[vm.sp-3]
  1733  	val := vm.stack[vm.sp-1]
  1734  	if receiverObj, ok := receiver.(*Object); ok {
  1735  		receiverObj.setOwn(propName, val, true)
  1736  	} else {
  1737  		base := receiver.ToObject(vm.r)
  1738  		base.set(propName, val, receiver, true)
  1739  	}
  1740  
  1741  	vm.sp -= 2
  1742  	vm.stack[vm.sp-1] = val
  1743  	vm.pc++
  1744  }
  1745  
  1746  type _setElemRecv struct{}
  1747  
  1748  var setElemRecv _setElemRecv
  1749  
  1750  func (_setElemRecv) exec(vm *vm) {
  1751  	receiver := vm.stack[vm.sp-4]
  1752  	propName := toPropertyKey(vm.stack[vm.sp-3])
  1753  	o := vm.stack[vm.sp-2]
  1754  	val := vm.stack[vm.sp-1]
  1755  	if obj, ok := o.(*Object); ok {
  1756  		obj.set(propName, val, receiver, false)
  1757  	} else {
  1758  		base := o.ToObject(vm.r)
  1759  		base.set(propName, val, receiver, false)
  1760  	}
  1761  
  1762  	vm.sp -= 3
  1763  	vm.stack[vm.sp-1] = val
  1764  	vm.pc++
  1765  }
  1766  
  1767  type _setElemRecvStrict struct{}
  1768  
  1769  var setElemRecvStrict _setElemRecvStrict
  1770  
  1771  func (_setElemRecvStrict) exec(vm *vm) {
  1772  	receiver := vm.stack[vm.sp-4]
  1773  	propName := toPropertyKey(vm.stack[vm.sp-3])
  1774  	o := vm.stack[vm.sp-2]
  1775  	val := vm.stack[vm.sp-1]
  1776  	if obj, ok := o.(*Object); ok {
  1777  		obj.set(propName, val, receiver, true)
  1778  	} else {
  1779  		base := o.ToObject(vm.r)
  1780  		base.set(propName, val, receiver, true)
  1781  	}
  1782  
  1783  	vm.sp -= 3
  1784  	vm.stack[vm.sp-1] = val
  1785  	vm.pc++
  1786  }
  1787  
  1788  type _setElemStrictP struct{}
  1789  
  1790  var setElemStrictP _setElemStrictP
  1791  
  1792  func (_setElemStrictP) exec(vm *vm) {
  1793  	propName := toPropertyKey(vm.stack[vm.sp-2])
  1794  	receiver := vm.stack[vm.sp-3]
  1795  	val := vm.stack[vm.sp-1]
  1796  	if receiverObj, ok := receiver.(*Object); ok {
  1797  		receiverObj.setOwn(propName, val, true)
  1798  	} else {
  1799  		base := receiver.ToObject(vm.r)
  1800  		base.set(propName, val, receiver, true)
  1801  	}
  1802  
  1803  	vm.sp -= 3
  1804  	vm.pc++
  1805  }
  1806  
  1807  type _setElemRecvP struct{}
  1808  
  1809  var setElemRecvP _setElemRecvP
  1810  
  1811  func (_setElemRecvP) exec(vm *vm) {
  1812  	receiver := vm.stack[vm.sp-4]
  1813  	propName := toPropertyKey(vm.stack[vm.sp-3])
  1814  	o := vm.stack[vm.sp-2]
  1815  	val := vm.stack[vm.sp-1]
  1816  	if obj, ok := o.(*Object); ok {
  1817  		obj.set(propName, val, receiver, false)
  1818  	} else {
  1819  		base := o.ToObject(vm.r)
  1820  		base.set(propName, val, receiver, false)
  1821  	}
  1822  
  1823  	vm.sp -= 4
  1824  	vm.pc++
  1825  }
  1826  
  1827  type _setElemRecvStrictP struct{}
  1828  
  1829  var setElemRecvStrictP _setElemRecvStrictP
  1830  
  1831  func (_setElemRecvStrictP) exec(vm *vm) {
  1832  	receiver := vm.stack[vm.sp-4]
  1833  	propName := toPropertyKey(vm.stack[vm.sp-3])
  1834  	o := vm.stack[vm.sp-2]
  1835  	val := vm.stack[vm.sp-1]
  1836  	if obj, ok := o.(*Object); ok {
  1837  		obj.set(propName, val, receiver, true)
  1838  	} else {
  1839  		base := o.ToObject(vm.r)
  1840  		base.set(propName, val, receiver, true)
  1841  	}
  1842  
  1843  	vm.sp -= 4
  1844  	vm.pc++
  1845  }
  1846  
  1847  type _deleteElem struct{}
  1848  
  1849  var deleteElem _deleteElem
  1850  
  1851  func (_deleteElem) exec(vm *vm) {
  1852  	obj := vm.stack[vm.sp-2].ToObject(vm.r)
  1853  	propName := toPropertyKey(vm.stack[vm.sp-1])
  1854  	if obj.delete(propName, false) {
  1855  		vm.stack[vm.sp-2] = valueTrue
  1856  	} else {
  1857  		vm.stack[vm.sp-2] = valueFalse
  1858  	}
  1859  	vm.sp--
  1860  	vm.pc++
  1861  }
  1862  
  1863  type _deleteElemStrict struct{}
  1864  
  1865  var deleteElemStrict _deleteElemStrict
  1866  
  1867  func (_deleteElemStrict) exec(vm *vm) {
  1868  	obj := vm.stack[vm.sp-2].ToObject(vm.r)
  1869  	propName := toPropertyKey(vm.stack[vm.sp-1])
  1870  	obj.delete(propName, true)
  1871  	vm.stack[vm.sp-2] = valueTrue
  1872  	vm.sp--
  1873  	vm.pc++
  1874  }
  1875  
  1876  type deleteProp unistring.String
  1877  
  1878  func (d deleteProp) exec(vm *vm) {
  1879  	obj := vm.stack[vm.sp-1].ToObject(vm.r)
  1880  	if obj.self.deleteStr(unistring.String(d), false) {
  1881  		vm.stack[vm.sp-1] = valueTrue
  1882  	} else {
  1883  		vm.stack[vm.sp-1] = valueFalse
  1884  	}
  1885  	vm.pc++
  1886  }
  1887  
  1888  type deletePropStrict unistring.String
  1889  
  1890  func (d deletePropStrict) exec(vm *vm) {
  1891  	obj := vm.stack[vm.sp-1].ToObject(vm.r)
  1892  	obj.self.deleteStr(unistring.String(d), true)
  1893  	vm.stack[vm.sp-1] = valueTrue
  1894  	vm.pc++
  1895  }
  1896  
  1897  type getPropRef unistring.String
  1898  
  1899  func (p getPropRef) exec(vm *vm) {
  1900  	vm.refStack = append(vm.refStack, &objRef{
  1901  		base: vm.stack[vm.sp-1].ToObject(vm.r),
  1902  		name: unistring.String(p),
  1903  	})
  1904  	vm.sp--
  1905  	vm.pc++
  1906  }
  1907  
  1908  type getPropRefRecv unistring.String
  1909  
  1910  func (p getPropRefRecv) exec(vm *vm) {
  1911  	vm.refStack = append(vm.refStack, &objRef{
  1912  		this: vm.stack[vm.sp-2],
  1913  		base: vm.stack[vm.sp-1].ToObject(vm.r),
  1914  		name: unistring.String(p),
  1915  	})
  1916  	vm.sp -= 2
  1917  	vm.pc++
  1918  }
  1919  
  1920  type getPropRefStrict unistring.String
  1921  
  1922  func (p getPropRefStrict) exec(vm *vm) {
  1923  	vm.refStack = append(vm.refStack, &objRef{
  1924  		base:   vm.stack[vm.sp-1].ToObject(vm.r),
  1925  		name:   unistring.String(p),
  1926  		strict: true,
  1927  	})
  1928  	vm.sp--
  1929  	vm.pc++
  1930  }
  1931  
  1932  type getPropRefRecvStrict unistring.String
  1933  
  1934  func (p getPropRefRecvStrict) exec(vm *vm) {
  1935  	vm.refStack = append(vm.refStack, &objRef{
  1936  		this:   vm.stack[vm.sp-2],
  1937  		base:   vm.stack[vm.sp-1].ToObject(vm.r),
  1938  		name:   unistring.String(p),
  1939  		strict: true,
  1940  	})
  1941  	vm.sp -= 2
  1942  	vm.pc++
  1943  }
  1944  
  1945  type setProp unistring.String
  1946  
  1947  func (p setProp) exec(vm *vm) {
  1948  	val := vm.stack[vm.sp-1]
  1949  	vm.stack[vm.sp-2].ToObject(vm.r).self.setOwnStr(unistring.String(p), val, false)
  1950  	vm.stack[vm.sp-2] = val
  1951  	vm.sp--
  1952  	vm.pc++
  1953  }
  1954  
  1955  type setPropP unistring.String
  1956  
  1957  func (p setPropP) exec(vm *vm) {
  1958  	val := vm.stack[vm.sp-1]
  1959  	vm.stack[vm.sp-2].ToObject(vm.r).self.setOwnStr(unistring.String(p), val, false)
  1960  	vm.sp -= 2
  1961  	vm.pc++
  1962  }
  1963  
  1964  type setPropStrict unistring.String
  1965  
  1966  func (p setPropStrict) exec(vm *vm) {
  1967  	receiver := vm.stack[vm.sp-2]
  1968  	val := vm.stack[vm.sp-1]
  1969  	propName := unistring.String(p)
  1970  	if receiverObj, ok := receiver.(*Object); ok {
  1971  		receiverObj.self.setOwnStr(propName, val, true)
  1972  	} else {
  1973  		base := receiver.ToObject(vm.r)
  1974  		base.setStr(propName, val, receiver, true)
  1975  	}
  1976  
  1977  	vm.stack[vm.sp-2] = val
  1978  	vm.sp--
  1979  	vm.pc++
  1980  }
  1981  
  1982  type setPropRecv unistring.String
  1983  
  1984  func (p setPropRecv) exec(vm *vm) {
  1985  	receiver := vm.stack[vm.sp-3]
  1986  	o := vm.stack[vm.sp-2]
  1987  	val := vm.stack[vm.sp-1]
  1988  	propName := unistring.String(p)
  1989  	if obj, ok := o.(*Object); ok {
  1990  		obj.setStr(propName, val, receiver, false)
  1991  	} else {
  1992  		base := o.ToObject(vm.r)
  1993  		base.setStr(propName, val, receiver, false)
  1994  	}
  1995  
  1996  	vm.stack[vm.sp-3] = val
  1997  	vm.sp -= 2
  1998  	vm.pc++
  1999  }
  2000  
  2001  type setPropRecvStrict unistring.String
  2002  
  2003  func (p setPropRecvStrict) exec(vm *vm) {
  2004  	receiver := vm.stack[vm.sp-3]
  2005  	o := vm.stack[vm.sp-2]
  2006  	val := vm.stack[vm.sp-1]
  2007  	propName := unistring.String(p)
  2008  	if obj, ok := o.(*Object); ok {
  2009  		obj.setStr(propName, val, receiver, true)
  2010  	} else {
  2011  		base := o.ToObject(vm.r)
  2012  		base.setStr(propName, val, receiver, true)
  2013  	}
  2014  
  2015  	vm.stack[vm.sp-3] = val
  2016  	vm.sp -= 2
  2017  	vm.pc++
  2018  }
  2019  
  2020  type setPropRecvP unistring.String
  2021  
  2022  func (p setPropRecvP) exec(vm *vm) {
  2023  	receiver := vm.stack[vm.sp-3]
  2024  	o := vm.stack[vm.sp-2]
  2025  	val := vm.stack[vm.sp-1]
  2026  	propName := unistring.String(p)
  2027  	if obj, ok := o.(*Object); ok {
  2028  		obj.setStr(propName, val, receiver, false)
  2029  	} else {
  2030  		base := o.ToObject(vm.r)
  2031  		base.setStr(propName, val, receiver, false)
  2032  	}
  2033  
  2034  	vm.sp -= 3
  2035  	vm.pc++
  2036  }
  2037  
  2038  type setPropRecvStrictP unistring.String
  2039  
  2040  func (p setPropRecvStrictP) exec(vm *vm) {
  2041  	receiver := vm.stack[vm.sp-3]
  2042  	o := vm.stack[vm.sp-2]
  2043  	val := vm.stack[vm.sp-1]
  2044  	propName := unistring.String(p)
  2045  	if obj, ok := o.(*Object); ok {
  2046  		obj.setStr(propName, val, receiver, true)
  2047  	} else {
  2048  		base := o.ToObject(vm.r)
  2049  		base.setStr(propName, val, receiver, true)
  2050  	}
  2051  
  2052  	vm.sp -= 3
  2053  	vm.pc++
  2054  }
  2055  
  2056  type setPropStrictP unistring.String
  2057  
  2058  func (p setPropStrictP) exec(vm *vm) {
  2059  	receiver := vm.stack[vm.sp-2]
  2060  	val := vm.stack[vm.sp-1]
  2061  	propName := unistring.String(p)
  2062  	if receiverObj, ok := receiver.(*Object); ok {
  2063  		receiverObj.self.setOwnStr(propName, val, true)
  2064  	} else {
  2065  		base := receiver.ToObject(vm.r)
  2066  		base.setStr(propName, val, receiver, true)
  2067  	}
  2068  
  2069  	vm.sp -= 2
  2070  	vm.pc++
  2071  }
  2072  
  2073  type putProp unistring.String
  2074  
  2075  func (p putProp) exec(vm *vm) {
  2076  	vm.r.toObject(vm.stack[vm.sp-2]).self._putProp(unistring.String(p), vm.stack[vm.sp-1], true, true, true)
  2077  
  2078  	vm.sp--
  2079  	vm.pc++
  2080  }
  2081  
  2082  // used in class declarations instead of putProp because DefineProperty must be observable by Proxy
  2083  type definePropKeyed unistring.String
  2084  
  2085  func (p definePropKeyed) exec(vm *vm) {
  2086  	vm.r.toObject(vm.stack[vm.sp-2]).self.defineOwnPropertyStr(unistring.String(p), PropertyDescriptor{
  2087  		Value:        vm.stack[vm.sp-1],
  2088  		Writable:     FLAG_TRUE,
  2089  		Configurable: FLAG_TRUE,
  2090  		Enumerable:   FLAG_TRUE,
  2091  	}, true)
  2092  
  2093  	vm.sp--
  2094  	vm.pc++
  2095  }
  2096  
  2097  type defineProp struct{}
  2098  
  2099  func (defineProp) exec(vm *vm) {
  2100  	vm.r.toObject(vm.stack[vm.sp-3]).defineOwnProperty(vm.stack[vm.sp-2], PropertyDescriptor{
  2101  		Value:        vm.stack[vm.sp-1],
  2102  		Writable:     FLAG_TRUE,
  2103  		Configurable: FLAG_TRUE,
  2104  		Enumerable:   FLAG_TRUE,
  2105  	}, true)
  2106  
  2107  	vm.sp -= 2
  2108  	vm.pc++
  2109  }
  2110  
  2111  type defineMethodKeyed struct {
  2112  	key        unistring.String
  2113  	enumerable bool
  2114  }
  2115  
  2116  func (d *defineMethodKeyed) exec(vm *vm) {
  2117  	obj := vm.r.toObject(vm.stack[vm.sp-2])
  2118  	method := vm.r.toObject(vm.stack[vm.sp-1])
  2119  
  2120  	obj.self.defineOwnPropertyStr(d.key, PropertyDescriptor{
  2121  		Value:        method,
  2122  		Writable:     FLAG_TRUE,
  2123  		Configurable: FLAG_TRUE,
  2124  		Enumerable:   ToFlag(d.enumerable),
  2125  	}, true)
  2126  
  2127  	vm.sp--
  2128  	vm.pc++
  2129  }
  2130  
  2131  type _setProto struct{}
  2132  
  2133  var setProto _setProto
  2134  
  2135  func (_setProto) exec(vm *vm) {
  2136  	vm.r.setObjectProto(vm.stack[vm.sp-2], vm.stack[vm.sp-1])
  2137  
  2138  	vm.sp--
  2139  	vm.pc++
  2140  }
  2141  
  2142  type defineGetterKeyed struct {
  2143  	key        unistring.String
  2144  	enumerable bool
  2145  }
  2146  
  2147  func (s *defineGetterKeyed) exec(vm *vm) {
  2148  	obj := vm.r.toObject(vm.stack[vm.sp-2])
  2149  	val := vm.stack[vm.sp-1]
  2150  	method := vm.r.toObject(val)
  2151  	method.self.defineOwnPropertyStr("name", PropertyDescriptor{
  2152  		Value:        asciiString("get ").Concat(stringValueFromRaw(s.key)),
  2153  		Configurable: FLAG_TRUE,
  2154  	}, true)
  2155  	descr := PropertyDescriptor{
  2156  		Getter:       val,
  2157  		Configurable: FLAG_TRUE,
  2158  		Enumerable:   ToFlag(s.enumerable),
  2159  	}
  2160  
  2161  	obj.self.defineOwnPropertyStr(s.key, descr, true)
  2162  
  2163  	vm.sp--
  2164  	vm.pc++
  2165  }
  2166  
  2167  type defineSetterKeyed struct {
  2168  	key        unistring.String
  2169  	enumerable bool
  2170  }
  2171  
  2172  func (s *defineSetterKeyed) exec(vm *vm) {
  2173  	obj := vm.r.toObject(vm.stack[vm.sp-2])
  2174  	val := vm.stack[vm.sp-1]
  2175  	method := vm.r.toObject(val)
  2176  	method.self.defineOwnPropertyStr("name", PropertyDescriptor{
  2177  		Value:        asciiString("set ").Concat(stringValueFromRaw(s.key)),
  2178  		Configurable: FLAG_TRUE,
  2179  	}, true)
  2180  
  2181  	descr := PropertyDescriptor{
  2182  		Setter:       val,
  2183  		Configurable: FLAG_TRUE,
  2184  		Enumerable:   ToFlag(s.enumerable),
  2185  	}
  2186  
  2187  	obj.self.defineOwnPropertyStr(s.key, descr, true)
  2188  
  2189  	vm.sp--
  2190  	vm.pc++
  2191  }
  2192  
  2193  type defineGetter struct {
  2194  	enumerable bool
  2195  }
  2196  
  2197  func (s *defineGetter) exec(vm *vm) {
  2198  	obj := vm.r.toObject(vm.stack[vm.sp-3])
  2199  	propName := vm.stack[vm.sp-2]
  2200  	val := vm.stack[vm.sp-1]
  2201  	method := vm.r.toObject(val)
  2202  	method.self.defineOwnPropertyStr("name", PropertyDescriptor{
  2203  		Value:        funcName("get ", propName),
  2204  		Configurable: FLAG_TRUE,
  2205  	}, true)
  2206  
  2207  	descr := PropertyDescriptor{
  2208  		Getter:       val,
  2209  		Configurable: FLAG_TRUE,
  2210  		Enumerable:   ToFlag(s.enumerable),
  2211  	}
  2212  
  2213  	obj.defineOwnProperty(propName, descr, true)
  2214  
  2215  	vm.sp -= 2
  2216  	vm.pc++
  2217  }
  2218  
  2219  type defineSetter struct {
  2220  	enumerable bool
  2221  }
  2222  
  2223  func (s *defineSetter) exec(vm *vm) {
  2224  	obj := vm.r.toObject(vm.stack[vm.sp-3])
  2225  	propName := vm.stack[vm.sp-2]
  2226  	val := vm.stack[vm.sp-1]
  2227  	method := vm.r.toObject(val)
  2228  
  2229  	method.self.defineOwnPropertyStr("name", PropertyDescriptor{
  2230  		Value:        funcName("set ", propName),
  2231  		Configurable: FLAG_TRUE,
  2232  	}, true)
  2233  
  2234  	descr := PropertyDescriptor{
  2235  		Setter:       val,
  2236  		Configurable: FLAG_TRUE,
  2237  		Enumerable:   FLAG_TRUE,
  2238  	}
  2239  
  2240  	obj.defineOwnProperty(propName, descr, true)
  2241  
  2242  	vm.sp -= 2
  2243  	vm.pc++
  2244  }
  2245  
  2246  type getProp unistring.String
  2247  
  2248  func (g getProp) exec(vm *vm) {
  2249  	v := vm.stack[vm.sp-1]
  2250  	obj := v.baseObject(vm.r)
  2251  	if obj == nil {
  2252  		vm.throw(vm.r.NewTypeError("Cannot read property '%s' of undefined", g))
  2253  		return
  2254  	}
  2255  	vm.stack[vm.sp-1] = nilSafe(obj.self.getStr(unistring.String(g), v))
  2256  
  2257  	vm.pc++
  2258  }
  2259  
  2260  type getPropRecv unistring.String
  2261  
  2262  func (g getPropRecv) exec(vm *vm) {
  2263  	recv := vm.stack[vm.sp-2]
  2264  	v := vm.stack[vm.sp-1]
  2265  	obj := v.baseObject(vm.r)
  2266  	if obj == nil {
  2267  		vm.throw(vm.r.NewTypeError("Cannot read property '%s' of undefined", g))
  2268  		return
  2269  	}
  2270  	vm.stack[vm.sp-2] = nilSafe(obj.self.getStr(unistring.String(g), recv))
  2271  	vm.sp--
  2272  	vm.pc++
  2273  }
  2274  
  2275  type getPropRecvCallee unistring.String
  2276  
  2277  func (g getPropRecvCallee) exec(vm *vm) {
  2278  	recv := vm.stack[vm.sp-2]
  2279  	v := vm.stack[vm.sp-1]
  2280  	obj := v.baseObject(vm.r)
  2281  	if obj == nil {
  2282  		vm.throw(vm.r.NewTypeError("Cannot read property '%s' of undefined", g))
  2283  		return
  2284  	}
  2285  
  2286  	n := unistring.String(g)
  2287  	prop := obj.self.getStr(n, recv)
  2288  	if prop == nil {
  2289  		prop = memberUnresolved{valueUnresolved{r: vm.r, ref: n}}
  2290  	}
  2291  
  2292  	vm.stack[vm.sp-1] = prop
  2293  	vm.pc++
  2294  }
  2295  
  2296  type getPropCallee unistring.String
  2297  
  2298  func (g getPropCallee) exec(vm *vm) {
  2299  	v := vm.stack[vm.sp-1]
  2300  	obj := v.baseObject(vm.r)
  2301  	n := unistring.String(g)
  2302  	if obj == nil {
  2303  		vm.throw(vm.r.NewTypeError("Cannot read property '%s' of undefined or null", n))
  2304  		return
  2305  	}
  2306  	prop := obj.self.getStr(n, v)
  2307  	if prop == nil {
  2308  		prop = memberUnresolved{valueUnresolved{r: vm.r, ref: n}}
  2309  	}
  2310  	vm.push(prop)
  2311  
  2312  	vm.pc++
  2313  }
  2314  
  2315  type _getElem struct{}
  2316  
  2317  var getElem _getElem
  2318  
  2319  func (_getElem) exec(vm *vm) {
  2320  	v := vm.stack[vm.sp-2]
  2321  	obj := v.baseObject(vm.r)
  2322  	propName := toPropertyKey(vm.stack[vm.sp-1])
  2323  	if obj == nil {
  2324  		vm.throw(vm.r.NewTypeError("Cannot read property '%s' of undefined", propName.String()))
  2325  		return
  2326  	}
  2327  
  2328  	vm.stack[vm.sp-2] = nilSafe(obj.get(propName, v))
  2329  
  2330  	vm.sp--
  2331  	vm.pc++
  2332  }
  2333  
  2334  type _getElemRecv struct{}
  2335  
  2336  var getElemRecv _getElemRecv
  2337  
  2338  func (_getElemRecv) exec(vm *vm) {
  2339  	recv := vm.stack[vm.sp-3]
  2340  	propName := toPropertyKey(vm.stack[vm.sp-2])
  2341  	v := vm.stack[vm.sp-1]
  2342  	obj := v.baseObject(vm.r)
  2343  	if obj == nil {
  2344  		vm.throw(vm.r.NewTypeError("Cannot read property '%s' of undefined", propName.String()))
  2345  		return
  2346  	}
  2347  
  2348  	vm.stack[vm.sp-3] = nilSafe(obj.get(propName, recv))
  2349  
  2350  	vm.sp -= 2
  2351  	vm.pc++
  2352  }
  2353  
  2354  type _getKey struct{}
  2355  
  2356  var getKey _getKey
  2357  
  2358  func (_getKey) exec(vm *vm) {
  2359  	v := vm.stack[vm.sp-2]
  2360  	obj := v.baseObject(vm.r)
  2361  	propName := vm.stack[vm.sp-1]
  2362  	if obj == nil {
  2363  		vm.throw(vm.r.NewTypeError("Cannot read property '%s' of undefined", propName.String()))
  2364  		return
  2365  	}
  2366  
  2367  	vm.stack[vm.sp-2] = nilSafe(obj.get(propName, v))
  2368  
  2369  	vm.sp--
  2370  	vm.pc++
  2371  }
  2372  
  2373  type _getElemCallee struct{}
  2374  
  2375  var getElemCallee _getElemCallee
  2376  
  2377  func (_getElemCallee) exec(vm *vm) {
  2378  	v := vm.stack[vm.sp-2]
  2379  	obj := v.baseObject(vm.r)
  2380  	propName := toPropertyKey(vm.stack[vm.sp-1])
  2381  	if obj == nil {
  2382  		vm.throw(vm.r.NewTypeError("Cannot read property '%s' of undefined", propName.String()))
  2383  		return
  2384  	}
  2385  
  2386  	prop := obj.get(propName, v)
  2387  	if prop == nil {
  2388  		prop = memberUnresolved{valueUnresolved{r: vm.r, ref: propName.string()}}
  2389  	}
  2390  	vm.stack[vm.sp-1] = prop
  2391  
  2392  	vm.pc++
  2393  }
  2394  
  2395  type _getElemRecvCallee struct{}
  2396  
  2397  var getElemRecvCallee _getElemRecvCallee
  2398  
  2399  func (_getElemRecvCallee) exec(vm *vm) {
  2400  	recv := vm.stack[vm.sp-3]
  2401  	v := vm.stack[vm.sp-2]
  2402  	obj := v.baseObject(vm.r)
  2403  	propName := toPropertyKey(vm.stack[vm.sp-1])
  2404  	if obj == nil {
  2405  		vm.throw(vm.r.NewTypeError("Cannot read property '%s' of undefined", propName.String()))
  2406  		return
  2407  	}
  2408  
  2409  	prop := obj.get(propName, recv)
  2410  	if prop == nil {
  2411  		prop = memberUnresolved{valueUnresolved{r: vm.r, ref: propName.string()}}
  2412  	}
  2413  	vm.stack[vm.sp-2] = prop
  2414  	vm.sp--
  2415  
  2416  	vm.pc++
  2417  }
  2418  
  2419  type _dup struct{}
  2420  
  2421  var dup _dup
  2422  
  2423  func (_dup) exec(vm *vm) {
  2424  	vm.push(vm.stack[vm.sp-1])
  2425  	vm.pc++
  2426  }
  2427  
  2428  type dupN uint32
  2429  
  2430  func (d dupN) exec(vm *vm) {
  2431  	vm.push(vm.stack[vm.sp-1-int(d)])
  2432  	vm.pc++
  2433  }
  2434  
  2435  type rdupN uint32
  2436  
  2437  func (d rdupN) exec(vm *vm) {
  2438  	vm.stack[vm.sp-1-int(d)] = vm.stack[vm.sp-1]
  2439  	vm.pc++
  2440  }
  2441  
  2442  type dupLast uint32
  2443  
  2444  func (d dupLast) exec(vm *vm) {
  2445  	e := vm.sp + int(d)
  2446  	vm.stack.expand(e)
  2447  	copy(vm.stack[vm.sp:e], vm.stack[vm.sp-int(d):])
  2448  	vm.sp = e
  2449  	vm.pc++
  2450  }
  2451  
  2452  type _newObject struct{}
  2453  
  2454  var newObject _newObject
  2455  
  2456  func (_newObject) exec(vm *vm) {
  2457  	vm.push(vm.r.NewObject())
  2458  	vm.pc++
  2459  }
  2460  
  2461  type newArray uint32
  2462  
  2463  func (l newArray) exec(vm *vm) {
  2464  	values := make([]Value, 0, l)
  2465  	vm.push(vm.r.newArrayValues(values))
  2466  	vm.pc++
  2467  }
  2468  
  2469  type _pushArrayItem struct{}
  2470  
  2471  var pushArrayItem _pushArrayItem
  2472  
  2473  func (_pushArrayItem) exec(vm *vm) {
  2474  	arr := vm.stack[vm.sp-2].(*Object).self.(*arrayObject)
  2475  	if arr.length < math.MaxUint32 {
  2476  		arr.length++
  2477  	} else {
  2478  		vm.throw(vm.r.newError(vm.r.global.RangeError, "Invalid array length"))
  2479  		return
  2480  	}
  2481  	val := vm.stack[vm.sp-1]
  2482  	arr.values = append(arr.values, val)
  2483  	if val != nil {
  2484  		arr.objCount++
  2485  	}
  2486  	vm.sp--
  2487  	vm.pc++
  2488  }
  2489  
  2490  type _pushArraySpread struct{}
  2491  
  2492  var pushArraySpread _pushArraySpread
  2493  
  2494  func (_pushArraySpread) exec(vm *vm) {
  2495  	arr := vm.stack[vm.sp-2].(*Object).self.(*arrayObject)
  2496  	vm.r.getIterator(vm.stack[vm.sp-1], nil).iterate(func(val Value) {
  2497  		if arr.length < math.MaxUint32 {
  2498  			arr.length++
  2499  		} else {
  2500  			vm.throw(vm.r.newError(vm.r.global.RangeError, "Invalid array length"))
  2501  			return
  2502  		}
  2503  		arr.values = append(arr.values, val)
  2504  		arr.objCount++
  2505  	})
  2506  	vm.sp--
  2507  	vm.pc++
  2508  }
  2509  
  2510  type _pushSpread struct{}
  2511  
  2512  var pushSpread _pushSpread
  2513  
  2514  func (_pushSpread) exec(vm *vm) {
  2515  	vm.sp--
  2516  	obj := vm.stack[vm.sp]
  2517  	vm.r.getIterator(obj, nil).iterate(func(val Value) {
  2518  		vm.push(val)
  2519  	})
  2520  	vm.pc++
  2521  }
  2522  
  2523  type _newArrayFromIter struct{}
  2524  
  2525  var newArrayFromIter _newArrayFromIter
  2526  
  2527  func (_newArrayFromIter) exec(vm *vm) {
  2528  	var values []Value
  2529  	l := len(vm.iterStack) - 1
  2530  	iter := vm.iterStack[l].iter
  2531  	vm.iterStack[l] = iterStackItem{}
  2532  	vm.iterStack = vm.iterStack[:l]
  2533  	if iter.iterator != nil {
  2534  		iter.iterate(func(val Value) {
  2535  			values = append(values, val)
  2536  		})
  2537  	}
  2538  	vm.push(vm.r.newArrayValues(values))
  2539  	vm.pc++
  2540  }
  2541  
  2542  type newRegexp struct {
  2543  	pattern *regexpPattern
  2544  	src     String
  2545  }
  2546  
  2547  func (n *newRegexp) exec(vm *vm) {
  2548  	vm.push(vm.r.newRegExpp(n.pattern.clone(), n.src, vm.r.global.RegExpPrototype).val)
  2549  	vm.pc++
  2550  }
  2551  
  2552  func (vm *vm) setLocalLex(s int) {
  2553  	v := vm.stack[vm.sp-1]
  2554  	level := s >> 24
  2555  	idx := uint32(s & 0x00FFFFFF)
  2556  	stash := vm.stash
  2557  	for i := 0; i < level; i++ {
  2558  		stash = stash.outer
  2559  	}
  2560  	p := &stash.values[idx]
  2561  	if *p == nil {
  2562  		panic(errAccessBeforeInit)
  2563  	}
  2564  	*p = v
  2565  	vm.pc++
  2566  }
  2567  
  2568  func (vm *vm) initLocal(s int) {
  2569  	v := vm.stack[vm.sp-1]
  2570  	level := s >> 24
  2571  	idx := uint32(s & 0x00FFFFFF)
  2572  	stash := vm.stash
  2573  	for i := 0; i < level; i++ {
  2574  		stash = stash.outer
  2575  	}
  2576  	stash.initByIdx(idx, v)
  2577  	vm.pc++
  2578  }
  2579  
  2580  type storeStash uint32
  2581  
  2582  func (s storeStash) exec(vm *vm) {
  2583  	vm.initLocal(int(s))
  2584  }
  2585  
  2586  type storeStashP uint32
  2587  
  2588  func (s storeStashP) exec(vm *vm) {
  2589  	vm.initLocal(int(s))
  2590  	vm.sp--
  2591  }
  2592  
  2593  type storeStashLex uint32
  2594  
  2595  func (s storeStashLex) exec(vm *vm) {
  2596  	vm.setLocalLex(int(s))
  2597  }
  2598  
  2599  type storeStashLexP uint32
  2600  
  2601  func (s storeStashLexP) exec(vm *vm) {
  2602  	vm.setLocalLex(int(s))
  2603  	vm.sp--
  2604  }
  2605  
  2606  type initStash uint32
  2607  
  2608  func (s initStash) exec(vm *vm) {
  2609  	vm.initLocal(int(s))
  2610  }
  2611  
  2612  type initStashP uint32
  2613  
  2614  func (s initStashP) exec(vm *vm) {
  2615  	vm.initLocal(int(s))
  2616  	vm.sp--
  2617  }
  2618  
  2619  type initGlobalP unistring.String
  2620  
  2621  func (s initGlobalP) exec(vm *vm) {
  2622  	vm.sp--
  2623  	vm.r.global.stash.initByName(unistring.String(s), vm.stack[vm.sp])
  2624  	vm.pc++
  2625  }
  2626  
  2627  type initGlobal unistring.String
  2628  
  2629  func (s initGlobal) exec(vm *vm) {
  2630  	vm.r.global.stash.initByName(unistring.String(s), vm.stack[vm.sp])
  2631  	vm.pc++
  2632  }
  2633  
  2634  type resolveVar1 unistring.String
  2635  
  2636  func (s resolveVar1) exec(vm *vm) {
  2637  	name := unistring.String(s)
  2638  	var ref ref
  2639  	for stash := vm.stash; stash != nil; stash = stash.outer {
  2640  		ref = stash.getRefByName(name, false)
  2641  		if ref != nil {
  2642  			goto end
  2643  		}
  2644  	}
  2645  
  2646  	ref = &objRef{
  2647  		base:    vm.r.globalObject,
  2648  		name:    name,
  2649  		binding: true,
  2650  	}
  2651  
  2652  end:
  2653  	vm.refStack = append(vm.refStack, ref)
  2654  	vm.pc++
  2655  }
  2656  
  2657  type deleteVar unistring.String
  2658  
  2659  func (d deleteVar) exec(vm *vm) {
  2660  	name := unistring.String(d)
  2661  	ret := true
  2662  	for stash := vm.stash; stash != nil; stash = stash.outer {
  2663  		if stash.obj != nil {
  2664  			if stashObjHas(stash.obj, name) {
  2665  				ret = stash.obj.self.deleteStr(name, false)
  2666  				goto end
  2667  			}
  2668  		} else {
  2669  			if idx, exists := stash.names[name]; exists {
  2670  				if idx&(maskVar|maskDeletable) == maskVar|maskDeletable {
  2671  					stash.deleteBinding(name)
  2672  				} else {
  2673  					ret = false
  2674  				}
  2675  				goto end
  2676  			}
  2677  		}
  2678  	}
  2679  
  2680  	if vm.r.globalObject.self.hasPropertyStr(name) {
  2681  		ret = vm.r.globalObject.self.deleteStr(name, false)
  2682  	}
  2683  
  2684  end:
  2685  	if ret {
  2686  		vm.push(valueTrue)
  2687  	} else {
  2688  		vm.push(valueFalse)
  2689  	}
  2690  	vm.pc++
  2691  }
  2692  
  2693  type deleteGlobal unistring.String
  2694  
  2695  func (d deleteGlobal) exec(vm *vm) {
  2696  	name := unistring.String(d)
  2697  	var ret bool
  2698  	if vm.r.globalObject.self.hasPropertyStr(name) {
  2699  		ret = vm.r.globalObject.self.deleteStr(name, false)
  2700  		if ret {
  2701  			delete(vm.r.global.varNames, name)
  2702  		}
  2703  	} else {
  2704  		ret = true
  2705  	}
  2706  	if ret {
  2707  		vm.push(valueTrue)
  2708  	} else {
  2709  		vm.push(valueFalse)
  2710  	}
  2711  	vm.pc++
  2712  }
  2713  
  2714  type resolveVar1Strict unistring.String
  2715  
  2716  func (s resolveVar1Strict) exec(vm *vm) {
  2717  	name := unistring.String(s)
  2718  	var ref ref
  2719  	for stash := vm.stash; stash != nil; stash = stash.outer {
  2720  		ref = stash.getRefByName(name, true)
  2721  		if ref != nil {
  2722  			goto end
  2723  		}
  2724  	}
  2725  
  2726  	if vm.r.globalObject.self.hasPropertyStr(name) {
  2727  		ref = &objRef{
  2728  			base:    vm.r.globalObject,
  2729  			name:    name,
  2730  			binding: true,
  2731  			strict:  true,
  2732  		}
  2733  		goto end
  2734  	}
  2735  
  2736  	ref = &unresolvedRef{
  2737  		runtime: vm.r,
  2738  		name:    name,
  2739  	}
  2740  
  2741  end:
  2742  	vm.refStack = append(vm.refStack, ref)
  2743  	vm.pc++
  2744  }
  2745  
  2746  type setGlobal unistring.String
  2747  
  2748  func (s setGlobal) exec(vm *vm) {
  2749  	vm.r.setGlobal(unistring.String(s), vm.peek(), false)
  2750  	vm.pc++
  2751  }
  2752  
  2753  type setGlobalStrict unistring.String
  2754  
  2755  func (s setGlobalStrict) exec(vm *vm) {
  2756  	vm.r.setGlobal(unistring.String(s), vm.peek(), true)
  2757  	vm.pc++
  2758  }
  2759  
  2760  // Load a var from stash
  2761  type loadStash uint32
  2762  
  2763  func (g loadStash) exec(vm *vm) {
  2764  	level := int(g >> 24)
  2765  	idx := uint32(g & 0x00FFFFFF)
  2766  	stash := vm.stash
  2767  	for i := 0; i < level; i++ {
  2768  		stash = stash.outer
  2769  	}
  2770  
  2771  	vm.push(nilSafe(stash.getByIdx(idx)))
  2772  	vm.pc++
  2773  }
  2774  
  2775  // Load a lexical binding from stash
  2776  type loadStashLex uint32
  2777  
  2778  func (g loadStashLex) exec(vm *vm) {
  2779  	level := int(g >> 24)
  2780  	idx := uint32(g & 0x00FFFFFF)
  2781  	stash := vm.stash
  2782  	for i := 0; i < level; i++ {
  2783  		stash = stash.outer
  2784  	}
  2785  
  2786  	v := stash.getByIdx(idx)
  2787  	if v == nil {
  2788  		vm.throw(errAccessBeforeInit)
  2789  		return
  2790  	}
  2791  	vm.push(v)
  2792  	vm.pc++
  2793  }
  2794  
  2795  // scan dynamic stashes up to the given level (encoded as 8 most significant bits of idx), if not found
  2796  // return the indexed var binding value from stash
  2797  type loadMixed struct {
  2798  	name   unistring.String
  2799  	idx    uint32
  2800  	callee bool
  2801  }
  2802  
  2803  func (g *loadMixed) exec(vm *vm) {
  2804  	level := int(g.idx >> 24)
  2805  	idx := g.idx & 0x00FFFFFF
  2806  	stash := vm.stash
  2807  	name := g.name
  2808  	for i := 0; i < level; i++ {
  2809  		if v, found := stash.getByName(name); found {
  2810  			if g.callee {
  2811  				if stash.obj != nil {
  2812  					vm.push(stash.obj)
  2813  				} else {
  2814  					vm.push(_undefined)
  2815  				}
  2816  			}
  2817  			vm.push(v)
  2818  			goto end
  2819  		}
  2820  		stash = stash.outer
  2821  	}
  2822  	if g.callee {
  2823  		vm.push(_undefined)
  2824  	}
  2825  	if stash != nil {
  2826  		vm.push(nilSafe(stash.getByIdx(idx)))
  2827  	}
  2828  end:
  2829  	vm.pc++
  2830  }
  2831  
  2832  // scan dynamic stashes up to the given level (encoded as 8 most significant bits of idx), if not found
  2833  // return the indexed lexical binding value from stash
  2834  type loadMixedLex loadMixed
  2835  
  2836  func (g *loadMixedLex) exec(vm *vm) {
  2837  	level := int(g.idx >> 24)
  2838  	idx := g.idx & 0x00FFFFFF
  2839  	stash := vm.stash
  2840  	name := g.name
  2841  	for i := 0; i < level; i++ {
  2842  		if v, found := stash.getByName(name); found {
  2843  			if g.callee {
  2844  				if stash.obj != nil {
  2845  					vm.push(stash.obj)
  2846  				} else {
  2847  					vm.push(_undefined)
  2848  				}
  2849  			}
  2850  			vm.push(v)
  2851  			goto end
  2852  		}
  2853  		stash = stash.outer
  2854  	}
  2855  	if g.callee {
  2856  		vm.push(_undefined)
  2857  	}
  2858  	if stash != nil {
  2859  		v := stash.getByIdx(idx)
  2860  		if v == nil {
  2861  			vm.throw(errAccessBeforeInit)
  2862  			return
  2863  		}
  2864  		vm.push(v)
  2865  	}
  2866  end:
  2867  	vm.pc++
  2868  }
  2869  
  2870  // scan dynamic stashes up to the given level (encoded as 8 most significant bits of idx), if not found
  2871  // return the indexed var binding value from stack
  2872  type loadMixedStack struct {
  2873  	name   unistring.String
  2874  	idx    int
  2875  	level  uint8
  2876  	callee bool
  2877  }
  2878  
  2879  // same as loadMixedStack, but the args have been moved to stash (therefore stack layout is different)
  2880  type loadMixedStack1 loadMixedStack
  2881  
  2882  func (g *loadMixedStack) exec(vm *vm) {
  2883  	stash := vm.stash
  2884  	name := g.name
  2885  	level := int(g.level)
  2886  	for i := 0; i < level; i++ {
  2887  		if v, found := stash.getByName(name); found {
  2888  			if g.callee {
  2889  				if stash.obj != nil {
  2890  					vm.push(stash.obj)
  2891  				} else {
  2892  					vm.push(_undefined)
  2893  				}
  2894  			}
  2895  			vm.push(v)
  2896  			goto end
  2897  		}
  2898  		stash = stash.outer
  2899  	}
  2900  	if g.callee {
  2901  		vm.push(_undefined)
  2902  	}
  2903  	loadStack(g.idx).exec(vm)
  2904  	return
  2905  end:
  2906  	vm.pc++
  2907  }
  2908  
  2909  func (g *loadMixedStack1) exec(vm *vm) {
  2910  	stash := vm.stash
  2911  	name := g.name
  2912  	level := int(g.level)
  2913  	for i := 0; i < level; i++ {
  2914  		if v, found := stash.getByName(name); found {
  2915  			if g.callee {
  2916  				if stash.obj != nil {
  2917  					vm.push(stash.obj)
  2918  				} else {
  2919  					vm.push(_undefined)
  2920  				}
  2921  			}
  2922  			vm.push(v)
  2923  			goto end
  2924  		}
  2925  		stash = stash.outer
  2926  	}
  2927  	if g.callee {
  2928  		vm.push(_undefined)
  2929  	}
  2930  	loadStack1(g.idx).exec(vm)
  2931  	return
  2932  end:
  2933  	vm.pc++
  2934  }
  2935  
  2936  type loadMixedStackLex loadMixedStack
  2937  
  2938  // same as loadMixedStackLex but when the arguments have been moved into stash
  2939  type loadMixedStack1Lex loadMixedStack
  2940  
  2941  func (g *loadMixedStackLex) exec(vm *vm) {
  2942  	stash := vm.stash
  2943  	name := g.name
  2944  	level := int(g.level)
  2945  	for i := 0; i < level; i++ {
  2946  		if v, found := stash.getByName(name); found {
  2947  			if g.callee {
  2948  				if stash.obj != nil {
  2949  					vm.push(stash.obj)
  2950  				} else {
  2951  					vm.push(_undefined)
  2952  				}
  2953  			}
  2954  			vm.push(v)
  2955  			goto end
  2956  		}
  2957  		stash = stash.outer
  2958  	}
  2959  	if g.callee {
  2960  		vm.push(_undefined)
  2961  	}
  2962  	loadStackLex(g.idx).exec(vm)
  2963  	return
  2964  end:
  2965  	vm.pc++
  2966  }
  2967  
  2968  func (g *loadMixedStack1Lex) exec(vm *vm) {
  2969  	stash := vm.stash
  2970  	name := g.name
  2971  	level := int(g.level)
  2972  	for i := 0; i < level; i++ {
  2973  		if v, found := stash.getByName(name); found {
  2974  			if g.callee {
  2975  				if stash.obj != nil {
  2976  					vm.push(stash.obj)
  2977  				} else {
  2978  					vm.push(_undefined)
  2979  				}
  2980  			}
  2981  			vm.push(v)
  2982  			goto end
  2983  		}
  2984  		stash = stash.outer
  2985  	}
  2986  	if g.callee {
  2987  		vm.push(_undefined)
  2988  	}
  2989  	loadStack1Lex(g.idx).exec(vm)
  2990  	return
  2991  end:
  2992  	vm.pc++
  2993  }
  2994  
  2995  type resolveMixed struct {
  2996  	name   unistring.String
  2997  	idx    uint32
  2998  	typ    varType
  2999  	strict bool
  3000  }
  3001  
  3002  func newStashRef(typ varType, name unistring.String, v *[]Value, idx int) ref {
  3003  	switch typ {
  3004  	case varTypeVar:
  3005  		return &stashRef{
  3006  			n:   name,
  3007  			v:   v,
  3008  			idx: idx,
  3009  		}
  3010  	case varTypeLet:
  3011  		return &stashRefLex{
  3012  			stashRef: stashRef{
  3013  				n:   name,
  3014  				v:   v,
  3015  				idx: idx,
  3016  			},
  3017  		}
  3018  	case varTypeConst, varTypeStrictConst:
  3019  		return &stashRefConst{
  3020  			stashRefLex: stashRefLex{
  3021  				stashRef: stashRef{
  3022  					n:   name,
  3023  					v:   v,
  3024  					idx: idx,
  3025  				},
  3026  			},
  3027  			strictConst: typ == varTypeStrictConst,
  3028  		}
  3029  	}
  3030  	panic("unsupported var type")
  3031  }
  3032  
  3033  func (r *resolveMixed) exec(vm *vm) {
  3034  	level := int(r.idx >> 24)
  3035  	idx := r.idx & 0x00FFFFFF
  3036  	stash := vm.stash
  3037  	var ref ref
  3038  	for i := 0; i < level; i++ {
  3039  		ref = stash.getRefByName(r.name, r.strict)
  3040  		if ref != nil {
  3041  			goto end
  3042  		}
  3043  		stash = stash.outer
  3044  	}
  3045  
  3046  	if stash != nil {
  3047  		ref = newStashRef(r.typ, r.name, &stash.values, int(idx))
  3048  		goto end
  3049  	}
  3050  
  3051  	ref = &unresolvedRef{
  3052  		runtime: vm.r,
  3053  		name:    r.name,
  3054  	}
  3055  
  3056  end:
  3057  	vm.refStack = append(vm.refStack, ref)
  3058  	vm.pc++
  3059  }
  3060  
  3061  type resolveMixedStack struct {
  3062  	name   unistring.String
  3063  	idx    int
  3064  	typ    varType
  3065  	level  uint8
  3066  	strict bool
  3067  }
  3068  
  3069  type resolveMixedStack1 resolveMixedStack
  3070  
  3071  func (r *resolveMixedStack) exec(vm *vm) {
  3072  	level := int(r.level)
  3073  	stash := vm.stash
  3074  	var ref ref
  3075  	var idx int
  3076  	for i := 0; i < level; i++ {
  3077  		ref = stash.getRefByName(r.name, r.strict)
  3078  		if ref != nil {
  3079  			goto end
  3080  		}
  3081  		stash = stash.outer
  3082  	}
  3083  
  3084  	if r.idx > 0 {
  3085  		idx = vm.sb + vm.args + r.idx
  3086  	} else {
  3087  		idx = vm.sb - r.idx
  3088  	}
  3089  
  3090  	ref = newStashRef(r.typ, r.name, (*[]Value)(&vm.stack), idx)
  3091  
  3092  end:
  3093  	vm.refStack = append(vm.refStack, ref)
  3094  	vm.pc++
  3095  }
  3096  
  3097  func (r *resolveMixedStack1) exec(vm *vm) {
  3098  	level := int(r.level)
  3099  	stash := vm.stash
  3100  	var ref ref
  3101  	for i := 0; i < level; i++ {
  3102  		ref = stash.getRefByName(r.name, r.strict)
  3103  		if ref != nil {
  3104  			goto end
  3105  		}
  3106  		stash = stash.outer
  3107  	}
  3108  
  3109  	ref = newStashRef(r.typ, r.name, (*[]Value)(&vm.stack), vm.sb+r.idx)
  3110  
  3111  end:
  3112  	vm.refStack = append(vm.refStack, ref)
  3113  	vm.pc++
  3114  }
  3115  
  3116  type _getValue struct{}
  3117  
  3118  var getValue _getValue
  3119  
  3120  func (_getValue) exec(vm *vm) {
  3121  	ref := vm.refStack[len(vm.refStack)-1]
  3122  	if v := ref.get(); v != nil {
  3123  		vm.push(v)
  3124  	} else {
  3125  		vm.throw(vm.r.newReferenceError(ref.refname()))
  3126  		return
  3127  	}
  3128  	vm.pc++
  3129  }
  3130  
  3131  type _putValue struct{}
  3132  
  3133  var putValue _putValue
  3134  
  3135  func (_putValue) exec(vm *vm) {
  3136  	l := len(vm.refStack) - 1
  3137  	ref := vm.refStack[l]
  3138  	vm.refStack[l] = nil
  3139  	vm.refStack = vm.refStack[:l]
  3140  	ref.set(vm.stack[vm.sp-1])
  3141  	vm.pc++
  3142  }
  3143  
  3144  type _putValueP struct{}
  3145  
  3146  var putValueP _putValueP
  3147  
  3148  func (_putValueP) exec(vm *vm) {
  3149  	l := len(vm.refStack) - 1
  3150  	ref := vm.refStack[l]
  3151  	vm.refStack[l] = nil
  3152  	vm.refStack = vm.refStack[:l]
  3153  	ref.set(vm.stack[vm.sp-1])
  3154  	vm.sp--
  3155  	vm.pc++
  3156  }
  3157  
  3158  type _initValueP struct{}
  3159  
  3160  var initValueP _initValueP
  3161  
  3162  func (_initValueP) exec(vm *vm) {
  3163  	l := len(vm.refStack) - 1
  3164  	ref := vm.refStack[l]
  3165  	vm.refStack[l] = nil
  3166  	vm.refStack = vm.refStack[:l]
  3167  	ref.init(vm.stack[vm.sp-1])
  3168  	vm.sp--
  3169  	vm.pc++
  3170  }
  3171  
  3172  type loadDynamic unistring.String
  3173  
  3174  func (n loadDynamic) exec(vm *vm) {
  3175  	name := unistring.String(n)
  3176  	var val Value
  3177  	for stash := vm.stash; stash != nil; stash = stash.outer {
  3178  		if v, exists := stash.getByName(name); exists {
  3179  			val = v
  3180  			break
  3181  		}
  3182  	}
  3183  	if val == nil {
  3184  		val = vm.r.globalObject.self.getStr(name, nil)
  3185  		if val == nil {
  3186  			vm.throw(vm.r.newReferenceError(name))
  3187  			return
  3188  		}
  3189  	}
  3190  	vm.push(val)
  3191  	vm.pc++
  3192  }
  3193  
  3194  type loadDynamicRef unistring.String
  3195  
  3196  func (n loadDynamicRef) exec(vm *vm) {
  3197  	name := unistring.String(n)
  3198  	var val Value
  3199  	for stash := vm.stash; stash != nil; stash = stash.outer {
  3200  		if v, exists := stash.getByName(name); exists {
  3201  			val = v
  3202  			break
  3203  		}
  3204  	}
  3205  	if val == nil {
  3206  		val = vm.r.globalObject.self.getStr(name, nil)
  3207  		if val == nil {
  3208  			val = valueUnresolved{r: vm.r, ref: name}
  3209  		}
  3210  	}
  3211  	vm.push(val)
  3212  	vm.pc++
  3213  }
  3214  
  3215  type loadDynamicCallee unistring.String
  3216  
  3217  func (n loadDynamicCallee) exec(vm *vm) {
  3218  	name := unistring.String(n)
  3219  	var val Value
  3220  	var callee *Object
  3221  	for stash := vm.stash; stash != nil; stash = stash.outer {
  3222  		if v, exists := stash.getByName(name); exists {
  3223  			callee = stash.obj
  3224  			val = v
  3225  			break
  3226  		}
  3227  	}
  3228  	if val == nil {
  3229  		val = vm.r.globalObject.self.getStr(name, nil)
  3230  		if val == nil {
  3231  			val = valueUnresolved{r: vm.r, ref: name}
  3232  		}
  3233  	}
  3234  	if callee != nil {
  3235  		vm.push(callee)
  3236  	} else {
  3237  		vm.push(_undefined)
  3238  	}
  3239  	vm.push(val)
  3240  	vm.pc++
  3241  }
  3242  
  3243  type _pop struct{}
  3244  
  3245  var pop _pop
  3246  
  3247  func (_pop) exec(vm *vm) {
  3248  	vm.sp--
  3249  	vm.pc++
  3250  }
  3251  
  3252  func (vm *vm) callEval(n int, strict bool) {
  3253  	if vm.r.toObject(vm.stack[vm.sp-n-1]) == vm.r.global.Eval {
  3254  		if n > 0 {
  3255  			srcVal := vm.stack[vm.sp-n]
  3256  			if src, ok := srcVal.(String); ok {
  3257  				ret := vm.r.eval(src, true, strict)
  3258  				vm.stack[vm.sp-n-2] = ret
  3259  			} else {
  3260  				vm.stack[vm.sp-n-2] = srcVal
  3261  			}
  3262  		} else {
  3263  			vm.stack[vm.sp-n-2] = _undefined
  3264  		}
  3265  
  3266  		vm.sp -= n + 1
  3267  		vm.pc++
  3268  	} else {
  3269  		call(n).exec(vm)
  3270  	}
  3271  }
  3272  
  3273  type callEval uint32
  3274  
  3275  func (numargs callEval) exec(vm *vm) {
  3276  	vm.callEval(int(numargs), false)
  3277  }
  3278  
  3279  type callEvalStrict uint32
  3280  
  3281  func (numargs callEvalStrict) exec(vm *vm) {
  3282  	vm.callEval(int(numargs), true)
  3283  }
  3284  
  3285  type _callEvalVariadic struct{}
  3286  
  3287  var callEvalVariadic _callEvalVariadic
  3288  
  3289  func (_callEvalVariadic) exec(vm *vm) {
  3290  	vm.callEval(vm.countVariadicArgs()-2, false)
  3291  }
  3292  
  3293  type _callEvalVariadicStrict struct{}
  3294  
  3295  var callEvalVariadicStrict _callEvalVariadicStrict
  3296  
  3297  func (_callEvalVariadicStrict) exec(vm *vm) {
  3298  	vm.callEval(vm.countVariadicArgs()-2, true)
  3299  }
  3300  
  3301  type _boxThis struct{}
  3302  
  3303  var boxThis _boxThis
  3304  
  3305  func (_boxThis) exec(vm *vm) {
  3306  	v := vm.stack[vm.sb]
  3307  	if v == _undefined || v == _null {
  3308  		vm.stack[vm.sb] = vm.r.globalObject
  3309  	} else {
  3310  		vm.stack[vm.sb] = v.ToObject(vm.r)
  3311  	}
  3312  	vm.pc++
  3313  }
  3314  
  3315  var variadicMarker Value = newSymbol(asciiString("[variadic marker]"))
  3316  
  3317  type _startVariadic struct{}
  3318  
  3319  var startVariadic _startVariadic
  3320  
  3321  func (_startVariadic) exec(vm *vm) {
  3322  	vm.push(variadicMarker)
  3323  	vm.pc++
  3324  }
  3325  
  3326  type _callVariadic struct{}
  3327  
  3328  var callVariadic _callVariadic
  3329  
  3330  func (vm *vm) countVariadicArgs() int {
  3331  	count := 0
  3332  	for i := vm.sp - 1; i >= 0; i-- {
  3333  		if vm.stack[i] == variadicMarker {
  3334  			return count
  3335  		}
  3336  		count++
  3337  	}
  3338  	panic("Variadic marker was not found. Compiler bug.")
  3339  }
  3340  
  3341  func (_callVariadic) exec(vm *vm) {
  3342  	call(vm.countVariadicArgs() - 2).exec(vm)
  3343  }
  3344  
  3345  type _endVariadic struct{}
  3346  
  3347  var endVariadic _endVariadic
  3348  
  3349  func (_endVariadic) exec(vm *vm) {
  3350  	vm.sp--
  3351  	vm.stack[vm.sp-1] = vm.stack[vm.sp]
  3352  	vm.pc++
  3353  }
  3354  
  3355  type call uint32
  3356  
  3357  func (numargs call) exec(vm *vm) {
  3358  	// this
  3359  	// callee
  3360  	// arg0
  3361  	// ...
  3362  	// arg<numargs-1>
  3363  	n := int(numargs)
  3364  	v := vm.stack[vm.sp-n-1] // callee
  3365  	obj := vm.toCallee(v)
  3366  	obj.self.vmCall(vm, n)
  3367  }
  3368  
  3369  func (vm *vm) clearStack() {
  3370  	sp := vm.sp
  3371  	stackTail := vm.stack[sp:]
  3372  	for i := range stackTail {
  3373  		stackTail[i] = nil
  3374  	}
  3375  	vm.stack = vm.stack[:sp]
  3376  }
  3377  
  3378  type enterBlock struct {
  3379  	names     map[unistring.String]uint32
  3380  	stashSize uint32
  3381  	stackSize uint32
  3382  }
  3383  
  3384  func (e *enterBlock) exec(vm *vm) {
  3385  	if e.stashSize > 0 {
  3386  		vm.newStash()
  3387  		vm.stash.values = make([]Value, e.stashSize)
  3388  		if len(e.names) > 0 {
  3389  			vm.stash.names = e.names
  3390  		}
  3391  	}
  3392  	ss := int(e.stackSize)
  3393  	vm.stack.expand(vm.sp + ss - 1)
  3394  	vv := vm.stack[vm.sp : vm.sp+ss]
  3395  	for i := range vv {
  3396  		vv[i] = nil
  3397  	}
  3398  	vm.sp += ss
  3399  	vm.pc++
  3400  }
  3401  
  3402  type enterCatchBlock struct {
  3403  	names     map[unistring.String]uint32
  3404  	stashSize uint32
  3405  	stackSize uint32
  3406  }
  3407  
  3408  func (e *enterCatchBlock) exec(vm *vm) {
  3409  	vm.newStash()
  3410  	vm.stash.values = make([]Value, e.stashSize)
  3411  	if len(e.names) > 0 {
  3412  		vm.stash.names = e.names
  3413  	}
  3414  	vm.sp--
  3415  	vm.stash.values[0] = vm.stack[vm.sp]
  3416  	ss := int(e.stackSize)
  3417  	vm.stack.expand(vm.sp + ss - 1)
  3418  	vv := vm.stack[vm.sp : vm.sp+ss]
  3419  	for i := range vv {
  3420  		vv[i] = nil
  3421  	}
  3422  	vm.sp += ss
  3423  	vm.pc++
  3424  }
  3425  
  3426  type leaveBlock struct {
  3427  	stackSize uint32
  3428  	popStash  bool
  3429  }
  3430  
  3431  func (l *leaveBlock) exec(vm *vm) {
  3432  	if l.popStash {
  3433  		vm.stash = vm.stash.outer
  3434  	}
  3435  	if ss := l.stackSize; ss > 0 {
  3436  		vm.sp -= int(ss)
  3437  	}
  3438  	vm.pc++
  3439  }
  3440  
  3441  type enterFunc struct {
  3442  	names       map[unistring.String]uint32
  3443  	stashSize   uint32
  3444  	stackSize   uint32
  3445  	numArgs     uint32
  3446  	funcType    funcType
  3447  	argsToStash bool
  3448  	extensible  bool
  3449  }
  3450  
  3451  func (e *enterFunc) exec(vm *vm) {
  3452  	// Input stack:
  3453  	//
  3454  	// callee
  3455  	// this
  3456  	// arg0
  3457  	// ...
  3458  	// argN
  3459  	// <- sp
  3460  
  3461  	// Output stack:
  3462  	//
  3463  	// this <- sb
  3464  	// <local stack vars...>
  3465  	// <- sp
  3466  	sp := vm.sp
  3467  	vm.sb = sp - vm.args - 1
  3468  	vm.newStash()
  3469  	stash := vm.stash
  3470  	stash.funcType = e.funcType
  3471  	stash.values = make([]Value, e.stashSize)
  3472  	if len(e.names) > 0 {
  3473  		if e.extensible {
  3474  			m := make(map[unistring.String]uint32, len(e.names))
  3475  			for name, idx := range e.names {
  3476  				m[name] = idx
  3477  			}
  3478  			stash.names = m
  3479  		} else {
  3480  			stash.names = e.names
  3481  		}
  3482  	}
  3483  
  3484  	ss := int(e.stackSize)
  3485  	ea := 0
  3486  	if e.argsToStash {
  3487  		offset := vm.args - int(e.numArgs)
  3488  		copy(stash.values, vm.stack[sp-vm.args:sp])
  3489  		if offset > 0 {
  3490  			vm.stash.extraArgs = make([]Value, offset)
  3491  			copy(stash.extraArgs, vm.stack[sp-offset:])
  3492  		} else {
  3493  			vv := stash.values[vm.args:e.numArgs]
  3494  			for i := range vv {
  3495  				vv[i] = _undefined
  3496  			}
  3497  		}
  3498  		sp -= vm.args
  3499  	} else {
  3500  		d := int(e.numArgs) - vm.args
  3501  		if d > 0 {
  3502  			ss += d
  3503  			ea = d
  3504  			vm.args = int(e.numArgs)
  3505  		}
  3506  	}
  3507  	vm.stack.expand(sp + ss - 1)
  3508  	if ea > 0 {
  3509  		vv := vm.stack[sp : vm.sp+ea]
  3510  		for i := range vv {
  3511  			vv[i] = _undefined
  3512  		}
  3513  	}
  3514  	vv := vm.stack[sp+ea : sp+ss]
  3515  	for i := range vv {
  3516  		vv[i] = nil
  3517  	}
  3518  	vm.sp = sp + ss
  3519  	vm.pc++
  3520  }
  3521  
  3522  // Similar to enterFunc, but for when arguments may be accessed before they are initialised,
  3523  // e.g. by an eval() code or from a closure, or from an earlier initialiser code.
  3524  // In this case the arguments remain on stack, first argsToCopy of them are copied to the stash.
  3525  type enterFunc1 struct {
  3526  	names      map[unistring.String]uint32
  3527  	stashSize  uint32
  3528  	numArgs    uint32
  3529  	argsToCopy uint32
  3530  	funcType   funcType
  3531  	extensible bool
  3532  }
  3533  
  3534  func (e *enterFunc1) exec(vm *vm) {
  3535  	sp := vm.sp
  3536  	vm.sb = sp - vm.args - 1
  3537  	vm.newStash()
  3538  	stash := vm.stash
  3539  	stash.funcType = e.funcType
  3540  	stash.values = make([]Value, e.stashSize)
  3541  	if len(e.names) > 0 {
  3542  		if e.extensible {
  3543  			m := make(map[unistring.String]uint32, len(e.names))
  3544  			for name, idx := range e.names {
  3545  				m[name] = idx
  3546  			}
  3547  			stash.names = m
  3548  		} else {
  3549  			stash.names = e.names
  3550  		}
  3551  	}
  3552  	offset := vm.args - int(e.argsToCopy)
  3553  	if offset > 0 {
  3554  		copy(stash.values, vm.stack[sp-vm.args:sp-offset])
  3555  		if offset := vm.args - int(e.numArgs); offset > 0 {
  3556  			vm.stash.extraArgs = make([]Value, offset)
  3557  			copy(stash.extraArgs, vm.stack[sp-offset:])
  3558  		}
  3559  	} else {
  3560  		copy(stash.values, vm.stack[sp-vm.args:sp])
  3561  		if int(e.argsToCopy) > vm.args {
  3562  			vv := stash.values[vm.args:e.argsToCopy]
  3563  			for i := range vv {
  3564  				vv[i] = _undefined
  3565  			}
  3566  		}
  3567  	}
  3568  
  3569  	vm.pc++
  3570  }
  3571  
  3572  // Finalises the initialisers section and starts the function body which has its own
  3573  // scope. When used in conjunction with enterFunc1 adjustStack is set to true which
  3574  // causes the arguments to be removed from the stack.
  3575  type enterFuncBody struct {
  3576  	enterBlock
  3577  	funcType    funcType
  3578  	extensible  bool
  3579  	adjustStack bool
  3580  }
  3581  
  3582  func (e *enterFuncBody) exec(vm *vm) {
  3583  	if e.stashSize > 0 || e.extensible {
  3584  		vm.newStash()
  3585  		stash := vm.stash
  3586  		stash.funcType = e.funcType
  3587  		stash.values = make([]Value, e.stashSize)
  3588  		if len(e.names) > 0 {
  3589  			if e.extensible {
  3590  				m := make(map[unistring.String]uint32, len(e.names))
  3591  				for name, idx := range e.names {
  3592  					m[name] = idx
  3593  				}
  3594  				stash.names = m
  3595  			} else {
  3596  				stash.names = e.names
  3597  			}
  3598  		}
  3599  	}
  3600  	sp := vm.sp
  3601  	if e.adjustStack {
  3602  		sp -= vm.args
  3603  	}
  3604  	nsp := sp + int(e.stackSize)
  3605  	if e.stackSize > 0 {
  3606  		vm.stack.expand(nsp - 1)
  3607  		vv := vm.stack[sp:nsp]
  3608  		for i := range vv {
  3609  			vv[i] = nil
  3610  		}
  3611  	}
  3612  	vm.sp = nsp
  3613  	vm.pc++
  3614  }
  3615  
  3616  type _ret struct{}
  3617  
  3618  var ret _ret
  3619  
  3620  func (_ret) exec(vm *vm) {
  3621  	// callee -3
  3622  	// this -2 <- sb
  3623  	// retval -1
  3624  
  3625  	vm.stack[vm.sb-1] = vm.stack[vm.sp-1]
  3626  	vm.sp = vm.sb
  3627  	vm.popCtx()
  3628  	vm.pc++
  3629  }
  3630  
  3631  type cret uint32
  3632  
  3633  func (c cret) exec(vm *vm) {
  3634  	vm.stack[vm.sb] = *vm.getStashPtr(uint32(c))
  3635  	ret.exec(vm)
  3636  }
  3637  
  3638  type enterFuncStashless struct {
  3639  	stackSize uint32
  3640  	args      uint32
  3641  }
  3642  
  3643  func (e *enterFuncStashless) exec(vm *vm) {
  3644  	sp := vm.sp
  3645  	vm.sb = sp - vm.args - 1
  3646  	d := int(e.args) - vm.args
  3647  	if d > 0 {
  3648  		ss := sp + int(e.stackSize) + d
  3649  		vm.stack.expand(ss)
  3650  		vv := vm.stack[sp : sp+d]
  3651  		for i := range vv {
  3652  			vv[i] = _undefined
  3653  		}
  3654  		vv = vm.stack[sp+d : ss]
  3655  		for i := range vv {
  3656  			vv[i] = nil
  3657  		}
  3658  		vm.args = int(e.args)
  3659  		vm.sp = ss
  3660  	} else {
  3661  		if e.stackSize > 0 {
  3662  			ss := sp + int(e.stackSize)
  3663  			vm.stack.expand(ss)
  3664  			vv := vm.stack[sp:ss]
  3665  			for i := range vv {
  3666  				vv[i] = nil
  3667  			}
  3668  			vm.sp = ss
  3669  		}
  3670  	}
  3671  	vm.pc++
  3672  }
  3673  
  3674  type newFuncInstruction interface {
  3675  	getPrg() *Program
  3676  }
  3677  
  3678  type newFunc struct {
  3679  	prg    *Program
  3680  	name   unistring.String
  3681  	source string
  3682  
  3683  	length int
  3684  	strict bool
  3685  }
  3686  
  3687  func (n *newFunc) exec(vm *vm) {
  3688  	obj := vm.r.newFunc(n.name, n.length, n.strict)
  3689  	obj.prg = n.prg
  3690  	obj.stash = vm.stash
  3691  	obj.privEnv = vm.privEnv
  3692  	obj.src = n.source
  3693  	vm.push(obj.val)
  3694  	vm.pc++
  3695  }
  3696  
  3697  func (n *newFunc) getPrg() *Program {
  3698  	return n.prg
  3699  }
  3700  
  3701  type newAsyncFunc struct {
  3702  	newFunc
  3703  }
  3704  
  3705  func (n *newAsyncFunc) exec(vm *vm) {
  3706  	obj := vm.r.newAsyncFunc(n.name, n.length, n.strict)
  3707  	obj.prg = n.prg
  3708  	obj.stash = vm.stash
  3709  	obj.privEnv = vm.privEnv
  3710  	obj.src = n.source
  3711  	vm.push(obj.val)
  3712  	vm.pc++
  3713  }
  3714  
  3715  type newGeneratorFunc struct {
  3716  	newFunc
  3717  }
  3718  
  3719  func (n *newGeneratorFunc) exec(vm *vm) {
  3720  	obj := vm.r.newGeneratorFunc(n.name, n.length, n.strict)
  3721  	obj.prg = n.prg
  3722  	obj.stash = vm.stash
  3723  	obj.privEnv = vm.privEnv
  3724  	obj.src = n.source
  3725  	vm.push(obj.val)
  3726  	vm.pc++
  3727  }
  3728  
  3729  type newMethod struct {
  3730  	newFunc
  3731  	homeObjOffset uint32
  3732  }
  3733  
  3734  func (n *newMethod) _exec(vm *vm, obj *methodFuncObject) {
  3735  	obj.prg = n.prg
  3736  	obj.stash = vm.stash
  3737  	obj.privEnv = vm.privEnv
  3738  	obj.src = n.source
  3739  	if n.homeObjOffset > 0 {
  3740  		obj.homeObject = vm.r.toObject(vm.stack[vm.sp-int(n.homeObjOffset)])
  3741  	}
  3742  	vm.push(obj.val)
  3743  	vm.pc++
  3744  }
  3745  
  3746  func (n *newMethod) exec(vm *vm) {
  3747  	n._exec(vm, vm.r.newMethod(n.name, n.length, n.strict))
  3748  }
  3749  
  3750  type newAsyncMethod struct {
  3751  	newMethod
  3752  }
  3753  
  3754  func (n *newAsyncMethod) exec(vm *vm) {
  3755  	obj := vm.r.newAsyncMethod(n.name, n.length, n.strict)
  3756  	n._exec(vm, &obj.methodFuncObject)
  3757  }
  3758  
  3759  type newGeneratorMethod struct {
  3760  	newMethod
  3761  }
  3762  
  3763  func (n *newGeneratorMethod) exec(vm *vm) {
  3764  	obj := vm.r.newGeneratorMethod(n.name, n.length, n.strict)
  3765  	n._exec(vm, &obj.methodFuncObject)
  3766  }
  3767  
  3768  type newArrowFunc struct {
  3769  	newFunc
  3770  }
  3771  
  3772  type newAsyncArrowFunc struct {
  3773  	newArrowFunc
  3774  }
  3775  
  3776  func getFuncObject(v Value) *Object {
  3777  	if o, ok := v.(*Object); ok {
  3778  		if fn, ok := o.self.(*arrowFuncObject); ok {
  3779  			return fn.funcObj
  3780  		}
  3781  		return o
  3782  	}
  3783  	if v == _undefined {
  3784  		return nil
  3785  	}
  3786  	panic(typeError("Value is not an Object"))
  3787  }
  3788  
  3789  func getHomeObject(v Value) *Object {
  3790  	if o, ok := v.(*Object); ok {
  3791  		switch fn := o.self.(type) {
  3792  		case *methodFuncObject:
  3793  			return fn.homeObject
  3794  		case *generatorMethodFuncObject:
  3795  			return fn.homeObject
  3796  		case *asyncMethodFuncObject:
  3797  			return fn.homeObject
  3798  		case *classFuncObject:
  3799  			return o.runtime.toObject(fn.getStr("prototype", nil))
  3800  		case *arrowFuncObject:
  3801  			return getHomeObject(fn.funcObj)
  3802  		case *asyncArrowFuncObject:
  3803  			return getHomeObject(fn.funcObj)
  3804  		}
  3805  	}
  3806  	panic(newTypeError("Compiler bug: getHomeObject() on the wrong value: %T", v))
  3807  }
  3808  
  3809  func (n *newArrowFunc) _exec(vm *vm, obj *arrowFuncObject) {
  3810  	obj.prg = n.prg
  3811  	obj.stash = vm.stash
  3812  	obj.privEnv = vm.privEnv
  3813  	obj.src = n.source
  3814  	if vm.sb > 0 {
  3815  		obj.funcObj = getFuncObject(vm.stack[vm.sb-1])
  3816  	}
  3817  	vm.push(obj.val)
  3818  	vm.pc++
  3819  }
  3820  
  3821  func (n *newArrowFunc) exec(vm *vm) {
  3822  	n._exec(vm, vm.r.newArrowFunc(n.name, n.length, n.strict))
  3823  }
  3824  
  3825  func (n *newAsyncArrowFunc) exec(vm *vm) {
  3826  	obj := vm.r.newAsyncArrowFunc(n.name, n.length, n.strict)
  3827  	n._exec(vm, &obj.arrowFuncObject)
  3828  }
  3829  
  3830  func (vm *vm) alreadyDeclared(name unistring.String) Value {
  3831  	return vm.r.newError(vm.r.global.SyntaxError, "Identifier '%s' has already been declared", name)
  3832  }
  3833  
  3834  func (vm *vm) checkBindVarsGlobal(names []unistring.String) {
  3835  	o := vm.r.globalObject.self
  3836  	sn := vm.r.global.stash.names
  3837  	if bo, ok := o.(*baseObject); ok {
  3838  		// shortcut
  3839  		if bo.extensible {
  3840  			for _, name := range names {
  3841  				if _, exists := sn[name]; exists {
  3842  					panic(vm.alreadyDeclared(name))
  3843  				}
  3844  			}
  3845  		} else {
  3846  			for _, name := range names {
  3847  				if !bo.hasOwnPropertyStr(name) {
  3848  					panic(vm.r.NewTypeError("Cannot define global variable '%s', global object is not extensible", name))
  3849  				}
  3850  				if _, exists := sn[name]; exists {
  3851  					panic(vm.alreadyDeclared(name))
  3852  				}
  3853  			}
  3854  		}
  3855  	} else {
  3856  		for _, name := range names {
  3857  			if !o.hasOwnPropertyStr(name) && !o.isExtensible() {
  3858  				panic(vm.r.NewTypeError("Cannot define global variable '%s', global object is not extensible", name))
  3859  			}
  3860  			if _, exists := sn[name]; exists {
  3861  				panic(vm.alreadyDeclared(name))
  3862  			}
  3863  		}
  3864  	}
  3865  }
  3866  
  3867  func (vm *vm) createGlobalVarBindings(names []unistring.String, d bool) {
  3868  	globalVarNames := vm.r.global.varNames
  3869  	if globalVarNames == nil {
  3870  		globalVarNames = make(map[unistring.String]struct{})
  3871  		vm.r.global.varNames = globalVarNames
  3872  	}
  3873  	o := vm.r.globalObject.self
  3874  	if bo, ok := o.(*baseObject); ok {
  3875  		for _, name := range names {
  3876  			if !bo.hasOwnPropertyStr(name) && bo.extensible {
  3877  				bo._putProp(name, _undefined, true, true, d)
  3878  			}
  3879  			globalVarNames[name] = struct{}{}
  3880  		}
  3881  	} else {
  3882  		var cf Flag
  3883  		if d {
  3884  			cf = FLAG_TRUE
  3885  		} else {
  3886  			cf = FLAG_FALSE
  3887  		}
  3888  		for _, name := range names {
  3889  			if !o.hasOwnPropertyStr(name) && o.isExtensible() {
  3890  				o.defineOwnPropertyStr(name, PropertyDescriptor{
  3891  					Value:        _undefined,
  3892  					Writable:     FLAG_TRUE,
  3893  					Enumerable:   FLAG_TRUE,
  3894  					Configurable: cf,
  3895  				}, true)
  3896  				o.setOwnStr(name, _undefined, false)
  3897  			}
  3898  			globalVarNames[name] = struct{}{}
  3899  		}
  3900  	}
  3901  }
  3902  
  3903  func (vm *vm) createGlobalFuncBindings(names []unistring.String, d bool) {
  3904  	globalVarNames := vm.r.global.varNames
  3905  	if globalVarNames == nil {
  3906  		globalVarNames = make(map[unistring.String]struct{})
  3907  		vm.r.global.varNames = globalVarNames
  3908  	}
  3909  	o := vm.r.globalObject.self
  3910  	b := vm.sp - len(names)
  3911  	var shortcutObj *baseObject
  3912  	if o, ok := o.(*baseObject); ok {
  3913  		shortcutObj = o
  3914  	}
  3915  	for i, name := range names {
  3916  		var desc PropertyDescriptor
  3917  		prop := o.getOwnPropStr(name)
  3918  		desc.Value = vm.stack[b+i]
  3919  		if shortcutObj != nil && prop == nil && shortcutObj.extensible {
  3920  			shortcutObj._putProp(name, desc.Value, true, true, d)
  3921  		} else {
  3922  			if prop, ok := prop.(*valueProperty); ok && !prop.configurable {
  3923  				// no-op
  3924  			} else {
  3925  				desc.Writable = FLAG_TRUE
  3926  				desc.Enumerable = FLAG_TRUE
  3927  				if d {
  3928  					desc.Configurable = FLAG_TRUE
  3929  				} else {
  3930  					desc.Configurable = FLAG_FALSE
  3931  				}
  3932  			}
  3933  			if shortcutObj != nil {
  3934  				shortcutObj.defineOwnPropertyStr(name, desc, true)
  3935  			} else {
  3936  				o.defineOwnPropertyStr(name, desc, true)
  3937  				o.setOwnStr(name, desc.Value, false) // not a bug, see https://262.ecma-international.org/#sec-createglobalfunctionbinding
  3938  			}
  3939  		}
  3940  		globalVarNames[name] = struct{}{}
  3941  	}
  3942  	vm.sp = b
  3943  }
  3944  
  3945  func (vm *vm) checkBindFuncsGlobal(names []unistring.String) {
  3946  	o := vm.r.globalObject.self
  3947  	sn := vm.r.global.stash.names
  3948  	for _, name := range names {
  3949  		if _, exists := sn[name]; exists {
  3950  			panic(vm.alreadyDeclared(name))
  3951  		}
  3952  		prop := o.getOwnPropStr(name)
  3953  		allowed := true
  3954  		switch prop := prop.(type) {
  3955  		case nil:
  3956  			allowed = o.isExtensible()
  3957  		case *valueProperty:
  3958  			allowed = prop.configurable || prop.getterFunc == nil && prop.setterFunc == nil && prop.writable && prop.enumerable
  3959  		}
  3960  		if !allowed {
  3961  			panic(vm.r.NewTypeError("Cannot redefine global function '%s'", name))
  3962  		}
  3963  	}
  3964  }
  3965  
  3966  func (vm *vm) checkBindLexGlobal(names []unistring.String) {
  3967  	o := vm.r.globalObject.self
  3968  	s := &vm.r.global.stash
  3969  	for _, name := range names {
  3970  		if _, exists := vm.r.global.varNames[name]; exists {
  3971  			goto fail
  3972  		}
  3973  		if _, exists := s.names[name]; exists {
  3974  			goto fail
  3975  		}
  3976  		if prop, ok := o.getOwnPropStr(name).(*valueProperty); ok && !prop.configurable {
  3977  			goto fail
  3978  		}
  3979  		continue
  3980  	fail:
  3981  		panic(vm.alreadyDeclared(name))
  3982  	}
  3983  }
  3984  
  3985  type bindVars struct {
  3986  	names     []unistring.String
  3987  	deletable bool
  3988  }
  3989  
  3990  func (d *bindVars) exec(vm *vm) {
  3991  	var target *stash
  3992  	for _, name := range d.names {
  3993  		for s := vm.stash; s != nil; s = s.outer {
  3994  			if idx, exists := s.names[name]; exists && idx&maskVar == 0 {
  3995  				vm.throw(vm.alreadyDeclared(name))
  3996  				return
  3997  			}
  3998  			if s.isVariable() {
  3999  				target = s
  4000  				break
  4001  			}
  4002  		}
  4003  	}
  4004  	if target == nil {
  4005  		target = vm.stash
  4006  	}
  4007  	deletable := d.deletable
  4008  	for _, name := range d.names {
  4009  		target.createBinding(name, deletable)
  4010  	}
  4011  	vm.pc++
  4012  }
  4013  
  4014  type bindGlobal struct {
  4015  	vars, funcs, lets, consts []unistring.String
  4016  
  4017  	deletable bool
  4018  }
  4019  
  4020  func (b *bindGlobal) exec(vm *vm) {
  4021  	vm.checkBindFuncsGlobal(b.funcs)
  4022  	vm.checkBindLexGlobal(b.lets)
  4023  	vm.checkBindLexGlobal(b.consts)
  4024  	vm.checkBindVarsGlobal(b.vars)
  4025  
  4026  	s := &vm.r.global.stash
  4027  	for _, name := range b.lets {
  4028  		s.createLexBinding(name, false)
  4029  	}
  4030  	for _, name := range b.consts {
  4031  		s.createLexBinding(name, true)
  4032  	}
  4033  	vm.createGlobalFuncBindings(b.funcs, b.deletable)
  4034  	vm.createGlobalVarBindings(b.vars, b.deletable)
  4035  	vm.pc++
  4036  }
  4037  
  4038  type jne int32
  4039  
  4040  func (j jne) exec(vm *vm) {
  4041  	vm.sp--
  4042  	if !vm.stack[vm.sp].ToBoolean() {
  4043  		vm.pc += int(j)
  4044  	} else {
  4045  		vm.pc++
  4046  	}
  4047  }
  4048  
  4049  type jeq int32
  4050  
  4051  func (j jeq) exec(vm *vm) {
  4052  	vm.sp--
  4053  	if vm.stack[vm.sp].ToBoolean() {
  4054  		vm.pc += int(j)
  4055  	} else {
  4056  		vm.pc++
  4057  	}
  4058  }
  4059  
  4060  type jeq1 int32
  4061  
  4062  func (j jeq1) exec(vm *vm) {
  4063  	if vm.stack[vm.sp-1].ToBoolean() {
  4064  		vm.pc += int(j)
  4065  	} else {
  4066  		vm.sp--
  4067  		vm.pc++
  4068  	}
  4069  }
  4070  
  4071  type jneq1 int32
  4072  
  4073  func (j jneq1) exec(vm *vm) {
  4074  	if !vm.stack[vm.sp-1].ToBoolean() {
  4075  		vm.pc += int(j)
  4076  	} else {
  4077  		vm.sp--
  4078  		vm.pc++
  4079  	}
  4080  }
  4081  
  4082  type jdef int32
  4083  
  4084  func (j jdef) exec(vm *vm) {
  4085  	if vm.stack[vm.sp-1] != _undefined {
  4086  		vm.pc += int(j)
  4087  	} else {
  4088  		vm.sp--
  4089  		vm.pc++
  4090  	}
  4091  }
  4092  
  4093  type jdefP int32
  4094  
  4095  func (j jdefP) exec(vm *vm) {
  4096  	if vm.stack[vm.sp-1] != _undefined {
  4097  		vm.pc += int(j)
  4098  	} else {
  4099  		vm.pc++
  4100  	}
  4101  	vm.sp--
  4102  }
  4103  
  4104  type jopt int32
  4105  
  4106  func (j jopt) exec(vm *vm) {
  4107  	switch vm.stack[vm.sp-1] {
  4108  	case _null:
  4109  		vm.stack[vm.sp-1] = _undefined
  4110  		fallthrough
  4111  	case _undefined:
  4112  		vm.pc += int(j)
  4113  	default:
  4114  		vm.pc++
  4115  	}
  4116  }
  4117  
  4118  type joptc int32
  4119  
  4120  func (j joptc) exec(vm *vm) {
  4121  	switch vm.stack[vm.sp-1].(type) {
  4122  	case valueNull, valueUndefined, memberUnresolved:
  4123  		vm.sp--
  4124  		vm.stack[vm.sp-1] = _undefined
  4125  		vm.pc += int(j)
  4126  	default:
  4127  		vm.pc++
  4128  	}
  4129  }
  4130  
  4131  type jcoalesc int32
  4132  
  4133  func (j jcoalesc) exec(vm *vm) {
  4134  	switch vm.stack[vm.sp-1] {
  4135  	case _undefined, _null:
  4136  		vm.sp--
  4137  		vm.pc++
  4138  	default:
  4139  		vm.pc += int(j)
  4140  	}
  4141  }
  4142  
  4143  type _not struct{}
  4144  
  4145  var not _not
  4146  
  4147  func (_not) exec(vm *vm) {
  4148  	if vm.stack[vm.sp-1].ToBoolean() {
  4149  		vm.stack[vm.sp-1] = valueFalse
  4150  	} else {
  4151  		vm.stack[vm.sp-1] = valueTrue
  4152  	}
  4153  	vm.pc++
  4154  }
  4155  
  4156  func toPrimitiveNumber(v Value) Value {
  4157  	if o, ok := v.(*Object); ok {
  4158  		return o.toPrimitiveNumber()
  4159  	}
  4160  	return v
  4161  }
  4162  
  4163  func toPrimitive(v Value) Value {
  4164  	if o, ok := v.(*Object); ok {
  4165  		return o.toPrimitive()
  4166  	}
  4167  	return v
  4168  }
  4169  
  4170  func cmp(px, py Value) Value {
  4171  	var ret bool
  4172  	var nx, ny float64
  4173  
  4174  	if xs, ok := px.(String); ok {
  4175  		if ys, ok := py.(String); ok {
  4176  			ret = xs.CompareTo(ys) < 0
  4177  			goto end
  4178  		}
  4179  	}
  4180  
  4181  	if xi, ok := px.(valueInt); ok {
  4182  		if yi, ok := py.(valueInt); ok {
  4183  			ret = xi < yi
  4184  			goto end
  4185  		}
  4186  	}
  4187  
  4188  	nx = px.ToFloat()
  4189  	ny = py.ToFloat()
  4190  
  4191  	if math.IsNaN(nx) || math.IsNaN(ny) {
  4192  		return _undefined
  4193  	}
  4194  
  4195  	ret = nx < ny
  4196  
  4197  end:
  4198  	if ret {
  4199  		return valueTrue
  4200  	}
  4201  	return valueFalse
  4202  
  4203  }
  4204  
  4205  type _op_lt struct{}
  4206  
  4207  var op_lt _op_lt
  4208  
  4209  func (_op_lt) exec(vm *vm) {
  4210  	left := toPrimitiveNumber(vm.stack[vm.sp-2])
  4211  	right := toPrimitiveNumber(vm.stack[vm.sp-1])
  4212  
  4213  	r := cmp(left, right)
  4214  	if r == _undefined {
  4215  		vm.stack[vm.sp-2] = valueFalse
  4216  	} else {
  4217  		vm.stack[vm.sp-2] = r
  4218  	}
  4219  	vm.sp--
  4220  	vm.pc++
  4221  }
  4222  
  4223  type _op_lte struct{}
  4224  
  4225  var op_lte _op_lte
  4226  
  4227  func (_op_lte) exec(vm *vm) {
  4228  	left := toPrimitiveNumber(vm.stack[vm.sp-2])
  4229  	right := toPrimitiveNumber(vm.stack[vm.sp-1])
  4230  
  4231  	r := cmp(right, left)
  4232  	if r == _undefined || r == valueTrue {
  4233  		vm.stack[vm.sp-2] = valueFalse
  4234  	} else {
  4235  		vm.stack[vm.sp-2] = valueTrue
  4236  	}
  4237  
  4238  	vm.sp--
  4239  	vm.pc++
  4240  }
  4241  
  4242  type _op_gt struct{}
  4243  
  4244  var op_gt _op_gt
  4245  
  4246  func (_op_gt) exec(vm *vm) {
  4247  	left := toPrimitiveNumber(vm.stack[vm.sp-2])
  4248  	right := toPrimitiveNumber(vm.stack[vm.sp-1])
  4249  
  4250  	r := cmp(right, left)
  4251  	if r == _undefined {
  4252  		vm.stack[vm.sp-2] = valueFalse
  4253  	} else {
  4254  		vm.stack[vm.sp-2] = r
  4255  	}
  4256  	vm.sp--
  4257  	vm.pc++
  4258  }
  4259  
  4260  type _op_gte struct{}
  4261  
  4262  var op_gte _op_gte
  4263  
  4264  func (_op_gte) exec(vm *vm) {
  4265  	left := toPrimitiveNumber(vm.stack[vm.sp-2])
  4266  	right := toPrimitiveNumber(vm.stack[vm.sp-1])
  4267  
  4268  	r := cmp(left, right)
  4269  	if r == _undefined || r == valueTrue {
  4270  		vm.stack[vm.sp-2] = valueFalse
  4271  	} else {
  4272  		vm.stack[vm.sp-2] = valueTrue
  4273  	}
  4274  
  4275  	vm.sp--
  4276  	vm.pc++
  4277  }
  4278  
  4279  type _op_eq struct{}
  4280  
  4281  var op_eq _op_eq
  4282  
  4283  func (_op_eq) exec(vm *vm) {
  4284  	if vm.stack[vm.sp-2].Equals(vm.stack[vm.sp-1]) {
  4285  		vm.stack[vm.sp-2] = valueTrue
  4286  	} else {
  4287  		vm.stack[vm.sp-2] = valueFalse
  4288  	}
  4289  	vm.sp--
  4290  	vm.pc++
  4291  }
  4292  
  4293  type _op_neq struct{}
  4294  
  4295  var op_neq _op_neq
  4296  
  4297  func (_op_neq) exec(vm *vm) {
  4298  	if vm.stack[vm.sp-2].Equals(vm.stack[vm.sp-1]) {
  4299  		vm.stack[vm.sp-2] = valueFalse
  4300  	} else {
  4301  		vm.stack[vm.sp-2] = valueTrue
  4302  	}
  4303  	vm.sp--
  4304  	vm.pc++
  4305  }
  4306  
  4307  type _op_strict_eq struct{}
  4308  
  4309  var op_strict_eq _op_strict_eq
  4310  
  4311  func (_op_strict_eq) exec(vm *vm) {
  4312  	if vm.stack[vm.sp-2].StrictEquals(vm.stack[vm.sp-1]) {
  4313  		vm.stack[vm.sp-2] = valueTrue
  4314  	} else {
  4315  		vm.stack[vm.sp-2] = valueFalse
  4316  	}
  4317  	vm.sp--
  4318  	vm.pc++
  4319  }
  4320  
  4321  type _op_strict_neq struct{}
  4322  
  4323  var op_strict_neq _op_strict_neq
  4324  
  4325  func (_op_strict_neq) exec(vm *vm) {
  4326  	if vm.stack[vm.sp-2].StrictEquals(vm.stack[vm.sp-1]) {
  4327  		vm.stack[vm.sp-2] = valueFalse
  4328  	} else {
  4329  		vm.stack[vm.sp-2] = valueTrue
  4330  	}
  4331  	vm.sp--
  4332  	vm.pc++
  4333  }
  4334  
  4335  type _op_instanceof struct{}
  4336  
  4337  var op_instanceof _op_instanceof
  4338  
  4339  func (_op_instanceof) exec(vm *vm) {
  4340  	left := vm.stack[vm.sp-2]
  4341  	right := vm.r.toObject(vm.stack[vm.sp-1])
  4342  
  4343  	if instanceOfOperator(left, right) {
  4344  		vm.stack[vm.sp-2] = valueTrue
  4345  	} else {
  4346  		vm.stack[vm.sp-2] = valueFalse
  4347  	}
  4348  
  4349  	vm.sp--
  4350  	vm.pc++
  4351  }
  4352  
  4353  type _op_in struct{}
  4354  
  4355  var op_in _op_in
  4356  
  4357  func (_op_in) exec(vm *vm) {
  4358  	left := vm.stack[vm.sp-2]
  4359  	right := vm.r.toObject(vm.stack[vm.sp-1])
  4360  
  4361  	if right.hasProperty(left) {
  4362  		vm.stack[vm.sp-2] = valueTrue
  4363  	} else {
  4364  		vm.stack[vm.sp-2] = valueFalse
  4365  	}
  4366  
  4367  	vm.sp--
  4368  	vm.pc++
  4369  }
  4370  
  4371  type try struct {
  4372  	catchOffset   int32
  4373  	finallyOffset int32
  4374  }
  4375  
  4376  func (t try) exec(vm *vm) {
  4377  	var catchPos, finallyPos int32
  4378  	if t.catchOffset > 0 {
  4379  		catchPos = int32(vm.pc) + t.catchOffset
  4380  	} else {
  4381  		catchPos = -1
  4382  	}
  4383  	if t.finallyOffset > 0 {
  4384  		finallyPos = int32(vm.pc) + t.finallyOffset
  4385  	} else {
  4386  		finallyPos = -1
  4387  	}
  4388  	vm.pushTryFrame(catchPos, finallyPos)
  4389  	vm.pc++
  4390  }
  4391  
  4392  type leaveTry struct{}
  4393  
  4394  func (leaveTry) exec(vm *vm) {
  4395  	tf := &vm.tryStack[len(vm.tryStack)-1]
  4396  	if tf.finallyPos >= 0 {
  4397  		tf.finallyRet = int32(vm.pc + 1)
  4398  		vm.pc = int(tf.finallyPos)
  4399  		tf.finallyPos = -1
  4400  		tf.catchPos = -1
  4401  	} else {
  4402  		vm.popTryFrame()
  4403  		vm.pc++
  4404  	}
  4405  }
  4406  
  4407  type enterFinally struct{}
  4408  
  4409  func (enterFinally) exec(vm *vm) {
  4410  	tf := &vm.tryStack[len(vm.tryStack)-1]
  4411  	tf.finallyPos = -1
  4412  	vm.pc++
  4413  }
  4414  
  4415  type leaveFinally struct{}
  4416  
  4417  func (leaveFinally) exec(vm *vm) {
  4418  	tf := &vm.tryStack[len(vm.tryStack)-1]
  4419  	ex, ret := tf.exception, tf.finallyRet
  4420  	tf.exception = nil
  4421  	vm.popTryFrame()
  4422  	if ex != nil {
  4423  		vm.throw(ex)
  4424  		return
  4425  	} else {
  4426  		if ret != -1 {
  4427  			vm.pc = int(ret)
  4428  		} else {
  4429  			vm.pc++
  4430  		}
  4431  	}
  4432  }
  4433  
  4434  type _throw struct{}
  4435  
  4436  var throw _throw
  4437  
  4438  func (_throw) exec(vm *vm) {
  4439  	v := vm.stack[vm.sp-1]
  4440  	var ex *Exception
  4441  	if o, ok := v.(*Object); ok {
  4442  		if e, ok := o.self.(*errorObject); ok {
  4443  			if len(e.stack) > 0 {
  4444  				frame0 := e.stack[0]
  4445  				// If the Error was created immediately before throwing it (i.e. 'throw new Error(....)')
  4446  				// avoid capturing the stack again by the reusing the stack from the Error.
  4447  				// These stacks would be almost identical and the difference doesn't matter for debugging.
  4448  				if frame0.prg == vm.prg && vm.pc-frame0.pc == 1 {
  4449  					ex = &Exception{
  4450  						val:   v,
  4451  						stack: e.stack,
  4452  					}
  4453  				}
  4454  			}
  4455  		}
  4456  	}
  4457  	if ex == nil {
  4458  		ex = &Exception{
  4459  			val:   v,
  4460  			stack: vm.captureStack(make([]StackFrame, 0, len(vm.callStack)+1), 0),
  4461  		}
  4462  	}
  4463  
  4464  	if ex = vm.handleThrow(ex); ex != nil {
  4465  		panic(ex)
  4466  	}
  4467  }
  4468  
  4469  type _newVariadic struct{}
  4470  
  4471  var newVariadic _newVariadic
  4472  
  4473  func (_newVariadic) exec(vm *vm) {
  4474  	_new(vm.countVariadicArgs() - 1).exec(vm)
  4475  }
  4476  
  4477  type _new uint32
  4478  
  4479  func (n _new) exec(vm *vm) {
  4480  	sp := vm.sp - int(n)
  4481  	obj := vm.stack[sp-1]
  4482  	ctor := vm.r.toConstructor(obj)
  4483  	vm.stack[sp-1] = ctor(vm.stack[sp:vm.sp], nil)
  4484  	vm.sp = sp
  4485  	vm.pc++
  4486  }
  4487  
  4488  type superCall uint32
  4489  
  4490  func (s superCall) exec(vm *vm) {
  4491  	l := len(vm.refStack) - 1
  4492  	thisRef := vm.refStack[l]
  4493  	vm.refStack[l] = nil
  4494  	vm.refStack = vm.refStack[:l]
  4495  
  4496  	obj := vm.r.toObject(vm.stack[vm.sb-1])
  4497  	var cls *classFuncObject
  4498  	switch fn := obj.self.(type) {
  4499  	case *classFuncObject:
  4500  		cls = fn
  4501  	case *arrowFuncObject:
  4502  		cls, _ = fn.funcObj.self.(*classFuncObject)
  4503  	}
  4504  	if cls == nil {
  4505  		vm.throw(vm.r.NewTypeError("wrong callee type for super()"))
  4506  		return
  4507  	}
  4508  	sp := vm.sp - int(s)
  4509  	newTarget := vm.r.toObject(vm.newTarget)
  4510  	v := cls.createInstance(vm.stack[sp:vm.sp], newTarget)
  4511  	thisRef.set(v)
  4512  	vm.sp = sp
  4513  	cls._initFields(v)
  4514  	vm.push(v)
  4515  	vm.pc++
  4516  }
  4517  
  4518  type _superCallVariadic struct{}
  4519  
  4520  var superCallVariadic _superCallVariadic
  4521  
  4522  func (_superCallVariadic) exec(vm *vm) {
  4523  	superCall(vm.countVariadicArgs()).exec(vm)
  4524  }
  4525  
  4526  type _loadNewTarget struct{}
  4527  
  4528  var loadNewTarget _loadNewTarget
  4529  
  4530  func (_loadNewTarget) exec(vm *vm) {
  4531  	if t := vm.newTarget; t != nil {
  4532  		vm.push(t)
  4533  	} else {
  4534  		vm.push(_undefined)
  4535  	}
  4536  	vm.pc++
  4537  }
  4538  
  4539  type _typeof struct{}
  4540  
  4541  var typeof _typeof
  4542  
  4543  func (_typeof) exec(vm *vm) {
  4544  	var r Value
  4545  	switch v := vm.stack[vm.sp-1].(type) {
  4546  	case valueUndefined, valueUnresolved:
  4547  		r = stringUndefined
  4548  	case valueNull:
  4549  		r = stringObjectC
  4550  	case *Object:
  4551  		r = v.self.typeOf()
  4552  	case valueBool:
  4553  		r = stringBoolean
  4554  	case String:
  4555  		r = stringString
  4556  	case valueInt, valueFloat:
  4557  		r = stringNumber
  4558  	case *Symbol:
  4559  		r = stringSymbol
  4560  	default:
  4561  		panic(newTypeError("Compiler bug: unknown type: %T", v))
  4562  	}
  4563  	vm.stack[vm.sp-1] = r
  4564  	vm.pc++
  4565  }
  4566  
  4567  type createArgsMapped uint32
  4568  
  4569  func (formalArgs createArgsMapped) exec(vm *vm) {
  4570  	v := &Object{runtime: vm.r}
  4571  	args := &argumentsObject{}
  4572  	args.extensible = true
  4573  	args.prototype = vm.r.global.ObjectPrototype
  4574  	args.class = "Arguments"
  4575  	v.self = args
  4576  	args.val = v
  4577  	args.length = vm.args
  4578  	args.init()
  4579  	i := 0
  4580  	c := int(formalArgs)
  4581  	if vm.args < c {
  4582  		c = vm.args
  4583  	}
  4584  	for ; i < c; i++ {
  4585  		args._put(unistring.String(strconv.Itoa(i)), &mappedProperty{
  4586  			valueProperty: valueProperty{
  4587  				writable:     true,
  4588  				configurable: true,
  4589  				enumerable:   true,
  4590  			},
  4591  			v: &vm.stash.values[i],
  4592  		})
  4593  	}
  4594  
  4595  	for _, v := range vm.stash.extraArgs {
  4596  		args._put(unistring.String(strconv.Itoa(i)), v)
  4597  		i++
  4598  	}
  4599  
  4600  	args._putProp("callee", vm.stack[vm.sb-1], true, false, true)
  4601  	args._putSym(SymIterator, valueProp(vm.r.global.arrayValues, true, false, true))
  4602  	vm.push(v)
  4603  	vm.pc++
  4604  }
  4605  
  4606  type createArgsUnmapped uint32
  4607  
  4608  func (formalArgs createArgsUnmapped) exec(vm *vm) {
  4609  	args := vm.r.newBaseObject(vm.r.global.ObjectPrototype, "Arguments")
  4610  	i := 0
  4611  	c := int(formalArgs)
  4612  	if vm.args < c {
  4613  		c = vm.args
  4614  	}
  4615  	for _, v := range vm.stash.values[:c] {
  4616  		args._put(unistring.String(strconv.Itoa(i)), v)
  4617  		i++
  4618  	}
  4619  
  4620  	for _, v := range vm.stash.extraArgs {
  4621  		args._put(unistring.String(strconv.Itoa(i)), v)
  4622  		i++
  4623  	}
  4624  
  4625  	args._putProp("length", intToValue(int64(vm.args)), true, false, true)
  4626  	args._put("callee", vm.r.global.throwerProperty)
  4627  	args._putSym(SymIterator, valueProp(vm.r.global.arrayValues, true, false, true))
  4628  	vm.push(args.val)
  4629  	vm.pc++
  4630  }
  4631  
  4632  type _enterWith struct{}
  4633  
  4634  var enterWith _enterWith
  4635  
  4636  func (_enterWith) exec(vm *vm) {
  4637  	vm.newStash()
  4638  	vm.stash.obj = vm.stack[vm.sp-1].ToObject(vm.r)
  4639  	vm.sp--
  4640  	vm.pc++
  4641  }
  4642  
  4643  type _leaveWith struct{}
  4644  
  4645  var leaveWith _leaveWith
  4646  
  4647  func (_leaveWith) exec(vm *vm) {
  4648  	vm.stash = vm.stash.outer
  4649  	vm.pc++
  4650  }
  4651  
  4652  func emptyIter() (propIterItem, iterNextFunc) {
  4653  	return propIterItem{}, nil
  4654  }
  4655  
  4656  type _enumerate struct{}
  4657  
  4658  var enumerate _enumerate
  4659  
  4660  func (_enumerate) exec(vm *vm) {
  4661  	v := vm.stack[vm.sp-1]
  4662  	if v == _undefined || v == _null {
  4663  		vm.iterStack = append(vm.iterStack, iterStackItem{f: emptyIter})
  4664  	} else {
  4665  		vm.iterStack = append(vm.iterStack, iterStackItem{f: enumerateRecursive(v.ToObject(vm.r))})
  4666  	}
  4667  	vm.sp--
  4668  	vm.pc++
  4669  }
  4670  
  4671  type enumNext int32
  4672  
  4673  func (jmp enumNext) exec(vm *vm) {
  4674  	l := len(vm.iterStack) - 1
  4675  	item, n := vm.iterStack[l].f()
  4676  	if n != nil {
  4677  		vm.iterStack[l].val = item.name
  4678  		vm.iterStack[l].f = n
  4679  		vm.pc++
  4680  	} else {
  4681  		vm.pc += int(jmp)
  4682  	}
  4683  }
  4684  
  4685  type _enumGet struct{}
  4686  
  4687  var enumGet _enumGet
  4688  
  4689  func (_enumGet) exec(vm *vm) {
  4690  	l := len(vm.iterStack) - 1
  4691  	vm.push(vm.iterStack[l].val)
  4692  	vm.pc++
  4693  }
  4694  
  4695  type _enumPop struct{}
  4696  
  4697  var enumPop _enumPop
  4698  
  4699  func (_enumPop) exec(vm *vm) {
  4700  	l := len(vm.iterStack) - 1
  4701  	vm.iterStack[l] = iterStackItem{}
  4702  	vm.iterStack = vm.iterStack[:l]
  4703  	vm.pc++
  4704  }
  4705  
  4706  type _enumPopClose struct{}
  4707  
  4708  var enumPopClose _enumPopClose
  4709  
  4710  func (_enumPopClose) exec(vm *vm) {
  4711  	l := len(vm.iterStack) - 1
  4712  	item := vm.iterStack[l]
  4713  	vm.iterStack[l] = iterStackItem{}
  4714  	vm.iterStack = vm.iterStack[:l]
  4715  	if iter := item.iter; iter != nil {
  4716  		iter.returnIter()
  4717  	}
  4718  	vm.pc++
  4719  }
  4720  
  4721  type _iterateP struct{}
  4722  
  4723  var iterateP _iterateP
  4724  
  4725  func (_iterateP) exec(vm *vm) {
  4726  	iter := vm.r.getIterator(vm.stack[vm.sp-1], nil)
  4727  	vm.iterStack = append(vm.iterStack, iterStackItem{iter: iter})
  4728  	vm.sp--
  4729  	vm.pc++
  4730  }
  4731  
  4732  type _iterate struct{}
  4733  
  4734  var iterate _iterate
  4735  
  4736  func (_iterate) exec(vm *vm) {
  4737  	iter := vm.r.getIterator(vm.stack[vm.sp-1], nil)
  4738  	vm.iterStack = append(vm.iterStack, iterStackItem{iter: iter})
  4739  	vm.pc++
  4740  }
  4741  
  4742  type iterNext int32
  4743  
  4744  func (jmp iterNext) exec(vm *vm) {
  4745  	l := len(vm.iterStack) - 1
  4746  	iter := vm.iterStack[l].iter
  4747  	value, ex := iter.step()
  4748  	if ex == nil {
  4749  		if value == nil {
  4750  			vm.pc += int(jmp)
  4751  		} else {
  4752  			vm.iterStack[l].val = value
  4753  			vm.pc++
  4754  		}
  4755  	} else {
  4756  		l := len(vm.iterStack) - 1
  4757  		vm.iterStack[l] = iterStackItem{}
  4758  		vm.iterStack = vm.iterStack[:l]
  4759  		vm.throw(ex.val)
  4760  		return
  4761  	}
  4762  }
  4763  
  4764  type iterGetNextOrUndef struct{}
  4765  
  4766  func (iterGetNextOrUndef) exec(vm *vm) {
  4767  	l := len(vm.iterStack) - 1
  4768  	iter := vm.iterStack[l].iter
  4769  	var value Value
  4770  	if iter.iterator != nil {
  4771  		var ex *Exception
  4772  		value, ex = iter.step()
  4773  		if ex != nil {
  4774  			l := len(vm.iterStack) - 1
  4775  			vm.iterStack[l] = iterStackItem{}
  4776  			vm.iterStack = vm.iterStack[:l]
  4777  			vm.throw(ex.val)
  4778  			return
  4779  		}
  4780  	}
  4781  	vm.push(nilSafe(value))
  4782  	vm.pc++
  4783  }
  4784  
  4785  type copyStash struct{}
  4786  
  4787  func (copyStash) exec(vm *vm) {
  4788  	oldStash := vm.stash
  4789  	newStash := &stash{
  4790  		outer: oldStash.outer,
  4791  	}
  4792  	vm.stashAllocs++
  4793  	newStash.values = append([]Value(nil), oldStash.values...)
  4794  	newStash.names = oldStash.names
  4795  	vm.stash = newStash
  4796  	vm.pc++
  4797  }
  4798  
  4799  type _throwAssignToConst struct{}
  4800  
  4801  var throwAssignToConst _throwAssignToConst
  4802  
  4803  func (_throwAssignToConst) exec(vm *vm) {
  4804  	vm.throw(errAssignToConst)
  4805  }
  4806  
  4807  func (r *Runtime) copyDataProperties(target, source Value) {
  4808  	targetObj := r.toObject(target)
  4809  	if source == _null || source == _undefined {
  4810  		return
  4811  	}
  4812  	sourceObj := source.ToObject(r)
  4813  	for item, next := iterateEnumerableProperties(sourceObj)(); next != nil; item, next = next() {
  4814  		createDataPropertyOrThrow(targetObj, item.name, item.value)
  4815  	}
  4816  }
  4817  
  4818  type _copySpread struct{}
  4819  
  4820  var copySpread _copySpread
  4821  
  4822  func (_copySpread) exec(vm *vm) {
  4823  	vm.r.copyDataProperties(vm.stack[vm.sp-2], vm.stack[vm.sp-1])
  4824  	vm.sp--
  4825  	vm.pc++
  4826  }
  4827  
  4828  type _copyRest struct{}
  4829  
  4830  var copyRest _copyRest
  4831  
  4832  func (_copyRest) exec(vm *vm) {
  4833  	vm.push(vm.r.NewObject())
  4834  	vm.r.copyDataProperties(vm.stack[vm.sp-1], vm.stack[vm.sp-2])
  4835  	vm.pc++
  4836  }
  4837  
  4838  type _createDestructSrc struct{}
  4839  
  4840  var createDestructSrc _createDestructSrc
  4841  
  4842  func (_createDestructSrc) exec(vm *vm) {
  4843  	v := vm.stack[vm.sp-1]
  4844  	vm.r.checkObjectCoercible(v)
  4845  	vm.push(vm.r.newDestructKeyedSource(v))
  4846  	vm.pc++
  4847  }
  4848  
  4849  type _checkObjectCoercible struct{}
  4850  
  4851  var checkObjectCoercible _checkObjectCoercible
  4852  
  4853  func (_checkObjectCoercible) exec(vm *vm) {
  4854  	vm.r.checkObjectCoercible(vm.stack[vm.sp-1])
  4855  	vm.pc++
  4856  }
  4857  
  4858  type createArgsRestStack int
  4859  
  4860  func (n createArgsRestStack) exec(vm *vm) {
  4861  	var values []Value
  4862  	delta := vm.args - int(n)
  4863  	if delta > 0 {
  4864  		values = make([]Value, delta)
  4865  		copy(values, vm.stack[vm.sb+int(n)+1:])
  4866  	}
  4867  	vm.push(vm.r.newArrayValues(values))
  4868  	vm.pc++
  4869  }
  4870  
  4871  type _createArgsRestStash struct{}
  4872  
  4873  var createArgsRestStash _createArgsRestStash
  4874  
  4875  func (_createArgsRestStash) exec(vm *vm) {
  4876  	vm.push(vm.r.newArrayValues(vm.stash.extraArgs))
  4877  	vm.stash.extraArgs = nil
  4878  	vm.pc++
  4879  }
  4880  
  4881  type concatStrings int
  4882  
  4883  func (n concatStrings) exec(vm *vm) {
  4884  	strs := vm.stack[vm.sp-int(n) : vm.sp]
  4885  	length := 0
  4886  	allAscii := true
  4887  	for i, s := range strs {
  4888  		switch s := s.(type) {
  4889  		case asciiString:
  4890  			length += s.Length()
  4891  		case unicodeString:
  4892  			length += s.Length()
  4893  			allAscii = false
  4894  		case *importedString:
  4895  			s.ensureScanned()
  4896  			if s.u != nil {
  4897  				strs[i] = s.u
  4898  				length += s.u.Length()
  4899  				allAscii = false
  4900  			} else {
  4901  				strs[i] = asciiString(s.s)
  4902  				length += len(s.s)
  4903  			}
  4904  		default:
  4905  			panic(unknownStringTypeErr(s))
  4906  		}
  4907  	}
  4908  
  4909  	vm.sp -= int(n) - 1
  4910  	if allAscii {
  4911  		var buf strings.Builder
  4912  		buf.Grow(length)
  4913  		for _, s := range strs {
  4914  			buf.WriteString(string(s.(asciiString)))
  4915  		}
  4916  		vm.stack[vm.sp-1] = asciiString(buf.String())
  4917  	} else {
  4918  		var buf unicodeStringBuilder
  4919  		buf.ensureStarted(length)
  4920  		for _, s := range strs {
  4921  			buf.writeString(s.(String))
  4922  		}
  4923  		vm.stack[vm.sp-1] = buf.String()
  4924  	}
  4925  	vm.pc++
  4926  }
  4927  
  4928  type getTaggedTmplObject struct {
  4929  	raw, cooked []Value
  4930  }
  4931  
  4932  // As tagged template objects are not cached (because it's hard to ensure the cache is cleaned without using
  4933  // finalizers) this wrapper is needed to override the equality method so that two objects for the same template
  4934  // literal appeared to be equal from the code's point of view.
  4935  type taggedTemplateArray struct {
  4936  	*arrayObject
  4937  	idPtr *[]Value
  4938  }
  4939  
  4940  func (a *taggedTemplateArray) equal(other objectImpl) bool {
  4941  	if o, ok := other.(*taggedTemplateArray); ok {
  4942  		return a.idPtr == o.idPtr
  4943  	}
  4944  	return false
  4945  }
  4946  
  4947  func (c *getTaggedTmplObject) exec(vm *vm) {
  4948  	cooked := vm.r.newArrayObject()
  4949  	setArrayValues(cooked, c.cooked)
  4950  	raw := vm.r.newArrayObject()
  4951  	setArrayValues(raw, c.raw)
  4952  
  4953  	cooked.propValueCount = len(c.cooked)
  4954  	cooked.lengthProp.writable = false
  4955  
  4956  	raw.propValueCount = len(c.raw)
  4957  	raw.lengthProp.writable = false
  4958  
  4959  	raw.preventExtensions(true)
  4960  	raw.val.self = &taggedTemplateArray{
  4961  		arrayObject: raw,
  4962  		idPtr:       &c.raw,
  4963  	}
  4964  
  4965  	cooked._putProp("raw", raw.val, false, false, false)
  4966  	cooked.preventExtensions(true)
  4967  	cooked.val.self = &taggedTemplateArray{
  4968  		arrayObject: cooked,
  4969  		idPtr:       &c.cooked,
  4970  	}
  4971  
  4972  	vm.push(cooked.val)
  4973  	vm.pc++
  4974  }
  4975  
  4976  type _loadSuper struct{}
  4977  
  4978  var loadSuper _loadSuper
  4979  
  4980  func (_loadSuper) exec(vm *vm) {
  4981  	homeObject := getHomeObject(vm.stack[vm.sb-1])
  4982  	if proto := homeObject.Prototype(); proto != nil {
  4983  		vm.push(proto)
  4984  	} else {
  4985  		vm.push(_undefined)
  4986  	}
  4987  	vm.pc++
  4988  }
  4989  
  4990  type newClass struct {
  4991  	ctor       *Program
  4992  	name       unistring.String
  4993  	source     string
  4994  	initFields *Program
  4995  
  4996  	privateFields, privateMethods       []unistring.String // only set when dynamic resolution is needed
  4997  	numPrivateFields, numPrivateMethods uint32
  4998  
  4999  	length        int
  5000  	hasPrivateEnv bool
  5001  }
  5002  
  5003  type newDerivedClass struct {
  5004  	newClass
  5005  }
  5006  
  5007  func (vm *vm) createPrivateType(f *classFuncObject, numFields, numMethods uint32) {
  5008  	typ := &privateEnvType{}
  5009  	typ.numFields = numFields
  5010  	typ.numMethods = numMethods
  5011  	f.privateEnvType = typ
  5012  	f.privateMethods = make([]Value, numMethods)
  5013  }
  5014  
  5015  func (vm *vm) fillPrivateNamesMap(typ *privateEnvType, privateFields, privateMethods []unistring.String) {
  5016  	if len(privateFields) > 0 || len(privateMethods) > 0 {
  5017  		penv := vm.privEnv.names
  5018  		if penv == nil {
  5019  			penv = make(privateNames)
  5020  			vm.privEnv.names = penv
  5021  		}
  5022  		for idx, field := range privateFields {
  5023  			penv[field] = &privateId{
  5024  				typ: typ,
  5025  				idx: uint32(idx),
  5026  			}
  5027  		}
  5028  		for idx, method := range privateMethods {
  5029  			penv[method] = &privateId{
  5030  				typ:      typ,
  5031  				idx:      uint32(idx),
  5032  				isMethod: true,
  5033  			}
  5034  		}
  5035  	}
  5036  }
  5037  
  5038  func (c *newClass) create(protoParent, ctorParent *Object, vm *vm, derived bool) (prototype, cls *Object) {
  5039  	proto := vm.r.newBaseObject(protoParent, classObject)
  5040  	f := vm.r.newClassFunc(c.name, c.length, ctorParent, derived)
  5041  	f._putProp("prototype", proto.val, false, false, false)
  5042  	proto._putProp("constructor", f.val, true, false, true)
  5043  	f.prg = c.ctor
  5044  	f.stash = vm.stash
  5045  	f.src = c.source
  5046  	f.initFields = c.initFields
  5047  	if c.hasPrivateEnv {
  5048  		vm.privEnv = &privateEnv{
  5049  			outer: vm.privEnv,
  5050  		}
  5051  		vm.createPrivateType(f, c.numPrivateFields, c.numPrivateMethods)
  5052  		vm.fillPrivateNamesMap(f.privateEnvType, c.privateFields, c.privateMethods)
  5053  		vm.privEnv.instanceType = f.privateEnvType
  5054  	}
  5055  	f.privEnv = vm.privEnv
  5056  	return proto.val, f.val
  5057  }
  5058  
  5059  func (c *newClass) exec(vm *vm) {
  5060  	proto, cls := c.create(vm.r.global.ObjectPrototype, vm.r.global.FunctionPrototype, vm, false)
  5061  	sp := vm.sp
  5062  	vm.stack.expand(sp + 1)
  5063  	vm.stack[sp] = proto
  5064  	vm.stack[sp+1] = cls
  5065  	vm.sp = sp + 2
  5066  	vm.pc++
  5067  }
  5068  
  5069  func (c *newDerivedClass) exec(vm *vm) {
  5070  	var protoParent *Object
  5071  	var superClass *Object
  5072  	if o := vm.stack[vm.sp-1]; o != _null {
  5073  		if sc, ok := o.(*Object); !ok || sc.self.assertConstructor() == nil {
  5074  			vm.throw(vm.r.NewTypeError("Class extends value is not a constructor or null"))
  5075  			return
  5076  		} else {
  5077  			v := sc.self.getStr("prototype", nil)
  5078  			if v != _null {
  5079  				if o, ok := v.(*Object); ok {
  5080  					protoParent = o
  5081  				} else {
  5082  					vm.throw(vm.r.NewTypeError("Class extends value does not have valid prototype property"))
  5083  					return
  5084  				}
  5085  			}
  5086  			superClass = sc
  5087  		}
  5088  	} else {
  5089  		superClass = vm.r.global.FunctionPrototype
  5090  	}
  5091  
  5092  	proto, cls := c.create(protoParent, superClass, vm, true)
  5093  	vm.stack[vm.sp-1] = proto
  5094  	vm.push(cls)
  5095  	vm.pc++
  5096  }
  5097  
  5098  // Creates a special instance of *classFuncObject which is only used during evaluation of a class declaration
  5099  // to initialise static fields and instance private methods of another class.
  5100  type newStaticFieldInit struct {
  5101  	initFields                          *Program
  5102  	numPrivateFields, numPrivateMethods uint32
  5103  }
  5104  
  5105  func (c *newStaticFieldInit) exec(vm *vm) {
  5106  	f := vm.r.newClassFunc("", 0, vm.r.global.FunctionPrototype, false)
  5107  	if c.numPrivateFields > 0 || c.numPrivateMethods > 0 {
  5108  		vm.createPrivateType(f, c.numPrivateFields, c.numPrivateMethods)
  5109  	}
  5110  	f.initFields = c.initFields
  5111  	f.stash = vm.stash
  5112  	vm.push(f.val)
  5113  	vm.pc++
  5114  }
  5115  
  5116  func (vm *vm) loadThis(v Value) {
  5117  	if v != nil {
  5118  		vm.push(v)
  5119  	} else {
  5120  		vm.throw(vm.r.newError(vm.r.global.ReferenceError, "Must call super constructor in derived class before accessing 'this'"))
  5121  		return
  5122  	}
  5123  	vm.pc++
  5124  }
  5125  
  5126  type loadThisStash uint32
  5127  
  5128  func (l loadThisStash) exec(vm *vm) {
  5129  	vm.loadThis(*vm.getStashPtr(uint32(l)))
  5130  }
  5131  
  5132  type loadThisStack struct{}
  5133  
  5134  func (loadThisStack) exec(vm *vm) {
  5135  	vm.loadThis(vm.stack[vm.sb])
  5136  }
  5137  
  5138  func (vm *vm) getStashPtr(s uint32) *Value {
  5139  	level := int(s) >> 24
  5140  	idx := s & 0x00FFFFFF
  5141  	stash := vm.stash
  5142  	for i := 0; i < level; i++ {
  5143  		stash = stash.outer
  5144  	}
  5145  
  5146  	return &stash.values[idx]
  5147  }
  5148  
  5149  type getThisDynamic struct{}
  5150  
  5151  func (getThisDynamic) exec(vm *vm) {
  5152  	for stash := vm.stash; stash != nil; stash = stash.outer {
  5153  		if stash.obj == nil {
  5154  			if v, exists := stash.getByName(thisBindingName); exists {
  5155  				vm.push(v)
  5156  				vm.pc++
  5157  				return
  5158  			}
  5159  		}
  5160  	}
  5161  	vm.push(vm.r.globalObject)
  5162  	vm.pc++
  5163  }
  5164  
  5165  type throwConst struct {
  5166  	v interface{}
  5167  }
  5168  
  5169  func (t throwConst) exec(vm *vm) {
  5170  	vm.throw(t.v)
  5171  }
  5172  
  5173  type resolveThisStack struct{}
  5174  
  5175  func (r resolveThisStack) exec(vm *vm) {
  5176  	vm.refStack = append(vm.refStack, &thisRef{v: (*[]Value)(&vm.stack), idx: vm.sb})
  5177  	vm.pc++
  5178  }
  5179  
  5180  type resolveThisStash uint32
  5181  
  5182  func (r resolveThisStash) exec(vm *vm) {
  5183  	level := int(r) >> 24
  5184  	idx := r & 0x00FFFFFF
  5185  	stash := vm.stash
  5186  	for i := 0; i < level; i++ {
  5187  		stash = stash.outer
  5188  	}
  5189  	vm.refStack = append(vm.refStack, &thisRef{v: &stash.values, idx: int(idx)})
  5190  	vm.pc++
  5191  }
  5192  
  5193  type resolveThisDynamic struct{}
  5194  
  5195  func (resolveThisDynamic) exec(vm *vm) {
  5196  	for stash := vm.stash; stash != nil; stash = stash.outer {
  5197  		if stash.obj == nil {
  5198  			if idx, exists := stash.names[thisBindingName]; exists {
  5199  				vm.refStack = append(vm.refStack, &thisRef{v: &stash.values, idx: int(idx &^ maskTyp)})
  5200  				vm.pc++
  5201  				return
  5202  			}
  5203  		}
  5204  	}
  5205  	panic(vm.r.newError(vm.r.global.ReferenceError, "Compiler bug: 'this' reference is not found in resolveThisDynamic"))
  5206  }
  5207  
  5208  type defineComputedKey int
  5209  
  5210  func (offset defineComputedKey) exec(vm *vm) {
  5211  	obj := vm.r.toObject(vm.stack[vm.sp-int(offset)])
  5212  	if h, ok := obj.self.(*classFuncObject); ok {
  5213  		key := toPropertyKey(vm.stack[vm.sp-1])
  5214  		h.computedKeys = append(h.computedKeys, key)
  5215  		vm.sp--
  5216  		vm.pc++
  5217  		return
  5218  	}
  5219  	panic(vm.r.NewTypeError("Compiler bug: unexpected target for defineComputedKey: %v", obj))
  5220  }
  5221  
  5222  type loadComputedKey int
  5223  
  5224  func (idx loadComputedKey) exec(vm *vm) {
  5225  	obj := vm.r.toObject(vm.stack[vm.sb-1])
  5226  	if h, ok := obj.self.(*classFuncObject); ok {
  5227  		vm.push(h.computedKeys[idx])
  5228  		vm.pc++
  5229  		return
  5230  	}
  5231  	panic(vm.r.NewTypeError("Compiler bug: unexpected target for loadComputedKey: %v", obj))
  5232  }
  5233  
  5234  type initStaticElements struct {
  5235  	privateFields, privateMethods []unistring.String
  5236  }
  5237  
  5238  func (i *initStaticElements) exec(vm *vm) {
  5239  	cls := vm.stack[vm.sp-1]
  5240  	staticInit := vm.r.toObject(vm.stack[vm.sp-3])
  5241  	vm.sp -= 2
  5242  	if h, ok := staticInit.self.(*classFuncObject); ok {
  5243  		h._putProp("prototype", cls, true, true, true) // so that 'super' resolution work
  5244  		h.privEnv = vm.privEnv
  5245  		if h.privateEnvType != nil {
  5246  			vm.privEnv.staticType = h.privateEnvType
  5247  			vm.fillPrivateNamesMap(h.privateEnvType, i.privateFields, i.privateMethods)
  5248  		}
  5249  		h._initFields(vm.r.toObject(cls))
  5250  		vm.stack[vm.sp-1] = cls
  5251  
  5252  		vm.pc++
  5253  		return
  5254  	}
  5255  	panic(vm.r.NewTypeError("Compiler bug: unexpected target for initStaticElements: %v", staticInit))
  5256  }
  5257  
  5258  type definePrivateMethod struct {
  5259  	idx          int
  5260  	targetOffset int
  5261  }
  5262  
  5263  func (d *definePrivateMethod) getPrivateMethods(vm *vm) []Value {
  5264  	obj := vm.r.toObject(vm.stack[vm.sp-d.targetOffset])
  5265  	if cls, ok := obj.self.(*classFuncObject); ok {
  5266  		return cls.privateMethods
  5267  	} else {
  5268  		panic(vm.r.NewTypeError("Compiler bug: wrong target type for definePrivateMethod: %T", obj.self))
  5269  	}
  5270  }
  5271  
  5272  func (d *definePrivateMethod) exec(vm *vm) {
  5273  	methods := d.getPrivateMethods(vm)
  5274  	methods[d.idx] = vm.stack[vm.sp-1]
  5275  	vm.sp--
  5276  	vm.pc++
  5277  }
  5278  
  5279  type definePrivateGetter struct {
  5280  	definePrivateMethod
  5281  }
  5282  
  5283  func (d *definePrivateGetter) exec(vm *vm) {
  5284  	methods := d.getPrivateMethods(vm)
  5285  	val := vm.stack[vm.sp-1]
  5286  	method := vm.r.toObject(val)
  5287  	p, _ := methods[d.idx].(*valueProperty)
  5288  	if p == nil {
  5289  		p = &valueProperty{
  5290  			accessor: true,
  5291  		}
  5292  		methods[d.idx] = p
  5293  	}
  5294  	if p.getterFunc != nil {
  5295  		vm.throw(vm.r.NewTypeError("Private getter has already been declared"))
  5296  		return
  5297  	}
  5298  	p.getterFunc = method
  5299  	vm.sp--
  5300  	vm.pc++
  5301  }
  5302  
  5303  type definePrivateSetter struct {
  5304  	definePrivateMethod
  5305  }
  5306  
  5307  func (d *definePrivateSetter) exec(vm *vm) {
  5308  	methods := d.getPrivateMethods(vm)
  5309  	val := vm.stack[vm.sp-1]
  5310  	method := vm.r.toObject(val)
  5311  	p, _ := methods[d.idx].(*valueProperty)
  5312  	if p == nil {
  5313  		p = &valueProperty{
  5314  			accessor: true,
  5315  		}
  5316  		methods[d.idx] = p
  5317  	}
  5318  	if p.setterFunc != nil {
  5319  		vm.throw(vm.r.NewTypeError("Private setter has already been declared"))
  5320  		return
  5321  	}
  5322  	p.setterFunc = method
  5323  	vm.sp--
  5324  	vm.pc++
  5325  }
  5326  
  5327  type definePrivateProp struct {
  5328  	idx int
  5329  }
  5330  
  5331  func (d *definePrivateProp) exec(vm *vm) {
  5332  	f := vm.r.toObject(vm.stack[vm.sb-1]).self.(*classFuncObject)
  5333  	obj := vm.r.toObject(vm.stack[vm.sp-2])
  5334  	penv := obj.self.getPrivateEnv(f.privateEnvType, false)
  5335  	penv.fields[d.idx] = vm.stack[vm.sp-1]
  5336  	vm.sp--
  5337  	vm.pc++
  5338  }
  5339  
  5340  type getPrivatePropRes resolvedPrivateName
  5341  
  5342  func (vm *vm) getPrivateType(level uint8, isStatic bool) *privateEnvType {
  5343  	e := vm.privEnv
  5344  	for i := uint8(0); i < level; i++ {
  5345  		e = e.outer
  5346  	}
  5347  	if isStatic {
  5348  		return e.staticType
  5349  	}
  5350  	return e.instanceType
  5351  }
  5352  
  5353  func (g *getPrivatePropRes) _get(base Value, vm *vm) Value {
  5354  	return vm.getPrivateProp(base, g.name, vm.getPrivateType(g.level, g.isStatic), g.idx, g.isMethod)
  5355  }
  5356  
  5357  func (g *getPrivatePropRes) exec(vm *vm) {
  5358  	vm.stack[vm.sp-1] = g._get(vm.stack[vm.sp-1], vm)
  5359  	vm.pc++
  5360  }
  5361  
  5362  type getPrivatePropId privateId
  5363  
  5364  func (g *getPrivatePropId) exec(vm *vm) {
  5365  	vm.stack[vm.sp-1] = vm.getPrivateProp(vm.stack[vm.sp-1], g.name, g.typ, g.idx, g.isMethod)
  5366  	vm.pc++
  5367  }
  5368  
  5369  type getPrivatePropIdCallee privateId
  5370  
  5371  func (g *getPrivatePropIdCallee) exec(vm *vm) {
  5372  	prop := vm.getPrivateProp(vm.stack[vm.sp-1], g.name, g.typ, g.idx, g.isMethod)
  5373  	if prop == nil {
  5374  		prop = memberUnresolved{valueUnresolved{r: vm.r, ref: (*privateId)(g).string()}}
  5375  	}
  5376  	vm.push(prop)
  5377  
  5378  	vm.pc++
  5379  }
  5380  
  5381  func (vm *vm) getPrivateProp(base Value, name unistring.String, typ *privateEnvType, idx uint32, isMethod bool) Value {
  5382  	obj := vm.r.toObject(base)
  5383  	penv := obj.self.getPrivateEnv(typ, false)
  5384  	var v Value
  5385  	if penv != nil {
  5386  		if isMethod {
  5387  			v = penv.methods[idx]
  5388  		} else {
  5389  			v = penv.fields[idx]
  5390  			if v == nil {
  5391  				panic(vm.r.NewTypeError("Private member #%s is accessed before it is initialized", name))
  5392  			}
  5393  		}
  5394  	} else {
  5395  		panic(vm.r.NewTypeError("Cannot read private member #%s from an object whose class did not declare it", name))
  5396  	}
  5397  	if prop, ok := v.(*valueProperty); ok {
  5398  		if prop.getterFunc == nil {
  5399  			panic(vm.r.NewTypeError("'#%s' was defined without a getter", name))
  5400  		}
  5401  		v = prop.get(obj)
  5402  	}
  5403  	return v
  5404  }
  5405  
  5406  type getPrivatePropResCallee getPrivatePropRes
  5407  
  5408  func (g *getPrivatePropResCallee) exec(vm *vm) {
  5409  	prop := (*getPrivatePropRes)(g)._get(vm.stack[vm.sp-1], vm)
  5410  	if prop == nil {
  5411  		prop = memberUnresolved{valueUnresolved{r: vm.r, ref: (*resolvedPrivateName)(g).string()}}
  5412  	}
  5413  	vm.push(prop)
  5414  
  5415  	vm.pc++
  5416  }
  5417  
  5418  func (vm *vm) setPrivateProp(base Value, name unistring.String, typ *privateEnvType, idx uint32, isMethod bool, val Value) {
  5419  	obj := vm.r.toObject(base)
  5420  	penv := obj.self.getPrivateEnv(typ, false)
  5421  	if penv != nil {
  5422  		if isMethod {
  5423  			v := penv.methods[idx]
  5424  			if prop, ok := v.(*valueProperty); ok {
  5425  				if prop.setterFunc != nil {
  5426  					prop.set(base, val)
  5427  				} else {
  5428  					panic(vm.r.NewTypeError("Cannot assign to read only property '#%s'", name))
  5429  				}
  5430  			} else {
  5431  				panic(vm.r.NewTypeError("Private method '#%s' is not writable", name))
  5432  			}
  5433  		} else {
  5434  			ptr := &penv.fields[idx]
  5435  			if *ptr == nil {
  5436  				panic(vm.r.NewTypeError("Private member #%s is accessed before it is initialized", name))
  5437  			}
  5438  			*ptr = val
  5439  		}
  5440  	} else {
  5441  		panic(vm.r.NewTypeError("Cannot write private member #%s from an object whose class did not declare it", name))
  5442  	}
  5443  }
  5444  
  5445  func (vm *vm) exceptionFromValue(x interface{}) *Exception {
  5446  	var ex *Exception
  5447  	switch x1 := x.(type) {
  5448  	case *Object:
  5449  		ex = &Exception{
  5450  			val: x1,
  5451  		}
  5452  		if er, ok := x1.self.(*errorObject); ok {
  5453  			ex.stack = er.stack
  5454  		}
  5455  	case Value:
  5456  		ex = &Exception{
  5457  			val: x1,
  5458  		}
  5459  	case *Exception:
  5460  		ex = x1
  5461  	case typeError:
  5462  		ex = &Exception{
  5463  			val: vm.r.NewTypeError(string(x1)),
  5464  		}
  5465  	case referenceError:
  5466  		ex = &Exception{
  5467  			val: vm.r.newError(vm.r.global.ReferenceError, string(x1)),
  5468  		}
  5469  	case rangeError:
  5470  		ex = &Exception{
  5471  			val: vm.r.newError(vm.r.global.RangeError, string(x1)),
  5472  		}
  5473  	case syntaxError:
  5474  		ex = &Exception{
  5475  			val: vm.r.newError(vm.r.global.SyntaxError, string(x1)),
  5476  		}
  5477  	default:
  5478  		/*
  5479  			if vm.prg != nil {
  5480  				vm.prg.dumpCode(log.Printf)
  5481  			}
  5482  			log.Print("Stack: ", string(debug.Stack()))
  5483  			panic(fmt.Errorf("Panic at %d: %v", vm.pc, x))
  5484  		*/
  5485  		return nil
  5486  	}
  5487  	if ex.stack == nil {
  5488  		ex.stack = vm.captureStack(make([]StackFrame, 0, len(vm.callStack)+1), 0)
  5489  	}
  5490  	return ex
  5491  }
  5492  
  5493  type setPrivatePropRes resolvedPrivateName
  5494  
  5495  func (p *setPrivatePropRes) _set(base Value, val Value, vm *vm) {
  5496  	vm.setPrivateProp(base, p.name, vm.getPrivateType(p.level, p.isStatic), p.idx, p.isMethod, val)
  5497  }
  5498  
  5499  func (p *setPrivatePropRes) exec(vm *vm) {
  5500  	v := vm.stack[vm.sp-1]
  5501  	p._set(vm.stack[vm.sp-2], v, vm)
  5502  	vm.stack[vm.sp-2] = v
  5503  	vm.sp--
  5504  	vm.pc++
  5505  }
  5506  
  5507  type setPrivatePropResP setPrivatePropRes
  5508  
  5509  func (p *setPrivatePropResP) exec(vm *vm) {
  5510  	v := vm.stack[vm.sp-1]
  5511  	(*setPrivatePropRes)(p)._set(vm.stack[vm.sp-2], v, vm)
  5512  	vm.sp -= 2
  5513  	vm.pc++
  5514  }
  5515  
  5516  type setPrivatePropId privateId
  5517  
  5518  func (p *setPrivatePropId) exec(vm *vm) {
  5519  	v := vm.stack[vm.sp-1]
  5520  	vm.setPrivateProp(vm.stack[vm.sp-2], p.name, p.typ, p.idx, p.isMethod, v)
  5521  	vm.stack[vm.sp-2] = v
  5522  	vm.sp--
  5523  	vm.pc++
  5524  }
  5525  
  5526  type setPrivatePropIdP privateId
  5527  
  5528  func (p *setPrivatePropIdP) exec(vm *vm) {
  5529  	v := vm.stack[vm.sp-1]
  5530  	vm.setPrivateProp(vm.stack[vm.sp-2], p.name, p.typ, p.idx, p.isMethod, v)
  5531  	vm.sp -= 2
  5532  	vm.pc++
  5533  }
  5534  
  5535  type popPrivateEnv struct{}
  5536  
  5537  func (popPrivateEnv) exec(vm *vm) {
  5538  	vm.privEnv = vm.privEnv.outer
  5539  	vm.pc++
  5540  }
  5541  
  5542  type privateInRes resolvedPrivateName
  5543  
  5544  func (i *privateInRes) exec(vm *vm) {
  5545  	obj := vm.r.toObject(vm.stack[vm.sp-1])
  5546  	pe := obj.self.getPrivateEnv(vm.getPrivateType(i.level, i.isStatic), false)
  5547  	if pe != nil && (i.isMethod && pe.methods[i.idx] != nil || !i.isMethod && pe.fields[i.idx] != nil) {
  5548  		vm.stack[vm.sp-1] = valueTrue
  5549  	} else {
  5550  		vm.stack[vm.sp-1] = valueFalse
  5551  	}
  5552  	vm.pc++
  5553  }
  5554  
  5555  type privateInId privateId
  5556  
  5557  func (i *privateInId) exec(vm *vm) {
  5558  	obj := vm.r.toObject(vm.stack[vm.sp-1])
  5559  	pe := obj.self.getPrivateEnv(i.typ, false)
  5560  	if pe != nil && (i.isMethod && pe.methods[i.idx] != nil || !i.isMethod && pe.fields[i.idx] != nil) {
  5561  		vm.stack[vm.sp-1] = valueTrue
  5562  	} else {
  5563  		vm.stack[vm.sp-1] = valueFalse
  5564  	}
  5565  	vm.pc++
  5566  }
  5567  
  5568  type getPrivateRefRes resolvedPrivateName
  5569  
  5570  func (r *getPrivateRefRes) exec(vm *vm) {
  5571  	vm.refStack = append(vm.refStack, &privateRefRes{
  5572  		base: vm.stack[vm.sp-1].ToObject(vm.r),
  5573  		name: (*resolvedPrivateName)(r),
  5574  	})
  5575  	vm.sp--
  5576  	vm.pc++
  5577  }
  5578  
  5579  type getPrivateRefId privateId
  5580  
  5581  func (r *getPrivateRefId) exec(vm *vm) {
  5582  	vm.refStack = append(vm.refStack, &privateRefId{
  5583  		base: vm.stack[vm.sp-1].ToObject(vm.r),
  5584  		id:   (*privateId)(r),
  5585  	})
  5586  	vm.sp--
  5587  	vm.pc++
  5588  }
  5589  
  5590  func (y *yieldMarker) exec(vm *vm) {
  5591  	vm.pc = -vm.pc // this will terminate the run loop
  5592  	vm.push(y)     // marker so the caller knows it's a yield, not a return
  5593  }
  5594  
  5595  func (y *yieldMarker) String() string {
  5596  	if y == yieldEmpty {
  5597  		return "empty"
  5598  	}
  5599  	switch y.resultType {
  5600  	case resultYield:
  5601  		return "yield"
  5602  	case resultYieldRes:
  5603  		return "yieldRes"
  5604  	case resultYieldDelegate:
  5605  		return "yield*"
  5606  	case resultYieldDelegateRes:
  5607  		return "yield*Res"
  5608  	case resultAwait:
  5609  		return "await"
  5610  	default:
  5611  		return "unknown"
  5612  	}
  5613  }