package goja

import (
	
	
	
	
	
	
	
	

	
)

const (
	maxInt = 1 << 53

	tryPanicMarker = -2
)

type valueStack []Value

type stash struct {
	values    []Value
	extraArgs []Value
	names     map[unistring.String]uint32
	obj       *Object

	outer *stash

	// If this is a top-level function stash, sets the type of the function. If set, dynamic var declarations
	// created by direct eval go here.
	funcType funcType
}

type context struct {
	prg       *Program
	stash     *stash
	privEnv   *privateEnv
	newTarget Value
	result    Value
	pc, sb    int
	args      int
}

type tryFrame struct {
	// holds an uncaught exception for the 'finally' block
	exception *Exception

	callStackLen, iterLen, refLen uint32

	sp      int32
	stash   *stash
	privEnv *privateEnv

	catchPos, finallyPos, finallyRet int32
}

type execCtx struct {
	context
	stack     []Value
	tryStack  []tryFrame
	iterStack []iterStackItem
	refStack  []ref
}

func ( *vm) ( *execCtx, , ,  uint32) {
	.saveCtx(&.context)
	.stack = append(.stack[:0], .stack[.sb-1:.sp]...)
	if len(.tryStack) > int() {
		.tryStack = append(.tryStack[:0], .tryStack[:]...)
		.tryStack = .tryStack[:]
		 := int32(.sb - 1)
		for  := range .tryStack {
			 := &.tryStack[]
			.iterLen -= 
			.refLen -= 
			.sp -= 
		}
	}
	if len(.iterStack) > int() {
		.iterStack = append(.iterStack[:0], .iterStack[:]...)
		.iterStack = .iterStack[:]
	}
	if len(.refStack) > int() {
		.refStack = append(.refStack[:0], .refStack[:]...)
		.refStack = .refStack[:]
	}
}

func ( *vm) ( *execCtx) {
	.restoreCtx(&.context)
	 := .sp
	.sb =  + 1
	.stack.expand( + len(.stack))
	copy(.stack[:], .stack)
	.sp += len(.stack)
	for  := range .tryStack {
		 := &.tryStack[]
		.callStackLen = uint32(len(.callStack))
		.iterLen += uint32(len(.iterStack))
		.refLen += uint32(len(.refStack))
		.sp += int32()
	}
	.tryStack = append(.tryStack, .tryStack...)
	.iterStack = append(.iterStack, .iterStack...)
	.refStack = append(.refStack, .refStack...)
}

type iterStackItem struct {
	val  Value
	f    iterNextFunc
	iter *iteratorRecord
}

type ref interface {
	get() Value
	set(Value)
	init(Value)
	refname() unistring.String
}

type stashRef struct {
	n   unistring.String
	v   *[]Value
	idx int
}

func ( *stashRef) () Value {
	return nilSafe((*.v)[.idx])
}

func ( *stashRef) ( Value) {
	(*.v)[.idx] = 
}

func ( *stashRef) ( Value) {
	.set()
}

func ( *stashRef) () unistring.String {
	return .n
}

type thisRef struct {
	v   *[]Value
	idx int
}

func ( *thisRef) () Value {
	 := (*.v)[.idx]
	if  == nil {
		panic(referenceError("Must call super constructor in derived class before accessing 'this'"))
	}

	return 
}

func ( *thisRef) ( Value) {
	 := &(*.v)[.idx]
	if * != nil {
		panic(referenceError("Super constructor may only be called once"))
	}
	* = 
}

func ( *thisRef) ( Value) {
	.set()
}

func ( *thisRef) () unistring.String {
	return thisBindingName
}

type stashRefLex struct {
	stashRef
}

func ( *stashRefLex) () Value {
	 := (*.v)[.idx]
	if  == nil {
		panic(errAccessBeforeInit)
	}
	return 
}

func ( *stashRefLex) ( Value) {
	 := &(*.v)[.idx]
	if * == nil {
		panic(errAccessBeforeInit)
	}
	* = 
}

func ( *stashRefLex) ( Value) {
	(*.v)[.idx] = 
}

type stashRefConst struct {
	stashRefLex
	strictConst bool
}

func ( *stashRefConst) ( Value) {
	if .strictConst {
		panic(errAssignToConst)
	}
}

type objRef struct {
	base   *Object
	name   Value
	this   Value
	strict bool

	nameConverted bool
}

func ( *objRef) () Value {
	if !.nameConverted {
		.name = toPropertyKey(.name)
		.nameConverted = true
	}
	return .name
}

func ( *objRef) () Value {
	return .base.get(.getKey(), .this)
}

func ( *objRef) ( Value) {
	 := .getKey()
	if .this != nil {
		.base.set(, , .this, .strict)
	} else {
		.base.setOwn(, , .strict)
	}
}

func ( *objRef) ( Value) {
	if .this != nil {
		.base.set(.getKey(), , .this, .strict)
	} else {
		.base.setOwn(.getKey(), , .strict)
	}
}

func ( *objRef) () unistring.String {
	return .getKey().string()
}

type objStrRef struct {
	base    *Object
	name    unistring.String
	this    Value
	strict  bool
	binding bool
}

func ( *objStrRef) () Value {
	return .base.self.getStr(.name, .this)
}

func ( *objStrRef) ( Value) {
	if .strict && .binding && !.base.self.hasOwnPropertyStr(.name) {
		panic(referenceError(fmt.Sprintf("%s is not defined", .name)))
	}
	if .this != nil {
		.base.setStr(.name, , .this, .strict)
	} else {
		.base.self.setOwnStr(.name, , .strict)
	}
}

func ( *objStrRef) ( Value) {
	if .this != nil {
		.base.setStr(.name, , .this, .strict)
	} else {
		.base.self.setOwnStr(.name, , .strict)
	}
}

func ( *objStrRef) () unistring.String {
	return .name
}

type privateRefRes struct {
	base *Object
	name *resolvedPrivateName
}

func ( *privateRefRes) () Value {
	return (*getPrivatePropRes)(.name)._get(.base, .base.runtime.vm)
}

func ( *privateRefRes) ( Value) {
	(*setPrivatePropRes)(.name)._set(.base, , .base.runtime.vm)
}

func ( *privateRefRes) ( Value) {
	panic("not supported")
}

func ( *privateRefRes) () unistring.String {
	return .name.string()
}

type privateRefId struct {
	base *Object
	id   *privateId
}

func ( *privateRefId) () Value {
	return .base.runtime.vm.getPrivateProp(.base, .id.name, .id.typ, .id.idx, .id.isMethod)
}

func ( *privateRefId) ( Value) {
	.base.runtime.vm.setPrivateProp(.base, .id.name, .id.typ, .id.idx, .id.isMethod, )
}

func ( *privateRefId) ( Value) {
	panic("not supported")
}

func ( *privateRefId) () unistring.String {
	return .id.string()
}

type unresolvedRef struct {
	runtime *Runtime
	name    unistring.String
}

func ( *unresolvedRef) () Value {
	.runtime.throwReferenceError(.name)
	panic("Unreachable")
}

func ( *unresolvedRef) (Value) {
	.get()
}

func ( *unresolvedRef) (Value) {
	.get()
}

func ( *unresolvedRef) () unistring.String {
	return .name
}

type vm struct {
	r            *Runtime
	prg          *Program
	pc           int
	stack        valueStack
	sp, sb, args int

	stash     *stash
	privEnv   *privateEnv
	callStack []context
	iterStack []iterStackItem
	refStack  []ref
	tryStack  []tryFrame
	newTarget Value
	result    Value

	maxCallStackSize int

	stashAllocs int

	interrupted   uint32
	interruptVal  interface{}
	interruptLock sync.Mutex

	curAsyncRunner *asyncRunner

	profTracker *profTracker
}

type instruction interface {
	exec(*vm)
}

func intToValue( int64) Value {
	if  := 256 + ;  >= 0 &&  < 256 {
		return intCache[]
	}
	if  >= -maxInt &&  <= maxInt {
		return valueInt()
	}
	return valueFloat()
}

func floatToInt( float64) ( int64,  bool) {
	if ( != 0 || !math.Signbit()) && !math.IsInf(, 0) &&  == math.Trunc() &&  >= -maxInt &&  <= maxInt {
		return int64(), true
	}
	return 0, false
}

func floatToValue( float64) ( Value) {
	if ,  := floatToInt();  {
		return intToValue()
	}
	switch {
	case  == 0:
		return _negativeZero
	case math.IsNaN():
		return _NaN
	case math.IsInf(, 1):
		return _positiveInf
	case math.IsInf(, -1):
		return _negativeInf
	}
	return valueFloat()
}

func toNumeric( Value) Value {
	switch v := .(type) {
	case valueInt, *valueBigInt:
		return 
	case valueFloat:
		return floatToValue(float64())
	case *Object:
		 := .toPrimitiveNumber()
		if ,  := .(*valueBigInt);  {
			return 
		}
		return .ToNumber()
	}
	return .ToNumber()
}

func ( *valueStack) ( int) {
	if  < len(*) {
		return
	}
	++
	if  < cap(*) {
		* = (*)[:]
	} else {
		var  int
		if  < 1024 {
			 =  * 2
		} else {
			 = ( + 1025) &^ 1023
		}
		 := make([]Value, , )
		copy(, *)
		* = 
	}
}

func stashObjHas( *Object,  unistring.String) bool {
	if .self.hasPropertyStr() {
		if ,  := .self.getSym(SymUnscopables, nil).(*Object);  {
			if  := .self.getStr(, nil);  != nil {
				return !.ToBoolean()
			}
		}
		return true
	}
	return false
}

func ( *stash) () bool {
	return .funcType != funcNone
}

func ( *stash) ( uint32,  Value) {
	if .obj != nil {
		panic("Attempt to init by idx into an object scope")
	}
	.values[] = 
}

func ( *stash) ( unistring.String,  Value) {
	if ,  := .names[];  {
		.values[&^maskTyp] = 
	} else {
		panic(referenceError(fmt.Sprintf("%s is not defined", )))
	}
}

func ( *stash) ( uint32) Value {
	return .values[]
}

func ( *stash) ( unistring.String) ( Value,  bool) {
	if .obj != nil {
		if stashObjHas(.obj, ) {
			return nilSafe(.obj.self.getStr(, nil)), true
		}
		return nil, false
	}
	if ,  := .names[];  {
		 := .values[&^maskTyp]
		if  == nil {
			if &maskVar == 0 {
				panic(errAccessBeforeInit)
			} else {
				 = _undefined
			}
		}
		return , true
	}
	return nil, false
}

func ( *stash) ( unistring.String,  bool) ref {
	if  := .obj;  != nil {
		if stashObjHas(, ) {
			return &objStrRef{
				base:    ,
				name:    ,
				strict:  ,
				binding: true,
			}
		}
	} else {
		if ,  := .names[];  {
			if &maskVar == 0 {
				if &maskConst == 0 {
					return &stashRefLex{
						stashRef: stashRef{
							n:   ,
							v:   &.values,
							idx: int( &^ maskTyp),
						},
					}
				} else {
					return &stashRefConst{
						stashRefLex: stashRefLex{
							stashRef: stashRef{
								n:   ,
								v:   &.values,
								idx: int( &^ maskTyp),
							},
						},
						strictConst:  || (&maskStrict != 0),
					}
				}
			} else {
				return &stashRef{
					n:   ,
					v:   &.values,
					idx: int( &^ maskTyp),
				}
			}
		}
	}
	return nil
}

func ( *stash) ( unistring.String,  bool) {
	if .names == nil {
		.names = make(map[unistring.String]uint32)
	}
	if ,  := .names[]; ! {
		 := uint32(len(.names)) | maskVar
		if  {
			 |= maskDeletable
		}
		.names[] = 
		.values = append(.values, _undefined)
	}
}

func ( *stash) ( unistring.String,  bool) {
	if .names == nil {
		.names = make(map[unistring.String]uint32)
	}
	if ,  := .names[]; ! {
		 := uint32(len(.names))
		if  {
			 |= maskConst | maskStrict
		}
		.names[] = 
		.values = append(.values, nil)
	}
}

func ( *stash) ( unistring.String) {
	delete(.names, )
}

func ( *vm) () {
	.stash = &stash{
		outer: .stash,
	}
	.stashAllocs++
}

func ( *vm) () {
	.sb = -1
	.stash = &.r.global.stash
	.maxCallStackSize = math.MaxInt32
}

func ( *vm) () bool {
	 := .pc
	return  < 0 ||  >= len(.prg.code)
}

func ( *vm) () {
	if .profTracker != nil && !.runWithProfiler() {
		return
	}
	 := 0
	 := false
	for {
		if  == 0 {
			if atomic.LoadInt32(&globalProfiler.enabled) == 1 && !.runWithProfiler() {
				return
			}
			 = 100
		} else {
			--
		}
		if  = atomic.LoadUint32(&.interrupted) != 0;  {
			break
		}
		 := .pc
		if  < 0 ||  >= len(.prg.code) {
			break
		}
		.prg.code[].exec()
	}

	if  {
		.interruptLock.Lock()
		 := &InterruptedError{
			iface: .interruptVal,
		}
		.stack = .captureStack(nil, 0)
		.interruptLock.Unlock()
		panic()
	}
}

func ( *vm) () bool {
	 := .profTracker
	if  == nil {
		 = globalProfiler.p.registerVm()
		.profTracker = 
		defer func() {
			atomic.StoreInt32(&.profTracker.finished, 1)
			.profTracker = nil
		}()
	}
	 := false
	for {
		if  = atomic.LoadUint32(&.interrupted) != 0;  {
			return true
		}
		 := .pc
		if  < 0 ||  >= len(.prg.code) {
			break
		}
		.prg.code[].exec()
		 := atomic.LoadInt32(&.req)
		if  == profReqStop {
			return true
		}
		if  == profReqDoSample {
			.stop = time.Now()

			.numFrames = len(.r.CaptureCallStack(len(.frames), .frames[:0]))
			.frames[0].pc = 
			atomic.StoreInt32(&.req, profReqSampleReady)
		}
	}

	return false
}

func ( *vm) ( interface{}) {
	.interruptLock.Lock()
	.interruptVal = 
	atomic.StoreUint32(&.interrupted, 1)
	.interruptLock.Unlock()
}

func ( *vm) () {
	atomic.StoreUint32(&.interrupted, 0)
}

func getFuncName( []Value,  int) unistring.String {
	if  > 0 {
		if ,  := [-1].(*Object);  {
			if ,  := .self.(*proxyObject);  {
				return "proxy"
			}
			return nilSafe(.self.getStr("name", nil)).string()
		}
	}
	return ""
}

func ( *vm) ( []StackFrame,  int) []StackFrame {
	// Unroll the context stack
	if .prg != nil || .sb > 0 {
		var  unistring.String
		if .prg != nil {
			 = .prg.funcName
		} else {
			 = getFuncName(.stack, .sb)
		}
		 = append(, StackFrame{prg: .prg, pc: .pc, funcName: })
	}
	for  := len(.callStack) - 1;  > -1; -- {
		 := &.callStack[]
		if .prg != nil || .sb > 0 {
			var  unistring.String
			if  := .prg;  != nil {
				 = .funcName
			} else {
				 = getFuncName(.stack, .sb)
			}
			 = append(, StackFrame{prg: .callStack[].prg, pc: .pc, funcName: })
		}
	}
	if  == 0 && .curAsyncRunner != nil {
		 = .captureAsyncStack(, .curAsyncRunner)
	}
	return 
}

func ( *vm) ( []StackFrame,  *asyncRunner) []StackFrame {
	if ,  := .promiseCap.promise.self.(*Promise);  != nil {
		if len(.fulfillReactions) == 1 {
			if  := .fulfillReactions[0].asyncRunner;  != nil {
				 := &.gen.ctx
				if .prg != nil || .sb > 0 {
					var  unistring.String
					if  := .prg;  != nil {
						 = .funcName
					} else {
						 = getFuncName(.stack, 1)
					}
					 = append(, StackFrame{prg: .prg, pc: .pc, funcName: })
				}
				 = .(, )
			}
		}
	}

	return 
}

func ( *vm) (,  int32) {
	.tryStack = append(.tryStack, tryFrame{
		callStackLen: uint32(len(.callStack)),
		iterLen:      uint32(len(.iterStack)),
		refLen:       uint32(len(.refStack)),
		sp:           int32(.sp),
		stash:        .stash,
		privEnv:      .privEnv,
		catchPos:     ,
		finallyPos:   ,
		finallyRet:   -1,
	})
}

func ( *vm) () {
	.tryStack = .tryStack[:len(.tryStack)-1]
}

