github.com/shawnclovie/gopher-lua@v0.0.0-20200520092726-90b44ec0e2f2/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.SetNumber(RA, LNumber(0))
   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  						newSize := cf.LocalBase + np
   732  						// this section is inlined by go-inline
   733  						// source function is 'func (rg *registry) checkSize(requiredSize int) ' in '_state.go'
   734  						{
   735  							rg := ls.reg
   736  							requiredSize := newSize
   737  							if requiredSize > cap(rg.array) {
   738  								rg.resize(requiredSize)
   739  							}
   740  						}
   741  						for i := nargs; i < np; i++ {
   742  							ls.reg.array[cf.LocalBase+i] = LNil
   743  							nargs = np
   744  						}
   745  
   746  						if (proto.IsVarArg & VarArgIsVarArg) == 0 {
   747  							if nargs < int(proto.NumUsedRegisters) {
   748  								nargs = int(proto.NumUsedRegisters)
   749  							}
   750  							newSize = cf.LocalBase + nargs
   751  							// this section is inlined by go-inline
   752  							// source function is 'func (rg *registry) checkSize(requiredSize int) ' in '_state.go'
   753  							{
   754  								rg := ls.reg
   755  								requiredSize := newSize
   756  								if requiredSize > cap(rg.array) {
   757  									rg.resize(requiredSize)
   758  								}
   759  							}
   760  							for i := np; i < nargs; i++ {
   761  								ls.reg.array[cf.LocalBase+i] = LNil
   762  							}
   763  							ls.reg.top = cf.LocalBase + int(proto.NumUsedRegisters)
   764  						} else {
   765  							/* swap vararg positions:
   766  									   closure
   767  									   namedparam1 <- lbase
   768  									   namedparam2
   769  									   vararg1
   770  									   vararg2
   771  
   772  							           TO
   773  
   774  									   closure
   775  									   nil
   776  									   nil
   777  									   vararg1
   778  									   vararg2
   779  									   namedparam1 <- lbase
   780  									   namedparam2
   781  							*/
   782  							nvarargs := nargs - np
   783  							if nvarargs < 0 {
   784  								nvarargs = 0
   785  							}
   786  
   787  							ls.reg.SetTop(cf.LocalBase + nargs + np)
   788  							for i := 0; i < np; i++ {
   789  								//ls.reg.Set(cf.LocalBase+nargs+i, ls.reg.Get(cf.LocalBase+i))
   790  								ls.reg.array[cf.LocalBase+nargs+i] = ls.reg.array[cf.LocalBase+i]
   791  								//ls.reg.Set(cf.LocalBase+i, LNil)
   792  								ls.reg.array[cf.LocalBase+i] = LNil
   793  							}
   794  
   795  							if CompatVarArg {
   796  								ls.reg.SetTop(cf.LocalBase + nargs + np + 1)
   797  								if (proto.IsVarArg & VarArgNeedsArg) != 0 {
   798  									argtb := newLTable(nvarargs, 0)
   799  									for i := 0; i < nvarargs; i++ {
   800  										argtb.RawSetInt(i+1, ls.reg.Get(cf.LocalBase+np+i))
   801  									}
   802  									argtb.RawSetString("n", LNumber(nvarargs))
   803  									//ls.reg.Set(cf.LocalBase+nargs+np, argtb)
   804  									ls.reg.array[cf.LocalBase+nargs+np] = argtb
   805  								} else {
   806  									ls.reg.array[cf.LocalBase+nargs+np] = LNil
   807  								}
   808  							}
   809  							cf.LocalBase += nargs
   810  							maxreg := cf.LocalBase + int(proto.NumUsedRegisters)
   811  							ls.reg.SetTop(maxreg)
   812  						}
   813  					}
   814  				}
   815  				ls.currentFrame = newcf
   816  			}
   817  			if callable.IsG && callGFunction(L, false) {
   818  				return 1
   819  			}
   820  			return 0
   821  		},
   822  		func(L *LState, inst uint32, baseframe *callFrame) int { //OP_TAILCALL
   823  			reg := L.reg
   824  			cf := L.currentFrame
   825  			lbase := cf.LocalBase
   826  			A := int(inst>>18) & 0xff //GETA
   827  			RA := lbase + A
   828  			B := int(inst & 0x1ff) //GETB
   829  			nargs := B - 1
   830  			if B == 0 {
   831  				nargs = reg.Top() - (RA + 1)
   832  			}
   833  			lv := reg.Get(RA)
   834  			var callable *LFunction
   835  			var meta bool
   836  			if fn, ok := lv.assertFunction(); ok {
   837  				callable = fn
   838  				meta = false
   839  			} else {
   840  				callable, meta = L.metaCall(lv)
   841  			}
   842  			if callable == nil {
   843  				L.RaiseError("attempt to call a non-function object")
   844  			}
   845  			// this section is inlined by go-inline
   846  			// source function is 'func (ls *LState) closeUpvalues(idx int) ' in '_state.go'
   847  			{
   848  				ls := L
   849  				idx := lbase
   850  				if ls.uvcache != nil {
   851  					var prev *Upvalue
   852  					for uv := ls.uvcache; uv != nil; uv = uv.next {
   853  						if uv.index >= idx {
   854  							if prev != nil {
   855  								prev.next = nil
   856  							} else {
   857  								ls.uvcache = nil
   858  							}
   859  							uv.Close()
   860  						}
   861  						prev = uv
   862  					}
   863  				}
   864  			}
   865  			if callable.IsG {
   866  				luaframe := cf
   867  				L.pushCallFrame(callFrame{
   868  					Fn:         callable,
   869  					Pc:         0,
   870  					Base:       RA,
   871  					LocalBase:  RA + 1,
   872  					ReturnBase: cf.ReturnBase,
   873  					NArgs:      nargs,
   874  					NRet:       cf.NRet,
   875  					Parent:     cf,
   876  					TailCall:   0,
   877  				}, lv, meta)
   878  				if callGFunction(L, true) {
   879  					return 1
   880  				}
   881  				if L.currentFrame == nil || L.currentFrame.Fn.IsG || luaframe == baseframe {
   882  					return 1
   883  				}
   884  			} else {
   885  				base := cf.Base
   886  				cf.Fn = callable
   887  				cf.Pc = 0
   888  				cf.Base = RA
   889  				cf.LocalBase = RA + 1
   890  				cf.ReturnBase = cf.ReturnBase
   891  				cf.NArgs = nargs
   892  				cf.NRet = cf.NRet
   893  				cf.TailCall++
   894  				lbase := cf.LocalBase
   895  				if meta {
   896  					cf.NArgs++
   897  					L.reg.Insert(lv, cf.LocalBase)
   898  				}
   899  				// this section is inlined by go-inline
   900  				// source function is 'func (ls *LState) initCallFrame(cf *callFrame) ' in '_state.go'
   901  				{
   902  					ls := L
   903  					if cf.Fn.IsG {
   904  						ls.reg.SetTop(cf.LocalBase + cf.NArgs)
   905  					} else {
   906  						proto := cf.Fn.Proto
   907  						nargs := cf.NArgs
   908  						np := int(proto.NumParameters)
   909  						newSize := cf.LocalBase + np
   910  						// this section is inlined by go-inline
   911  						// source function is 'func (rg *registry) checkSize(requiredSize int) ' in '_state.go'
   912  						{
   913  							rg := ls.reg
   914  							requiredSize := newSize
   915  							if requiredSize > cap(rg.array) {
   916  								rg.resize(requiredSize)
   917  							}
   918  						}
   919  						for i := nargs; i < np; i++ {
   920  							ls.reg.array[cf.LocalBase+i] = LNil
   921  							nargs = np
   922  						}
   923  
   924  						if (proto.IsVarArg & VarArgIsVarArg) == 0 {
   925  							if nargs < int(proto.NumUsedRegisters) {
   926  								nargs = int(proto.NumUsedRegisters)
   927  							}
   928  							newSize = cf.LocalBase + nargs
   929  							// this section is inlined by go-inline
   930  							// source function is 'func (rg *registry) checkSize(requiredSize int) ' in '_state.go'
   931  							{
   932  								rg := ls.reg
   933  								requiredSize := newSize
   934  								if requiredSize > cap(rg.array) {
   935  									rg.resize(requiredSize)
   936  								}
   937  							}
   938  							for i := np; i < nargs; i++ {
   939  								ls.reg.array[cf.LocalBase+i] = LNil
   940  							}
   941  							ls.reg.top = cf.LocalBase + int(proto.NumUsedRegisters)
   942  						} else {
   943  							/* swap vararg positions:
   944  									   closure
   945  									   namedparam1 <- lbase
   946  									   namedparam2
   947  									   vararg1
   948  									   vararg2
   949  
   950  							           TO
   951  
   952  									   closure
   953  									   nil
   954  									   nil
   955  									   vararg1
   956  									   vararg2
   957  									   namedparam1 <- lbase
   958  									   namedparam2
   959  							*/
   960  							nvarargs := nargs - np
   961  							if nvarargs < 0 {
   962  								nvarargs = 0
   963  							}
   964  
   965  							ls.reg.SetTop(cf.LocalBase + nargs + np)
   966  							for i := 0; i < np; i++ {
   967  								//ls.reg.Set(cf.LocalBase+nargs+i, ls.reg.Get(cf.LocalBase+i))
   968  								ls.reg.array[cf.LocalBase+nargs+i] = ls.reg.array[cf.LocalBase+i]
   969  								//ls.reg.Set(cf.LocalBase+i, LNil)
   970  								ls.reg.array[cf.LocalBase+i] = LNil
   971  							}
   972  
   973  							if CompatVarArg {
   974  								ls.reg.SetTop(cf.LocalBase + nargs + np + 1)
   975  								if (proto.IsVarArg & VarArgNeedsArg) != 0 {
   976  									argtb := newLTable(nvarargs, 0)
   977  									for i := 0; i < nvarargs; i++ {
   978  										argtb.RawSetInt(i+1, ls.reg.Get(cf.LocalBase+np+i))
   979  									}
   980  									argtb.RawSetString("n", LNumber(nvarargs))
   981  									//ls.reg.Set(cf.LocalBase+nargs+np, argtb)
   982  									ls.reg.array[cf.LocalBase+nargs+np] = argtb
   983  								} else {
   984  									ls.reg.array[cf.LocalBase+nargs+np] = LNil
   985  								}
   986  							}
   987  							cf.LocalBase += nargs
   988  							maxreg := cf.LocalBase + int(proto.NumUsedRegisters)
   989  							ls.reg.SetTop(maxreg)
   990  						}
   991  					}
   992  				}
   993  				// this section is inlined by go-inline
   994  				// source function is 'func (rg *registry) CopyRange(regv, start, limit, n int) ' in '_state.go'
   995  				{
   996  					rg := L.reg
   997  					regv := base
   998  					start := RA
   999  					limit := -1
  1000  					n := reg.Top() - RA - 1
  1001  					newSize := regv + n
  1002  					// this section is inlined by go-inline
  1003  					// source function is 'func (rg *registry) checkSize(requiredSize int) ' in '_state.go'
  1004  					{
  1005  						requiredSize := newSize
  1006  						if requiredSize > cap(rg.array) {
  1007  							rg.resize(requiredSize)
  1008  						}
  1009  					}
  1010  					if limit == -1 || limit > rg.top {
  1011  						limit = rg.top
  1012  					}
  1013  					for i := 0; i < n; i++ {
  1014  						srcIdx := start + i
  1015  						if srcIdx >= limit || srcIdx < 0 {
  1016  							rg.array[regv+i] = LNil
  1017  						} else {
  1018  							rg.array[regv+i] = rg.array[srcIdx]
  1019  						}
  1020  					}
  1021  
  1022  					// values beyond top don't need to be valid LValues, so setting them to nil is fine
  1023  					// setting them to nil rather than LNil lets us invoke the golang memclr opto
  1024  					oldtop := rg.top
  1025  					rg.top = regv + n
  1026  					if rg.top < oldtop {
  1027  						nilRange := rg.array[rg.top:oldtop]
  1028  						for i := range nilRange {
  1029  							nilRange[i] = nil
  1030  						}
  1031  					}
  1032  				}
  1033  				cf.Base = base
  1034  				cf.LocalBase = base + (cf.LocalBase - lbase + 1)
  1035  			}
  1036  			return 0
  1037  		},
  1038  		func(L *LState, inst uint32, baseframe *callFrame) int { //OP_RETURN
  1039  			reg := L.reg
  1040  			cf := L.currentFrame
  1041  			lbase := cf.LocalBase
  1042  			A := int(inst>>18) & 0xff //GETA
  1043  			RA := lbase + A
  1044  			B := int(inst & 0x1ff) //GETB
  1045  			// this section is inlined by go-inline
  1046  			// source function is 'func (ls *LState) closeUpvalues(idx int) ' in '_state.go'
  1047  			{
  1048  				ls := L
  1049  				idx := lbase
  1050  				if ls.uvcache != nil {
  1051  					var prev *Upvalue
  1052  					for uv := ls.uvcache; uv != nil; uv = uv.next {
  1053  						if uv.index >= idx {
  1054  							if prev != nil {
  1055  								prev.next = nil
  1056  							} else {
  1057  								ls.uvcache = nil
  1058  							}
  1059  							uv.Close()
  1060  						}
  1061  						prev = uv
  1062  					}
  1063  				}
  1064  			}
  1065  			nret := B - 1
  1066  			if B == 0 {
  1067  				nret = reg.Top() - RA
  1068  			}
  1069  			n := cf.NRet
  1070  			if cf.NRet == MultRet {
  1071  				n = nret
  1072  			}
  1073  
  1074  			if L.Parent != nil && L.stack.Sp() == 1 {
  1075  				// this section is inlined by go-inline
  1076  				// source function is 'func copyReturnValues(L *LState, regv, start, n, b int) ' in '_vm.go'
  1077  				{
  1078  					regv := reg.Top()
  1079  					start := RA
  1080  					b := B
  1081  					if b == 1 {
  1082  						// this section is inlined by go-inline
  1083  						// source function is 'func (rg *registry) FillNil(regm, n int) ' in '_state.go'
  1084  						{
  1085  							rg := L.reg
  1086  							regm := regv
  1087  							newSize := regm + n
  1088  							// this section is inlined by go-inline
  1089  							// source function is 'func (rg *registry) checkSize(requiredSize int) ' in '_state.go'
  1090  							{
  1091  								requiredSize := newSize
  1092  								if requiredSize > cap(rg.array) {
  1093  									rg.resize(requiredSize)
  1094  								}
  1095  							}
  1096  							for i := 0; i < n; i++ {
  1097  								rg.array[regm+i] = LNil
  1098  							}
  1099  							// values beyond top don't need to be valid LValues, so setting them to nil is fine
  1100  							// setting them to nil rather than LNil lets us invoke the golang memclr opto
  1101  							oldtop := rg.top
  1102  							rg.top = regm + n
  1103  							if rg.top < oldtop {
  1104  								nilRange := rg.array[rg.top:oldtop]
  1105  								for i := range nilRange {
  1106  									nilRange[i] = nil
  1107  								}
  1108  							}
  1109  						}
  1110  					} else {
  1111  						// this section is inlined by go-inline
  1112  						// source function is 'func (rg *registry) CopyRange(regv, start, limit, n int) ' in '_state.go'
  1113  						{
  1114  							rg := L.reg
  1115  							limit := -1
  1116  							newSize := regv + n
  1117  							// this section is inlined by go-inline
  1118  							// source function is 'func (rg *registry) checkSize(requiredSize int) ' in '_state.go'
  1119  							{
  1120  								requiredSize := newSize
  1121  								if requiredSize > cap(rg.array) {
  1122  									rg.resize(requiredSize)
  1123  								}
  1124  							}
  1125  							if limit == -1 || limit > rg.top {
  1126  								limit = rg.top
  1127  							}
  1128  							for i := 0; i < n; i++ {
  1129  								srcIdx := start + i
  1130  								if srcIdx >= limit || srcIdx < 0 {
  1131  									rg.array[regv+i] = LNil
  1132  								} else {
  1133  									rg.array[regv+i] = rg.array[srcIdx]
  1134  								}
  1135  							}
  1136  
  1137  							// values beyond top don't need to be valid LValues, so setting them to nil is fine
  1138  							// setting them to nil rather than LNil lets us invoke the golang memclr opto
  1139  							oldtop := rg.top
  1140  							rg.top = regv + n
  1141  							if rg.top < oldtop {
  1142  								nilRange := rg.array[rg.top:oldtop]
  1143  								for i := range nilRange {
  1144  									nilRange[i] = nil
  1145  								}
  1146  							}
  1147  						}
  1148  						if b > 1 && n > (b-1) {
  1149  							// this section is inlined by go-inline
  1150  							// source function is 'func (rg *registry) FillNil(regm, n int) ' in '_state.go'
  1151  							{
  1152  								rg := L.reg
  1153  								regm := regv + b - 1
  1154  								n := n - (b - 1)
  1155  								newSize := regm + n
  1156  								// this section is inlined by go-inline
  1157  								// source function is 'func (rg *registry) checkSize(requiredSize int) ' in '_state.go'
  1158  								{
  1159  									requiredSize := newSize
  1160  									if requiredSize > cap(rg.array) {
  1161  										rg.resize(requiredSize)
  1162  									}
  1163  								}
  1164  								for i := 0; i < n; i++ {
  1165  									rg.array[regm+i] = LNil
  1166  								}
  1167  								// values beyond top don't need to be valid LValues, so setting them to nil is fine
  1168  								// setting them to nil rather than LNil lets us invoke the golang memclr opto
  1169  								oldtop := rg.top
  1170  								rg.top = regm + n
  1171  								if rg.top < oldtop {
  1172  									nilRange := rg.array[rg.top:oldtop]
  1173  									for i := range nilRange {
  1174  										nilRange[i] = nil
  1175  									}
  1176  								}
  1177  							}
  1178  						}
  1179  					}
  1180  				}
  1181  				switchToParentThread(L, n, false, true)
  1182  				return 1
  1183  			}
  1184  			islast := baseframe == L.stack.Pop() || L.stack.IsEmpty()
  1185  			// this section is inlined by go-inline
  1186  			// source function is 'func copyReturnValues(L *LState, regv, start, n, b int) ' in '_vm.go'
  1187  			{
  1188  				regv := cf.ReturnBase
  1189  				start := RA
  1190  				b := B
  1191  				if b == 1 {
  1192  					// this section is inlined by go-inline
  1193  					// source function is 'func (rg *registry) FillNil(regm, n int) ' in '_state.go'
  1194  					{
  1195  						rg := L.reg
  1196  						regm := regv
  1197  						newSize := regm + n
  1198  						// this section is inlined by go-inline
  1199  						// source function is 'func (rg *registry) checkSize(requiredSize int) ' in '_state.go'
  1200  						{
  1201  							requiredSize := newSize
  1202  							if requiredSize > cap(rg.array) {
  1203  								rg.resize(requiredSize)
  1204  							}
  1205  						}
  1206  						for i := 0; i < n; i++ {
  1207  							rg.array[regm+i] = LNil
  1208  						}
  1209  						// values beyond top don't need to be valid LValues, so setting them to nil is fine
  1210  						// setting them to nil rather than LNil lets us invoke the golang memclr opto
  1211  						oldtop := rg.top
  1212  						rg.top = regm + n
  1213  						if rg.top < oldtop {
  1214  							nilRange := rg.array[rg.top:oldtop]
  1215  							for i := range nilRange {
  1216  								nilRange[i] = nil
  1217  							}
  1218  						}
  1219  					}
  1220  				} else {
  1221  					// this section is inlined by go-inline
  1222  					// source function is 'func (rg *registry) CopyRange(regv, start, limit, n int) ' in '_state.go'
  1223  					{
  1224  						rg := L.reg
  1225  						limit := -1
  1226  						newSize := regv + n
  1227  						// this section is inlined by go-inline
  1228  						// source function is 'func (rg *registry) checkSize(requiredSize int) ' in '_state.go'
  1229  						{
  1230  							requiredSize := newSize
  1231  							if requiredSize > cap(rg.array) {
  1232  								rg.resize(requiredSize)
  1233  							}
  1234  						}
  1235  						if limit == -1 || limit > rg.top {
  1236  							limit = rg.top
  1237  						}
  1238  						for i := 0; i < n; i++ {
  1239  							srcIdx := start + i
  1240  							if srcIdx >= limit || srcIdx < 0 {
  1241  								rg.array[regv+i] = LNil
  1242  							} else {
  1243  								rg.array[regv+i] = rg.array[srcIdx]
  1244  							}
  1245  						}
  1246  
  1247  						// values beyond top don't need to be valid LValues, so setting them to nil is fine
  1248  						// setting them to nil rather than LNil lets us invoke the golang memclr opto
  1249  						oldtop := rg.top
  1250  						rg.top = regv + n
  1251  						if rg.top < oldtop {
  1252  							nilRange := rg.array[rg.top:oldtop]
  1253  							for i := range nilRange {
  1254  								nilRange[i] = nil
  1255  							}
  1256  						}
  1257  					}
  1258  					if b > 1 && n > (b-1) {
  1259  						// this section is inlined by go-inline
  1260  						// source function is 'func (rg *registry) FillNil(regm, n int) ' in '_state.go'
  1261  						{
  1262  							rg := L.reg
  1263  							regm := regv + b - 1
  1264  							n := n - (b - 1)
  1265  							newSize := regm + n
  1266  							// this section is inlined by go-inline
  1267  							// source function is 'func (rg *registry) checkSize(requiredSize int) ' in '_state.go'
  1268  							{
  1269  								requiredSize := newSize
  1270  								if requiredSize > cap(rg.array) {
  1271  									rg.resize(requiredSize)
  1272  								}
  1273  							}
  1274  							for i := 0; i < n; i++ {
  1275  								rg.array[regm+i] = LNil
  1276  							}
  1277  							// values beyond top don't need to be valid LValues, so setting them to nil is fine
  1278  							// setting them to nil rather than LNil lets us invoke the golang memclr opto
  1279  							oldtop := rg.top
  1280  							rg.top = regm + n
  1281  							if rg.top < oldtop {
  1282  								nilRange := rg.array[rg.top:oldtop]
  1283  								for i := range nilRange {
  1284  									nilRange[i] = nil
  1285  								}
  1286  							}
  1287  						}
  1288  					}
  1289  				}
  1290  			}
  1291  			L.currentFrame = L.stack.Last()
  1292  			if islast || L.currentFrame == nil || L.currentFrame.Fn.IsG {
  1293  				return 1
  1294  			}
  1295  			return 0
  1296  		},
  1297  		func(L *LState, inst uint32, baseframe *callFrame) int { //OP_FORLOOP
  1298  			reg := L.reg
  1299  			cf := L.currentFrame
  1300  			lbase := cf.LocalBase
  1301  			A := int(inst>>18) & 0xff //GETA
  1302  			RA := lbase + A
  1303  			if init, ok1 := reg.Get(RA).assertFloat64(); ok1 {
  1304  				if limit, ok2 := reg.Get(RA + 1).assertFloat64(); ok2 {
  1305  					if step, ok3 := reg.Get(RA + 2).assertFloat64(); ok3 {
  1306  						init += step
  1307  						reg.SetNumber(RA, LNumber(init))
  1308  						if (step > 0 && init <= limit) || (step <= 0 && init >= limit) {
  1309  							Sbx := int(inst&0x3ffff) - opMaxArgSbx //GETSBX
  1310  							cf.Pc += Sbx
  1311  							reg.SetNumber(RA+3, LNumber(init))
  1312  						} else {
  1313  							reg.SetTop(RA + 1)
  1314  						}
  1315  					} else {
  1316  						L.RaiseError("for statement step must be a number")
  1317  					}
  1318  				} else {
  1319  					L.RaiseError("for statement limit must be a number")
  1320  				}
  1321  			} else {
  1322  				L.RaiseError("for statement init must be a number")
  1323  			}
  1324  			return 0
  1325  		},
  1326  		func(L *LState, inst uint32, baseframe *callFrame) int { //OP_FORPREP
  1327  			reg := L.reg
  1328  			cf := L.currentFrame
  1329  			lbase := cf.LocalBase
  1330  			A := int(inst>>18) & 0xff //GETA
  1331  			RA := lbase + A
  1332  			Sbx := int(inst&0x3ffff) - opMaxArgSbx //GETSBX
  1333  			if init, ok1 := reg.Get(RA).assertFloat64(); ok1 {
  1334  				if step, ok2 := reg.Get(RA + 2).assertFloat64(); ok2 {
  1335  					reg.SetNumber(RA, LNumber(init-step))
  1336  				} else {
  1337  					L.RaiseError("for statement step must be a number")
  1338  				}
  1339  			} else {
  1340  				L.RaiseError("for statement init must be a number")
  1341  			}
  1342  			cf.Pc += Sbx
  1343  			return 0
  1344  		},
  1345  		func(L *LState, inst uint32, baseframe *callFrame) int { //OP_TFORLOOP
  1346  			reg := L.reg
  1347  			cf := L.currentFrame
  1348  			lbase := cf.LocalBase
  1349  			A := int(inst>>18) & 0xff //GETA
  1350  			RA := lbase + A
  1351  			C := int(inst>>9) & 0x1ff //GETC
  1352  			nret := C
  1353  			reg.SetTop(RA + 3 + 2)
  1354  			reg.Set(RA+3+2, reg.Get(RA+2))
  1355  			reg.Set(RA+3+1, reg.Get(RA+1))
  1356  			reg.Set(RA+3, reg.Get(RA))
  1357  			L.callR(2, nret, RA+3)
  1358  			if value := reg.Get(RA + 3); value != LNil {
  1359  				reg.Set(RA+2, value)
  1360  				pc := cf.Fn.Proto.Code[cf.Pc]
  1361  				cf.Pc += int(pc&0x3ffff) - opMaxArgSbx
  1362  			}
  1363  			cf.Pc++
  1364  			return 0
  1365  		},
  1366  		func(L *LState, inst uint32, baseframe *callFrame) int { //OP_SETLIST
  1367  			reg := L.reg
  1368  			cf := L.currentFrame
  1369  			lbase := cf.LocalBase
  1370  			A := int(inst>>18) & 0xff //GETA
  1371  			RA := lbase + A
  1372  			B := int(inst & 0x1ff)    //GETB
  1373  			C := int(inst>>9) & 0x1ff //GETC
  1374  			if C == 0 {
  1375  				C = int(cf.Fn.Proto.Code[cf.Pc])
  1376  				cf.Pc++
  1377  			}
  1378  			offset := (C - 1) * FieldsPerFlush
  1379  			table := reg.Get(RA).(*LTable)
  1380  			nelem := B
  1381  			if B == 0 {
  1382  				nelem = reg.Top() - RA - 1
  1383  			}
  1384  			for i := 1; i <= nelem; i++ {
  1385  				table.RawSetInt(offset+i, reg.Get(RA+i))
  1386  			}
  1387  			return 0
  1388  		},
  1389  		func(L *LState, inst uint32, baseframe *callFrame) int { //OP_CLOSE
  1390  			cf := L.currentFrame
  1391  			lbase := cf.LocalBase
  1392  			A := int(inst>>18) & 0xff //GETA
  1393  			RA := lbase + A
  1394  			// this section is inlined by go-inline
  1395  			// source function is 'func (ls *LState) closeUpvalues(idx int) ' in '_state.go'
  1396  			{
  1397  				ls := L
  1398  				idx := RA
  1399  				if ls.uvcache != nil {
  1400  					var prev *Upvalue
  1401  					for uv := ls.uvcache; uv != nil; uv = uv.next {
  1402  						if uv.index >= idx {
  1403  							if prev != nil {
  1404  								prev.next = nil
  1405  							} else {
  1406  								ls.uvcache = nil
  1407  							}
  1408  							uv.Close()
  1409  						}
  1410  						prev = uv
  1411  					}
  1412  				}
  1413  			}
  1414  			return 0
  1415  		},
  1416  		func(L *LState, inst uint32, baseframe *callFrame) int { //OP_CLOSURE
  1417  			reg := L.reg
  1418  			cf := L.currentFrame
  1419  			lbase := cf.LocalBase
  1420  			A := int(inst>>18) & 0xff //GETA
  1421  			RA := lbase + A
  1422  			Bx := int(inst & 0x3ffff) //GETBX
  1423  			proto := cf.Fn.Proto.FunctionPrototypes[Bx]
  1424  			closure := newLFunctionL(proto, cf.Fn.Env, int(proto.NumUpvalues))
  1425  			reg.Set(RA, closure)
  1426  			for i := 0; i < int(proto.NumUpvalues); i++ {
  1427  				inst = cf.Fn.Proto.Code[cf.Pc]
  1428  				cf.Pc++
  1429  				B := opGetArgB(inst)
  1430  				switch opGetOpCode(inst) {
  1431  				case OP_MOVE:
  1432  					closure.Upvalues[i] = L.findUpvalue(lbase + B)
  1433  				case OP_GETUPVAL:
  1434  					closure.Upvalues[i] = cf.Fn.Upvalues[B]
  1435  				}
  1436  			}
  1437  			return 0
  1438  		},
  1439  		func(L *LState, inst uint32, baseframe *callFrame) int { //OP_VARARG
  1440  			reg := L.reg
  1441  			cf := L.currentFrame
  1442  			lbase := cf.LocalBase
  1443  			A := int(inst>>18) & 0xff //GETA
  1444  			RA := lbase + A
  1445  			B := int(inst & 0x1ff) //GETB
  1446  			nparams := int(cf.Fn.Proto.NumParameters)
  1447  			nvarargs := cf.NArgs - nparams
  1448  			if nvarargs < 0 {
  1449  				nvarargs = 0
  1450  			}
  1451  			nwant := B - 1
  1452  			if B == 0 {
  1453  				nwant = nvarargs
  1454  			}
  1455  			// this section is inlined by go-inline
  1456  			// source function is 'func (rg *registry) CopyRange(regv, start, limit, n int) ' in '_state.go'
  1457  			{
  1458  				rg := reg
  1459  				regv := RA
  1460  				start := cf.Base + nparams + 1
  1461  				limit := cf.LocalBase
  1462  				n := nwant
  1463  				newSize := regv + n
  1464  				// this section is inlined by go-inline
  1465  				// source function is 'func (rg *registry) checkSize(requiredSize int) ' in '_state.go'
  1466  				{
  1467  					requiredSize := newSize
  1468  					if requiredSize > cap(rg.array) {
  1469  						rg.resize(requiredSize)
  1470  					}
  1471  				}
  1472  				if limit == -1 || limit > rg.top {
  1473  					limit = rg.top
  1474  				}
  1475  				for i := 0; i < n; i++ {
  1476  					srcIdx := start + i
  1477  					if srcIdx >= limit || srcIdx < 0 {
  1478  						rg.array[regv+i] = LNil
  1479  					} else {
  1480  						rg.array[regv+i] = rg.array[srcIdx]
  1481  					}
  1482  				}
  1483  
  1484  				// values beyond top don't need to be valid LValues, so setting them to nil is fine
  1485  				// setting them to nil rather than LNil lets us invoke the golang memclr opto
  1486  				oldtop := rg.top
  1487  				rg.top = regv + n
  1488  				if rg.top < oldtop {
  1489  					nilRange := rg.array[rg.top:oldtop]
  1490  					for i := range nilRange {
  1491  						nilRange[i] = nil
  1492  					}
  1493  				}
  1494  			}
  1495  			return 0
  1496  		},
  1497  		func(L *LState, inst uint32, baseframe *callFrame) int { //OP_NOP
  1498  			return 0
  1499  		},
  1500  	}
  1501  }
  1502  
  1503  func opArith(L *LState, inst uint32, baseframe *callFrame) int { //OP_ADD, OP_SUB, OP_MUL, OP_DIV, OP_MOD, OP_POW
  1504  	reg := L.reg
  1505  	cf := L.currentFrame
  1506  	lbase := cf.LocalBase
  1507  	A := int(inst>>18) & 0xff //GETA
  1508  	RA := lbase + A
  1509  	opcode := int(inst >> 26) //GETOPCODE
  1510  	B := int(inst & 0x1ff)    //GETB
  1511  	C := int(inst>>9) & 0x1ff //GETC
  1512  	lhs := L.rkValue(B)
  1513  	rhs := L.rkValue(C)
  1514  	v1, ok1 := lhs.assertFloat64()
  1515  	v2, ok2 := rhs.assertFloat64()
  1516  	if ok1 && ok2 {
  1517  		reg.SetNumber(RA, numberArith(L, opcode, LNumber(v1), LNumber(v2)))
  1518  	} else {
  1519  		reg.Set(RA, objectArith(L, opcode, lhs, rhs))
  1520  	}
  1521  	return 0
  1522  }
  1523  
  1524  func luaModulo(lhs, rhs LNumber) LNumber {
  1525  	flhs := float64(lhs)
  1526  	frhs := float64(rhs)
  1527  	v := math.Mod(flhs, frhs)
  1528  	if flhs < 0 || frhs < 0 && !(flhs < 0 && frhs < 0) {
  1529  		v += frhs
  1530  	}
  1531  	return LNumber(v)
  1532  }
  1533  
  1534  func numberArith(L *LState, opcode int, lhs, rhs LNumber) LNumber {
  1535  	switch opcode {
  1536  	case OP_ADD:
  1537  		return lhs + rhs
  1538  	case OP_SUB:
  1539  		return lhs - rhs
  1540  	case OP_MUL:
  1541  		return lhs * rhs
  1542  	case OP_DIV:
  1543  		return lhs / rhs
  1544  	case OP_MOD:
  1545  		return luaModulo(lhs, rhs)
  1546  	case OP_POW:
  1547  		flhs := float64(lhs)
  1548  		frhs := float64(rhs)
  1549  		return LNumber(math.Pow(flhs, frhs))
  1550  	}
  1551  	panic("should not reach here")
  1552  	return LNumber(0)
  1553  }
  1554  
  1555  func objectArith(L *LState, opcode int, lhs, rhs LValue) LValue {
  1556  	event := ""
  1557  	switch opcode {
  1558  	case OP_ADD:
  1559  		event = "__add"
  1560  	case OP_SUB:
  1561  		event = "__sub"
  1562  	case OP_MUL:
  1563  		event = "__mul"
  1564  	case OP_DIV:
  1565  		event = "__div"
  1566  	case OP_MOD:
  1567  		event = "__mod"
  1568  	case OP_POW:
  1569  		event = "__pow"
  1570  	}
  1571  	op := L.metaOp2(lhs, rhs, event)
  1572  	if op.Type() == LTFunction {
  1573  		L.reg.Push(op)
  1574  		L.reg.Push(lhs)
  1575  		L.reg.Push(rhs)
  1576  		L.Call(2, 1)
  1577  		return L.reg.Pop()
  1578  	}
  1579  	if str, ok := lhs.(LString); ok {
  1580  		if lnum, err := parseNumber(string(str)); err == nil {
  1581  			lhs = lnum
  1582  		}
  1583  	}
  1584  	if str, ok := rhs.(LString); ok {
  1585  		if rnum, err := parseNumber(string(str)); err == nil {
  1586  			rhs = rnum
  1587  		}
  1588  	}
  1589  	if v1, ok1 := lhs.assertFloat64(); ok1 {
  1590  		if v2, ok2 := rhs.assertFloat64(); ok2 {
  1591  			return numberArith(L, opcode, LNumber(v1), LNumber(v2))
  1592  		}
  1593  	}
  1594  	L.RaiseError(fmt.Sprintf("cannot perform %v operation between %v and %v",
  1595  		strings.TrimLeft(event, "_"), lhs.Type().String(), rhs.Type().String()))
  1596  
  1597  	return LNil
  1598  }
  1599  
  1600  func stringConcat(L *LState, total, last int) LValue {
  1601  	rhs := L.reg.Get(last)
  1602  	total--
  1603  	for i := last - 1; total > 0; {
  1604  		lhs := L.reg.Get(i)
  1605  		if !(LVCanConvToString(lhs) && LVCanConvToString(rhs)) {
  1606  			op := L.metaOp2(lhs, rhs, "__concat")
  1607  			if op.Type() == LTFunction {
  1608  				L.reg.Push(op)
  1609  				L.reg.Push(lhs)
  1610  				L.reg.Push(rhs)
  1611  				L.Call(2, 1)
  1612  				rhs = L.reg.Pop()
  1613  				total--
  1614  				i--
  1615  			} else {
  1616  				L.RaiseError("cannot perform concat operation between %v and %v", lhs.Type().String(), rhs.Type().String())
  1617  				return LNil
  1618  			}
  1619  		} else {
  1620  			buf := make([]string, total+1)
  1621  			buf[total] = LVAsString(rhs)
  1622  			for total > 0 {
  1623  				lhs = L.reg.Get(i)
  1624  				if !LVCanConvToString(lhs) {
  1625  					break
  1626  				}
  1627  				buf[total-1] = LVAsString(lhs)
  1628  				i--
  1629  				total--
  1630  			}
  1631  			rhs = LString(strings.Join(buf, ""))
  1632  		}
  1633  	}
  1634  	return rhs
  1635  }
  1636  
  1637  func lessThan(L *LState, lhs, rhs LValue) bool {
  1638  	// optimization for numbers
  1639  	if v1, ok1 := lhs.assertFloat64(); ok1 {
  1640  		if v2, ok2 := rhs.assertFloat64(); ok2 {
  1641  			return v1 < v2
  1642  		}
  1643  		L.RaiseError("attempt to compare %v with %v", lhs.Type().String(), rhs.Type().String())
  1644  	}
  1645  	if lhs.Type() != rhs.Type() {
  1646  		L.RaiseError("attempt to compare %v with %v", lhs.Type().String(), rhs.Type().String())
  1647  		return false
  1648  	}
  1649  	ret := false
  1650  	switch lhs.Type() {
  1651  	case LTString:
  1652  		ret = strCmp(string(lhs.(LString)), string(rhs.(LString))) < 0
  1653  	default:
  1654  		ret = objectRationalWithError(L, lhs, rhs, "__lt")
  1655  	}
  1656  	return ret
  1657  }
  1658  
  1659  func equals(L *LState, lhs, rhs LValue, raw bool) bool {
  1660  	if lhs.Type() != rhs.Type() {
  1661  		return false
  1662  	}
  1663  
  1664  	ret := false
  1665  	switch lhs.Type() {
  1666  	case LTNil:
  1667  		ret = true
  1668  	case LTNumber:
  1669  		v1, _ := lhs.assertFloat64()
  1670  		v2, _ := rhs.assertFloat64()
  1671  		ret = v1 == v2
  1672  	case LTBool:
  1673  		ret = bool(lhs.(LBool)) == bool(rhs.(LBool))
  1674  	case LTString:
  1675  		ret = string(lhs.(LString)) == string(rhs.(LString))
  1676  	case LTUserData, LTTable:
  1677  		if lhs == rhs {
  1678  			ret = true
  1679  		} else if !raw {
  1680  			switch objectRational(L, lhs, rhs, "__eq") {
  1681  			case 1:
  1682  				ret = true
  1683  			default:
  1684  				ret = false
  1685  			}
  1686  		}
  1687  	default:
  1688  		ret = lhs == rhs
  1689  	}
  1690  	return ret
  1691  }
  1692  
  1693  func objectRationalWithError(L *LState, lhs, rhs LValue, event string) bool {
  1694  	switch objectRational(L, lhs, rhs, event) {
  1695  	case 1:
  1696  		return true
  1697  	case 0:
  1698  		return false
  1699  	}
  1700  	L.RaiseError("attempt to compare %v with %v", lhs.Type().String(), rhs.Type().String())
  1701  	return false
  1702  }
  1703  
  1704  func objectRational(L *LState, lhs, rhs LValue, event string) int {
  1705  	m1 := L.metaOp1(lhs, event)
  1706  	m2 := L.metaOp1(rhs, event)
  1707  	if m1.Type() == LTFunction && m1 == m2 {
  1708  		L.reg.Push(m1)
  1709  		L.reg.Push(lhs)
  1710  		L.reg.Push(rhs)
  1711  		L.Call(2, 1)
  1712  		if LVAsBool(L.reg.Pop()) {
  1713  			return 1
  1714  		}
  1715  		return 0
  1716  	}
  1717  	return -1
  1718  }