1package lua
2
3////////////////////////////////////////////////////////
4// This file was generated by go-inline. DO NOT EDIT. //
5////////////////////////////////////////////////////////
6
7import (
8	"fmt"
9	"math"
10	"strings"
11)
12
13func 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
37func 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.
74func 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
176func 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
200func 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
267func 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
297type instFunc func(*LState, uint32, *callFrame) int
298
299var jumpTable [opCodeMax + 1]instFunc
300
301func 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
1503func 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
1524func 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
1534func 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
1555func 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
1600func 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
1637func 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
1659func 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
1693func 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
1704func 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}
1719