func ( *vm) (,  uint32) ( *Exception) {
	// Restore other stacks
	 := .iterStack[:]
	for  := len() - 1;  >= 0; -- {
		if  := [].iter;  != nil {
			 := .try(func() {
				.returnIter()
			})
			if  != nil &&  == nil {
				 = 
			}
		}
		[] = iterStackItem{}
	}
	.iterStack = .iterStack[:]
	 := .refStack[:]
	for  := range  {
		[] = nil
	}
	.refStack = .refStack[:]
	return
}

func ( *vm) ( interface{}) *Exception {
	 := .exceptionFromValue()
	for len(.tryStack) > 0 {
		 := &.tryStack[len(.tryStack)-1]
		if .catchPos == -1 && .finallyPos == -1 ||  == nil && .catchPos != tryPanicMarker {
			.exception = nil
			.popTryFrame()
			continue
		}
		if int(.callStackLen) < len(.callStack) {
			 := &.callStack[.callStackLen]
			.prg, .newTarget, .result, .pc, .sb, .args =
				.prg, .newTarget, .result, .pc, .sb, .args
			.callStack = .callStack[:.callStackLen]
		}
		.sp = int(.sp)
		.stash = .stash
		.privEnv = .privEnv
		_ = .restoreStacks(.iterLen, .refLen)

		if .catchPos == tryPanicMarker {
			break
		}

		if .catchPos >= 0 {
			// exception is caught
			.push(.val)
			.pc = int(.catchPos)
			.catchPos = -1
			return nil
		}
		if .finallyPos >= 0 {
			// no 'catch' block, but there is a 'finally' block
			.exception = 
			.pc = int(.finallyPos)
			.finallyPos = -1
			.finallyRet = -1
			return nil
		}
	}
	if  == nil {
		panic()
	}
	return 
}

// Calls to this method must be made from the run() loop and must be the last statement before 'return'.
// In all other cases exceptions must be thrown using panic().
func ( *vm) ( interface{}) {
	if  := .handleThrow();  != nil {
		panic()
	}
}

func ( *vm) ( func()) ( *Exception) {
	.pushTryFrame(tryPanicMarker, -1)
	defer .popTryFrame()

	defer func() {
		if  := recover();  != nil {
			 = .handleThrow()
		}
	}()

	()
	return
}

func ( *vm) () ( *Exception) {
	.pushTryFrame(tryPanicMarker, -1)
	defer .popTryFrame()

	for {
		 = .runTryInner()
		if  != nil || .halted() {
			return
		}
	}
}

func ( *vm) () ( *Exception) {
	defer func() {
		if  := recover();  != nil {
			 = .handleThrow()
		}
	}()

	.run()
	return
}

func ( *vm) ( Value) {
	.stack.expand(.sp)
	.stack[.sp] = 
	.sp++
}

func ( *vm) () Value {
	.sp--
	return .stack[.sp]
}

func ( *vm) () Value {
	return .stack[.sp-1]
}

func ( *vm) ( *context) {
	.prg, .stash, .privEnv, .newTarget, .result, .pc, .sb, .args =
		.prg, .stash, .privEnv, .newTarget, .result, .pc, .sb, .args
}

func ( *vm) () {
	if len(.callStack) > .maxCallStackSize {
		 := &StackOverflowError{}
		.stack = .captureStack(nil, 0)
		panic()
	}
	.callStack = append(.callStack, context{})
	 := &.callStack[len(.callStack)-1]
	.saveCtx()
}

func ( *vm) ( *context) {
	.prg, .stash, .privEnv, .newTarget, .result, .pc, .sb, .args =
		.prg, .stash, .privEnv, .newTarget, .result, .pc, .sb, .args
}

func ( *vm) () {
	 := len(.callStack) - 1
	 := &.callStack[]
	.restoreCtx()

	if .prg != nil {
		* = context{}
	}

	.callStack = .callStack[:]
}

func ( *vm) ( Value) *Object {
	if ,  := .(*Object);  {
		return 
	}
	switch unresolved := .(type) {
	case valueUnresolved:
		.throw()
		panic("Unreachable")
	case memberUnresolved:
		panic(.r.NewTypeError("Object has no member '%s'", .ref))
	}
	panic(.r.NewTypeError("Value is not an object: %s", .toString()))
}

type loadVal struct {
	v Value
}

func ( loadVal) ( *vm) {
	.push(.v)
	.pc++
}

type _loadUndef struct{}

var loadUndef _loadUndef

func (_loadUndef) ( *vm) {
	.push(_undefined)
	.pc++
}

type _loadNil struct{}

var loadNil _loadNil

func (_loadNil) ( *vm) {
	.push(nil)
	.pc++
}

type _saveResult struct{}

var saveResult _saveResult

func (_saveResult) ( *vm) {
	.sp--
	.result = .stack[.sp]
	.pc++
}

type _loadResult struct{}

var loadResult _loadResult

func (_loadResult) ( *vm) {
	.push(.result)
	.pc++
}

type _clearResult struct{}

var clearResult _clearResult

func (_clearResult) ( *vm) {
	.result = _undefined
	.pc++
}

type _loadGlobalObject struct{}

var loadGlobalObject _loadGlobalObject

func (_loadGlobalObject) ( *vm) {
	.push(.r.globalObject)
	.pc++
}

type loadStack int

func ( loadStack) ( *vm) {
	// l > 0 -- var<l-1>
	// l == 0 -- this

	if  > 0 {
		.push(nilSafe(.stack[.sb+.args+int()]))
	} else {
		.push(.stack[.sb])
	}
	.pc++
}

type loadStack1 int

func ( loadStack1) ( *vm) {
	// args are in stash
	// l > 0 -- var<l-1>
	// l == 0 -- this

	if  > 0 {
		.push(nilSafe(.stack[.sb+int()]))
	} else {
		.push(.stack[.sb])
	}
	.pc++
}

type loadStackLex int

func ( loadStackLex) ( *vm) {
	// l < 0 -- arg<-l-1>
	// l > 0 -- var<l-1>
	// l == 0 -- this
	var  *Value
	if  <= 0 {
		 := int(-)
		if  > .args {
			.push(_undefined)
			.pc++
			return
		} else {
			 = &.stack[.sb+]
		}
	} else {
		 = &.stack[.sb+.args+int()]
	}
	if * == nil {
		.throw(errAccessBeforeInit)
		return
	}
	.push(*)
	.pc++
}

type loadStack1Lex int

func ( loadStack1Lex) ( *vm) {
	 := &.stack[.sb+int()]
	if * == nil {
		.throw(errAccessBeforeInit)
		return
	}
	.push(*)
	.pc++
}

type _loadCallee struct{}

var loadCallee _loadCallee

func (_loadCallee) ( *vm) {
	.push(.stack[.sb-1])
	.pc++
}

func ( *vm) ( int) {
	// l > 0 -- var<l-1>

	if  > 0 {
		.stack[.sb+.args+] = .stack[.sp-1]
	} else {
		panic("Illegal stack var index")
	}
	.pc++
}

func ( *vm) ( int) {
	// args are in stash
	// l > 0 -- var<l-1>

	if  > 0 {
		.stack[.sb+] = .stack[.sp-1]
	} else {
		panic("Illegal stack var index")
	}
	.pc++
}

func ( *vm) ( int) {
	// l < 0 -- arg<-l-1>
	// l > 0 -- var<l-1>
	var  *Value
	if  < 0 {
		 = &.stack[.sb-]
	} else {
		 = &.stack[.sb+.args+]
	}

	if * != nil {
		* = .stack[.sp-1]
	} else {
		panic(errAccessBeforeInit)
	}
	.pc++
}

func ( *vm) ( int) {
	// args are in stash
	// s > 0 -- var<l-1>
	if  <= 0 {
		panic("Illegal stack var index")
	}
	 := &.stack[.sb+]
	if * != nil {
		* = .stack[.sp-1]
	} else {
		panic(errAccessBeforeInit)
	}
	.pc++
}

func ( *vm) ( int) {
	if  <= 0 {
		.stack[.sb-] = .stack[.sp-1]
	} else {
		.stack[.sb+.args+] = .stack[.sp-1]
	}
	.pc++
}

func ( *vm) ( int) {
	if  <= 0 {
		panic("Illegal stack var index")
	}
	.stack[.sb+] = .stack[.sp-1]
	.pc++
}

type storeStack int

func ( storeStack) ( *vm) {
	.storeStack(int())
}

type storeStack1 int

func ( storeStack1) ( *vm) {
	.storeStack1(int())
}

type storeStackLex int

func ( storeStackLex) ( *vm) {
	.storeStackLex(int())
}

type storeStack1Lex int

func ( storeStack1Lex) ( *vm) {
	.storeStack1Lex(int())
}

type initStack int

func ( initStack) ( *vm) {
	.initStack(int())
}

type initStackP int

func ( initStackP) ( *vm) {
	.initStack(int())
	.sp--
}

type initStack1 int

func ( initStack1) ( *vm) {
	.initStack1(int())
}

type initStack1P int

func ( initStack1P) ( *vm) {
	.initStack1(int())
	.sp--
}

type storeStackP int

func ( storeStackP) ( *vm) {
	.storeStack(int())
	.sp--
}

type storeStack1P int

func ( storeStack1P) ( *vm) {
	.storeStack1(int())
	.sp--
}

type storeStackLexP int

func ( storeStackLexP) ( *vm) {
	.storeStackLex(int())
	.sp--
}

type storeStack1LexP int

func ( storeStack1LexP) ( *vm) {
	.storeStack1Lex(int())
	.sp--
}

type _toNumber struct{}

var toNumber _toNumber

func (_toNumber) ( *vm) {
	.stack[.sp-1] = toNumeric(.stack[.sp-1])
	.pc++
}

type _add struct{}

var add _add

func (_add) ( *vm) {
	 := .stack[.sp-1]
	 := .stack[.sp-2]

	if ,  := .(*Object);  {
		 = .toPrimitive()
	}

	if ,  := .(*Object);  {
		 = .toPrimitive()
	}

	var  Value

	,  := .(String)
	,  := .(String)

	if  ||  {
		if ! {
			 = .toString()
		}
		if ! {
			 = .toString()
		}
		 = .Concat()
	} else {
		switch left := .(type) {
		case valueInt:
			switch right := .(type) {
			case valueInt:
				 = intToValue(int64() + int64())
			case *valueBigInt:
				panic(errMixBigIntType)
			default:
				 = floatToValue(float64() + .ToFloat())
			}
		case *valueBigInt:
			if ,  := .(*valueBigInt);  {
				 = (*valueBigInt)(new(big.Int).Add((*big.Int)(), (*big.Int)()))
			} else {
				panic(errMixBigIntType)
			}
		default:
			if ,  := .(*valueBigInt);  {
				panic(errMixBigIntType)
			}
			 = floatToValue(.ToFloat() + .ToFloat())
		}
	}

	.stack[.sp-2] = 
	.sp--
	.pc++
}

type _sub struct{}

var sub _sub

func (_sub) ( *vm) {
	 := .stack[.sp-1]
	 := .stack[.sp-2]

	 = toNumeric()
	 = toNumeric()

	var  Value

	switch left := .(type) {
	case valueInt:
		switch right := .(type) {
		case valueInt:
			 = intToValue(int64() - int64())
			goto 
		case *valueBigInt:
			panic(errMixBigIntType)
		}
	case valueFloat:
		if ,  := .(*valueBigInt);  {
			panic(errMixBigIntType)
		}
	case *valueBigInt:
		if ,  := .(*valueBigInt);  {
			 = (*valueBigInt)(new(big.Int).Sub((*big.Int)(), (*big.Int)()))
			goto 
		}
		panic(errMixBigIntType)
	}

	 = floatToValue(.ToFloat() - .ToFloat())
:
	.sp--
	.stack[.sp-1] = 
	.pc++
}

type _mul struct{}

var mul _mul

func (_mul) ( *vm) {
	 := toNumeric(.stack[.sp-2])
	 := toNumeric(.stack[.sp-1])

	var  Value

	switch left := .(type) {
	case valueInt:
		switch right := .(type) {
		case valueInt:
			if  == 0 &&  == -1 ||  == -1 &&  == 0 {
				 = _negativeZero
				goto 
			}
			 :=  * 
			// check for overflow
			if  == 0 ||  == 0 || / ==  {
				 = intToValue(int64())
				goto 
			}
		case *valueBigInt:
			panic(errMixBigIntType)
		}
	case valueFloat:
		if ,  := .(*valueBigInt);  {
			panic(errMixBigIntType)
		}
	case *valueBigInt:
		if ,  := .(*valueBigInt);  {
			 = (*valueBigInt)(new(big.Int).Mul((*big.Int)(), (*big.Int)()))
			goto 
		}
		panic(errMixBigIntType)
	}

	 = floatToValue(.ToFloat() * .ToFloat())

:
	.sp--
	.stack[.sp-1] = 
	.pc++
}

type _exp struct{}

var exp _exp

func (_exp) ( *vm) {
	.sp--
	 := .stack[.sp-1]
	 := .stack[.sp]

	 = toNumeric()
	 = toNumeric()

	var  Value
	if ,  := .(*valueBigInt);  {
		if ,  := .(*valueBigInt);  {
			if (*big.Int)().Cmp(big.NewInt(0)) < 0 {
				panic(.r.newError(.r.getRangeError(), "exponent must be positive"))
			}
			 = (*valueBigInt)(new(big.Int).Exp((*big.Int)(), (*big.Int)(), nil))
			goto 
		}
		panic(errMixBigIntType)
	} else if ,  := .(*valueBigInt);  {
		panic(errMixBigIntType)
	}

	 = pow(, )
:
	.stack[.sp-1] = 
	.pc++
}

type _div struct{}

var div _div

func (_div) ( *vm) {
	 := toNumeric(.stack[.sp-2])
	 := toNumeric(.stack[.sp-1])

	var (
		      Value
		,  float64
	)

	if ,  := .(*valueBigInt);  {
		if ,  := .(*valueBigInt);  {
			if (*big.Int)().Cmp(big.NewInt(0)) == 0 {
				panic(.r.newError(.r.getRangeError(), "Division by zero"))
			}
			if (*big.Int)().CmpAbs((*big.Int)()) < 0 {
				 = (*valueBigInt)(big.NewInt(0))
			} else {
				,  := new(big.Int).QuoRem((*big.Int)(), (*big.Int)(), big.NewInt(0))
				 = (*valueBigInt)()
			}
			goto 
		}
		panic(errMixBigIntType)
	} else if ,  := .(*valueBigInt);  {
		panic(errMixBigIntType)
	}
	,  = .ToFloat(), .ToFloat()

	if math.IsNaN() || math.IsNaN() {
		 = _NaN
		goto 
	}
	if math.IsInf(, 0) && math.IsInf(, 0) {
		 = _NaN
		goto 
	}
	if  == 0 &&  == 0 {
		 = _NaN
		goto 
	}

	if math.IsInf(, 0) {
		if math.Signbit() == math.Signbit() {
			 = _positiveInf
			goto 
		} else {
			 = _negativeInf
			goto 
		}
	}
	if math.IsInf(, 0) {
		if math.Signbit() == math.Signbit() {
			 = _positiveZero
			goto 
		} else {
			 = _negativeZero
			goto 
		}
	}
	if  == 0 {
		if math.Signbit() == math.Signbit() {
			 = _positiveInf
			goto 
		} else {
			 = _negativeInf
			goto 
		}
	}

	 = floatToValue( / )

:
	.sp--
	.stack[.sp-1] = 
	.pc++
}

type _mod struct{}

var mod _mod

func (_mod) ( *vm) {
	 := toNumeric(.stack[.sp-2])
	 := toNumeric(.stack[.sp-1])

	var  Value

	switch left := .(type) {
	case valueInt:
		switch right := .(type) {
		case valueInt:
			if  == 0 {
				 = _NaN
				goto 
			}
			 :=  % 
			if  == 0 &&  < 0 {
				 = _negativeZero
			} else {
				 = intToValue(int64( % ))
			}
			goto 
		case *valueBigInt:
			panic(errMixBigIntType)
		}
	case valueFloat:
		if ,  := .(*valueBigInt);  {
			panic(errMixBigIntType)
		}
	case *valueBigInt:
		if ,  := .(*valueBigInt);  {
			switch {
			case (*big.Int)().Cmp(big.NewInt(0)) == 0:
				panic(.r.newError(.r.getRangeError(), "Division by zero"))
			case (*big.Int)().Cmp(big.NewInt(0)) < 0:
				 := new(big.Int).Abs((*big.Int)())
				 := new(big.Int).Mod(, (*big.Int)())
				 = (*valueBigInt)(.Neg())
			default:
				 = (*valueBigInt)(new(big.Int).Mod((*big.Int)(), (*big.Int)()))
			}
			goto 
		}
		panic(errMixBigIntType)
	}

	 = floatToValue(math.Mod(.ToFloat(), .ToFloat()))
:
	.sp--
	.stack[.sp-1] = 
	.pc++
}

