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