github.com/assemblaj/gopher-lua@v0.0.0-20221116224352-d57295a0d9e8/vm.go (about)

     1  package lua
     2  
     3  ////////////////////////////////////////////////////////
     4  // This file was generated by go-inline. DO NOT EDIT. //
     5  ////////////////////////////////////////////////////////
     6  
     7  import (
     8  	"fmt"
     9  	"math"
    10  	"strings"
    11  )
    12  
    13  func mainLoop(L *LState, baseframe *callFrame) {
    14  	var inst uint32
    15  	var cf *callFrame
    16  
    17  	if L.stack.IsEmpty() {
    18  		return
    19  	}
    20  
    21  	L.currentFrame = L.stack.Last()
    22  	if L.currentFrame.Fn.IsG {
    23  		callGFunction(L, false)
    24  		return
    25  	}
    26  
    27  	for {
    28  		cf = L.currentFrame
    29  		inst = cf.Fn.Proto.Code[cf.Pc]
    30  		cf.Pc++
    31  		if jumpTable[int(inst>>26)](L, inst, baseframe) == 1 {
    32  			return
    33  		}
    34  	}
    35  }
    36  
    37  func mainLoopWithContext(L *LState, baseframe *callFrame) {
    38  	var inst uint32
    39  	var cf *callFrame
    40  
    41  	if L.stack.IsEmpty() {
    42  		return
    43  	}
    44  
    45  	L.currentFrame = L.stack.Last()
    46  	if L.currentFrame.Fn.IsG {
    47  		callGFunction(L, false)
    48  		return
    49  	}
    50  
    51  	for {
    52  		cf = L.currentFrame
    53  		inst = cf.Fn.Proto.Code[cf.Pc]
    54  		cf.Pc++
    55  		select {
    56  		case <-L.ctx.Done():
    57  			L.RaiseError(L.ctx.Err().Error())
    58  			return
    59  		default:
    60  			if jumpTable[int(inst>>26)](L, inst, baseframe) == 1 {
    61  				return
    62  			}
    63  		}
    64  	}
    65  }
    66  
    67  // regv is the first target register to copy the return values to.
    68  // It can be reg.top, indicating that the copied values are going into new registers, or it can be below reg.top
    69  // Indicating that the values should be within the existing registers.
    70  // b is the available number of return values + 1.
    71  // n is the desired number of return values.
    72  // If n more than the available return values then the extra values are set to nil.
    73  // When this function returns the top of the registry will be set to regv+n.
    74  func copyReturnValues(L *LState, regv, start, n, b int) { // +inline-start
    75  	if b == 1 {
    76  		// this section is inlined by go-inline
    77  		// source function is 'func (rg *registry) FillNil(regm, n int) ' in '_state.go'
    78  		{
    79  			rg := L.reg
    80  			regm := regv
    81  			newSize := regm + n
    82  			// this section is inlined by go-inline
    83  			// source function is 'func (rg *registry) checkSize(requiredSize int) ' in '_state.go'
    84  			{
    85  				requiredSize := newSize
    86  				if requiredSize > cap(rg.array) {
    87  					rg.resize(requiredSize)
    88  				}
    89  			}
    90  			for i := 0; i < n; i++ {
    91  				rg.array[regm+i] = LNil
    92  			}
    93  			// values beyond top don't need to be valid LValues, so setting them to nil is fine
    94  			// setting them to nil rather than LNil lets us invoke the golang memclr opto
    95  			oldtop := rg.top
    96  			rg.top = regm + n
    97  			if rg.top < oldtop {
    98  				nilRange := rg.array[rg.top:oldtop]
    99  				for i := range nilRange {
   100  					nilRange[i] = nil
   101  				}
   102  			}
   103  		}
   104  	} else {
   105  		// this section is inlined by go-inline
   106  		// source function is 'func (rg *registry) CopyRange(regv, start, limit, n int) ' in '_state.go'
   107  		{
   108  			rg := L.reg
   109  			limit := -1
   110  			newSize := regv + n
   111  			// this section is inlined by go-inline
   112  			// source function is 'func (rg *registry) checkSize(requiredSize int) ' in '_state.go'
   113  			{
   114  				requiredSize := newSize
   115  				if requiredSize > cap(rg.array) {
   116  					rg.resize(requiredSize)
   117  				}
   118  			}
   119  			if limit == -1 || limit > rg.top {
   120  				limit = rg.top
   121  			}
   122  			for i := 0; i < n; i++ {
   123  				srcIdx := start + i
   124  				if srcIdx >= limit || srcIdx < 0 {
   125  					rg.array[regv+i] = LNil
   126  				} else {
   127  					rg.array[regv+i] = rg.array[srcIdx]
   128  				}
   129  			}
   130  
   131  			// values beyond top don't need to be valid LValues, so setting them to nil is fine
   132  			// setting them to nil rather than LNil lets us invoke the golang memclr opto
   133  			oldtop := rg.top
   134  			rg.top = regv + n
   135  			if rg.top < oldtop {
   136  				nilRange := rg.array[rg.top:oldtop]
   137  				for i := range nilRange {
   138  					nilRange[i] = nil
   139  				}
   140  			}
   141  		}
   142  		if b > 1 && n > (b-1) {
   143  			// this section is inlined by go-inline
   144  			// source function is 'func (rg *registry) FillNil(regm, n int) ' in '_state.go'
   145  			{
   146  				rg := L.reg
   147  				regm := regv + b - 1
   148  				n := n - (b - 1)
   149  				newSize := regm + n
   150  				// this section is inlined by go-inline
   151  				// source function is 'func (rg *registry) checkSize(requiredSize int) ' in '_state.go'
   152  				{
   153  					requiredSize := newSize
   154  					if requiredSize > cap(rg.array) {
   155  						rg.resize(requiredSize)
   156  					}
   157  				}
   158  				for i := 0; i < n; i++ {
   159  					rg.array[regm+i] = LNil
   160  				}
   161  				// values beyond top don't need to be valid LValues, so setting them to nil is fine
   162  				// setting them to nil rather than LNil lets us invoke the golang memclr opto
   163  				oldtop := rg.top
   164  				rg.top = regm + n
   165  				if rg.top < oldtop {
   166  					nilRange := rg.array[rg.top:oldtop]
   167  					for i := range nilRange {
   168  						nilRange[i] = nil
   169  					}
   170  				}
   171  			}
   172  		}
   173  	}
   174  } // +inline-end
   175  
   176  func switchToParentThread(L *LState, nargs int, haserror bool, kill bool) {
   177  	parent := L.Parent
   178  	if parent == nil {
   179  		L.RaiseError("can not yield from outside of a coroutine")
   180  	}
   181  	L.G.CurrentThread = parent
   182  	L.Parent = nil
   183  	if !L.wrapped {
   184  		if haserror {
   185  			parent.Push(LFalse)
   186  		} else {
   187  			parent.Push(LTrue)
   188  		}
   189  	}
   190  	L.XMoveTo(parent, nargs)
   191  	L.stack.Pop()
   192  	offset := L.currentFrame.LocalBase - L.currentFrame.ReturnBase
   193  	L.currentFrame = L.stack.Last()
   194  	L.reg.SetTop(L.reg.Top() - offset) // remove 'yield' function(including tailcalled functions)
   195  	if kill {
   196  		L.kill()
   197  	}
   198  }
   199  
   200  func callGFunction(L *LState, tailcall bool) bool {
   201  	frame := L.currentFrame
   202  	gfnret := frame.Fn.GFunction(L)
   203  	if tailcall {
   204  		L.currentFrame = L.RemoveCallerFrame()
   205  	}
   206  
   207  	if gfnret < 0 {
   208  		switchToParentThread(L, L.GetTop(), false, false)
   209  		return true
   210  	}
   211  
   212  	wantret := frame.NRet
   213  	if wantret == MultRet {
   214  		wantret = gfnret
   215  	}
   216  
   217  	if tailcall && L.Parent != nil && L.stack.Sp() == 1 {
   218  		switchToParentThread(L, wantret, false, true)
   219  		return true
   220  	}
   221  
   222  	// this section is inlined by go-inline
   223  	// source function is 'func (rg *registry) CopyRange(regv, start, limit, n int) ' in '_state.go'
   224  	{
   225  		rg := L.reg
   226  		regv := frame.ReturnBase
   227  		start := L.reg.Top() - gfnret
   228  		limit := -1
   229  		n := wantret
   230  		newSize := regv + n
   231  		// this section is inlined by go-inline
   232  		// source function is 'func (rg *registry) checkSize(requiredSize int) ' in '_state.go'
   233  		{
   234  			requiredSize := newSize
   235  			if requiredSize > cap(rg.array) {
   236  				rg.resize(requiredSize)
   237  			}
   238  		}
   239  		if limit == -1 || limit > rg.top {
   240  			limit = rg.top
   241  		}
   242  		for i := 0; i < n; i++ {
   243  			srcIdx := start + i
   244  			if srcIdx >= limit || srcIdx < 0 {
   245  				rg.array[regv+i] = LNil
   246  			} else {
   247  				rg.array[regv+i] = rg.array[srcIdx]
   248  			}
   249  		}
   250  
   251  		// values beyond top don't need to be valid LValues, so setting them to nil is fine
   252  		// setting them to nil rather than LNil lets us invoke the golang memclr opto
   253  		oldtop := rg.top
   254  		rg.top = regv + n
   255  		if rg.top < oldtop {
   256  			nilRange := rg.array[rg.top:oldtop]
   257  			for i := range nilRange {
   258  				nilRange[i] = nil
   259  			}
   260  		}
   261  	}
   262  	L.stack.Pop()
   263  	L.currentFrame = L.stack.Last()
   264  	return false
   265  }
   266  
   267  func threadRun(L *LState) {
   268  	if L.stack.IsEmpty() {
   269  		return
   270  	}
   271  
   272  	defer func() {
   273  		if rcv := recover(); rcv != nil {
   274  			var lv LValue
   275  			if v, ok := rcv.(*ApiError); ok {
   276  				lv = v.Object
   277  			} else {
   278  				lv = LString(fmt.Sprint(rcv))
   279  			}
   280  			if parent := L.Parent; parent != nil {
   281  				if L.wrapped {
   282  					L.Push(lv)
   283  					parent.Panic(L)
   284  				} else {
   285  					L.SetTop(0)
   286  					L.Push(lv)
   287  					switchToParentThread(L, 1, true, true)
   288  				}
   289  			} else {
   290  				panic(rcv)
   291  			}
   292  		}
   293  	}()
   294  	L.mainLoop(L, nil)
   295  }
   296  
   297  type instFunc func(*LState, uint32, *callFrame) int
   298  
   299  var jumpTable [opCodeMax + 1]instFunc
   300  
   301  func init() {
   302  	jumpTable = [opCodeMax + 1]instFunc{
   303  		func(L *LState, inst uint32, baseframe *callFrame) int { //OP_MOVE
   304  			reg := L.reg
   305  			cf := L.currentFrame
   306  			lbase := cf.LocalBase
   307  			A := int(inst>>18) & 0xff //GETA
   308  			RA := lbase + A
   309  			B := int(inst & 0x1ff) //GETB
   310  			reg.Set(RA, reg.Get(lbase+B))
   311  			return 0
   312  		},
   313  		func(L *LState, inst uint32, baseframe *callFrame) int { //OP_MOVEN
   314  			reg := L.reg
   315  			cf := L.currentFrame
   316  			lbase := cf.LocalBase
   317  			A := int(inst>>18) & 0xff //GETA
   318  			B := int(inst & 0x1ff)    //GETB
   319  			C := int(inst>>9) & 0x1ff //GETC
   320  			reg.Set(lbase+A, reg.Get(lbase+B))
   321  			code := cf.Fn.Proto.Code
   322  			pc := cf.Pc
   323  			for i := 0; i < C; i++ {
   324  				inst = code[pc]
   325  				pc++
   326  				A = int(inst>>18) & 0xff //GETA
   327  				B = int(inst & 0x1ff)    //GETB
   328  				reg.Set(lbase+A, reg.Get(lbase+B))
   329  			}
   330  			cf.Pc = pc
   331  			return 0
   332  		},
   333  		func(L *LState, inst uint32, baseframe *callFrame) int { //OP_LOADK
   334  			reg := L.reg
   335  			cf := L.currentFrame
   336  			lbase := cf.LocalBase
   337  			A := int(inst>>18) & 0xff //GETA
   338  			RA := lbase + A
   339  			Bx := int(inst & 0x3ffff) //GETBX
   340  			reg.Set(RA, cf.Fn.Proto.Constants[Bx])
   341  			return 0
   342  		},
   343  		func(L *LState, inst uint32, baseframe *callFrame) int { //OP_LOADBOOL
   344  			reg := L.reg
   345  			cf := L.currentFrame
   346  			lbase := cf.LocalBase
   347  			A := int(inst>>18) & 0xff //GETA
   348  			RA := lbase + A
   349  			B := int(inst & 0x1ff)    //GETB
   350  			C := int(inst>>9) & 0x1ff //GETC
   351  			if B != 0 {
   352  				reg.Set(RA, LTrue)
   353  			} else {
   354  				reg.Set(RA, LFalse)
   355  			}
   356  			if C != 0 {
   357  				cf.Pc++
   358  			}
   359  			return 0
   360  		},
   361  		func(L *LState, inst uint32, baseframe *callFrame) int { //OP_LOADNIL
   362  			reg := L.reg
   363  			cf := L.currentFrame
   364  			lbase := cf.LocalBase
   365  			A := int(inst>>18) & 0xff //GETA
   366  			RA := lbase + A
   367  			B := int(inst & 0x1ff) //GETB
   368  			for i := RA; i <= lbase+B; i++ {
   369  				reg.Set(i, LNil)
   370  			}
   371  			return 0
   372  		},
   373  		func(L *LState, inst uint32, baseframe *callFrame) int { //OP_GETUPVAL
   374  			reg := L.reg
   375  			cf := L.currentFrame
   376  			lbase := cf.LocalBase
   377  			A := int(inst>>18) & 0xff //GETA
   378  			RA := lbase + A
   379  			B := int(inst & 0x1ff) //GETB
   380  			reg.Set(RA, cf.Fn.Upvalues[B].Value())
   381  			return 0
   382  		},
   383  		func(L *LState, inst uint32, baseframe *callFrame) int { //OP_GETGLOBAL
   384  			reg := L.reg
   385  			cf := L.currentFrame
   386  			lbase := cf.LocalBase
   387  			A := int(inst>>18) & 0xff //GETA
   388  			RA := lbase + A
   389  			Bx := int(inst & 0x3ffff) //GETBX
   390  			//reg.Set(RA, L.getField(cf.Fn.Env, cf.Fn.Proto.Constants[Bx]))
   391  			reg.Set(RA, L.getFieldString(cf.Fn.Env, cf.Fn.Proto.stringConstants[Bx]))
   392  			return 0
   393  		},
   394  		func(L *LState, inst uint32, baseframe *callFrame) int { //OP_GETTABLE
   395  			reg := L.reg
   396  			cf := L.currentFrame
   397  			lbase := cf.LocalBase
   398  			A := int(inst>>18) & 0xff //GETA
   399  			RA := lbase + A
   400  			B := int(inst & 0x1ff)    //GETB
   401  			C := int(inst>>9) & 0x1ff //GETC
   402  			reg.Set(RA, L.getField(reg.Get(lbase+B), L.rkValue(C)))
   403  			return 0
   404  		},
   405  		func(L *LState, inst uint32, baseframe *callFrame) int { //OP_GETTABLEKS
   406  			reg := L.reg
   407  			cf := L.currentFrame
   408  			lbase := cf.LocalBase
   409  			A := int(inst>>18) & 0xff //GETA
   410  			RA := lbase + A
   411  			B := int(inst & 0x1ff)    //GETB
   412  			C := int(inst>>9) & 0x1ff //GETC
   413  			reg.Set(RA, L.getFieldString(reg.Get(lbase+B), L.rkString(C)))
   414  			return 0
   415  		},
   416  		func(L *LState, inst uint32, baseframe *callFrame) int { //OP_SETGLOBAL
   417  			reg := L.reg
   418  			cf := L.currentFrame
   419  			lbase := cf.LocalBase
   420  			A := int(inst>>18) & 0xff //GETA
   421  			RA := lbase + A
   422  			Bx := int(inst & 0x3ffff) //GETBX
   423  			//L.setField(cf.Fn.Env, cf.Fn.Proto.Constants[Bx], reg.Get(RA))
   424  			L.setFieldString(cf.Fn.Env, cf.Fn.Proto.stringConstants[Bx], reg.Get(RA))
   425  			return 0
   426  		},
   427  		func(L *LState, inst uint32, baseframe *callFrame) int { //OP_SETUPVAL
   428  			reg := L.reg
   429  			cf := L.currentFrame
   430  			lbase := cf.LocalBase
   431  			A := int(inst>>18) & 0xff //GETA
   432  			RA := lbase + A
   433  			B := int(inst & 0x1ff) //GETB
   434  			cf.Fn.Upvalues[B].SetValue(reg.Get(RA))
   435  			return 0
   436  		},
   437  		func(L *LState, inst uint32, baseframe *callFrame) int { //OP_SETTABLE
   438  			reg := L.reg
   439  			cf := L.currentFrame
   440  			lbase := cf.LocalBase
   441  			A := int(inst>>18) & 0xff //GETA
   442  			RA := lbase + A
   443  			B := int(inst & 0x1ff)    //GETB
   444  			C := int(inst>>9) & 0x1ff //GETC
   445  			L.setField(reg.Get(RA), L.rkValue(B), L.rkValue(C))
   446  			return 0
   447  		},
   448  		func(L *LState, inst uint32, baseframe *callFrame) int { //OP_SETTABLEKS
   449  			reg := L.reg
   450  			cf := L.currentFrame
   451  			lbase := cf.LocalBase
   452  			A := int(inst>>18) & 0xff //GETA
   453  			RA := lbase + A
   454  			B := int(inst & 0x1ff)    //GETB
   455  			C := int(inst>>9) & 0x1ff //GETC
   456  			L.setFieldString(reg.Get(RA), L.rkString(B), L.rkValue(C))
   457  			return 0
   458  		},
   459  		func(L *LState, inst uint32, baseframe *callFrame) int { //OP_NEWTABLE
   460  			reg := L.reg
   461  			cf := L.currentFrame
   462  			lbase := cf.LocalBase
   463  			A := int(inst>>18) & 0xff //GETA
   464  			RA := lbase + A
   465  			B := int(inst & 0x1ff)    //GETB
   466  			C := int(inst>>9) & 0x1ff //GETC
   467  			reg.Set(RA, newLTable(B, C))
   468  			return 0
   469  		},
   470  		func(L *LState, inst uint32, baseframe *callFrame) int { //OP_SELF
   471  			reg := L.reg
   472  			cf := L.currentFrame
   473  			lbase := cf.LocalBase
   474  			A := int(inst>>18) & 0xff //GETA
   475  			RA := lbase + A
   476  			B := int(inst & 0x1ff)    //GETB
   477  			C := int(inst>>9) & 0x1ff //GETC
   478  			selfobj := reg.Get(lbase + B)
   479  			reg.Set(RA, L.getFieldString(selfobj, L.rkString(C)))
   480  			reg.Set(RA+1, selfobj)
   481  			return 0
   482  		},
   483  		opArith, // OP_ADD
   484  		opArith, // OP_SUB
   485  		opArith, // OP_MUL
   486  		opArith, // OP_DIV
   487  		opArith, // OP_MOD
   488  		opArith, // OP_POW
   489  		func(L *LState, inst uint32, baseframe *callFrame) int { //OP_UNM
   490  			reg := L.reg
   491  			cf := L.currentFrame
   492  			lbase := cf.LocalBase
   493  			A := int(inst>>18) & 0xff //GETA
   494  			RA := lbase + A
   495  			B := int(inst & 0x1ff) //GETB
   496  			unaryv := L.rkValue(B)
   497  			if nm, ok := unaryv.(LNumber); ok {
   498  				reg.SetNumber(RA, -nm)
   499  			} else {
   500  				op := L.metaOp1(unaryv, "__unm")
   501  				if op.Type() == LTFunction {
   502  					reg.Push(op)
   503  					reg.Push(unaryv)
   504  					L.Call(1, 1)
   505  					reg.Set(RA, reg.Pop())
   506  				} else if str, ok1 := unaryv.(LString); ok1 {
   507  					if num, err := parseNumber(string(str)); err == nil {
   508  						reg.Set(RA, -num)
   509  					} else {
   510  						L.RaiseError("__unm undefined")
   511  					}
   512  				} else {
   513  					L.RaiseError("__unm undefined")
   514  				}
   515  			}
   516  			return 0
   517  		},
   518  		func(L *LState, inst uint32, baseframe *callFrame) int { //OP_NOT
   519  			reg := L.reg
   520  			cf := L.currentFrame
   521  			lbase := cf.LocalBase
   522  			A := int(inst>>18) & 0xff //GETA
   523  			RA := lbase + A
   524  			B := int(inst & 0x1ff) //GETB
   525  			if LVIsFalse(reg.Get(lbase + B)) {
   526  				reg.Set(RA, LTrue)
   527  			} else {
   528  				reg.Set(RA, LFalse)
   529  			}
   530  			return 0
   531  		},
   532  		func(L *LState, inst uint32, baseframe *callFrame) int { //OP_LEN
   533  			reg := L.reg
   534  			cf := L.currentFrame
   535  			lbase := cf.LocalBase
   536  			A := int(inst>>18) & 0xff //GETA
   537  			RA := lbase + A
   538  			B := int(inst & 0x1ff) //GETB
   539  			switch lv := L.rkValue(B).(type) {
   540  			case LString:
   541  				reg.SetNumber(RA, LNumber(len(lv)))
   542  			default:
   543  				op := L.metaOp1(lv, "__len")
   544  				if op.Type() == LTFunction {
   545  					reg.Push(op)
   546  					reg.Push(lv)
   547  					L.Call(1, 1)
   548  					ret := reg.Pop()
   549  					if ret.Type() == LTNumber {
   550  						reg.SetNumber(RA, ret.(LNumber))
   551  					} else {
   552  						reg.Set(RA, ret)
   553  					}
   554  				} else if lv.Type() == LTTable {
   555  					reg.SetNumber(RA, LNumber(lv.(*LTable).Len()))
   556  				} else {
   557  					L.RaiseError("__len undefined")
   558  				}
   559  			}
   560  			return 0
   561  		},
   562  		func(L *LState, inst uint32, baseframe *callFrame) int { //OP_CONCAT
   563  			reg := L.reg
   564  			cf := L.currentFrame
   565  			lbase := cf.LocalBase
   566  			A := int(inst>>18) & 0xff //GETA
   567  			RA := lbase + A
   568  			B := int(inst & 0x1ff)    //GETB
   569  			C := int(inst>>9) & 0x1ff //GETC
   570  			RC := lbase + C
   571  			RB := lbase + B
   572  			reg.Set(RA, stringConcat(L, RC-RB+1, RC))
   573  			return 0
   574  		},
   575  		func(L *LState, inst uint32, baseframe *callFrame) int { //OP_JMP
   576  			cf := L.currentFrame
   577  			Sbx := int(inst&0x3ffff) - opMaxArgSbx //GETSBX
   578  			cf.Pc += Sbx
   579  			return 0
   580  		},
   581  		func(L *LState, inst uint32, baseframe *callFrame) int { //OP_EQ
   582  			cf := L.currentFrame
   583  			A := int(inst>>18) & 0xff //GETA
   584  			B := int(inst & 0x1ff)    //GETB
   585  			C := int(inst>>9) & 0x1ff //GETC
   586  			ret := equals(L, L.rkValue(B), L.rkValue(C), false)
   587  			v := 1
   588  			if ret {
   589  				v = 0
   590  			}
   591  			if v == A {
   592  				cf.Pc++
   593  			}
   594  			return 0
   595  		},
   596  		func(L *LState, inst uint32, baseframe *callFrame) int { //OP_LT
   597  			cf := L.currentFrame
   598  			A := int(inst>>18) & 0xff //GETA
   599  			B := int(inst & 0x1ff)    //GETB
   600  			C := int(inst>>9) & 0x1ff //GETC
   601  			ret := lessThan(L, L.rkValue(B), L.rkValue(C))
   602  			v := 1
   603  			if ret {
   604  				v = 0
   605  			}
   606  			if v == A {
   607  				cf.Pc++
   608  			}
   609  			return 0
   610  		},
   611  		func(L *LState, inst uint32, baseframe *callFrame) int { //OP_LE
   612  			cf := L.currentFrame
   613  			A := int(inst>>18) & 0xff //GETA
   614  			B := int(inst & 0x1ff)    //GETB
   615  			C := int(inst>>9) & 0x1ff //GETC
   616  			lhs := L.rkValue(B)
   617  			rhs := L.rkValue(C)
   618  			ret := false
   619  
   620  			if v1, ok1 := lhs.assertFloat64(); ok1 {
   621  				if v2, ok2 := rhs.assertFloat64(); ok2 {
   622  					ret = v1 <= v2
   623  				} else {
   624  					L.RaiseError("attempt to compare %v with %v", lhs.Type().String(), rhs.Type().String())
   625  				}
   626  			} else {
   627  				if lhs.Type() != rhs.Type() {
   628  					L.RaiseError("attempt to compare %v with %v", lhs.Type().String(), rhs.Type().String())
   629  				}
   630  				switch lhs.Type() {
   631  				case LTString:
   632  					ret = strCmp(string(lhs.(LString)), string(rhs.(LString))) <= 0
   633  				default:
   634  					switch objectRational(L, lhs, rhs, "__le") {
   635  					case 1:
   636  						ret = true
   637  					case 0:
   638  						ret = false
   639  					default:
   640  						ret = !objectRationalWithError(L, rhs, lhs, "__lt")
   641  					}
   642  				}
   643  			}
   644  
   645  			v := 1
   646  			if ret {
   647  				v = 0
   648  			}
   649  			if v == A {
   650  				cf.Pc++
   651  			}
   652  			return 0
   653  		},
   654  		func(L *LState, inst uint32, baseframe *callFrame) int { //OP_TEST
   655  			reg := L.reg
   656  			cf := L.currentFrame
   657  			lbase := cf.LocalBase
   658  			A := int(inst>>18) & 0xff //GETA
   659  			RA := lbase + A
   660  			C := int(inst>>9) & 0x1ff //GETC
   661  			if LVAsBool(reg.Get(RA)) == (C == 0) {
   662  				cf.Pc++
   663  			}
   664  			return 0
   665  		},
   666  		func(L *LState, inst uint32, baseframe *callFrame) int { //OP_TESTSET
   667  			reg := L.reg
   668  			cf := L.currentFrame
   669  			lbase := cf.LocalBase
   670  			A := int(inst>>18) & 0xff //GETA
   671  			RA := lbase + A
   672  			B := int(inst & 0x1ff)    //GETB
   673  			C := int(inst>>9) & 0x1ff //GETC
   674  			if value := reg.Get(lbase + B); LVAsBool(value) != (C == 0) {
   675  				reg.Set(RA, value)
   676  			} else {
   677  				cf.Pc++
   678  			}
   679  			return 0
   680  		},
   681  		func(L *LState, inst uint32, baseframe *callFrame) int { //OP_CALL
   682  			reg := L.reg
   683  			cf := L.currentFrame
   684  			lbase := cf.LocalBase
   685  			A := int(inst>>18) & 0xff //GETA
   686  			RA := lbase + A
   687  			B := int(inst & 0x1ff)    //GETB
   688  			C := int(inst>>9) & 0x1ff //GETC
   689  			nargs := B - 1
   690  			if B == 0 {
   691  				nargs = reg.Top() - (RA + 1)
   692  			}
   693  			lv := reg.Get(RA)
   694  			nret := C - 1
   695  			var callable *LFunction
   696  			var meta bool
   697  			if fn, ok := lv.assertFunction(); ok {
   698  				callable = fn
   699  				meta = false
   700  			} else {
   701  				callable, meta = L.metaCall(lv)
   702  			}
   703  			// this section is inlined by go-inline
   704  			// source function is 'func (ls *LState) pushCallFrame(cf callFrame, fn LValue, meta bool) ' in '_state.go'
   705  			{
   706  				ls := L
   707  				cf := callFrame{Fn: callable, Pc: 0, Base: RA, LocalBase: RA + 1, ReturnBase: RA, NArgs: nargs, NRet: nret, Parent: cf, TailCall: 0}
   708  				fn := lv
   709  				if meta {
   710  					cf.NArgs++
   711  					ls.reg.Insert(fn, cf.LocalBase)
   712  				}
   713  				if cf.Fn == nil {
   714  					ls.RaiseError("attempt to call a non-function object")
   715  				}
   716  				if ls.stack.IsFull() {
   717  					ls.RaiseError("stack overflow")
   718  				}
   719  				ls.stack.Push(cf)
   720  				newcf := ls.stack.Last()
   721  				// this section is inlined by go-inline
   722  				// source function is 'func (ls *LState) initCallFrame(cf *callFrame) ' in '_state.go'
   723  				{
   724  					cf := newcf
   725  					if cf.Fn.IsG {
   726  						ls.reg.SetTop(cf.LocalBase + cf.NArgs)
   727  					} else {
   728  						proto := cf.Fn.Proto
   729  						nargs := cf.NArgs
   730  						np := int(proto.NumParameters)
   731  						if nargs < np {
   732  							// default any missing arguments to nil
   733  							newSize := cf.LocalBase + np
   734  							// this section is inlined by go-inline
   735  							// source function is 'func (rg *registry) checkSize(requiredSize int) ' in '_state.go'
   736  							{
   737  								rg := ls.reg
   738  								requiredSize := newSize
   739  								if requiredSize > cap(rg.array) {
   740  									rg.resize(requiredSize)
   741  								}
   742  							}
   743  							for i := nargs; i < np; i++ {
   744  								ls.reg.array[cf.LocalBase+i] = LNil
   745  							}
   746  							nargs = np
   747  							ls.reg.top = newSize
   748  						}
   749  
   750  						if (proto.IsVarArg & VarArgIsVarArg) == 0 {
   751  							if nargs < int(proto.NumUsedRegisters) {
   752  								nargs = int(proto.NumUsedRegisters)
   753  							}
   754  							newSize := cf.LocalBase + nargs
   755  							// this section is inlined by go-inline
   756  							// source function is 'func (rg *registry) checkSize(requiredSize int) ' in '_state.go'
   757  							{
   758  								rg := ls.reg
   759  								requiredSize := newSize
   760  								if requiredSize > cap(rg.array) {
   761  									rg.resize(requiredSize)
   762  								}
   763  							}
   764  							for i := np; i < nargs; i++ {
   765  								ls.reg.array[cf.LocalBase+i] = LNil
   766  							}
   767  							ls.reg.top = cf.LocalBase + int(proto.NumUsedRegisters)
   768  						} else {
   769  							/* swap vararg positions:
   770  									   closure
   771  									   namedparam1 <- lbase
   772  									   namedparam2
   773  									   vararg1
   774  									   vararg2
   775  
   776  							           TO
   777  
   778  									   closure
   779  									   nil
   780  									   nil
   781  									   vararg1
   782  									   vararg2
   783  									   namedparam1 <- lbase
   784  									   namedparam2
   785  							*/
   786  							nvarargs := nargs - np
   787  							if nvarargs < 0 {
   788  								nvarargs = 0
   789  							}
   790  
   791  							ls.reg.SetTop(cf.LocalBase + nargs + np)
   792  							for i := 0; i < np; i++ {
   793  								//ls.reg.Set(cf.LocalBase+nargs+i, ls.reg.Get(cf.LocalBase+i))
   794  								ls.reg.array[cf.LocalBase+nargs+i] = ls.reg.array[cf.LocalBase+i]
   795  								//ls.reg.Set(cf.LocalBase+i, LNil)
   796  								ls.reg.array[cf.LocalBase+i] = LNil
   797  							}
   798  
   799  							if CompatVarArg {
   800  								ls.reg.SetTop(cf.LocalBase + nargs + np + 1)
   801  								if (proto.IsVarArg & VarArgNeedsArg) != 0 {
   802  									argtb := newLTable(nvarargs, 0)
   803  									for i := 0; i < nvarargs; i++ {
   804  										argtb.RawSetInt(i+1, ls.reg.Get(cf.LocalBase+np+i))
   805  									}
   806  									argtb.RawSetString("n", LNumber(nvarargs))
   807  									//ls.reg.Set(cf.LocalBase+nargs+np, argtb)
   808  									ls.reg.array[cf.LocalBase+nargs+np] = argtb
   809  								} else {
   810  									ls.reg.array[cf.LocalBase+nargs+np] = LNil
   811  								}
   812  							}
   813  							cf.LocalBase += nargs
   814  							maxreg := cf.LocalBase + int(proto.NumUsedRegisters)
   815  							ls.reg.SetTop(maxreg)
   816  						}
   817  					}
   818  				}
   819  				ls.currentFrame = newcf
   820  			}
   821  			if callable.IsG && callGFunction(L, false) {
   822  				return 1
   823  			}
   824  			return 0
   825  		},
   826  		func(L *LState, inst uint32, baseframe *callFrame) int { //OP_TAILCALL
   827  			reg := L.reg
   828  			cf := L.currentFrame
   829  			lbase := cf.LocalBase
   830  			A := int(inst>>18) & 0xff //GETA
   831  			RA := lbase + A
   832  			B := int(inst & 0x1ff) //GETB
   833  			nargs := B - 1
   834  			if B == 0 {
   835  				nargs = reg.Top() - (RA + 1)
   836  			}
   837  			lv := reg.Get(RA)
   838  			var callable *LFunction
   839  			var meta bool
   840  			if fn, ok := lv.assertFunction(); ok {
   841  				callable = fn
   842  				meta = false
   843  			} else {
   844  				callable, meta = L.metaCall(lv)
   845  			}
   846  			if callable == nil {
   847  				L.RaiseError("attempt to call a non-function object")
   848  			}
   849  			// this section is inlined by go-inline
   850  			// source function is 'func (ls *LState) closeUpvalues(idx int) ' in '_state.go'
   851  			{
   852  				ls := L
   853  				idx := lbase
   854  				if ls.uvcache != nil {
   855  					var prev *Upvalue
   856  					for uv := ls.uvcache; uv != nil; uv = uv.next {
   857  						if uv.index >= idx {
   858  							if prev != nil {
   859  								prev.next = nil
   860  							} else {
   861  								ls.uvcache = nil
   862  							}
   863  							uv.Close()
   864  						}
   865  						prev = uv
   866  					}
   867  				}
   868  			}
   869  			if callable.IsG {
   870  				luaframe := cf
   871  				L.pushCallFrame(callFrame{
   872  					Fn:         callable,
   873  					Pc:         0,
   874  					Base:       RA,
   875  					LocalBase:  RA + 1,
   876  					ReturnBase: cf.ReturnBase,
   877  					NArgs:      nargs,
   878  					NRet:       cf.NRet,
   879  					Parent:     cf,
   880  					TailCall:   0,
   881  				}, lv, meta)
   882  				if callGFunction(L, true) {
   883  					return 1
   884  				}
   885  				if L.currentFrame == nil || L.currentFrame.Fn.IsG || luaframe == baseframe {
   886  					return 1
   887  				}
   888  			} else {
   889  				base := cf.Base
   890  				cf.Fn = callable
   891  				cf.Pc = 0
   892  				cf.Base = RA
   893  				cf.LocalBase = RA + 1
   894  				cf.ReturnBase = cf.ReturnBase
   895  				cf.NArgs = nargs
   896  				cf.NRet = cf.NRet
   897  				cf.TailCall++
   898  				lbase := cf.LocalBase
   899  				if meta {
   900  					cf.NArgs++
   901  					L.reg.Insert(lv, cf.LocalBase)
   902  				}
   903  				// this section is inlined by go-inline
   904  				// source function is 'func (ls *LState) initCallFrame(cf *callFrame) ' in '_state.go'
   905  				{
   906  					ls := L
   907  					if cf.Fn.IsG {
   908  						ls.reg.SetTop(cf.LocalBase + cf.NArgs)
   909  					} else {
   910  						proto := cf.Fn.Proto
   911  						nargs := cf.NArgs
   912  						np := int(proto.NumParameters)
   913  						if nargs < np {
   914  							// default any missing arguments to nil
   915  							newSize := cf.LocalBase + np
   916  							// this section is inlined by go-inline
   917  							// source function is 'func (rg *registry) checkSize(requiredSize int) ' in '_state.go'
   918  							{
   919  								rg := ls.reg
   920  								requiredSize := newSize
   921  								if requiredSize > cap(rg.array) {
   922  									rg.resize(requiredSize)
   923  								}
   924  							}
   925  							for i := nargs; i < np; i++ {
   926  								ls.reg.array[cf.LocalBase+i] = LNil
   927  							}
   928  							nargs = np
   929  							ls.reg.top = newSize
   930  						}
   931  
   932  						if (proto.IsVarArg & VarArgIsVarArg) == 0 {
   933  							if nargs < int(proto.NumUsedRegisters) {
   934  								nargs = int(proto.NumUsedRegisters)
   935  							}
   936  							newSize := cf.LocalBase + nargs
   937  							// this section is inlined by go-inline
   938  							// source function is 'func (rg *registry) checkSize(requiredSize int) ' in '_state.go'
   939  							{
   940  								rg := ls.reg
   941  								requiredSize := newSize
   942  								if requiredSize > cap(rg.array) {
   943  									rg.resize(requiredSize)
   944  								}
   945  							}
   946  							for i := np; i < nargs; i++ {
   947  								ls.reg.array[cf.LocalBase+i] = LNil
   948  							}
   949  							ls.reg.top = cf.LocalBase + int(proto.NumUsedRegisters)
   950  						} else {
   951  							/* swap vararg positions:
   952  									   closure
   953  									   namedparam1 <- lbase
   954  									   namedparam2
   955  									   vararg1
   956  									   vararg2
   957  
   958  							           TO
   959  
   960  									   closure
   961  									   nil
   962  									   nil
   963  									   vararg1
   964  									   vararg2
   965  									   namedparam1 <- lbase
   966  									   namedparam2
   967  							*/
   968  							nvarargs := nargs - np
   969  							if nvarargs < 0 {
   970  								nvarargs = 0
   971  							}
   972  
   973  							ls.reg.SetTop(cf.LocalBase + nargs + np)
   974  							for i := 0; i < np; i++ {
   975  								//ls.reg.Set(cf.LocalBase+nargs+i, ls.reg.Get(cf.LocalBase+i))
   976  								ls.reg.array[cf.LocalBase+nargs+i] = ls.reg.array[cf.LocalBase+i]
   977  								//ls.reg.Set(cf.LocalBase+i, LNil)
   978  								ls.reg.array[cf.LocalBase+i] = LNil
   979  							}
   980  
   981  							if CompatVarArg {
   982  								ls.reg.SetTop(cf.LocalBase + nargs + np + 1)
   983  								if (proto.IsVarArg & VarArgNeedsArg) != 0 {
   984  									argtb := newLTable(nvarargs, 0)
   985  									for i := 0; i < nvarargs; i++ {
   986  										argtb.RawSetInt(i+1, ls.reg.Get(cf.LocalBase+np+i))
   987  									}
   988  									argtb.RawSetString("n", LNumber(nvarargs))
   989  									//ls.reg.Set(cf.LocalBase+nargs+np, argtb)
   990  									ls.reg.array[cf.LocalBase+nargs+np] = argtb
   991  								} else {
   992  									ls.reg.array[cf.LocalBase+nargs+np] = LNil
   993  								}
   994  							}
   995  							cf.LocalBase += nargs
   996  							maxreg := cf.LocalBase + int(proto.NumUsedRegisters)
   997  							ls.reg.SetTop(maxreg)
   998  						}
   999  					}
  1000  				}
  1001  				// this section is inlined by go-inline
  1002  				// source function is 'func (rg *registry) CopyRange(regv, start, limit, n int) ' in '_state.go'
  1003  				{
  1004  					rg := L.reg
  1005  					regv := base
  1006  					start := RA
  1007  					limit := -1
  1008  					n := reg.Top() - RA - 1
  1009  					newSize := regv + n
  1010  					// this section is inlined by go-inline
  1011  					// source function is 'func (rg *registry) checkSize(requiredSize int) ' in '_state.go'
  1012  					{
  1013  						requiredSize := newSize
  1014  						if requiredSize > cap(rg.array) {
  1015  							rg.resize(requiredSize)
  1016  						}
  1017  					}
  1018  					if limit == -1 || limit > rg.top {
  1019  						limit = rg.top
  1020  					}
  1021  					for i := 0; i < n; i++ {
  1022  						srcIdx := start + i
  1023  						if srcIdx >= limit || srcIdx < 0 {
  1024  							rg.array[regv+i] = LNil
  1025  						} else {
  1026  							rg.array[regv+i] = rg.array[srcIdx]
  1027  						}
  1028  					}
  1029  
  1030  					// values beyond top don't need to be valid LValues, so setting them to nil is fine
  1031  					// setting them to nil rather than LNil lets us invoke the golang memclr opto
  1032  					oldtop := rg.top
  1033  					rg.top = regv + n
  1034  					if rg.top < oldtop {
  1035  						nilRange := rg.array[rg.top:oldtop]
  1036  						for i := range nilRange {
  1037  							nilRange[i] = nil
  1038  						}
  1039  					}
  1040  				}
  1041  				cf.Base = base
  1042  				cf.LocalBase = base + (cf.LocalBase - lbase + 1)
  1043  			}
  1044  			return 0
  1045  		},
  1046  		func(L *LState, inst uint32, baseframe *callFrame) int { //OP_RETURN
  1047  			reg := L.reg
  1048  			cf := L.currentFrame
  1049  			lbase := cf.LocalBase
  1050  			A := int(inst>>18) & 0xff //GETA
  1051  			RA := lbase + A
  1052  			B := int(inst & 0x1ff) //GETB
  1053  			// this section is inlined by go-inline
  1054  			// source function is 'func (ls *LState) closeUpvalues(idx int) ' in '_state.go'
  1055  			{
  1056  				ls := L
  1057  				idx := lbase
  1058  				if ls.uvcache != nil {
  1059  					var prev *Upvalue
  1060  					for uv := ls.uvcache; uv != nil; uv = uv.next {
  1061  						if uv.index >= idx {
  1062  							if prev != nil {
  1063  								prev.next = nil
  1064  							} else {
  1065  								ls.uvcache = nil
  1066  							}
  1067  							uv.Close()
  1068  						}
  1069  						prev = uv
  1070  					}
  1071  				}
  1072  			}
  1073  			nret := B - 1
  1074  			if B == 0 {
  1075  				nret = reg.Top() - RA
  1076  			}
  1077  			n := cf.NRet
  1078  			if cf.NRet == MultRet {
  1079  				n = nret
  1080  			}
  1081  
  1082  			if L.Parent != nil && L.stack.Sp() == 1 {
  1083  				// this section is inlined by go-inline
  1084  				// source function is 'func copyReturnValues(L *LState, regv, start, n, b int) ' in '_vm.go'
  1085  				{
  1086  					regv := reg.Top()
  1087  					start := RA
  1088  					b := B
  1089  					if b == 1 {
  1090  						// this section is inlined by go-inline
  1091  						// source function is 'func (rg *registry) FillNil(regm, n int) ' in '_state.go'
  1092  						{
  1093  							rg := L.reg
  1094  							regm := regv
  1095  							newSize := regm + n
  1096  							// this section is inlined by go-inline
  1097  							// source function is 'func (rg *registry) checkSize(requiredSize int) ' in '_state.go'
  1098  							{
  1099  								requiredSize := newSize
  1100  								if requiredSize > cap(rg.array) {
  1101  									rg.resize(requiredSize)
  1102  								}
  1103  							}
  1104  							for i := 0; i < n; i++ {
  1105  								rg.array[regm+i] = LNil
  1106  							}
  1107  							// values beyond top don't need to be valid LValues, so setting them to nil is fine
  1108  							// setting them to nil rather than LNil lets us invoke the golang memclr opto
  1109  							oldtop := rg.top
  1110  							rg.top = regm + n
  1111  							if rg.top < oldtop {
  1112  								nilRange := rg.array[rg.top:oldtop]
  1113  								for i := range nilRange {
  1114  									nilRange[i] = nil
  1115  								}
  1116  							}
  1117  						}
  1118  					} else {
  1119  						// this section is inlined by go-inline
  1120  						// source function is 'func (rg *registry) CopyRange(regv, start, limit, n int) ' in '_state.go'
  1121  						{
  1122  							rg := L.reg
  1123  							limit := -1
  1124  							newSize := regv + n
  1125  							// this section is inlined by go-inline
  1126  							// source function is 'func (rg *registry) checkSize(requiredSize int) ' in '_state.go'
  1127  							{
  1128  								requiredSize := newSize
  1129  								if requiredSize > cap(rg.array) {
  1130  									rg.resize(requiredSize)
  1131  								}
  1132  							}
  1133  							if limit == -1 || limit > rg.top {
  1134  								limit = rg.top
  1135  							}
  1136  							for i := 0; i < n; i++ {
  1137  								srcIdx := start + i
  1138  								if srcIdx >= limit || srcIdx < 0 {
  1139  									rg.array[regv+i] = LNil
  1140  								} else {
  1141  									rg.array[regv+i] = rg.array[srcIdx]
  1142  								}
  1143  							}
  1144  
  1145  							// values beyond top don't need to be valid LValues, so setting them to nil is fine
  1146  							// setting them to nil rather than LNil lets us invoke the golang memclr opto
  1147  							oldtop := rg.top
  1148  							rg.top = regv + n
  1149  							if rg.top < oldtop {
  1150  								nilRange := rg.array[rg.top:oldtop]
  1151  								for i := range nilRange {
  1152  									nilRange[i] = nil
  1153  								}
  1154  							}
  1155  						}
  1156  						if b > 1 && n > (b-1) {
  1157  							// this section is inlined by go-inline
  1158  							// source function is 'func (rg *registry) FillNil(regm, n int) ' in '_state.go'
  1159  							{
  1160  								rg := L.reg
  1161  								regm := regv + b - 1
  1162  								n := n - (b - 1)
  1163  								newSize := regm + n
  1164  								// this section is inlined by go-inline
  1165  								// source function is 'func (rg *registry) checkSize(requiredSize int) ' in '_state.go'
  1166  								{
  1167  									requiredSize := newSize
  1168  									if requiredSize > cap(rg.array) {
  1169  										rg.resize(requiredSize)
  1170  									}
  1171  								}
  1172  								for i := 0; i < n; i++ {
  1173  									rg.array[regm+i] = LNil
  1174  								}
  1175  								// values beyond top don't need to be valid LValues, so setting them to nil is fine
  1176  								// setting them to nil rather than LNil lets us invoke the golang memclr opto
  1177  								oldtop := rg.top
  1178  								rg.top = regm + n
  1179  								if rg.top < oldtop {
  1180  									nilRange := rg.array[rg.top:oldtop]
  1181  									for i := range nilRange {
  1182  										nilRange[i] = nil
  1183  									}
  1184  								}
  1185  							}
  1186  						}
  1187  					}
  1188  				}
  1189  				switchToParentThread(L, n, false, true)
  1190  				return 1
  1191  			}
  1192  			islast := baseframe == L.stack.Pop() || L.stack.IsEmpty()
  1193  			// this section is inlined by go-inline
  1194  			// source function is 'func copyReturnValues(L *LState, regv, start, n, b int) ' in '_vm.go'
  1195  			{
  1196  				regv := cf.ReturnBase
  1197  				start := RA
  1198  				b := B
  1199  				if b == 1 {
  1200  					// this section is inlined by go-inline
  1201  					// source function is 'func (rg *registry) FillNil(regm, n int) ' in '_state.go'
  1202  					{
  1203  						rg := L.reg
  1204  						regm := regv
  1205  						newSize := regm + n
  1206  						// this section is inlined by go-inline
  1207  						// source function is 'func (rg *registry) checkSize(requiredSize int) ' in '_state.go'
  1208  						{
  1209  							requiredSize := newSize
  1210  							if requiredSize > cap(rg.array) {
  1211  								rg.resize(requiredSize)
  1212  							}
  1213  						}
  1214  						for i := 0; i < n; i++ {
  1215  							rg.array[regm+i] = LNil
  1216  						}
  1217  						// values beyond top don't need to be valid LValues, so setting them to nil is fine
  1218  						// setting them to nil rather than LNil lets us invoke the golang memclr opto
  1219  						oldtop := rg.top
  1220  						rg.top = regm + n
  1221  						if rg.top < oldtop {
  1222  							nilRange := rg.array[rg.top:oldtop]
  1223  							for i := range nilRange {
  1224  								nilRange[i] = nil
  1225  							}
  1226  						}
  1227  					}
  1228  				} else {
  1229  					// this section is inlined by go-inline
  1230  					// source function is 'func (rg *registry) CopyRange(regv, start, limit, n int) ' in '_state.go'
  1231  					{
  1232  						rg := L.reg
  1233  						limit := -1
  1234  						newSize := regv + n
  1235  						// this section is inlined by go-inline
  1236  						// source function is 'func (rg *registry) checkSize(requiredSize int) ' in '_state.go'
  1237  						{
  1238  							requiredSize := newSize
  1239  							if requiredSize > cap(rg.array) {
  1240  								rg.resize(requiredSize)
  1241  							}
  1242  						}
  1243  						if limit == -1 || limit > rg.top {
  1244  							limit = rg.top
  1245  						}
  1246  						for i := 0; i < n; i++ {
  1247  							srcIdx := start + i
  1248  							if srcIdx >= limit || srcIdx < 0 {
  1249  								rg.array[regv+i] = LNil
  1250  							} else {
  1251  								rg.array[regv+i] = rg.array[srcIdx]
  1252  							}
  1253  						}
  1254  
  1255  						// values beyond top don't need to be valid LValues, so setting them to nil is fine
  1256  						// setting them to nil rather than LNil lets us invoke the golang memclr opto
  1257  						oldtop := rg.top
  1258  						rg.top = regv + n
  1259  						if rg.top < oldtop {
  1260  							nilRange := rg.array[rg.top:oldtop]
  1261  							for i := range nilRange {
  1262  								nilRange[i] = nil
  1263  							}
  1264  						}
  1265  					}
  1266  					if b > 1 && n > (b-1) {
  1267  						// this section is inlined by go-inline
  1268  						// source function is 'func (rg *registry) FillNil(regm, n int) ' in '_state.go'
  1269  						{
  1270  							rg := L.reg
  1271  							regm := regv + b - 1
  1272  							n := n - (b - 1)
  1273  							newSize := regm + n
  1274  							// this section is inlined by go-inline
  1275  							// source function is 'func (rg *registry) checkSize(requiredSize int) ' in '_state.go'
  1276  							{
  1277  								requiredSize := newSize
  1278  								if requiredSize > cap(rg.array) {
  1279  									rg.resize(requiredSize)
  1280  								}
  1281  							}
  1282  							for i := 0; i < n; i++ {
  1283  								rg.array[regm+i] = LNil
  1284  							}
  1285  							// values beyond top don't need to be valid LValues, so setting them to nil is fine
  1286  							// setting them to nil rather than LNil lets us invoke the golang memclr opto
  1287  							oldtop := rg.top
  1288  							rg.top = regm + n
  1289  							if rg.top < oldtop {
  1290  								nilRange := rg.array[rg.top:oldtop]
  1291  								for i := range nilRange {
  1292  									nilRange[i] = nil
  1293  								}
  1294  							}
  1295  						}
  1296  					}
  1297  				}
  1298  			}
  1299  			L.currentFrame = L.stack.Last()
  1300  			if islast || L.currentFrame == nil || L.currentFrame.Fn.IsG {
  1301  				return 1
  1302  			}
  1303  			return 0
  1304  		},
  1305  		func(L *LState, inst uint32, baseframe *callFrame) int { //OP_FORLOOP
  1306  			reg := L.reg
  1307  			cf := L.currentFrame
  1308  			lbase := cf.LocalBase
  1309  			A := int(inst>>18) & 0xff //GETA
  1310  			RA := lbase + A
  1311  			if init, ok1 := reg.Get(RA).assertFloat64(); ok1 {
  1312  				if limit, ok2 := reg.Get(RA + 1).assertFloat64(); ok2 {
  1313  					if step, ok3 := reg.Get(RA + 2).assertFloat64(); ok3 {
  1314  						init += step
  1315  						reg.SetNumber(RA, LNumber(init))
  1316  						if (step > 0 && init <= limit) || (step <= 0 && init >= limit) {
  1317  							Sbx := int(inst&0x3ffff) - opMaxArgSbx //GETSBX
  1318  							cf.Pc += Sbx
  1319  							reg.SetNumber(RA+3, LNumber(init))
  1320  						} else {
  1321  							reg.SetTop(RA + 1)
  1322  						}
  1323  					} else {
  1324  						L.RaiseError("for statement step must be a number")
  1325  					}
  1326  				} else {
  1327  					L.RaiseError("for statement limit must be a number")
  1328  				}
  1329  			} else {
  1330  				L.RaiseError("for statement init must be a number")
  1331  			}
  1332  			return 0
  1333  		},
  1334  		func(L *LState, inst uint32, baseframe *callFrame) int { //OP_FORPREP
  1335  			reg := L.reg
  1336  			cf := L.currentFrame
  1337  			lbase := cf.LocalBase
  1338  			A := int(inst>>18) & 0xff //GETA
  1339  			RA := lbase + A
  1340  			Sbx := int(inst&0x3ffff) - opMaxArgSbx //GETSBX
  1341  			if init, ok1 := reg.Get(RA).assertFloat64(); ok1 {
  1342  				if step, ok2 := reg.Get(RA + 2).assertFloat64(); ok2 {
  1343  					reg.SetNumber(RA, LNumber(init-step))
  1344  				} else {
  1345  					L.RaiseError("for statement step must be a number")
  1346  				}
  1347  			} else {
  1348  				L.RaiseError("for statement init must be a number")
  1349  			}
  1350  			cf.Pc += Sbx
  1351  			return 0
  1352  		},
  1353  		func(L *LState, inst uint32, baseframe *callFrame) int { //OP_TFORLOOP
  1354  			reg := L.reg
  1355  			cf := L.currentFrame
  1356  			lbase := cf.LocalBase
  1357  			A := int(inst>>18) & 0xff //GETA
  1358  			RA := lbase + A
  1359  			C := int(inst>>9) & 0x1ff //GETC
  1360  			nret := C
  1361  			reg.SetTop(RA + 3 + 2)
  1362  			reg.Set(RA+3+2, reg.Get(RA+2))
  1363  			reg.Set(RA+3+1, reg.Get(RA+1))
  1364  			reg.Set(RA+3, reg.Get(RA))
  1365  			L.callR(2, nret, RA+3)
  1366  			if value := reg.Get(RA + 3); value != LNil {
  1367  				reg.Set(RA+2, value)
  1368  				pc := cf.Fn.Proto.Code[cf.Pc]
  1369  				cf.Pc += int(pc&0x3ffff) - opMaxArgSbx
  1370  			}
  1371  			cf.Pc++
  1372  			return 0
  1373  		},
  1374  		func(L *LState, inst uint32, baseframe *callFrame) int { //OP_SETLIST
  1375  			reg := L.reg
  1376  			cf := L.currentFrame
  1377  			lbase := cf.LocalBase
  1378  			A := int(inst>>18) & 0xff //GETA
  1379  			RA := lbase + A
  1380  			B := int(inst & 0x1ff)    //GETB
  1381  			C := int(inst>>9) & 0x1ff //GETC
  1382  			if C == 0 {
  1383  				C = int(cf.Fn.Proto.Code[cf.Pc])
  1384  				cf.Pc++
  1385  			}
  1386  			offset := (C - 1) * FieldsPerFlush
  1387  			table := reg.Get(RA).(*LTable)
  1388  			nelem := B
  1389  			if B == 0 {
  1390  				nelem = reg.Top() - RA - 1
  1391  			}
  1392  			for i := 1; i <= nelem; i++ {
  1393  				table.RawSetInt(offset+i, reg.Get(RA+i))
  1394  			}
  1395  			return 0
  1396  		},
  1397  		func(L *LState, inst uint32, baseframe *callFrame) int { //OP_CLOSE
  1398  			cf := L.currentFrame
  1399  			lbase := cf.LocalBase
  1400  			A := int(inst>>18) & 0xff //GETA
  1401  			RA := lbase + A
  1402  			// this section is inlined by go-inline
  1403  			// source function is 'func (ls *LState) closeUpvalues(idx int) ' in '_state.go'
  1404  			{
  1405  				ls := L
  1406  				idx := RA
  1407  				if ls.uvcache != nil {
  1408  					var prev *Upvalue
  1409  					for uv := ls.uvcache; uv != nil; uv = uv.next {
  1410  						if uv.index >= idx {
  1411  							if prev != nil {
  1412  								prev.next = nil
  1413  							} else {
  1414  								ls.uvcache = nil
  1415  							}
  1416  							uv.Close()
  1417  						}
  1418  						prev = uv
  1419  					}
  1420  				}
  1421  			}
  1422  			return 0
  1423  		},
  1424  		func(L *LState, inst uint32, baseframe *callFrame) int { //OP_CLOSURE
  1425  			reg := L.reg
  1426  			cf := L.currentFrame
  1427  			lbase := cf.LocalBase
  1428  			A := int(inst>>18) & 0xff //GETA
  1429  			RA := lbase + A
  1430  			Bx := int(inst & 0x3ffff) //GETBX
  1431  			proto := cf.Fn.Proto.FunctionPrototypes[Bx]
  1432  			closure := newLFunctionL(proto, cf.Fn.Env, int(proto.NumUpvalues))
  1433  			reg.Set(RA, closure)
  1434  			for i := 0; i < int(proto.NumUpvalues); i++ {
  1435  				inst = cf.Fn.Proto.Code[cf.Pc]
  1436  				cf.Pc++
  1437  				B := opGetArgB(inst)
  1438  				switch opGetOpCode(inst) {
  1439  				case OP_MOVE:
  1440  					closure.Upvalues[i] = L.findUpvalue(lbase + B)
  1441  				case OP_GETUPVAL:
  1442  					closure.Upvalues[i] = cf.Fn.Upvalues[B]
  1443  				}
  1444  			}
  1445  			return 0
  1446  		},
  1447  		func(L *LState, inst uint32, baseframe *callFrame) int { //OP_VARARG
  1448  			reg := L.reg
  1449  			cf := L.currentFrame
  1450  			lbase := cf.LocalBase
  1451  			A := int(inst>>18) & 0xff //GETA
  1452  			RA := lbase + A
  1453  			B := int(inst & 0x1ff) //GETB
  1454  			nparams := int(cf.Fn.Proto.NumParameters)
  1455  			nvarargs := cf.NArgs - nparams
  1456  			if nvarargs < 0 {
  1457  				nvarargs = 0
  1458  			}
  1459  			nwant := B - 1
  1460  			if B == 0 {
  1461  				nwant = nvarargs
  1462  			}
  1463  			// this section is inlined by go-inline
  1464  			// source function is 'func (rg *registry) CopyRange(regv, start, limit, n int) ' in '_state.go'
  1465  			{
  1466  				rg := reg
  1467  				regv := RA
  1468  				start := cf.Base + nparams + 1
  1469  				limit := cf.LocalBase
  1470  				n := nwant
  1471  				newSize := regv + n
  1472  				// this section is inlined by go-inline
  1473  				// source function is 'func (rg *registry) checkSize(requiredSize int) ' in '_state.go'
  1474  				{
  1475  					requiredSize := newSize
  1476  					if requiredSize > cap(rg.array) {
  1477  						rg.resize(requiredSize)
  1478  					}
  1479  				}
  1480  				if limit == -1 || limit > rg.top {
  1481  					limit = rg.top
  1482  				}
  1483  				for i := 0; i < n; i++ {
  1484  					srcIdx := start + i
  1485  					if srcIdx >= limit || srcIdx < 0 {
  1486  						rg.array[regv+i] = LNil
  1487  					} else {
  1488  						rg.array[regv+i] = rg.array[srcIdx]
  1489  					}
  1490  				}
  1491  
  1492  				// values beyond top don't need to be valid LValues, so setting them to nil is fine
  1493  				// setting them to nil rather than LNil lets us invoke the golang memclr opto
  1494  				oldtop := rg.top
  1495  				rg.top = regv + n
  1496  				if rg.top < oldtop {
  1497  					nilRange := rg.array[rg.top:oldtop]
  1498  					for i := range nilRange {
  1499  						nilRange[i] = nil
  1500  					}
  1501  				}
  1502  			}
  1503  			return 0
  1504  		},
  1505  		func(L *LState, inst uint32, baseframe *callFrame) int { //OP_NOP
  1506  			return 0
  1507  		},
  1508  	}
  1509  }
  1510  
  1511  func opArith(L *LState, inst uint32, baseframe *callFrame) int { //OP_ADD, OP_SUB, OP_MUL, OP_DIV, OP_MOD, OP_POW
  1512  	reg := L.reg
  1513  	cf := L.currentFrame
  1514  	lbase := cf.LocalBase
  1515  	A := int(inst>>18) & 0xff //GETA
  1516  	RA := lbase + A
  1517  	opcode := int(inst >> 26) //GETOPCODE
  1518  	B := int(inst & 0x1ff)    //GETB
  1519  	C := int(inst>>9) & 0x1ff //GETC
  1520  	lhs := L.rkValue(B)
  1521  	rhs := L.rkValue(C)
  1522  	v1, ok1 := lhs.assertFloat64()
  1523  	v2, ok2 := rhs.assertFloat64()
  1524  	if ok1 && ok2 {
  1525  		reg.SetNumber(RA, numberArith(L, opcode, LNumber(v1), LNumber(v2)))
  1526  	} else {
  1527  		reg.Set(RA, objectArith(L, opcode, lhs, rhs))
  1528  	}
  1529  	return 0
  1530  }
  1531  
  1532  func luaModulo(lhs, rhs LNumber) LNumber {
  1533  	flhs := float64(lhs)
  1534  	frhs := float64(rhs)
  1535  	v := math.Mod(flhs, frhs)
  1536  	if flhs < 0 || frhs < 0 && !(flhs < 0 && frhs < 0) {
  1537  		v += frhs
  1538  	}
  1539  	return LNumber(v)
  1540  }
  1541  
  1542  func numberArith(L *LState, opcode int, lhs, rhs LNumber) LNumber {
  1543  	switch opcode {
  1544  	case OP_ADD:
  1545  		return lhs + rhs
  1546  	case OP_SUB:
  1547  		return lhs - rhs
  1548  	case OP_MUL:
  1549  		return lhs * rhs
  1550  	case OP_DIV:
  1551  		return lhs / rhs
  1552  	case OP_MOD:
  1553  		return luaModulo(lhs, rhs)
  1554  	case OP_POW:
  1555  		flhs := float64(lhs)
  1556  		frhs := float64(rhs)
  1557  		return LNumber(math.Pow(flhs, frhs))
  1558  	}
  1559  	panic("should not reach here")
  1560  	return LNumber(0)
  1561  }
  1562  
  1563  func objectArith(L *LState, opcode int, lhs, rhs LValue) LValue {
  1564  	event := ""
  1565  	switch opcode {
  1566  	case OP_ADD:
  1567  		event = "__add"
  1568  	case OP_SUB:
  1569  		event = "__sub"
  1570  	case OP_MUL:
  1571  		event = "__mul"
  1572  	case OP_DIV:
  1573  		event = "__div"
  1574  	case OP_MOD:
  1575  		event = "__mod"
  1576  	case OP_POW:
  1577  		event = "__pow"
  1578  	}
  1579  	op := L.metaOp2(lhs, rhs, event)
  1580  	if op.Type() == LTFunction {
  1581  		L.reg.Push(op)
  1582  		L.reg.Push(lhs)
  1583  		L.reg.Push(rhs)
  1584  		L.Call(2, 1)
  1585  		return L.reg.Pop()
  1586  	}
  1587  	if str, ok := lhs.(LString); ok {
  1588  		if lnum, err := parseNumber(string(str)); err == nil {
  1589  			lhs = lnum
  1590  		}
  1591  	}
  1592  	if str, ok := rhs.(LString); ok {
  1593  		if rnum, err := parseNumber(string(str)); err == nil {
  1594  			rhs = rnum
  1595  		}
  1596  	}
  1597  	if v1, ok1 := lhs.assertFloat64(); ok1 {
  1598  		if v2, ok2 := rhs.assertFloat64(); ok2 {
  1599  			return numberArith(L, opcode, LNumber(v1), LNumber(v2))
  1600  		}
  1601  	}
  1602  	L.RaiseError(fmt.Sprintf("cannot perform %v operation between %v and %v",
  1603  		strings.TrimLeft(event, "_"), lhs.Type().String(), rhs.Type().String()))
  1604  
  1605  	return LNil
  1606  }
  1607  
  1608  func stringConcat(L *LState, total, last int) LValue {
  1609  	rhs := L.reg.Get(last)
  1610  	total--
  1611  	for i := last - 1; total > 0; {
  1612  		lhs := L.reg.Get(i)
  1613  		if !(LVCanConvToString(lhs) && LVCanConvToString(rhs)) {
  1614  			op := L.metaOp2(lhs, rhs, "__concat")
  1615  			if op.Type() == LTFunction {
  1616  				L.reg.Push(op)
  1617  				L.reg.Push(lhs)
  1618  				L.reg.Push(rhs)
  1619  				L.Call(2, 1)
  1620  				rhs = L.reg.Pop()
  1621  				total--
  1622  				i--
  1623  			} else {
  1624  				L.RaiseError("cannot perform concat operation between %v and %v", lhs.Type().String(), rhs.Type().String())
  1625  				return LNil
  1626  			}
  1627  		} else {
  1628  			buf := make([]string, total+1)
  1629  			buf[total] = LVAsString(rhs)
  1630  			for total > 0 {
  1631  				lhs = L.reg.Get(i)
  1632  				if !LVCanConvToString(lhs) {
  1633  					break
  1634  				}
  1635  				buf[total-1] = LVAsString(lhs)
  1636  				i--
  1637  				total--
  1638  			}
  1639  			rhs = LString(strings.Join(buf, ""))
  1640  		}
  1641  	}
  1642  	return rhs
  1643  }
  1644  
  1645  func lessThan(L *LState, lhs, rhs LValue) bool {
  1646  	// optimization for numbers
  1647  	if v1, ok1 := lhs.assertFloat64(); ok1 {
  1648  		if v2, ok2 := rhs.assertFloat64(); ok2 {
  1649  			return v1 < v2
  1650  		}
  1651  		L.RaiseError("attempt to compare %v with %v", lhs.Type().String(), rhs.Type().String())
  1652  	}
  1653  	if lhs.Type() != rhs.Type() {
  1654  		L.RaiseError("attempt to compare %v with %v", lhs.Type().String(), rhs.Type().String())
  1655  		return false
  1656  	}
  1657  	ret := false
  1658  	switch lhs.Type() {
  1659  	case LTString:
  1660  		ret = strCmp(string(lhs.(LString)), string(rhs.(LString))) < 0
  1661  	default:
  1662  		ret = objectRationalWithError(L, lhs, rhs, "__lt")
  1663  	}
  1664  	return ret
  1665  }
  1666  
  1667  func equals(L *LState, lhs, rhs LValue, raw bool) bool {
  1668  	if lhs.Type() != rhs.Type() {
  1669  		return false
  1670  	}
  1671  
  1672  	ret := false
  1673  	switch lhs.Type() {
  1674  	case LTNil:
  1675  		ret = true
  1676  	case LTNumber:
  1677  		v1, _ := lhs.assertFloat64()
  1678  		v2, _ := rhs.assertFloat64()
  1679  		ret = v1 == v2
  1680  	case LTBool:
  1681  		ret = bool(lhs.(LBool)) == bool(rhs.(LBool))
  1682  	case LTString:
  1683  		ret = string(lhs.(LString)) == string(rhs.(LString))
  1684  	case LTUserData, LTTable:
  1685  		if lhs == rhs {
  1686  			ret = true
  1687  		} else if !raw {
  1688  			switch objectRational(L, lhs, rhs, "__eq") {
  1689  			case 1:
  1690  				ret = true
  1691  			default:
  1692  				ret = false
  1693  			}
  1694  		}
  1695  	default:
  1696  		ret = lhs == rhs
  1697  	}
  1698  	return ret
  1699  }
  1700  
  1701  func objectRationalWithError(L *LState, lhs, rhs LValue, event string) bool {
  1702  	switch objectRational(L, lhs, rhs, event) {
  1703  	case 1:
  1704  		return true
  1705  	case 0:
  1706  		return false
  1707  	}
  1708  	L.RaiseError("attempt to compare %v with %v", lhs.Type().String(), rhs.Type().String())
  1709  	return false
  1710  }
  1711  
  1712  func objectRational(L *LState, lhs, rhs LValue, event string) int {
  1713  	m1 := L.metaOp1(lhs, event)
  1714  	m2 := L.metaOp1(rhs, event)
  1715  	if m1.Type() == LTFunction && m1 == m2 {
  1716  		L.reg.Push(m1)
  1717  		L.reg.Push(lhs)
  1718  		L.reg.Push(rhs)
  1719  		L.Call(2, 1)
  1720  		if LVAsBool(L.reg.Pop()) {
  1721  			return 1
  1722  		}
  1723  		return 0
  1724  	}
  1725  	return -1
  1726  }