type _neg struct{}

var neg _neg

func (_neg) ( *vm) {
	 := .stack[.sp-1]

	var  Value

	switch n := toNumeric().(type) {
	case *valueBigInt:
		 = (*valueBigInt)(new(big.Int).Neg((*big.Int)()))
	case valueInt:
		if  == 0 {
			 = _negativeZero
		} else {
			 = -
		}
	default:
		 := .ToFloat()
		if !math.IsNaN() {
			 = -
		}
		 = valueFloat()
	}

	.stack[.sp-1] = 
	.pc++
}

type _plus struct{}

var plus _plus

func (_plus) ( *vm) {
	.stack[.sp-1] = .stack[.sp-1].ToNumber()
	.pc++
}

type _inc struct{}

var inc _inc

func (_inc) ( *vm) {
	 := .stack[.sp-1]

	switch n := .(type) {
	case *valueBigInt:
		 = (*valueBigInt)(new(big.Int).Add((*big.Int)(), big.NewInt(1)))
	case valueInt:
		 = intToValue(int64( + 1))
	default:
		 = valueFloat(.ToFloat() + 1)
	}

	.stack[.sp-1] = 
	.pc++
}

type _dec struct{}

var dec _dec

func (_dec) ( *vm) {
	 := .stack[.sp-1]

	switch n := .(type) {
	case *valueBigInt:
		 = (*valueBigInt)(new(big.Int).Sub((*big.Int)(), big.NewInt(1)))
	case valueInt:
		 = intToValue(int64( - 1))
	default:
		 = valueFloat(.ToFloat() - 1)
	}

	.stack[.sp-1] = 
	.pc++
}

type _and struct{}

var and _and

func (_and) ( *vm) {
	 := toNumeric(.stack[.sp-2])
	 := toNumeric(.stack[.sp-1])
	var  Value

	if ,  := .(*valueBigInt);  {
		if ,  := .(*valueBigInt);  {
			 = (*valueBigInt)(new(big.Int).And((*big.Int)(), (*big.Int)()))
			goto 
		}
		panic(errMixBigIntType)
	} else if ,  := .(*valueBigInt);  {
		panic(errMixBigIntType)
	}

	 = intToValue(int64(toInt32() & toInt32()))
:
	.stack[.sp-2] = 
	.sp--
	.pc++
}

type _or struct{}

var or _or

func (_or) ( *vm) {
	 := toNumeric(.stack[.sp-2])
	 := toNumeric(.stack[.sp-1])
	var  Value

	if ,  := .(*valueBigInt);  {
		if ,  := .(*valueBigInt);  {
			 = (*valueBigInt)(new(big.Int).Or((*big.Int)(), (*big.Int)()))
			goto 
		}
		panic(errMixBigIntType)
	} else if ,  := .(*valueBigInt);  {
		panic(errMixBigIntType)
	}

	 = intToValue(int64(toInt32() | toInt32()))
:
	.stack[.sp-2] = 
	.sp--
	.pc++
}

type _xor struct{}

var xor _xor

func (_xor) ( *vm) {
	 := toNumeric(.stack[.sp-2])
	 := toNumeric(.stack[.sp-1])
	var  Value

	if ,  := .(*valueBigInt);  {
		if ,  := .(*valueBigInt);  {
			 = (*valueBigInt)(new(big.Int).Xor((*big.Int)(), (*big.Int)()))
			goto 
		}
		panic(errMixBigIntType)
	} else if ,  := .(*valueBigInt);  {
		panic(errMixBigIntType)
	}

	 = intToValue(int64(toInt32() ^ toInt32()))
:
	.stack[.sp-2] = 
	.sp--
	.pc++
}

type _bnot struct{}

var bnot _bnot

func (_bnot) ( *vm) {
	 := .stack[.sp-1]
	switch n := toNumeric().(type) {
	case *valueBigInt:
		 = (*valueBigInt)(new(big.Int).Not((*big.Int)()))
	default:
		 = intToValue(int64(^toInt32()))
	}
	.stack[.sp-1] = 
	.pc++
}

type _sal struct{}

var sal _sal

func (_sal) ( *vm) {
	 := toNumeric(.stack[.sp-2])
	 := toNumeric(.stack[.sp-1])
	var  Value

	if ,  := .(*valueBigInt);  {
		if ,  := .(*valueBigInt);  {
			 := uint((*big.Int)().Uint64())
			if (*big.Int)().Sign() < 0 {
				 = (*valueBigInt)(new(big.Int).Rsh((*big.Int)(), ))
			} else {
				 = (*valueBigInt)(new(big.Int).Lsh((*big.Int)(), ))
			}
			goto 
		}
		panic(errMixBigIntType)
	} else if ,  := .(*valueBigInt);  {
		panic(errMixBigIntType)
	}

	 = intToValue(int64(toInt32() << (toUint32() & 0x1F)))
:
	.stack[.sp-2] = 
	.sp--
	.pc++
}

type _sar struct{}

var sar _sar

func (_sar) ( *vm) {
	 := toNumeric(.stack[.sp-2])
	 := toNumeric(.stack[.sp-1])
	var  Value

	if ,  := .(*valueBigInt);  {
		if ,  := .(*valueBigInt);  {
			 := uint((*big.Int)().Uint64())
			if (*big.Int)().Sign() < 0 {
				 = (*valueBigInt)(new(big.Int).Lsh((*big.Int)(), ))
			} else {
				 = (*valueBigInt)(new(big.Int).Rsh((*big.Int)(), ))
			}
			goto 
		}
		panic(errMixBigIntType)
	} else if ,  := .(*valueBigInt);  {
		panic(errMixBigIntType)
	}

	 = intToValue(int64(toInt32() >> (toUint32() & 0x1F)))
:
	.stack[.sp-2] = 
	.sp--
	.pc++
}

type _shr struct{}

var shr _shr

func (_shr) ( *vm) {
	 := toNumeric(.stack[.sp-2])
	 := toNumeric(.stack[.sp-1])

	if ,  := .(*valueBigInt);  {
		_ = toNumeric()
		panic(.r.NewTypeError("BigInts have no unsigned right shift, use >> instead"))
	} else if ,  := .(*valueBigInt);  {
		panic(.r.NewTypeError("BigInts have no unsigned right shift, use >> instead"))
	}

	.stack[.sp-2] = intToValue(int64(toUint32() >> (toUint32() & 0x1F)))
	.sp--
	.pc++
}

type jump int32

func ( jump) ( *vm) {
	.pc += int()
}

type _toPropertyKey struct{}

func (_toPropertyKey) ( *vm) {
	 := .sp - 1
	.stack[] = toPropertyKey(.stack[])
	.pc++
}

type _toString struct{}

func (_toString) ( *vm) {
	 := .sp - 1
	.stack[] = .stack[].toString()
	.pc++
}

type _getElemRef struct{}

var getElemRef _getElemRef

func (_getElemRef) ( *vm) {
	 := .stack[.sp-2].ToObject(.r)
	 := .stack[.sp-1]
	.refStack = append(.refStack, &objRef{
		base: ,
		name: ,
	})
	.sp -= 2
	.pc++
}

type _getElemRefRecv struct{}

var getElemRefRecv _getElemRefRecv

func (_getElemRefRecv) ( *vm) {
	 := .stack[.sp-1].ToObject(.r)
	 := .stack[.sp-2]
	.refStack = append(.refStack, &objRef{
		base: ,
		name: ,
		this: .stack[.sp-3],
	})
	.sp -= 3
	.pc++
}

type _getElemRefStrict struct{}

var getElemRefStrict _getElemRefStrict

func (_getElemRefStrict) ( *vm) {
	 := .stack[.sp-2].ToObject(.r)
	 := .stack[.sp-1]
	.refStack = append(.refStack, &objRef{
		base:   ,
		name:   ,
		strict: true,
	})
	.sp -= 2
	.pc++
}

type _getElemRefRecvStrict struct{}

var getElemRefRecvStrict _getElemRefRecvStrict

func (_getElemRefRecvStrict) ( *vm) {
	 := .stack[.sp-1].ToObject(.r)
	 := .stack[.sp-2]
	.refStack = append(.refStack, &objRef{
		base:   ,
		name:   ,
		this:   .stack[.sp-3],
		strict: true,
	})
	.sp -= 3
	.pc++
}

type _setElem struct{}

var setElem _setElem

func (_setElem) ( *vm) {
	 := .stack[.sp-3].ToObject(.r)
	 := toPropertyKey(.stack[.sp-2])
	 := .stack[.sp-1]

	.setOwn(, , false)

	.sp -= 2
	.stack[.sp-1] = 
	.pc++
}

type _setElem1 struct{}

var setElem1 _setElem1

func (_setElem1) ( *vm) {
	 := .stack[.sp-3].ToObject(.r)
	 := .stack[.sp-2]
	 := .stack[.sp-1]

	.setOwn(, , true)

	.sp -= 2
	.pc++
}

type _setElem1Named struct{}

var setElem1Named _setElem1Named

func (_setElem1Named) ( *vm) {
	 := .stack[.sp-3]
	 := .ToObject(.r)
	 := .stack[.sp-2]
	 := .stack[.sp-1]
	.r.toObject().self.defineOwnPropertyStr("name", PropertyDescriptor{
		Value:        funcName("", ),
		Configurable: FLAG_TRUE,
	}, true)
	.set(, , , true)

	.sp -= 2
	.pc++
}

type defineMethod struct {
	enumerable bool
}

func ( *defineMethod) ( *vm) {
	 := .r.toObject(.stack[.sp-3])
	 := .stack[.sp-2]
	 := .r.toObject(.stack[.sp-1])
	.self.defineOwnPropertyStr("name", PropertyDescriptor{
		Value:        funcName("", ),
		Configurable: FLAG_TRUE,
	}, true)
	.defineOwnProperty(, PropertyDescriptor{
		Value:        ,
		Writable:     FLAG_TRUE,
		Configurable: FLAG_TRUE,
		Enumerable:   ToFlag(.enumerable),
	}, true)

	.sp -= 2
	.pc++
}

type _setElemP struct{}

var setElemP _setElemP

func (_setElemP) ( *vm) {
	 := .stack[.sp-3].ToObject(.r)
	 := toPropertyKey(.stack[.sp-2])
	 := .stack[.sp-1]

	.setOwn(, , false)

	.sp -= 3
	.pc++
}

type _setElemStrict struct{}

var setElemStrict _setElemStrict

func (_setElemStrict) ( *vm) {
	 := toPropertyKey(.stack[.sp-2])
	 := .stack[.sp-3]
	 := .stack[.sp-1]
	if ,  := .(*Object);  {
		.setOwn(, , true)
	} else {
		 := .ToObject(.r)
		.set(, , , true)
	}

	.sp -= 2
	.stack[.sp-1] = 
	.pc++
}

type _setElemRecv struct{}

var setElemRecv _setElemRecv

func (_setElemRecv) ( *vm) {
	 := .stack[.sp-4]
	 := toPropertyKey(.stack[.sp-3])
	 := .stack[.sp-2]
	 := .stack[.sp-1]
	if ,  := .(*Object);  {
		.set(, , , false)
	} else {
		 := .ToObject(.r)
		.set(, , , false)
	}

	.sp -= 3
	.stack[.sp-1] = 
	.pc++
}

type _setElemRecvStrict struct{}

var setElemRecvStrict _setElemRecvStrict

func (_setElemRecvStrict) ( *vm) {
	 := .stack[.sp-4]
	 := toPropertyKey(.stack[.sp-3])
	 := .stack[.sp-2]
	 := .stack[.sp-1]
	if ,  := .(*Object);  {
		.set(, , , true)
	} else {
		 := .ToObject(.r)
		.set(, , , true)
	}

	.sp -= 3
	.stack[.sp-1] = 
	.pc++
}

type _setElemStrictP struct{}

var setElemStrictP _setElemStrictP

func (_setElemStrictP) ( *vm) {
	 := toPropertyKey(.stack[.sp-2])
	 := .stack[.sp-3]
	 := .stack[.sp-1]
	if ,  := .(*Object);  {
		.setOwn(, , true)
	} else {
		 := .ToObject(.r)
		.set(, , , true)
	}

	.sp -= 3
	.pc++
}

type _setElemRecvP struct{}

var setElemRecvP _setElemRecvP

func (_setElemRecvP) ( *vm) {
	 := .stack[.sp-4]
	 := toPropertyKey(.stack[.sp-3])
	 := .stack[.sp-2]
	 := .stack[.sp-1]
	if ,  := .(*Object);  {
		.set(, , , false)
	} else {
		 := .ToObject(.r)
		.set(, , , false)
	}

	.sp -= 4
	.pc++
}

type _setElemRecvStrictP struct{}

var setElemRecvStrictP _setElemRecvStrictP

func (_setElemRecvStrictP) ( *vm) {
	 := .stack[.sp-4]
	 := toPropertyKey(.stack[.sp-3])
	 := .stack[.sp-2]
	 := .stack[.sp-1]
	if ,  := .(*Object);  {
		.set(, , , true)
	} else {
		 := .ToObject(.r)
		.set(, , , true)
	}

	.sp -= 4
	.pc++
}

type _deleteElem struct{}

var deleteElem _deleteElem

func (_deleteElem) ( *vm) {
	 := .stack[.sp-2].ToObject(.r)
	 := toPropertyKey(.stack[.sp-1])
	if .delete(, false) {
		.stack[.sp-2] = valueTrue
	} else {
		.stack[.sp-2] = valueFalse
	}
	.sp--
	.pc++
}

type _deleteElemStrict struct{}

var deleteElemStrict _deleteElemStrict

func (_deleteElemStrict) ( *vm) {
	 := .stack[.sp-2].ToObject(.r)
	 := toPropertyKey(.stack[.sp-1])
	.delete(, true)
	.stack[.sp-2] = valueTrue
	.sp--
	.pc++
}

type deleteProp unistring.String

func ( deleteProp) ( *vm) {
	 := .stack[.sp-1].ToObject(.r)
	if .self.deleteStr(unistring.String(), false) {
		.stack[.sp-1] = valueTrue
	} else {
		.stack[.sp-1] = valueFalse
	}
	.pc++
}

type deletePropStrict unistring.String

func ( deletePropStrict) ( *vm) {
	 := .stack[.sp-1].ToObject(.r)
	.self.deleteStr(unistring.String(), true)
	.stack[.sp-1] = valueTrue
	.pc++
}

type getPropRef unistring.String

func ( getPropRef) ( *vm) {
	.refStack = append(.refStack, &objStrRef{
		base: .stack[.sp-1].ToObject(.r),
		name: unistring.String(),
	})
	.sp--
	.pc++
}

type getPropRefRecv unistring.String

func ( getPropRefRecv) ( *vm) {
	.refStack = append(.refStack, &objStrRef{
		this: .stack[.sp-2],
		base: .stack[.sp-1].ToObject(.r),
		name: unistring.String(),
	})
	.sp -= 2
	.pc++
}

type getPropRefStrict unistring.String

func ( getPropRefStrict) ( *vm) {
	.refStack = append(.refStack, &objStrRef{
		base:   .stack[.sp-1].ToObject(.r),
		name:   unistring.String(),
		strict: true,
	})
	.sp--
	.pc++
}

type getPropRefRecvStrict unistring.String

func ( getPropRefRecvStrict) ( *vm) {
	.refStack = append(.refStack, &objStrRef{
		this:   .stack[.sp-2],
		base:   .stack[.sp-1].ToObject(.r),
		name:   unistring.String(),
		strict: true,
	})
	.sp -= 2
	.pc++
}

type setProp unistring.String

func ( setProp) ( *vm) {
	 := .stack[.sp-1]
	.stack[.sp-2].ToObject(.r).self.setOwnStr(unistring.String(), , false)
	.stack[.sp-2] = 
	.sp--
	.pc++
}

type setPropP unistring.String

func ( setPropP) ( *vm) {
	 := .stack[.sp-1]
	.stack[.sp-2].ToObject(.r).self.setOwnStr(unistring.String(), , false)
	.sp -= 2
	.pc++
}

type setPropStrict unistring.String

func ( setPropStrict) ( *vm) {
	 := .stack[.sp-2]
	 := .stack[.sp-1]
	 := unistring.String()
	if ,  := .(*Object);  {
		.self.setOwnStr(, , true)
	} else {
		 := .ToObject(.r)
		.setStr(, , , true)
	}

	.stack[.sp-2] = 
	.sp--
	.pc++
}

type setPropRecv unistring.String

func ( setPropRecv) ( *vm) {
	 := .stack[.sp-3]
	 := .stack[.sp-2]
	 := .stack[.sp-1]
	 := unistring.String()
	if ,  := .(*Object);  {
		.setStr(, , , false)
	} else {
		 := .ToObject(.r)
		.setStr(, , , false)
	}

	.stack[.sp-3] = 
	.sp -= 2
	.pc++
}

type setPropRecvStrict unistring.String

func ( setPropRecvStrict) ( *vm) {
	 := .stack[.sp-3]
	 := .stack[.sp-2]
	 := .stack[.sp-1]
	 := unistring.String()
	if ,  := .(*Object);  {
		.setStr(, , , true)
	} else {
		 := .ToObject(.r)
		.setStr(, , , true)
	}

	.stack[.sp-3] = 
	.sp -= 2
	.pc++
}

type setPropRecvP unistring.String

func ( setPropRecvP) ( *vm) {
	 := .stack[.sp-3]
	 := .stack[.sp-2]
	 := .stack[.sp-1]
	 := unistring.String()
	if ,  := .(*Object);  {
		.setStr(, , , false)
	} else {
		 := .ToObject(.r)
		.setStr(, , , false)
	}

	.sp -= 3
	.pc++
}

type setPropRecvStrictP unistring.String

func ( setPropRecvStrictP) ( *vm) {
	 := .stack[.sp-3]
	 := .stack[.sp-2]
	 := .stack[.sp-1]
	 := unistring.String()
	if ,  := .(*Object);  {
		.setStr(, , , true)
	} else {
		 := .ToObject(.r)
		.setStr(, , , true)
	}

	.sp -= 3
	.pc++
}

type setPropStrictP unistring.String

func ( setPropStrictP) ( *vm) {
	 := .stack[.sp-2]
	 := .stack[.sp-1]
	 := unistring.String()
	if ,  := .(*Object);  {
		.self.setOwnStr(, , true)
	} else {
		 := .ToObject(.r)
		.setStr(, , , true)
	}

	.sp -= 2
	.pc++
}

type putProp unistring.String

func ( putProp) ( *vm) {
	.r.toObject(.stack[.sp-2]).self._putProp(unistring.String(), .stack[.sp-1], true, true, true)

	.sp--
	.pc++
}

// used in class declarations instead of putProp because DefineProperty must be observable by Proxy
type definePropKeyed unistring.String

func ( definePropKeyed) ( *vm) {
	.r.toObject(.stack[.sp-2]).self.defineOwnPropertyStr(unistring.String(), PropertyDescriptor{
		Value:        .stack[.sp-1],
		Writable:     FLAG_TRUE,
		Configurable: FLAG_TRUE,
		Enumerable:   FLAG_TRUE,
	}, true)

	.sp--
	.pc++
}

type defineProp struct{}

func (defineProp) ( *vm) {
	.r.toObject(.stack[.sp-3]).defineOwnProperty(.stack[.sp-2], PropertyDescriptor{
		Value:        .stack[.sp-1],
		Writable:     FLAG_TRUE,
		Configurable: FLAG_TRUE,
		Enumerable:   FLAG_TRUE,
	}, true)

	.sp -= 2
	.pc++
}

type defineMethodKeyed struct {
	key        unistring.String
	enumerable bool
}

func ( *defineMethodKeyed) ( *vm) {
	 := .r.toObject(.stack[.sp-2])
	 := .r.toObject(.stack[.sp-1])

	.self.defineOwnPropertyStr(.key, PropertyDescriptor{
		Value:        ,
		Writable:     FLAG_TRUE,
		Configurable: FLAG_TRUE,
		Enumerable:   ToFlag(.enumerable),
	}, true)

	.sp--
	.pc++
}

type _setProto struct{}

var setProto _setProto

func (_setProto) ( *vm) {
	.r.setObjectProto(.stack[.sp-2], .stack[.sp-1])

	.sp--
	.pc++
}

type defineGetterKeyed struct {
	key        unistring.String
	enumerable bool
}

func ( *defineGetterKeyed) ( *vm) {
	 := .r.toObject(.stack[.sp-2])
	 := .stack[.sp-1]
	 := .r.toObject()
	.self.defineOwnPropertyStr("name", PropertyDescriptor{
		Value:        asciiString("get ").Concat(stringValueFromRaw(.key)),
		Configurable: FLAG_TRUE,
	}, true)
	 := PropertyDescriptor{
		Getter:       ,
		Configurable: FLAG_TRUE,
		Enumerable:   ToFlag(.enumerable),
	}

	.self.defineOwnPropertyStr(.key, , true)

	.sp--
	.pc++
}

type defineSetterKeyed struct {
	key        unistring.String
	enumerable bool
}

func ( *defineSetterKeyed) ( *vm) {
	 := .r.toObject(.stack[.sp-2])
	 := .stack[.sp-1]
	 := .r.toObject()
	.self.defineOwnPropertyStr("name", PropertyDescriptor{
		Value:        asciiString("set ").Concat(stringValueFromRaw(.key)),
		Configurable: FLAG_TRUE,
	}, true)

	 := PropertyDescriptor{
		Setter:       ,
		Configurable: FLAG_TRUE,
		Enumerable:   ToFlag(.enumerable),
	}

	.self.defineOwnPropertyStr(.key, , true)

	.sp--
	.pc++
}

type defineGetter struct {
	enumerable bool
}

func ( *defineGetter) ( *vm) {
	 := .r.toObject(.stack[.sp-3])
	 := .stack[.sp-2]
	 := .stack[.sp-1]
	 := .r.toObject()
	.self.defineOwnPropertyStr("name", PropertyDescriptor{
		Value:        funcName("get ", ),
		Configurable: FLAG_TRUE,
	}, true)

	 := PropertyDescriptor{
		Getter:       ,
		Configurable: FLAG_TRUE,
		Enumerable:   ToFlag(.enumerable),
	}

	.defineOwnProperty(, , true)

	.sp -= 2
	.pc++
}

type defineSetter struct {
	enumerable bool
}

func ( *defineSetter) ( *vm) {
	 := .r.toObject(.stack[.sp-3])
	 := .stack[.sp-2]
	 := .stack[.sp-1]
	 := .r.toObject()

	.self.defineOwnPropertyStr("name", PropertyDescriptor{
		Value:        funcName("set ", ),
		Configurable: FLAG_TRUE,
	}, true)

	 := PropertyDescriptor{
		Setter:       ,
		Configurable: FLAG_TRUE,
		Enumerable:   FLAG_TRUE,
	}

	.defineOwnProperty(, , true)

	.sp -= 2
	.pc++
}

type getProp unistring.String

func ( getProp) ( *vm) {
	 := .stack[.sp-1]
	 := .baseObject(.r)
	if  == nil {
		.throw(.r.NewTypeError("Cannot read property '%s' of undefined", ))
		return
	}
	.stack[.sp-1] = nilSafe(.self.getStr(unistring.String(), ))

	.pc++
}

type getPropRecv unistring.String

func ( getPropRecv) ( *vm) {
	 := .stack[.sp-2]
	 := .stack[.sp-1]
	 := .baseObject(.r)
	if  == nil {
		.throw(.r.NewTypeError("Cannot read property '%s' of undefined", ))
		return
	}
	.stack[.sp-2] = nilSafe(.self.getStr(unistring.String(), ))
	.sp--
	.pc++
}

type getPropRecvCallee unistring.String

func ( getPropRecvCallee) ( *vm) {
	 := .stack[.sp-2]
	 := .stack[.sp-1]
	 := .baseObject(.r)
	if  == nil {
		.throw(.r.NewTypeError("Cannot read property '%s' of undefined", ))
		return
	}

	 := unistring.String()
	 := .self.getStr(, )
	if  == nil {
		 = memberUnresolved{valueUnresolved{r: .r, ref: }}
	}

	.stack[.sp-1] = 
	.pc++
}

type getPropCallee unistring.String

func ( getPropCallee) ( *vm) {
	 := .stack[.sp-1]
	 := .baseObject(.r)
	 := unistring.String()
	if  == nil {
		.throw(.r.NewTypeError("Cannot read property '%s' of undefined or null", ))
		return
	}
	 := .self.getStr(, )
	if  == nil {
		 = memberUnresolved{valueUnresolved{r: .r, ref: }}
	}
	.push()

	.pc++
}

type _getElem struct{}

var getElem _getElem

func (_getElem) ( *vm) {
	 := .stack[.sp-2]
	 := .baseObject(.r)
	if  == nil {
		.throw(.r.NewTypeError("Cannot read property '%s' of undefined", .stack[.sp-1]))
		return
	}
	 := toPropertyKey(.stack[.sp-1])

	.stack[.sp-2] = nilSafe(.get(, ))

	.sp--
	.pc++
}

type _getElemRecv struct{}

var getElemRecv _getElemRecv

func (_getElemRecv) ( *vm) {
	 := .stack[.sp-3]
	 := .stack[.sp-1]
	 := .baseObject(.r)
	if  == nil {
		.throw(.r.NewTypeError("Cannot read property '%s' of undefined", .stack[.sp-2]))
		return
	}
	 := toPropertyKey(.stack[.sp-2])

	.stack[.sp-3] = nilSafe(.get(, ))

	.sp -= 2
	.pc++
}

type _getKey struct{}

var getKey _getKey

func (_getKey) ( *vm) {
	 := .stack[.sp-2]
	 := .baseObject(.r)
	 := .stack[.sp-1]
	if  == nil {
		.throw(.r.NewTypeError("Cannot read property '%s' of undefined", .String()))
		return
	}

	.stack[.sp-2] = nilSafe(.get(, ))

	.sp--
	.pc++
}

type _getElemCallee struct{}

var getElemCallee _getElemCallee

func (_getElemCallee) ( *vm) {
	 := .stack[.sp-2]
	 := .baseObject(.r)
	if  == nil {
		.throw(.r.NewTypeError("Cannot read property '%s' of undefined", .stack[.sp-1]))
		return
	}

	 := toPropertyKey(.stack[.sp-1])
	 := .get(, )
	if  == nil {
		 = memberUnresolved{valueUnresolved{r: .r, ref: .string()}}
	}
	.stack[.sp-1] = 

	.pc++
}

type _getElemRecvCallee struct{}

var getElemRecvCallee _getElemRecvCallee

func (_getElemRecvCallee) ( *vm) {
	 := .stack[.sp-3]
	 := .stack[.sp-2]
	 := .baseObject(.r)
	if  == nil {
		.throw(.r.NewTypeError("Cannot read property '%s' of undefined", .stack[.sp-1]))
		return
	}

	 := toPropertyKey(.stack[.sp-1])
	 := .get(, )
	if  == nil {
		 = memberUnresolved{valueUnresolved{r: .r, ref: .string()}}
	}
	.stack[.sp-2] = 
	.sp--

	.pc++
}

type _dup struct{}

var dup _dup

func (_dup) ( *vm) {
	.push(.stack[.sp-1])
	.pc++
}

type dupN uint32

func ( dupN) ( *vm) {
	.push(.stack[.sp-1-int()])
	.pc++
}

type rdupN uint32

func ( rdupN) ( *vm) {
	.stack[.sp-1-int()] = .stack[.sp-1]
	.pc++
}

type dupLast uint32

func ( dupLast) ( *vm) {
	 := .sp + int()
	.stack.expand()
	copy(.stack[.sp:], .stack[.sp-int():])
	.sp = 
	.pc++
}

type _newObject struct{}

var newObject _newObject

func (_newObject) ( *vm) {
	.push(.r.NewObject())
	.pc++
}

type newArray uint32

func ( newArray) ( *vm) {
	 := make([]Value, 0, )
	.push(.r.newArrayValues())
	.pc++
}

type _pushArrayItem struct{}

var pushArrayItem _pushArrayItem

func (_pushArrayItem) ( *vm) {
	 := .stack[.sp-2].(*Object).self.(*arrayObject)
	if .length < math.MaxUint32 {
		.length++
	} else {
		.throw(.r.newError(.r.getRangeError(), "Invalid array length"))
		return
	}
	 := .stack[.sp-1]
	.values = append(.values, )
	if  != nil {
		.objCount++
	}
	.sp--
	.pc++
}

type _pushArraySpread struct{}

var pushArraySpread _pushArraySpread

func (_pushArraySpread) ( *vm) {
	 := .stack[.sp-2].(*Object).self.(*arrayObject)
	.r.getIterator(.stack[.sp-1], nil).iterate(func( Value) {
		if .length < math.MaxUint32 {
			.length++
		} else {
			.throw(.r.newError(.r.getRangeError(), "Invalid array length"))
			return
		}
		.values = append(.values, )
		.objCount++
	})
	.sp--
	.pc++
}

type _pushSpread struct{}

var pushSpread _pushSpread

func (_pushSpread) ( *vm) {
	.sp--
	 := .stack[.sp]
	.r.getIterator(, nil).iterate(func( Value) {
		.push()
	})
	.pc++
}

type _newArrayFromIter struct{}

var newArrayFromIter _newArrayFromIter

func (_newArrayFromIter) ( *vm) {
	var  []Value
	 := len(.iterStack) - 1
	 := .iterStack[].iter
	.iterStack[] = iterStackItem{}
	.iterStack = .iterStack[:]
	if .iterator != nil {
		.iterate(func( Value) {
			 = append(, )
		})
	}
	.push(.r.newArrayValues())
	.pc++
}

type newRegexp struct {
	pattern *regexpPattern
	src     String
}

func ( *newRegexp) ( *vm) {
	.push(.r.newRegExpp(.pattern.clone(), .src, .r.getRegExpPrototype()).val)
	.pc++
}

func ( *vm) ( int) {
	 := .stack[.sp-1]
	 :=  >> 24
	 := uint32( & 0x00FFFFFF)
	 := .stash
	for  := 0;  < ; ++ {
		 = .outer
	}
	 := &.values[]
	if * == nil {
		panic(errAccessBeforeInit)
	}
	* = 
	.pc++
}

func ( *vm) ( int) {
	 := .stack[.sp-1]
	 :=  >> 24
	 := uint32( & 0x00FFFFFF)
	 := .stash
	for  := 0;  < ; ++ {
		 = .outer
	}
	.initByIdx(, )
	.pc++
}

type storeStash uint32

func ( storeStash) ( *vm) {
	.initLocal(int())
}

type storeStashP uint32

func ( storeStashP) ( *vm) {
	.initLocal(int())
	.sp--
}

type storeStashLex uint32

func ( storeStashLex) ( *vm) {
	.setLocalLex(int())
}

type storeStashLexP uint32

func ( storeStashLexP) ( *vm) {
	.setLocalLex(int())
	.sp--
}

type initStash uint32

func ( initStash) ( *vm) {
	.initLocal(int())
}

type initStashP uint32

func ( initStashP) ( *vm) {
	.initLocal(int())
	.sp--
}

type initGlobalP unistring.String

func ( initGlobalP) ( *vm) {
	.sp--
	.r.global.stash.initByName(unistring.String(), .stack[.sp])
	.pc++
}

type initGlobal unistring.String

func ( initGlobal) ( *vm) {
	.r.global.stash.initByName(unistring.String(), .stack[.sp])
	.pc++
}

type resolveVar1 unistring.String

func ( resolveVar1) ( *vm) {
	 := unistring.String()
	var  ref
	for  := .stash;  != nil;  = .outer {
		 = .getRefByName(, false)
		if  != nil {
			goto 
		}
	}

	 = &objStrRef{
		base:    .r.globalObject,
		name:    ,
		binding: true,
	}

:
	.refStack = append(.refStack, )
	.pc++
}

type deleteVar unistring.String

func ( deleteVar) ( *vm) {
	 := unistring.String()
	 := true
	for  := .stash;  != nil;  = .outer {
		if .obj != nil {
			if stashObjHas(.obj, ) {
				 = .obj.self.deleteStr(, false)
				goto 
			}
		} else {
			if ,  := .names[];  {
				if &(maskVar|maskDeletable) == maskVar|maskDeletable {
					.deleteBinding()
				} else {
					 = false
				}
				goto 
			}
		}
	}

	if .r.globalObject.self.hasPropertyStr() {
		 = .r.globalObject.self.deleteStr(, false)
	}

:
	if  {
		.push(valueTrue)
	} else {
		.push(valueFalse)
	}
	.pc++
}

type deleteGlobal unistring.String

func ( deleteGlobal) ( *vm) {
	 := unistring.String()
	var  bool
	if .r.globalObject.self.hasPropertyStr() {
		 = .r.globalObject.self.deleteStr(, false)
	} else {
		 = true
	}
	if  {
		.push(valueTrue)
	} else {
		.push(valueFalse)
	}
	.pc++
}

type resolveVar1Strict unistring.String

func ( resolveVar1Strict) ( *vm) {
	 := unistring.String()
	var  ref
	for  := .stash;  != nil;  = .outer {
		 = .getRefByName(, true)
		if  != nil {
			goto 
		}
	}

	if .r.globalObject.self.hasPropertyStr() {
		 = &objStrRef{
			base:    .r.globalObject,
			name:    ,
			binding: true,
			strict:  true,
		}
		goto 
	}

	 = &unresolvedRef{
		runtime: .r,
		name:    ,
	}

:
	.refStack = append(.refStack, )
	.pc++
}

type setGlobal unistring.String

func ( setGlobal) ( *vm) {
	.r.setGlobal(unistring.String(), .peek(), false)
	.pc++
}

type setGlobalStrict unistring.String

func ( setGlobalStrict) ( *vm) {
	.r.setGlobal(unistring.String(), .peek(), true)
	.pc++
}

// Load a var from stash
type loadStash uint32

func ( loadStash) ( *vm) {
	 := int( >> 24)
	 := uint32( & 0x00FFFFFF)
	 := .stash
	for  := 0;  < ; ++ {
		 = .outer
	}

	.push(nilSafe(.getByIdx()))
	.pc++
}

// Load a lexical binding from stash
type loadStashLex uint32

func ( loadStashLex) ( *vm) {
	 := int( >> 24)
	 := uint32( & 0x00FFFFFF)
	 := .stash
	for  := 0;  < ; ++ {
		 = .outer
	}

	 := .getByIdx()
	if  == nil {
		.throw(errAccessBeforeInit)
		return
	}
	.push()
	.pc++
}

// scan dynamic stashes up to the given level (encoded as 8 most significant bits of idx), if not found
// return the indexed var binding value from stash
type loadMixed struct {
	name   unistring.String
	idx    uint32
	callee bool
}

func ( *loadMixed) ( *vm) {
	 := int(.idx >> 24)
	 := .idx & 0x00FFFFFF
	 := .stash
	 := .name
	for  := 0;  < ; ++ {
		if ,  := .getByName();  {
			if .callee {
				if .obj != nil {
					.push(.obj)
				} else {
					.push(_undefined)
				}
			}
			.push()
			goto 
		}
		 = .outer
	}
	if .callee {
		.push(_undefined)
	}
	if  != nil {
		.push(nilSafe(.getByIdx()))
	}
:
	.pc++
}

// scan dynamic stashes up to the given level (encoded as 8 most significant bits of idx), if not found
// return the indexed lexical binding value from stash
type loadMixedLex loadMixed

func ( *loadMixedLex) ( *vm) {
	 := int(.idx >> 24)
	 := .idx & 0x00FFFFFF
	 := .stash
	 := .name
	for  := 0;  < ; ++ {
		if ,  := .getByName();  {
			if .callee {
				if .obj != nil {
					.push(.obj)
				} else {
					.push(_undefined)
				}
			}
			.push()
			goto 
		}
		 = .outer
	}
	if .callee {
		.push(_undefined)
	}
	if  != nil {
		 := .getByIdx()
		if  == nil {
			.throw(errAccessBeforeInit)
			return
		}
		.push()
	}
:
	.pc++
}

// scan dynamic stashes up to the given level (encoded as 8 most significant bits of idx), if not found
// return the indexed var binding value from stack
type loadMixedStack struct {
	name   unistring.String
	idx    int
	level  uint8
	callee bool
}

// same as loadMixedStack, but the args have been moved to stash (therefore stack layout is different)
type loadMixedStack1 loadMixedStack

func ( *loadMixedStack) ( *vm) {
	 := .stash
	 := .name
	 := int(.level)
	for  := 0;  < ; ++ {
		if ,  := .getByName();  {
			if .callee {
				if .obj != nil {
					.push(.obj)
				} else {
					.push(_undefined)
				}
			}
			.push()
			goto 
		}
		 = .outer
	}
	if .callee {
		.push(_undefined)
	}
	loadStack(.idx).exec()
	return
:
	.pc++
}

func ( *loadMixedStack1) ( *vm) {
	 := .stash
	 := .name
	 := int(.level)
	for  := 0;  < ; ++ {
		if ,  := .getByName();  {
			if .callee {
				if .obj != nil {
					.push(.obj)
				} else {
					.push(_undefined)
				}
			}
			.push()
			goto 
		}
		 = .outer
	}
	if .callee {
		.push(_undefined)
	}
	loadStack1(.idx).exec()
	return
:
	.pc++
}

type loadMixedStackLex loadMixedStack

// same as loadMixedStackLex but when the arguments have been moved into stash
type loadMixedStack1Lex loadMixedStack

func ( *loadMixedStackLex) ( *vm) {
	 := .stash
	 := .name
	 := int(.level)
	for  := 0;  < ; ++ {
		if ,  := .getByName();  {
			if .callee {
				if .obj != nil {
					.push(.obj)
				} else {
					.push(_undefined)
				}
			}
			.push()
			goto 
		}
		 = .outer
	}
	if .callee {
		.push(_undefined)
	}
	loadStackLex(.idx).exec()
	return
:
	.pc++
}

func ( *loadMixedStack1Lex) ( *vm) {
	 := .stash
	 := .name
	 := int(.level)
	for  := 0;  < ; ++ {
		if ,  := .getByName();  {
			if .callee {
				if .obj != nil {
					.push(.obj)
				} else {
					.push(_undefined)
				}
			}
			.push()
			goto 
		}
		 = .outer
	}
	if .callee {
		.push(_undefined)
	}
	loadStack1Lex(.idx).exec()
	return
:
	.pc++
}

type resolveMixed struct {
	name   unistring.String
	idx    uint32
	typ    varType
	strict bool
}

func newStashRef( varType,  unistring.String,  *[]Value,  int) ref {
	switch  {
	case varTypeVar:
		return &stashRef{
			n:   ,
			v:   ,
			idx: ,
		}
	case varTypeLet:
		return &stashRefLex{
			stashRef: stashRef{
				n:   ,
				v:   ,
				idx: ,
			},
		}
	case varTypeConst, varTypeStrictConst:
		return &stashRefConst{
			stashRefLex: stashRefLex{
				stashRef: stashRef{
					n:   ,
					v:   ,
					idx: ,
				},
			},
			strictConst:  == varTypeStrictConst,
		}
	}
	panic("unsupported var type")
}

func ( *resolveMixed) ( *vm) {
	 := int(.idx >> 24)
	 := .idx & 0x00FFFFFF
	 := .stash
	var  ref
	for  := 0;  < ; ++ {
		 = .getRefByName(.name, .strict)
		if  != nil {
			goto 
		}
		 = .outer
	}

	if  != nil {
		 = newStashRef(.typ, .name, &.values, int())
		goto 
	}

	 = &unresolvedRef{
		runtime: .r,
		name:    .name,
	}

:
	.refStack = append(.refStack, )
	.pc++
}

type resolveMixedStack struct {
	name   unistring.String
	idx    int
	typ    varType
	level  uint8
	strict bool
}

type resolveMixedStack1 resolveMixedStack

func ( *resolveMixedStack) ( *vm) {
	 := int(.level)
	 := .stash
	var  ref
	var  int
	for  := 0;  < ; ++ {
		 = .getRefByName(.name, .strict)
		if  != nil {
			goto 
		}
		 = .outer
	}

	if .idx > 0 {
		 = .sb + .args + .idx
	} else {
		 = .sb - .idx
	}

	 = newStashRef(.typ, .name, (*[]Value)(&.stack), )

:
	.refStack = append(.refStack, )
	.pc++
}

func ( *resolveMixedStack1) ( *vm) {
	 := int(.level)
	 := .stash
	var  ref
	for  := 0;  < ; ++ {
		 = .getRefByName(.name, .strict)
		if  != nil {
			goto 
		}
		 = .outer
	}

	 = newStashRef(.typ, .name, (*[]Value)(&.stack), .sb+.idx)

:
	.refStack = append(.refStack, )
	.pc++
}

type _getValue struct{}

var getValue _getValue

func (_getValue) ( *vm) {
	 := .refStack[len(.refStack)-1]
	if  := .get();  != nil {
		.push()
	} else {
		.throw(.r.newReferenceError(.refname()))
		return
	}
	.pc++
}

type _putValue struct{}

var putValue _putValue

func (_putValue) ( *vm) {
	 := len(.refStack) - 1
	 := .refStack[]
	.refStack[] = nil
	.refStack = .refStack[:]
	.set(.stack[.sp-1])
	.pc++
}

type _putValueP struct{}

var putValueP _putValueP

func (_putValueP) ( *vm) {
	 := len(.refStack) - 1
	 := .refStack[]
	.refStack[] = nil
	.refStack = .refStack[:]
	.set(.stack[.sp-1])
	.sp--
	.pc++
}

type _initValueP struct{}

var initValueP _initValueP

func (_initValueP) ( *vm) {
	 := len(.refStack) - 1
	 := .refStack[]
	.refStack[] = nil
	.refStack = .refStack[:]
	.init(.stack[.sp-1])
	.sp--
	.pc++
}

type loadDynamic unistring.String

func ( loadDynamic) ( *vm) {
	 := unistring.String()
	var  Value
	for  := .stash;  != nil;  = .outer {
		if ,  := .getByName();  {
			 = 
			break
		}
	}
	if  == nil {
		 = .r.globalObject.self.getStr(, nil)
		if  == nil {
			.throw(.r.newReferenceError())
			return
		}
	}
	.push()
	.pc++
}

type loadDynamicRef unistring.String

func ( loadDynamicRef) ( *vm) {
	 := unistring.String()
	var  Value
	for  := .stash;  != nil;  = .outer {
		if ,  := .getByName();  {
			 = 
			break
		}
	}
	if  == nil {
		 = .r.globalObject.self.getStr(, nil)
		if  == nil {
			 = valueUnresolved{r: .r, ref: }
		}
	}
	.push()
	.pc++
}

type loadDynamicCallee unistring.String

func ( loadDynamicCallee) ( *vm) {
	 := unistring.String()
	var  Value
	var  *Object
	for  := .stash;  != nil;  = .outer {
		if ,  := .getByName();  {
			 = .obj
			 = 
			break
		}
	}
	if  == nil {
		 = .r.globalObject.self.getStr(, nil)
		if  == nil {
			 = valueUnresolved{r: .r, ref: }
		}
	}
	if  != nil {
		.push()
	} else {
		.push(_undefined)
	}
	.push()
	.pc++
}

type _pop struct{}

var pop _pop

func (_pop) ( *vm) {
	.sp--
	.pc++
}

func ( *vm) ( int,  bool) {
	if .r.toObject(.stack[.sp--1]) == .r.global.Eval {
		if  > 0 {
			 := .stack[.sp-]
			if ,  := .(String);  {
				 := .r.eval(, true, )
				.stack[.sp--2] = 
			} else {
				.stack[.sp--2] = 
			}
		} else {
			.stack[.sp--2] = _undefined
		}

		.sp -=  + 1
		.pc++
	} else {
		call().exec()
	}
}

type callEval uint32

func ( callEval) ( *vm) {
	.callEval(int(), false)
}

type callEvalStrict uint32

func ( callEvalStrict) ( *vm) {
	.callEval(int(), true)
}

type _callEvalVariadic struct{}

var callEvalVariadic _callEvalVariadic

func (_callEvalVariadic) ( *vm) {
	.callEval(.countVariadicArgs()-2, false)
}

type _callEvalVariadicStrict struct{}

var callEvalVariadicStrict _callEvalVariadicStrict

func (_callEvalVariadicStrict) ( *vm) {
	.callEval(.countVariadicArgs()-2, true)
}

type _boxThis struct{}

var boxThis _boxThis

func (_boxThis) ( *vm) {
	 := .stack[.sb]
	if  == _undefined ||  == _null {
		.stack[.sb] = .r.globalObject
	} else {
		.stack[.sb] = .ToObject(.r)
	}
	.pc++
}

var variadicMarker Value = newSymbol(asciiString("[variadic marker]"))

type _startVariadic struct{}

var startVariadic _startVariadic

func (_startVariadic) ( *vm) {
	.push(variadicMarker)
	.pc++
}

type _callVariadic struct{}

var callVariadic _callVariadic

func ( *vm) () int {
	 := 0
	for  := .sp - 1;  >= 0; -- {
		if .stack[] == variadicMarker {
			return 
		}
		++
	}
	panic("Variadic marker was not found. Compiler bug.")
}

func (_callVariadic) ( *vm) {
	call(.countVariadicArgs() - 2).exec()
}

type _endVariadic struct{}

var endVariadic _endVariadic

func (_endVariadic) ( *vm) {
	.sp--
	.stack[.sp-1] = .stack[.sp]
	.pc++
}

type call uint32

func ( call) ( *vm) {
	// this
	// callee
	// arg0
	// ...
	// arg<numargs-1>
	 := int()
	 := .stack[.sp--1] // callee
	 := .toCallee()
	.self.vmCall(, )
}

func ( *vm) () {
	 := .sp
	 := .stack[:]
	for  := range  {
		[] = nil
	}
	.stack = .stack[:]
}

type enterBlock struct {
	names     map[unistring.String]uint32
	stashSize uint32
	stackSize uint32
}

func ( *enterBlock) ( *vm) {
	if .stashSize > 0 {
		.newStash()
		.stash.values = make([]Value, .stashSize)
		if len(.names) > 0 {
			.stash.names = .names
		}
	}
	 := int(.stackSize)
	.stack.expand(.sp +  - 1)
	 := .stack[.sp : .sp+]
	for  := range  {
		[] = nil
	}
	.sp += 
	.pc++
}

type enterCatchBlock struct {
	names     map[unistring.String]uint32
	stashSize uint32
	stackSize uint32
}

func ( *enterCatchBlock) ( *vm) {
	.newStash()
	.stash.values = make([]Value, .stashSize)
	if len(.names) > 0 {
		.stash.names = .names
	}
	.sp--
	.stash.values[0] = .stack[.sp]
	 := int(.stackSize)
	.stack.expand(.sp +  - 1)
	 := .stack[.sp : .sp+]
	for  := range  {
		[] = nil
	}
	.sp += 
	.pc++
}

type leaveBlock struct {
	stackSize uint32
	popStash  bool
}

func ( *leaveBlock) ( *vm) {
	if .popStash {
		.stash = .stash.outer
	}
	if  := .stackSize;  > 0 {
		.sp -= int()
	}
	.pc++
}

type enterFunc struct {
	names       map[unistring.String]uint32
	stashSize   uint32
	stackSize   uint32
	numArgs     uint32
	funcType    funcType
	argsToStash bool
	extensible  bool
}

func ( *enterFunc) ( *vm) {
	// Input stack:
	//
	// callee
	// this
	// arg0
	// ...
	// argN
	// <- sp

	// Output stack:
	//
	// this <- sb
	// <local stack vars...>
	// <- sp
	 := .sp
	.sb =  - .args - 1
	.newStash()
	 := .stash
	.funcType = .funcType
	.values = make([]Value, .stashSize)
	if len(.names) > 0 {
		if .extensible {
			 := make(map[unistring.String]uint32, len(.names))
			for ,  := range .names {
				[] = 
			}
			.names = 
		} else {
			.names = .names
		}
	}

	 := int(.stackSize)
	 := 0
	if .argsToStash {
		 := .args - int(.numArgs)
		copy(.values, .stack[-.args:])
		if  > 0 {
			.stash.extraArgs = make([]Value, )
			copy(.extraArgs, .stack[-:])
		} else {
			 := .values[.args:.numArgs]
			for  := range  {
				[] = _undefined
			}
		}
		 -= .args
	} else {
		 := int(.numArgs) - .args
		if  > 0 {
			 += 
			 = 
			.args = int(.numArgs)
		}
	}
	.stack.expand( +  - 1)
	if  > 0 {
		 := .stack[ : .sp+]
		for  := range  {
			[] = _undefined
		}
	}
	 := .stack[+ : +]
	for  := range  {
		[] = nil
	}
	.sp =  + 
	.pc++
}

// Similar to enterFunc, but for when arguments may be accessed before they are initialised,
// e.g. by an eval() code or from a closure, or from an earlier initialiser code.
// In this case the arguments remain on stack, first argsToCopy of them are copied to the stash.
type enterFunc1 struct {
	names      map[unistring.String]uint32
	stashSize  uint32
	numArgs    uint32
	argsToCopy uint32
	funcType   funcType
	extensible bool
}

func ( *enterFunc1) ( *vm) {
	 := .sp
	.sb =  - .args - 1
	.newStash()
	 := .stash
	.funcType = .funcType
	.values = make([]Value, .stashSize)
	if len(.names) > 0 {
		if .extensible {
			 := make(map[unistring.String]uint32, len(.names))
			for ,  := range .names {
				[] = 
			}
			.names = 
		} else {
			.names = .names
		}
	}
	 := .args - int(.argsToCopy)
	if  > 0 {
		copy(.values, .stack[-.args:-])
		if  := .args - int(.numArgs);  > 0 {
			.stash.extraArgs = make([]Value, )
			copy(.extraArgs, .stack[-:])
		}
	} else {
		copy(.values, .stack[-.args:])
		if int(.argsToCopy) > .args {
			 := .values[.args:.argsToCopy]
			for  := range  {
				[] = _undefined
			}
		}
	}

	.pc++
}

// Finalises the initialisers section and starts the function body which has its own
// scope. When used in conjunction with enterFunc1 adjustStack is set to true which
// causes the arguments to be removed from the stack.
type enterFuncBody struct {
	enterBlock
	funcType    funcType
	extensible  bool
	adjustStack bool
}

func ( *enterFuncBody) ( *vm) {
	if .stashSize > 0 || .extensible {
		.newStash()
		 := .stash
		.funcType = .funcType
		.values = make([]Value, .stashSize)
		if len(.names) > 0 {
			if .extensible {
				 := make(map[unistring.String]uint32, len(.names))
				for ,  := range .names {
					[] = 
				}
				.names = 
			} else {
				.names = .names
			}
		}
	}
	 := .sp
	if .adjustStack {
		 -= .args
	}
	 :=  + int(.stackSize)
	if .stackSize > 0 {
		.stack.expand( - 1)
		 := .stack[:]
		for  := range  {
			[] = nil
		}
	}
	.sp = 
	.pc++
}

type _ret struct{}

var ret _ret

func (_ret) ( *vm) {
	// callee -3
	// this -2 <- sb
	// retval -1

	.stack[.sb-1] = .stack[.sp-1]
	.sp = .sb
	.popCtx()
	.pc++
}

type cret uint32

func ( cret) ( *vm) {
	.stack[.sb] = *.getStashPtr(uint32())
	ret.exec()
}

type enterFuncStashless struct {
	stackSize uint32
	args      uint32
}

func ( *enterFuncStashless) ( *vm) {
	 := .sp
	.sb =  - .args - 1
	 := int(.args) - .args
	if  > 0 {
		 :=  + int(.stackSize) + 
		.stack.expand()
		 := .stack[ : +]
		for  := range  {
			[] = _undefined
		}
		 = .stack[+ : ]
		for  := range  {
			[] = nil
		}
		.args = int(.args)
		.sp = 
	} else {
		if .stackSize > 0 {
			 :=  + int(.stackSize)
			.stack.expand()
			 := .stack[:]
			for  := range  {
				[] = nil
			}
			.sp = 
		}
	}
	.pc++
}

type newFuncInstruction interface {
	getPrg() *Program
}

type newFunc struct {
	prg    *Program
	name   unistring.String
	source string

	length int
	strict bool
}

func ( *newFunc) ( *vm) {
	 := .r.newFunc(.name, .length, .strict)
	.prg = .prg
	.stash = .stash
	.privEnv = .privEnv
	.src = .source
	.push(.val)
	.pc++
}

func ( *newFunc) () *Program {
	return .prg
}

type newAsyncFunc struct {
	newFunc
}

func ( *newAsyncFunc) ( *vm) {
	 := .r.newAsyncFunc(.name, .length, .strict)
	.prg = .prg
	.stash = .stash
	.privEnv = .privEnv
	.src = .source
	.push(.val)
	.pc++
}

type newGeneratorFunc struct {
	newFunc
}

func ( *newGeneratorFunc) ( *vm) {
	 := .r.newGeneratorFunc(.name, .length, .strict)
	.prg = .prg
	.stash = .stash
	.privEnv = .privEnv
	.src = .source
	.push(.val)
	.pc++
}

type newMethod struct {
	newFunc
	homeObjOffset uint32
}

func ( *newMethod) ( *vm,  *methodFuncObject) {
	.prg = .prg
	.stash = .stash
	.privEnv = .privEnv
	.src = .source
	if .homeObjOffset > 0 {
		.homeObject = .r.toObject(.stack[.sp-int(.homeObjOffset)])
	}
	.push(.val)
	.pc++
}

func ( *newMethod) ( *vm) {
	._exec(, .r.newMethod(.name, .length, .strict))
}

type newAsyncMethod struct {
	newMethod
}

func ( *newAsyncMethod) ( *vm) {
	 := .r.newAsyncMethod(.name, .length, .strict)
	._exec(, &.methodFuncObject)
}

type newGeneratorMethod struct {
	newMethod
}

func ( *newGeneratorMethod) ( *vm) {
	 := .r.newGeneratorMethod(.name, .length, .strict)
	._exec(, &.methodFuncObject)
}

type newArrowFunc struct {
	newFunc
}

type newAsyncArrowFunc struct {
	newArrowFunc
}

func getFuncObject( Value) *Object {
	if ,  := .(*Object);  {
		if ,  := .self.(*arrowFuncObject);  {
			return .funcObj
		}
		return 
	}
	if  == _undefined {
		return nil
	}
	panic(typeError("Value is not an Object"))
}

func getHomeObject( Value) *Object {
	if ,  := .(*Object);  {
		switch fn := .self.(type) {
		case *methodFuncObject:
			return .homeObject
		case *generatorMethodFuncObject:
			return .homeObject
		case *asyncMethodFuncObject:
			return .homeObject
		case *classFuncObject:
			return .runtime.toObject(.getStr("prototype", nil))
		case *arrowFuncObject:
			return (.funcObj)
		case *asyncArrowFuncObject:
			return (.funcObj)
		}
	}
	panic(newTypeError("Compiler bug: getHomeObject() on the wrong value: %T", ))
}

func ( *newArrowFunc) ( *vm,  *arrowFuncObject) {
	.prg = .prg
	.stash = .stash
	.privEnv = .privEnv
	.src = .source
	if .sb > 0 {
		.funcObj = getFuncObject(.stack[.sb-1])
	}
	.push(.val)
	.pc++
}

func ( *newArrowFunc) ( *vm) {
	._exec(, .r.newArrowFunc(.name, .length, .strict))
}

func ( *newAsyncArrowFunc) ( *vm) {
	 := .r.newAsyncArrowFunc(.name, .length, .strict)
	._exec(, &.arrowFuncObject)
}

func ( *vm) ( unistring.String) Value {
	return .r.newError(.r.getSyntaxError(), "Identifier '%s' has already been declared", )
}

func ( *vm) ( []unistring.String) {
	 := .r.globalObject.self
	 := .r.global.stash.names
	if ,  := .(*baseObject);  {
		// shortcut
		if .extensible {
			for ,  := range  {
				if ,  := [];  {
					panic(.alreadyDeclared())
				}
			}
		} else {
			for ,  := range  {
				if !.hasOwnPropertyStr() {
					panic(.r.NewTypeError("Cannot define global variable '%s', global object is not extensible", ))
				}
				if ,  := [];  {
					panic(.alreadyDeclared())
				}
			}
		}
	} else {
		for ,  := range  {
			if !.hasOwnPropertyStr() && !.isExtensible() {
				panic(.r.NewTypeError("Cannot define global variable '%s', global object is not extensible", ))
			}
			if ,  := [];  {
				panic(.alreadyDeclared())
			}
		}
	}
}

func ( *vm) ( []unistring.String,  bool) {
	 := .r.globalObject.self
	if ,  := .(*templatedObject);  {
		for ,  := range  {
			if !.hasOwnPropertyStr() && .extensible {
				._putProp(, _undefined, true, true, )
			}
		}
	} else {
		var  Flag
		if  {
			 = FLAG_TRUE
		} else {
			 = FLAG_FALSE
		}
		for ,  := range  {
			if !.hasOwnPropertyStr() && .isExtensible() {
				.defineOwnPropertyStr(, PropertyDescriptor{
					Value:        _undefined,
					Writable:     FLAG_TRUE,
					Enumerable:   FLAG_TRUE,
					Configurable: ,
				}, true)
				.setOwnStr(, _undefined, false)
			}
		}
	}
}

func ( *vm) ( []unistring.String,  bool) {
	 := .r.globalObject.self
	 := .sp - len()
	var  *templatedObject
	if ,  := .(*templatedObject);  {
		 = 
	}
	for ,  := range  {
		var  PropertyDescriptor
		 := .getOwnPropStr()
		.Value = .stack[+]
		if  != nil &&  == nil && .extensible {
			._putProp(, .Value, true, true, )
		} else {
			if ,  := .(*valueProperty);  && !.configurable {
				// no-op
			} else {
				.Writable = FLAG_TRUE
				.Enumerable = FLAG_TRUE
				if  {
					.Configurable = FLAG_TRUE
				} else {
					.Configurable = FLAG_FALSE
				}
			}
			if  != nil {
				.defineOwnPropertyStr(, , true)
			} else {
				.defineOwnPropertyStr(, , true)
				.setOwnStr(, .Value, false) // not a bug, see https://262.ecma-international.org/#sec-createglobalfunctionbinding
			}
		}
	}
	.sp = 
}

func ( *vm) ( []unistring.String) {
	 := .r.globalObject.self
	 := .r.global.stash.names
	for ,  := range  {
		if ,  := [];  {
			panic(.alreadyDeclared())
		}
		 := .getOwnPropStr()
		 := true
		switch prop := .(type) {
		case nil:
			 = .isExtensible()
		case *valueProperty:
			 = .configurable || .getterFunc == nil && .setterFunc == nil && .writable && .enumerable
		}
		if ! {
			panic(.r.NewTypeError("Cannot redefine global function '%s'", ))
		}
	}
}

func ( *vm) ( []unistring.String) {
	 := .r.globalObject.self
	 := &.r.global.stash
	for ,  := range  {
		if ,  := .names[];  {
			goto 
		}
		if ,  := .getOwnPropStr().(*valueProperty);  && !.configurable {
			goto 
		}
		continue
	:
		panic(.alreadyDeclared())
	}
}

type bindVars struct {
	names     []unistring.String
	deletable bool
}

func ( *bindVars) ( *vm) {
	var  *stash
	for ,  := range .names {
		for  := .stash;  != nil;  = .outer {
			if ,  := .names[];  && &maskVar == 0 {
				.throw(.alreadyDeclared())
				return
			}
			if .isVariable() {
				 = 
				break
			}
		}
	}
	if  == nil {
		 = .stash
	}
	 := .deletable
	for ,  := range .names {
		.createBinding(, )
	}
	.pc++
}

type bindGlobal struct {
	vars, funcs, lets, consts []unistring.String

	deletable bool
}

func ( *bindGlobal) ( *vm) {
	.checkBindFuncsGlobal(.funcs)
	.checkBindLexGlobal(.lets)
	.checkBindLexGlobal(.consts)
	.checkBindVarsGlobal(.vars)

	 := &.r.global.stash
	for ,  := range .lets {
		.createLexBinding(, false)
	}
	for ,  := range .consts {
		.createLexBinding(, true)
	}
	.createGlobalFuncBindings(.funcs, .deletable)
	.createGlobalVarBindings(.vars, .deletable)
	.pc++
}

type jne int32

func ( jne) ( *vm) {
	.sp--
	if !.stack[.sp].ToBoolean() {
		.pc += int()
	} else {
		.pc++
	}
}

type jeq int32

func ( jeq) ( *vm) {
	.sp--
	if .stack[.sp].ToBoolean() {
		.pc += int()
	} else {
		.pc++
	}
}

type jeq1 int32

func ( jeq1) ( *vm) {
	if .stack[.sp-1].ToBoolean() {
		.pc += int()
	} else {
		.sp--
		.pc++
	}
}

type jneq1 int32

func ( jneq1) ( *vm) {
	if !.stack[.sp-1].ToBoolean() {
		.pc += int()
	} else {
		.sp--
		.pc++
	}
}

type jdef int32

func ( jdef) ( *vm) {
	if .stack[.sp-1] != _undefined {
		.pc += int()
	} else {
		.sp--
		.pc++
	}
}

type jdefP int32

func ( jdefP) ( *vm) {
	if .stack[.sp-1] != _undefined {
		.pc += int()
	} else {
		.pc++
	}
	.sp--
}

type jopt int32

func ( jopt) ( *vm) {
	switch .stack[.sp-1] {
	case _null:
		.stack[.sp-1] = _undefined
		fallthrough
	case _undefined:
		.pc += int()
	default:
		.pc++
	}
}

type joptc int32

func ( joptc) ( *vm) {
	switch .stack[.sp-1].(type) {
	case valueNull, valueUndefined, memberUnresolved:
		.sp--
		.stack[.sp-1] = _undefined
		.pc += int()
	default:
		.pc++
	}
}

type jcoalesc int32

func ( jcoalesc) ( *vm) {
	switch .stack[.sp-1] {
	case _undefined, _null:
		.sp--
		.pc++
	default:
		.pc += int()
	}
}

type _not struct{}

var not _not

func (_not) ( *vm) {
	if .stack[.sp-1].ToBoolean() {
		.stack[.sp-1] = valueFalse
	} else {
		.stack[.sp-1] = valueTrue
	}
	.pc++
}

func toPrimitiveNumber( Value) Value {
	if ,  := .(*Object);  {
		return .toPrimitiveNumber()
	}
	return 
}

func toPrimitive( Value) Value {
	if ,  := .(*Object);  {
		return .toPrimitive()
	}
	return 
}

func cmp(,  Value) Value {
	var  bool
	,  := .(String)
	,  := .(String)

	if  &&  {
		 = .CompareTo() < 0
		goto 
	} else {
		if ,  := .(*valueBigInt);  &&  {
			,  := stringToBigInt(.toTrimmedUTF8())
			if  != nil {
				return _undefined
			}
			 = (*big.Int)().Cmp() < 0
			goto 
		}
		if ,  := .(*valueBigInt);  &&  {
			,  := stringToBigInt(.toTrimmedUTF8())
			if  != nil {
				return _undefined
			}
			 = .Cmp((*big.Int)()) < 0
			goto 
		}
	}

	 = toNumeric()
	 = toNumeric()

	switch nx := .(type) {
	case valueInt:
		switch ny := .(type) {
		case valueInt:
			 =  < 
			goto 
		case *valueBigInt:
			 = big.NewInt(int64()).Cmp((*big.Int)()) < 0
			goto 
		}
	case valueFloat:
		switch ny := .(type) {
		case *valueBigInt:
			switch {
			case math.IsNaN(float64()):
				return _undefined
			case  == _negativeInf:
				 = true
				goto 
			}
			if  := big.NewFloat(float64()); .IsInt() {
				,  := .Int(nil)
				 = .Cmp((*big.Int)()) < 0
			} else {
				 = .Cmp(new(big.Float).SetInt((*big.Int)())) < 0
			}
			goto 
		}
	case *valueBigInt:
		switch ny := .(type) {
		case valueInt:
			 = (*big.Int)().Cmp(big.NewInt(int64())) < 0
			goto 
		case valueFloat:
			switch {
			case math.IsNaN(float64()):
				return _undefined
			case  == _positiveInf:
				 = true
				goto 
			}
			if  := big.NewFloat(float64()); .IsInt() {
				,  := .Int(nil)
				 = (*big.Int)().Cmp() < 0
			} else {
				 = new(big.Float).SetInt((*big.Int)()).Cmp() < 0
			}
			goto 
		case *valueBigInt:
			 = (*big.Int)().Cmp((*big.Int)()) < 0
			goto 
		}
	}

	if ,  := .ToFloat(), .ToFloat(); math.IsNaN() || math.IsNaN() {
		return _undefined
	} else {
		 =  < 
	}

:
	if  {
		return valueTrue
	}
	return valueFalse

}

type _op_lt struct{}

var op_lt _op_lt

func (_op_lt) ( *vm) {
	 := toPrimitiveNumber(.stack[.sp-2])
	 := toPrimitiveNumber(.stack[.sp-1])

	 := cmp(, )
	if  == _undefined {
		.stack[.sp-2] = valueFalse
	} else {
		.stack[.sp-2] = 
	}
	.sp--
	.pc++
}

type _op_lte struct{}

var op_lte _op_lte

func (_op_lte) ( *vm) {
	 := toPrimitiveNumber(.stack[.sp-2])
	 := toPrimitiveNumber(.stack[.sp-1])

	 := cmp(, )
	if  == _undefined ||  == valueTrue {
		.stack[.sp-2] = valueFalse
	} else {
		.stack[.sp-2] = valueTrue
	}

	.sp--
	.pc++
}

type _op_gt struct{}

var op_gt _op_gt

func (_op_gt) ( *vm) {
	 := toPrimitiveNumber(.stack[.sp-2])
	 := toPrimitiveNumber(.stack[.sp-1])

	 := cmp(, )
	if  == _undefined {
		.stack[.sp-2] = valueFalse
	} else {
		.stack[.sp-2] = 
	}
	.sp--
	.pc++
}

type _op_gte struct{}

var op_gte _op_gte

func (_op_gte) ( *vm) {
	 := toPrimitiveNumber(.stack[.sp-2])
	 := toPrimitiveNumber(.stack[.sp-1])

	 := cmp(, )
	if  == _undefined ||  == valueTrue {
		.stack[.sp-2] = valueFalse
	} else {
		.stack[.sp-2] = valueTrue
	}

	.sp--
	.pc++
}

type _op_eq struct{}

var op_eq _op_eq

func (_op_eq) ( *vm) {
	if .stack[.sp-2].Equals(.stack[.sp-1]) {
		.stack[.sp-2] = valueTrue
	} else {
		.stack[.sp-2] = valueFalse
	}
	.sp--
	.pc++
}

type _op_neq struct{}

var op_neq _op_neq

func (_op_neq) ( *vm) {
	if .stack[.sp-2].Equals(.stack[.sp-1]) {
		.stack[.sp-2] = valueFalse
	} else {
		.stack[.sp-2] = valueTrue
	}
	.sp--
	.pc++
}

type _op_strict_eq struct{}

var op_strict_eq _op_strict_eq

func (_op_strict_eq) ( *vm) {
	if .stack[.sp-2].StrictEquals(.stack[.sp-1]) {
		.stack[.sp-2] = valueTrue
	} else {
		.stack[.sp-2] = valueFalse
	}
	.sp--
	.pc++
}

type _op_strict_neq struct{}

var op_strict_neq _op_strict_neq

func (_op_strict_neq) ( *vm) {
	if .stack[.sp-2].StrictEquals(.stack[.sp-1]) {
		.stack[.sp-2] = valueFalse
	} else {
		.stack[.sp-2] = valueTrue
	}
	.sp--
	.pc++
}

type _op_instanceof struct{}

var op_instanceof _op_instanceof

func (_op_instanceof) ( *vm) {
	 := .stack[.sp-2]
	 := .r.toObject(.stack[.sp-1])

	if instanceOfOperator(, ) {
		.stack[.sp-2] = valueTrue
	} else {
		.stack[.sp-2] = valueFalse
	}

	.sp--
	.pc++
}

type _op_in struct{}

var op_in _op_in

func (_op_in) ( *vm) {
	 := .stack[.sp-2]
	 := .r.toObject(.stack[.sp-1])

	if .hasProperty() {
		.stack[.sp-2] = valueTrue
	} else {
		.stack[.sp-2] = valueFalse
	}

	.sp--
	.pc++
}

type try struct {
	catchOffset   int32
	finallyOffset int32
}

func ( try) ( *vm) {
	var ,  int32
	if .catchOffset > 0 {
		 = int32(.pc) + .catchOffset
	} else {
		 = -1
	}
	if .finallyOffset > 0 {
		 = int32(.pc) + .finallyOffset
	} else {
		 = -1
	}
	.pushTryFrame(, )
	.pc++
}

type leaveTry struct{}

func (leaveTry) ( *vm) {
	 := &.tryStack[len(.tryStack)-1]
	if .finallyPos >= 0 {
		.finallyRet = int32(.pc + 1)
		.pc = int(.finallyPos)
		.finallyPos = -1
		.catchPos = -1
	} else {
		.popTryFrame()
		.pc++
	}
}

type enterFinally struct{}

func (enterFinally) ( *vm) {
	 := &.tryStack[len(.tryStack)-1]
	.finallyPos = -1
	.pc++
}

type leaveFinally struct{}

func (leaveFinally) ( *vm) {
	 := &.tryStack[len(.tryStack)-1]
	,  := .exception, .finallyRet
	.exception = nil
	.popTryFrame()
	if  != nil {
		.throw()
		return
	} else {
		if  != -1 {
			.pc = int()
		} else {
			.pc++
		}
	}
}

type _throw struct{}

var throw _throw

func (_throw) ( *vm) {
	 := .stack[.sp-1]
	 := &Exception{
		val: ,
	}

	if ,  := .(*Object);  {
		if ,  := .self.(*errorObject);  {
			if len(.stack) > 0 {
				.stack = .stack
			}
		}
	}

	if .stack == nil {
		.stack = .captureStack(make([]StackFrame, 0, len(.callStack)+1), 0)
	}

	if  = .handleThrow();  != nil {
		panic()
	}
}

type _newVariadic struct{}

var newVariadic _newVariadic

func (_newVariadic) ( *vm) {
	_new(.countVariadicArgs() - 1).exec()
}

type _new uint32

func ( _new) ( *vm) {
	 := .sp - int()
	 := .stack[-1]
	 := .r.toConstructor()
	.stack[-1] = (.stack[:.sp], nil)
	.sp = 
	.pc++
}

type superCall uint32

func ( superCall) ( *vm) {
	 := len(.refStack) - 1
	 := .refStack[]
	.refStack[] = nil
	.refStack = .refStack[:]

	 := .r.toObject(.stack[.sb-1])
	var  *classFuncObject
	switch fn := .self.(type) {
	case *classFuncObject:
		 = 
	case *arrowFuncObject:
		, _ = .funcObj.self.(*classFuncObject)
	}
	if  == nil {
		.throw(.r.NewTypeError("wrong callee type for super()"))
		return
	}
	 := .sp - int()
	 := .r.toObject(.newTarget)
	 := .createInstance(.stack[:.sp], )
	.set()
	.sp = 
	._initFields()
	.push()
	.pc++
}

type _superCallVariadic struct{}

var superCallVariadic _superCallVariadic

func (_superCallVariadic) ( *vm) {
	superCall(.countVariadicArgs()).exec()
}

type _loadNewTarget struct{}

var loadNewTarget _loadNewTarget

func (_loadNewTarget) ( *vm) {
	if  := .newTarget;  != nil {
		.push()
	} else {
		.push(_undefined)
	}
	.pc++
}

type _typeof struct{}

var typeof _typeof

func (_typeof) ( *vm) {
	var  Value
	switch v := .stack[.sp-1].(type) {
	case valueUndefined, valueUnresolved:
		 = stringUndefined
	case valueNull:
		 = stringObjectC
	case *Object:
		 = .self.typeOf()
	case valueBool:
		 = stringBoolean
	case String:
		 = stringString
	case valueInt, valueFloat:
		 = stringNumber
	case *valueBigInt:
		 = stringBigInt
	case *Symbol:
		 = stringSymbol
	default:
		panic(newTypeError("Compiler bug: unknown type: %T", ))
	}
	.stack[.sp-1] = 
	.pc++
}

type createArgsMapped uint32

func ( createArgsMapped) ( *vm) {
	 := &Object{runtime: .r}
	 := &argumentsObject{}
	.extensible = true
	.prototype = .r.global.ObjectPrototype
	.class = "Arguments"
	.self = 
	.val = 
	.length = .args
	.init()
	 := 0
	 := int()
	if .args <  {
		 = .args
	}
	for ;  < ; ++ {
		._put(unistring.String(strconv.Itoa()), &mappedProperty{
			valueProperty: valueProperty{
				writable:     true,
				configurable: true,
				enumerable:   true,
			},
			v: &.stash.values[],
		})
	}

	for ,  := range .stash.extraArgs {
		._put(unistring.String(strconv.Itoa()), )
		++
	}

	._putProp("callee", .stack[.sb-1], true, false, true)
	._putSym(SymIterator, valueProp(.r.getArrayValues(), true, false, true))
	.push()
	.pc++
}

type createArgsUnmapped uint32

func ( createArgsUnmapped) ( *vm) {
	 := .r.newBaseObject(.r.global.ObjectPrototype, "Arguments")
	 := 0
	 := int()
	if .args <  {
		 = .args
	}
	for ,  := range .stash.values[:] {
		._put(unistring.String(strconv.Itoa()), )
		++
	}

	for ,  := range .stash.extraArgs {
		._put(unistring.String(strconv.Itoa()), )
		++
	}

	._putProp("length", intToValue(int64(.args)), true, false, true)
	._put("callee", .r.newThrowerProperty(false))
	._putSym(SymIterator, valueProp(.r.getArrayValues(), true, false, true))
	.push(.val)
	.pc++
}

type _enterWith struct{}

var enterWith _enterWith

func (_enterWith) ( *vm) {
	.newStash()
	.stash.obj = .stack[.sp-1].ToObject(.r)
	.sp--
	.pc++
}

type _leaveWith struct{}

var leaveWith _leaveWith

func (_leaveWith) ( *vm) {
	.stash = .stash.outer
	.pc++
}

func emptyIter() (propIterItem, iterNextFunc) {
	return propIterItem{}, nil
}

type _enumerate struct{}

var enumerate _enumerate

func (_enumerate) ( *vm) {
	 := .stack[.sp-1]
	if  == _undefined ||  == _null {
		.iterStack = append(.iterStack, iterStackItem{f: emptyIter})
	} else {
		.iterStack = append(.iterStack, iterStackItem{f: enumerateRecursive(.ToObject(.r))})
	}
	.sp--
	.pc++
}

type enumNext int32

func ( enumNext) ( *vm) {
	 := len(.iterStack) - 1
	,  := .iterStack[].f()
	if  != nil {
		.iterStack[].val = .name
		.iterStack[].f = 
		.pc++
	} else {
		.pc += int()
	}
}

type _enumGet struct{}

var enumGet _enumGet

func (_enumGet) ( *vm) {
	 := len(.iterStack) - 1
	.push(.iterStack[].val)
	.pc++
}

type _enumPop struct{}

var enumPop _enumPop

func (_enumPop) ( *vm) {
	 := len(.iterStack) - 1
	.iterStack[] = iterStackItem{}
	.iterStack = .iterStack[:]
	.pc++
}

type _enumPopClose struct{}

var enumPopClose _enumPopClose

func (_enumPopClose) ( *vm) {
	 := len(.iterStack) - 1
	 := .iterStack[]
	.iterStack[] = iterStackItem{}
	.iterStack = .iterStack[:]
	if  := .iter;  != nil {
		.returnIter()
	}
	.pc++
}

type _iterateP struct{}

var iterateP _iterateP

func (_iterateP) ( *vm) {
	 := .r.getIterator(.stack[.sp-1], nil)
	.iterStack = append(.iterStack, iterStackItem{iter: })
	.sp--
	.pc++
}

type _iterate struct{}

var iterate _iterate

func (_iterate) ( *vm) {
	 := .r.getIterator(.stack[.sp-1], nil)
	.iterStack = append(.iterStack, iterStackItem{iter: })
	.pc++
}

type iterNext int32

func ( iterNext) ( *vm) {
	 := len(.iterStack) - 1
	 := .iterStack[].iter
	,  := .step()
	if  == nil {
		if  == nil {
			.pc += int()
		} else {
			.iterStack[].val = 
			.pc++
		}
	} else {
		 := len(.iterStack) - 1
		.iterStack[] = iterStackItem{}
		.iterStack = .iterStack[:]
		.throw(.val)
		return
	}
}

type iterGetNextOrUndef struct{}

func (iterGetNextOrUndef) ( *vm) {
	 := len(.iterStack) - 1
	 := .iterStack[].iter
	var  Value
	if .iterator != nil {
		var  *Exception
		,  = .step()
		if  != nil {
			 := len(.iterStack) - 1
			.iterStack[] = iterStackItem{}
			.iterStack = .iterStack[:]
			.throw(.val)
			return
		}
	}
	.push(nilSafe())
	.pc++
}

type copyStash struct{}

func (copyStash) ( *vm) {
	 := .stash
	 := &stash{
		outer: .outer,
	}
	.stashAllocs++
	.values = append([]Value(nil), .values...)
	.names = .names
	.stash = 
	.pc++
}

type _throwAssignToConst struct{}

var throwAssignToConst _throwAssignToConst

func (_throwAssignToConst) ( *vm) {
	.throw(errAssignToConst)
}

func ( *Runtime) (,  Value) {
	 := .toObject()
	if  == _null ||  == _undefined {
		return
	}
	 := .ToObject()
	for ,  := iterateEnumerableProperties()();  != nil; ,  = () {
		createDataPropertyOrThrow(, .name, .value)
	}
}

type _copySpread struct{}

var copySpread _copySpread

func (_copySpread) ( *vm) {
	.r.copyDataProperties(.stack[.sp-2], .stack[.sp-1])
	.sp--
	.pc++
}

type _copyRest struct{}

var copyRest _copyRest

func (_copyRest) ( *vm) {
	.push(.r.NewObject())
	.r.copyDataProperties(.stack[.sp-1], .stack[.sp-2])
	.pc++
}

type _createDestructSrc struct{}

var createDestructSrc _createDestructSrc

func (_createDestructSrc) ( *vm) {
	 := .stack[.sp-1]
	.r.checkObjectCoercible()
	.push(.r.newDestructKeyedSource())
	.pc++
}

type _checkObjectCoercible struct{}

var checkObjectCoercible _checkObjectCoercible

func (_checkObjectCoercible) ( *vm) {
	.r.checkObjectCoercible(.stack[.sp-1])
	.pc++
}

type createArgsRestStack int

func ( createArgsRestStack) ( *vm) {
	var  []Value
	 := .args - int()
	if  > 0 {
		 = make([]Value, )
		copy(, .stack[.sb+int()+1:])
	}
	.push(.r.newArrayValues())
	.pc++
}

type _createArgsRestStash struct{}

var createArgsRestStash _createArgsRestStash

func (_createArgsRestStash) ( *vm) {
	.push(.r.newArrayValues(.stash.extraArgs))
	.stash.extraArgs = nil
	.pc++
}

type concatStrings int

func ( concatStrings) ( *vm) {
	 := .stack[.sp-int() : .sp]
	 := 0
	 := true
	for ,  := range  {
		switch s := .(type) {
		case asciiString:
			 += .Length()
		case unicodeString:
			 += .Length()
			 = false
		case *importedString:
			.ensureScanned()
			if .u != nil {
				[] = .u
				 += .u.Length()
				 = false
			} else {
				[] = asciiString(.s)
				 += len(.s)
			}
		default:
			panic(unknownStringTypeErr())
		}
	}

	.sp -= int() - 1
	if  {
		var  strings.Builder
		.Grow()
		for ,  := range  {
			.WriteString(string(.(asciiString)))
		}
		.stack[.sp-1] = asciiString(.String())
	} else {
		var  unicodeStringBuilder
		.ensureStarted()
		for ,  := range  {
			.writeString(.(String))
		}
		.stack[.sp-1] = .String()
	}
	.pc++
}

type getTaggedTmplObject struct {
	raw, cooked []Value
}

// As tagged template objects are not cached (because it's hard to ensure the cache is cleaned without using
// finalizers) this wrapper is needed to override the equality method so that two objects for the same template
// literal appeared to be equal from the code's point of view.
type taggedTemplateArray struct {
	*arrayObject
	idPtr *[]Value
}

func ( *taggedTemplateArray) ( objectImpl) bool {
	if ,  := .(*taggedTemplateArray);  {
		return .idPtr == .idPtr
	}
	return false
}

func ( *getTaggedTmplObject) ( *vm) {
	 := .r.newArrayObject()
	setArrayValues(, .cooked)
	 := .r.newArrayObject()
	setArrayValues(, .raw)

	.propValueCount = len(.cooked)
	.lengthProp.writable = false

	.propValueCount = len(.raw)
	.lengthProp.writable = false

	.preventExtensions(true)
	.val.self = &taggedTemplateArray{
		arrayObject: ,
		idPtr:       &.raw,
	}

	._putProp("raw", .val, false, false, false)
	.preventExtensions(true)
	.val.self = &taggedTemplateArray{
		arrayObject: ,
		idPtr:       &.cooked,
	}

	.push(.val)
	.pc++
}

type _loadSuper struct{}

var loadSuper _loadSuper

func (_loadSuper) ( *vm) {
	 := getHomeObject(.stack[.sb-1])
	if  := .Prototype();  != nil {
		.push()
	} else {
		.push(_undefined)
	}
	.pc++
}

type newClass struct {
	ctor       *Program
	name       unistring.String
	source     string
	initFields *Program

	privateFields, privateMethods       []unistring.String // only set when dynamic resolution is needed
	numPrivateFields, numPrivateMethods uint32

	length        int
	hasPrivateEnv bool
}

type newDerivedClass struct {
	newClass
}

func ( *vm) ( *classFuncObject, ,  uint32) {
	 := &privateEnvType{}
	.numFields = 
	.numMethods = 
	.privateEnvType = 
	.privateMethods = make([]Value, )
}

func ( *vm) ( *privateEnvType, ,  []unistring.String) {
	if len() > 0 || len() > 0 {
		 := .privEnv.names
		if  == nil {
			 = make(privateNames)
			.privEnv.names = 
		}
		for ,  := range  {
			[] = &privateId{
				typ: ,
				idx: uint32(),
			}
		}
		for ,  := range  {
			[] = &privateId{
				typ:      ,
				idx:      uint32(),
				isMethod: true,
			}
		}
	}
}

func ( *newClass) (,  *Object,  *vm,  bool) (,  *Object) {
	 := .r.newBaseObject(, classObject)
	 := .r.newClassFunc(.name, .length, , )
	._putProp("prototype", .val, false, false, false)
	._putProp("constructor", .val, true, false, true)
	.prg = .ctor
	.stash = .stash
	.src = .source
	.initFields = .initFields
	if .hasPrivateEnv {
		.privEnv = &privateEnv{
			outer: .privEnv,
		}
		.createPrivateType(, .numPrivateFields, .numPrivateMethods)
		.fillPrivateNamesMap(.privateEnvType, .privateFields, .privateMethods)
		.privEnv.instanceType = .privateEnvType
	}
	.privEnv = .privEnv
	return .val, .val
}

func ( *newClass) ( *vm) {
	,  := .create(.r.global.ObjectPrototype, .r.getFunctionPrototype(), , false)
	 := .sp
	.stack.expand( + 1)
	.stack[] = 
	.stack[+1] = 
	.sp =  + 2
	.pc++
}

func ( *newDerivedClass) ( *vm) {
	var  *Object
	var  *Object
	if  := .stack[.sp-1];  != _null {
		if ,  := .(*Object); ! || .self.assertConstructor() == nil {
			.throw(.r.NewTypeError("Class extends value is not a constructor or null"))
			return
		} else {
			 := .self.getStr("prototype", nil)
			if  != _null {
				if ,  := .(*Object);  {
					 = 
				} else {
					.throw(.r.NewTypeError("Class extends value does not have valid prototype property"))
					return
				}
			}
			 = 
		}
	} else {
		 = .r.getFunctionPrototype()
	}

	,  := .create(, , , true)
	.stack[.sp-1] = 
	.push()
	.pc++
}

// Creates a special instance of *classFuncObject which is only used during evaluation of a class declaration
// to initialise static fields and instance private methods of another class.
type newStaticFieldInit struct {
	initFields                          *Program
	numPrivateFields, numPrivateMethods uint32
}

func ( *newStaticFieldInit) ( *vm) {
	 := .r.newClassFunc("", 0, .r.getFunctionPrototype(), false)
	if .numPrivateFields > 0 || .numPrivateMethods > 0 {
		.createPrivateType(, .numPrivateFields, .numPrivateMethods)
	}
	.initFields = .initFields
	.stash = .stash
	.push(.val)
	.pc++
}

func ( *vm) ( Value) {
	if  != nil {
		.push()
	} else {
		.throw(.r.newError(.r.getReferenceError(), "Must call super constructor in derived class before accessing 'this'"))
		return
	}
	.pc++
}

type loadThisStash uint32

func ( loadThisStash) ( *vm) {
	.loadThis(*.getStashPtr(uint32()))
}

type loadThisStack struct{}

func (loadThisStack) ( *vm) {
	.loadThis(.stack[.sb])
}

func ( *vm) ( uint32) *Value {
	 := int() >> 24
	 :=  & 0x00FFFFFF
	 := .stash
	for  := 0;  < ; ++ {
		 = .outer
	}

	return &.values[]
}

type getThisDynamic struct{}

func (getThisDynamic) ( *vm) {
	for  := .stash;  != nil;  = .outer {
		if .obj == nil {
			if ,  := .getByName(thisBindingName);  {
				.push()
				.pc++
				return
			}
		}
	}
	.push(.r.globalObject)
	.pc++
}

type throwConst struct {
	v interface{}
}

func ( throwConst) ( *vm) {
	.throw(.v)
}

type resolveThisStack struct{}

func ( resolveThisStack) ( *vm) {
	.refStack = append(.refStack, &thisRef{v: (*[]Value)(&.stack), idx: .sb})
	.pc++
}

type resolveThisStash uint32

func ( resolveThisStash) ( *vm) {
	 := int() >> 24
	 :=  & 0x00FFFFFF
	 := .stash
	for  := 0;  < ; ++ {
		 = .outer
	}
	.refStack = append(.refStack, &thisRef{v: &.values, idx: int()})
	.pc++
}

type resolveThisDynamic struct{}

func (resolveThisDynamic) ( *vm) {
	for  := .stash;  != nil;  = .outer {
		if .obj == nil {
			if ,  := .names[thisBindingName];  {
				.refStack = append(.refStack, &thisRef{v: &.values, idx: int( &^ maskTyp)})
				.pc++
				return
			}
		}
	}
	panic(.r.newError(.r.getReferenceError(), "Compiler bug: 'this' reference is not found in resolveThisDynamic"))
}

type defineComputedKey int

func ( defineComputedKey) ( *vm) {
	 := .r.toObject(.stack[.sp-int()])
	if ,  := .self.(*classFuncObject);  {
		 := toPropertyKey(.stack[.sp-1])
		.computedKeys = append(.computedKeys, )
		.sp--
		.pc++
		return
	}
	panic(.r.NewTypeError("Compiler bug: unexpected target for defineComputedKey: %v", ))
}

type loadComputedKey int

func ( loadComputedKey) ( *vm) {
	 := .r.toObject(.stack[.sb-1])
	if ,  := .self.(*classFuncObject);  {
		.push(.computedKeys[])
		.pc++
		return
	}
	panic(.r.NewTypeError("Compiler bug: unexpected target for loadComputedKey: %v", ))
}

type initStaticElements struct {
	privateFields, privateMethods []unistring.String
}

func ( *initStaticElements) ( *vm) {
	 := .stack[.sp-1]
	 := .r.toObject(.stack[.sp-3])
	.sp -= 2
	if ,  := .self.(*classFuncObject);  {
		._putProp("prototype", , true, true, true) // so that 'super' resolution work
		.privEnv = .privEnv
		if .privateEnvType != nil {
			.privEnv.staticType = .privateEnvType
			.fillPrivateNamesMap(.privateEnvType, .privateFields, .privateMethods)
		}
		._initFields(.r.toObject())
		.stack[.sp-1] = 

		.pc++
		return
	}
	panic(.r.NewTypeError("Compiler bug: unexpected target for initStaticElements: %v", ))
}

type definePrivateMethod struct {
	idx          int
	targetOffset int
}

func ( *definePrivateMethod) ( *vm) []Value {
	 := .r.toObject(.stack[.sp-.targetOffset])
	if ,  := .self.(*classFuncObject);  {
		return .privateMethods
	} else {
		panic(.r.NewTypeError("Compiler bug: wrong target type for definePrivateMethod: %T", .self))
	}
}

func ( *definePrivateMethod) ( *vm) {
	 := .getPrivateMethods()
	[.idx] = .stack[.sp-1]
	.sp--
	.pc++
}

type definePrivateGetter struct {
	definePrivateMethod
}

func ( *definePrivateGetter) ( *vm) {
	 := .getPrivateMethods()
	 := .stack[.sp-1]
	 := .r.toObject()
	,  := [.idx].(*valueProperty)
	if  == nil {
		 = &valueProperty{
			accessor: true,
		}
		[.idx] = 
	}
	if .getterFunc != nil {
		.throw(.r.NewTypeError("Private getter has already been declared"))
		return
	}
	.getterFunc = 
	.sp--
	.pc++
}

type definePrivateSetter struct {
	definePrivateMethod
}

func ( *definePrivateSetter) ( *vm) {
	 := .getPrivateMethods()
	 := .stack[.sp-1]
	 := .r.toObject()
	,  := [.idx].(*valueProperty)
	if  == nil {
		 = &valueProperty{
			accessor: true,
		}
		[.idx] = 
	}
	if .setterFunc != nil {
		.throw(.r.NewTypeError("Private setter has already been declared"))
		return
	}
	.setterFunc = 
	.sp--
	.pc++
}

type definePrivateProp struct {
	idx int
}

func ( *definePrivateProp) ( *vm) {
	 := .r.toObject(.stack[.sb-1]).self.(*classFuncObject)
	 := .r.toObject(.stack[.sp-2])
	 := .self.getPrivateEnv(.privateEnvType, false)
	.fields[.idx] = .stack[.sp-1]
	.sp--
	.pc++
}

type getPrivatePropRes resolvedPrivateName

func ( *vm) ( uint8,  bool) *privateEnvType {
	 := .privEnv
	for  := uint8(0);  < ; ++ {
		 = .outer
	}
	if  {
		return .staticType
	}
	return .instanceType
}

func ( *getPrivatePropRes) ( Value,  *vm) Value {
	return .getPrivateProp(, .name, .getPrivateType(.level, .isStatic), .idx, .isMethod)
}

func ( *getPrivatePropRes) ( *vm) {
	.stack[.sp-1] = ._get(.stack[.sp-1], )
	.pc++
}

type getPrivatePropId privateId

func ( *getPrivatePropId) ( *vm) {
	.stack[.sp-1] = .getPrivateProp(.stack[.sp-1], .name, .typ, .idx, .isMethod)
	.pc++
}

type getPrivatePropIdCallee privateId

func ( *getPrivatePropIdCallee) ( *vm) {
	 := .getPrivateProp(.stack[.sp-1], .name, .typ, .idx, .isMethod)
	if  == nil {
		 = memberUnresolved{valueUnresolved{r: .r, ref: (*privateId)().string()}}
	}
	.push()

	.pc++
}

func ( *vm) ( Value,  unistring.String,  *privateEnvType,  uint32,  bool) Value {
	 := .r.toObject()
	 := .self.getPrivateEnv(, false)
	var  Value
	if  != nil {
		if  {
			 = .methods[]
		} else {
			 = .fields[]
			if  == nil {
				panic(.r.NewTypeError("Private member #%s is accessed before it is initialized", ))
			}
		}
	} else {
		panic(.r.NewTypeError("Cannot read private member #%s from an object whose class did not declare it", ))
	}
	if ,  := .(*valueProperty);  {
		if .getterFunc == nil {
			panic(.r.NewTypeError("'#%s' was defined without a getter", ))
		}
		 = .get()
	}
	return 
}

type getPrivatePropResCallee getPrivatePropRes

func ( *getPrivatePropResCallee) ( *vm) {
	 := (*getPrivatePropRes)()._get(.stack[.sp-1], )
	if  == nil {
		 = memberUnresolved{valueUnresolved{r: .r, ref: (*resolvedPrivateName)().string()}}
	}
	.push()

	.pc++
}

func ( *vm) ( Value,  unistring.String,  *privateEnvType,  uint32,  bool,  Value) {
	 := .r.toObject()
	 := .self.getPrivateEnv(, false)
	if  != nil {
		if  {
			 := .methods[]
			if ,  := .(*valueProperty);  {
				if .setterFunc != nil {
					.set(, )
				} else {
					panic(.r.NewTypeError("Cannot assign to read only property '#%s'", ))
				}
			} else {
				panic(.r.NewTypeError("Private method '#%s' is not writable", ))
			}
		} else {
			 := &.fields[]
			if * == nil {
				panic(.r.NewTypeError("Private member #%s is accessed before it is initialized", ))
			}
			* = 
		}
	} else {
		panic(.r.NewTypeError("Cannot write private member #%s from an object whose class did not declare it", ))
	}
}

func ( *vm) ( interface{}) *Exception {
	var  *Exception
	switch x1 := .(type) {
	case *Object:
		 = &Exception{
			val: ,
		}
		if ,  := .self.(*errorObject);  {
			.stack = .stack
		}
	case Value:
		 = &Exception{
			val: ,
		}
	case *Exception:
		 = 
	case typeError:
		 = &Exception{
			val: .r.NewTypeError(string()),
		}
	case referenceError:
		 = &Exception{
			val: .r.newError(.r.getReferenceError(), string()),
		}
	case rangeError:
		 = &Exception{
			val: .r.newError(.r.getRangeError(), string()),
		}
	case syntaxError:
		 = &Exception{
			val: .r.newError(.r.getSyntaxError(), string()),
		}
	default:
		/*
			if vm.prg != nil {
				vm.prg.dumpCode(log.Printf)
			}
			log.Print("Stack: ", string(debug.Stack()))
			panic(fmt.Errorf("Panic at %d: %v", vm.pc, x))
		*/
		return nil
	}
	if .stack == nil {
		.stack = .captureStack(make([]StackFrame, 0, len(.callStack)+1), 0)
	}
	return 
}

type setPrivatePropRes resolvedPrivateName

func ( *setPrivatePropRes) ( Value,  Value,  *vm) {
	.setPrivateProp(, .name, .getPrivateType(.level, .isStatic), .idx, .isMethod, )
}

func ( *setPrivatePropRes) ( *vm) {
	 := .stack[.sp-1]
	._set(.stack[.sp-2], , )
	.stack[.sp-2] = 
	.sp--
	.pc++
}

type setPrivatePropResP setPrivatePropRes

func ( *setPrivatePropResP) ( *vm) {
	 := .stack[.sp-1]
	(*setPrivatePropRes)()._set(.stack[.sp-2], , )
	.sp -= 2
	.pc++
}

type setPrivatePropId privateId

func ( *setPrivatePropId) ( *vm) {
	 := .stack[.sp-1]
	.setPrivateProp(.stack[.sp-2], .name, .typ, .idx, .isMethod, )
	.stack[.sp-2] = 
	.sp--
	.pc++
}

type setPrivatePropIdP privateId

func ( *setPrivatePropIdP) ( *vm) {
	 := .stack[.sp-1]
	.setPrivateProp(.stack[.sp-2], .name, .typ, .idx, .isMethod, )
	.sp -= 2
	.pc++
}

type popPrivateEnv struct{}

func (popPrivateEnv) ( *vm) {
	.privEnv = .privEnv.outer
	.pc++
}

type privateInRes resolvedPrivateName

func ( *privateInRes) ( *vm) {
	 := .r.toObject(.stack[.sp-1])
	 := .self.getPrivateEnv(.getPrivateType(.level, .isStatic), false)
	if  != nil && (.isMethod && .methods[.idx] != nil || !.isMethod && .fields[.idx] != nil) {
		.stack[.sp-1] = valueTrue
	} else {
		.stack[.sp-1] = valueFalse
	}
	.pc++
}

type privateInId privateId

func ( *privateInId) ( *vm) {
	 := .r.toObject(.stack[.sp-1])
	 := .self.getPrivateEnv(.typ, false)
	if  != nil && (.isMethod && .methods[.idx] != nil || !.isMethod && .fields[.idx] != nil) {
		.stack[.sp-1] = valueTrue
	} else {
		.stack[.sp-1] = valueFalse
	}
	.pc++
}

type getPrivateRefRes resolvedPrivateName

func ( *getPrivateRefRes) ( *vm) {
	.refStack = append(.refStack, &privateRefRes{
		base: .stack[.sp-1].ToObject(.r),
		name: (*resolvedPrivateName)(),
	})
	.sp--
	.pc++
}

type getPrivateRefId privateId

func ( *getPrivateRefId) ( *vm) {
	.refStack = append(.refStack, &privateRefId{
		base: .stack[.sp-1].ToObject(.r),
		id:   (*privateId)(),
	})
	.sp--
	.pc++
}

func ( *yieldMarker) ( *vm) {
	.pc = -.pc // this will terminate the run loop
	.push()     // marker so the caller knows it's a yield, not a return
}

func ( *yieldMarker) () string {
	if  == yieldEmpty {
		return "empty"
	}
	switch .resultType {
	case resultYield:
		return "yield"
	case resultYieldRes:
		return "yieldRes"
	case resultYieldDelegate:
		return "yield*"
	case resultYieldDelegateRes:
		return "yield*Res"
	case resultAwait:
		return "await"
	default:
		return "unknown"
	}
}