diff --git a/README.rst b/README.rst index 1ac57dca..c20920de 100644 --- a/README.rst +++ b/README.rst @@ -56,7 +56,7 @@ Installation go get github.com/yuin/gopher-lua -GopherLua supports >= Go1.9. +GopherLua supports >= Go1.20. ---------------------------------------------------------------- Usage diff --git a/_state.go b/_state.go index 6e9febfb..5de19267 100644 --- a/_state.go +++ b/_state.go @@ -576,7 +576,6 @@ func newLState(options Options) *LState { wrapped: false, uvcache: nil, hasErrorFunc: false, - mainLoop: mainLoop, ctx: nil, } if options.MinimizeStackMemory { @@ -1051,9 +1050,9 @@ func (ls *LState) callR(nargs, nret, rbase int) { if ls.G.MainThread == nil { ls.G.MainThread = ls ls.G.CurrentThread = ls - ls.mainLoop(ls, nil) + mainLoop(ls, nil) } else { - ls.mainLoop(ls, ls.currentFrame) + mainLoop(ls, ls.currentFrame) } if nret != MultRet { ls.reg.SetTop(rbase + nret) @@ -1404,7 +1403,6 @@ func (ls *LState) NewThread() (*LState, context.CancelFunc) { thread.Env = ls.Env var f context.CancelFunc = nil if ls.ctx != nil { - thread.mainLoop = mainLoopWithContext thread.ctx, f = context.WithCancel(ls.ctx) thread.ctxCancelFn = f } @@ -2044,9 +2042,8 @@ func (ls *LState) SetMx(mx int) { }() } -// SetContext set a context ctx to this LState. The provided ctx must be non-nil. +// SetContext set a context ctx to this LState. func (ls *LState) SetContext(ctx context.Context) { - ls.mainLoop = mainLoopWithContext ls.ctx = ctx } @@ -2058,7 +2055,6 @@ func (ls *LState) Context() context.Context { // RemoveContext removes the context associated with this LState and returns this context. func (ls *LState) RemoveContext() context.Context { oldctx := ls.ctx - ls.mainLoop = mainLoop ls.ctx = nil return oldctx } diff --git a/_vm.go b/_vm.go index ee2be040..e6770213 100644 --- a/_vm.go +++ b/_vm.go @@ -7,33 +7,6 @@ import ( ) func mainLoop(L *LState, baseframe *callFrame) { - var inst uint32 - var cf *callFrame - - if L.stack.IsEmpty() { - return - } - - L.currentFrame = L.stack.Last() - if L.currentFrame.Fn.IsG { - callGFunction(L, false) - return - } - - for { - cf = L.currentFrame - inst = cf.Fn.Proto.Code[cf.Pc] - cf.Pc++ - if jumpTable[int(inst>>26)](L, inst, baseframe) == 1 { - return - } - } -} - -func mainLoopWithContext(L *LState, baseframe *callFrame) { - var inst uint32 - var cf *callFrame - if L.stack.IsEmpty() { return } @@ -44,143 +17,22 @@ func mainLoopWithContext(L *LState, baseframe *callFrame) { return } - for { - cf = L.currentFrame - inst = cf.Fn.Proto.Code[cf.Pc] + reg := L.reg + for L.ctx == nil || L.ctx.Err() == nil { + cf := L.currentFrame + inst := cf.Fn.Proto.Code[cf.Pc] + lbase := cf.LocalBase cf.Pc++ - select { - case <-L.ctx.Done(): - L.RaiseError(L.ctx.Err().Error()) - return - default: - if jumpTable[int(inst>>26)](L, inst, baseframe) == 1 { - return - } - } - } -} - -// regv is the first target register to copy the return values to. -// It can be reg.top, indicating that the copied values are going into new registers, or it can be below reg.top -// Indicating that the values should be within the existing registers. -// b is the available number of return values + 1. -// n is the desired number of return values. -// If n more than the available return values then the extra values are set to nil. -// When this function returns the top of the registry will be set to regv+n. -func copyReturnValues(L *LState, regv, start, n, b int) { // +inline-start - if b == 1 { - // +inline-call L.reg.FillNil regv n - } else { - // +inline-call L.reg.CopyRange regv start -1 n - if b > 1 && n > (b-1) { - // +inline-call L.reg.FillNil regv+b-1 n-(b-1) - } - } -} // +inline-end - -func switchToParentThread(L *LState, nargs int, haserror bool, kill bool) { - parent := L.Parent - if parent == nil { - L.RaiseError("can not yield from outside of a coroutine") - } - L.G.CurrentThread = parent - L.Parent = nil - if !L.wrapped { - if haserror { - parent.Push(LFalse) - } else { - parent.Push(LTrue) - } - } - L.XMoveTo(parent, nargs) - L.stack.Pop() - offset := L.currentFrame.LocalBase - L.currentFrame.ReturnBase - L.currentFrame = L.stack.Last() - L.reg.SetTop(L.reg.Top() - offset) // remove 'yield' function(including tailcalled functions) - if kill { - L.kill() - } -} - -func callGFunction(L *LState, tailcall bool) bool { - frame := L.currentFrame - gfnret := frame.Fn.GFunction(L) - if tailcall { - L.currentFrame = L.RemoveCallerFrame() - } - - if gfnret < 0 { - switchToParentThread(L, L.GetTop(), false, false) - return true - } - - wantret := frame.NRet - if wantret == MultRet { - wantret = gfnret - } - - if tailcall && L.Parent != nil && L.stack.Sp() == 1 { - switchToParentThread(L, wantret, false, true) - return true - } - - // +inline-call L.reg.CopyRange frame.ReturnBase L.reg.Top()-gfnret -1 wantret - L.stack.Pop() - L.currentFrame = L.stack.Last() - return false -} - -func threadRun(L *LState) { - if L.stack.IsEmpty() { - return - } - - defer func() { - if rcv := recover(); rcv != nil { - var lv LValue - if v, ok := rcv.(*ApiError); ok { - lv = v.Object - } else { - lv = LString(fmt.Sprint(rcv)) - } - if parent := L.Parent; parent != nil { - if L.wrapped { - L.Push(lv) - parent.Panic(L) - } else { - L.SetTop(0) - L.Push(lv) - switchToParentThread(L, 1, true, true) - } - } else { - panic(rcv) - } - } - }() - L.mainLoop(L, nil) -} - -type instFunc func(*LState, uint32, *callFrame) int -var jumpTable [opCodeMax + 1]instFunc - -func init() { - jumpTable = [opCodeMax + 1]instFunc{ - func(L *LState, inst uint32, baseframe *callFrame) int { //OP_MOVE - reg := L.reg - cf := L.currentFrame - lbase := cf.LocalBase + opcode := int(inst >> 26) + switch opcode { + case OP_MOVE: A := int(inst>>18) & 0xff //GETA RA := lbase + A B := int(inst & 0x1ff) //GETB v := reg.Get(lbase + B) // +inline-call reg.Set RA v - return 0 - }, - func(L *LState, inst uint32, baseframe *callFrame) int { //OP_MOVEN - reg := L.reg - cf := L.currentFrame - lbase := cf.LocalBase + case OP_MOVEN: A := int(inst>>18) & 0xff //GETA B := int(inst & 0x1ff) //GETB C := int(inst>>9) & 0x1ff //GETC @@ -197,23 +49,13 @@ func init() { // +inline-call reg.Set lbase+A v } cf.Pc = pc - return 0 - }, - func(L *LState, inst uint32, baseframe *callFrame) int { //OP_LOADK - reg := L.reg - cf := L.currentFrame - lbase := cf.LocalBase + case OP_LOADK: A := int(inst>>18) & 0xff //GETA RA := lbase + A Bx := int(inst & 0x3ffff) //GETBX v := cf.Fn.Proto.Constants[Bx] // +inline-call reg.Set RA v - return 0 - }, - func(L *LState, inst uint32, baseframe *callFrame) int { //OP_LOADBOOL - reg := L.reg - cf := L.currentFrame - lbase := cf.LocalBase + case OP_LOADBOOL: A := int(inst>>18) & 0xff //GETA RA := lbase + A B := int(inst & 0x1ff) //GETB @@ -226,126 +68,71 @@ func init() { if C != 0 { cf.Pc++ } - return 0 - }, - func(L *LState, inst uint32, baseframe *callFrame) int { //OP_LOADNIL - reg := L.reg - cf := L.currentFrame - lbase := cf.LocalBase + case OP_LOADNIL: A := int(inst>>18) & 0xff //GETA RA := lbase + A B := int(inst & 0x1ff) //GETB for i := RA; i <= lbase+B; i++ { // +inline-call reg.Set i LNil } - return 0 - }, - func(L *LState, inst uint32, baseframe *callFrame) int { //OP_GETUPVAL - reg := L.reg - cf := L.currentFrame - lbase := cf.LocalBase + case OP_GETUPVAL: A := int(inst>>18) & 0xff //GETA RA := lbase + A B := int(inst & 0x1ff) //GETB v := cf.Fn.Upvalues[B].Value() // +inline-call reg.Set RA v - return 0 - }, - func(L *LState, inst uint32, baseframe *callFrame) int { //OP_GETGLOBAL - reg := L.reg - cf := L.currentFrame - lbase := cf.LocalBase + case OP_GETGLOBAL: A := int(inst>>18) & 0xff //GETA RA := lbase + A Bx := int(inst & 0x3ffff) //GETBX //reg.Set(RA, L.getField(cf.Fn.Env, cf.Fn.Proto.Constants[Bx])) v := L.getFieldString(cf.Fn.Env, cf.Fn.Proto.stringConstants[Bx]) // +inline-call reg.Set RA v - return 0 - }, - func(L *LState, inst uint32, baseframe *callFrame) int { //OP_GETTABLE - reg := L.reg - cf := L.currentFrame - lbase := cf.LocalBase + case OP_GETTABLE: A := int(inst>>18) & 0xff //GETA RA := lbase + A B := int(inst & 0x1ff) //GETB C := int(inst>>9) & 0x1ff //GETC v := L.getField(reg.Get(lbase+B), L.rkValue(C)) // +inline-call reg.Set RA v - return 0 - }, - func(L *LState, inst uint32, baseframe *callFrame) int { //OP_GETTABLEKS - reg := L.reg - cf := L.currentFrame - lbase := cf.LocalBase + case OP_GETTABLEKS: A := int(inst>>18) & 0xff //GETA RA := lbase + A B := int(inst & 0x1ff) //GETB C := int(inst>>9) & 0x1ff //GETC v := L.getFieldString(reg.Get(lbase+B), L.rkString(C)) // +inline-call reg.Set RA v - return 0 - }, - func(L *LState, inst uint32, baseframe *callFrame) int { //OP_SETGLOBAL - reg := L.reg - cf := L.currentFrame - lbase := cf.LocalBase + case OP_SETGLOBAL: A := int(inst>>18) & 0xff //GETA RA := lbase + A Bx := int(inst & 0x3ffff) //GETBX //L.setField(cf.Fn.Env, cf.Fn.Proto.Constants[Bx], reg.Get(RA)) L.setFieldString(cf.Fn.Env, cf.Fn.Proto.stringConstants[Bx], reg.Get(RA)) - return 0 - }, - func(L *LState, inst uint32, baseframe *callFrame) int { //OP_SETUPVAL - reg := L.reg - cf := L.currentFrame - lbase := cf.LocalBase + case OP_SETUPVAL: A := int(inst>>18) & 0xff //GETA RA := lbase + A B := int(inst & 0x1ff) //GETB cf.Fn.Upvalues[B].SetValue(reg.Get(RA)) - return 0 - }, - func(L *LState, inst uint32, baseframe *callFrame) int { //OP_SETTABLE - reg := L.reg - cf := L.currentFrame - lbase := cf.LocalBase + case OP_SETTABLE: A := int(inst>>18) & 0xff //GETA RA := lbase + A B := int(inst & 0x1ff) //GETB C := int(inst>>9) & 0x1ff //GETC L.setField(reg.Get(RA), L.rkValue(B), L.rkValue(C)) - return 0 - }, - func(L *LState, inst uint32, baseframe *callFrame) int { //OP_SETTABLEKS - reg := L.reg - cf := L.currentFrame - lbase := cf.LocalBase + case OP_SETTABLEKS: A := int(inst>>18) & 0xff //GETA RA := lbase + A B := int(inst & 0x1ff) //GETB C := int(inst>>9) & 0x1ff //GETC L.setFieldString(reg.Get(RA), L.rkString(B), L.rkValue(C)) - return 0 - }, - func(L *LState, inst uint32, baseframe *callFrame) int { //OP_NEWTABLE - reg := L.reg - cf := L.currentFrame - lbase := cf.LocalBase + case OP_NEWTABLE: A := int(inst>>18) & 0xff //GETA RA := lbase + A B := int(inst & 0x1ff) //GETB C := int(inst>>9) & 0x1ff //GETC v := newLTable(B, C) // +inline-call reg.Set RA v - return 0 - }, - func(L *LState, inst uint32, baseframe *callFrame) int { //OP_SELF - reg := L.reg - cf := L.currentFrame - lbase := cf.LocalBase + case OP_SELF: A := int(inst>>18) & 0xff //GETA RA := lbase + A B := int(inst & 0x1ff) //GETB @@ -354,18 +141,24 @@ func init() { v := L.getFieldString(selfobj, L.rkString(C)) // +inline-call reg.Set RA v // +inline-call reg.Set RA+1 selfobj - return 0 - }, - opArith, // OP_ADD - opArith, // OP_SUB - opArith, // OP_MUL - opArith, // OP_DIV - opArith, // OP_MOD - opArith, // OP_POW - func(L *LState, inst uint32, baseframe *callFrame) int { //OP_UNM - reg := L.reg - cf := L.currentFrame - lbase := cf.LocalBase + case OP_ADD, OP_SUB, OP_MUL, OP_DIV, OP_MOD, OP_POW: + A := int(inst>>18) & 0xff //GETA + RA := lbase + A + B := int(inst & 0x1ff) //GETB + C := int(inst>>9) & 0x1ff //GETC + lhs := L.rkValue(B) + rhs := L.rkValue(C) + v1, ok1 := lhs.(LNumber) + v2, ok2 := rhs.(LNumber) + if ok1 && ok2 { + v := numberArith(L, opcode, LNumber(v1), LNumber(v2)) + // +inline-call reg.SetNumber RA v + } else { + v := objectArith(L, opcode, lhs, rhs) + // +inline-call reg.Set RA v + } + + case OP_UNM: A := int(inst>>18) & 0xff //GETA RA := lbase + A B := int(inst & 0x1ff) //GETB @@ -389,12 +182,7 @@ func init() { L.RaiseError("__unm undefined") } } - return 0 - }, - func(L *LState, inst uint32, baseframe *callFrame) int { //OP_NOT - reg := L.reg - cf := L.currentFrame - lbase := cf.LocalBase + case OP_NOT: A := int(inst>>18) & 0xff //GETA RA := lbase + A B := int(inst & 0x1ff) //GETB @@ -403,12 +191,7 @@ func init() { } else { // +inline-call reg.Set RA LFalse } - return 0 - }, - func(L *LState, inst uint32, baseframe *callFrame) int { //OP_LEN - reg := L.reg - cf := L.currentFrame - lbase := cf.LocalBase + case OP_LEN: A := int(inst>>18) & 0xff //GETA RA := lbase + A B := int(inst & 0x1ff) //GETB @@ -434,12 +217,7 @@ func init() { L.RaiseError("__len undefined") } } - return 0 - }, - func(L *LState, inst uint32, baseframe *callFrame) int { //OP_CONCAT - reg := L.reg - cf := L.currentFrame - lbase := cf.LocalBase + case OP_CONCAT: A := int(inst>>18) & 0xff //GETA RA := lbase + A B := int(inst & 0x1ff) //GETB @@ -448,16 +226,10 @@ func init() { RB := lbase + B v := stringConcat(L, RC-RB+1, RC) // +inline-call reg.Set RA v - return 0 - }, - func(L *LState, inst uint32, baseframe *callFrame) int { //OP_JMP - cf := L.currentFrame + case OP_JMP: Sbx := int(inst&0x3ffff) - opMaxArgSbx //GETSBX cf.Pc += Sbx - return 0 - }, - func(L *LState, inst uint32, baseframe *callFrame) int { //OP_EQ - cf := L.currentFrame + case OP_EQ: A := int(inst>>18) & 0xff //GETA B := int(inst & 0x1ff) //GETB C := int(inst>>9) & 0x1ff //GETC @@ -469,10 +241,7 @@ func init() { if v == A { cf.Pc++ } - return 0 - }, - func(L *LState, inst uint32, baseframe *callFrame) int { //OP_LT - cf := L.currentFrame + case OP_LT: A := int(inst>>18) & 0xff //GETA B := int(inst & 0x1ff) //GETB C := int(inst>>9) & 0x1ff //GETC @@ -484,10 +253,7 @@ func init() { if v == A { cf.Pc++ } - return 0 - }, - func(L *LState, inst uint32, baseframe *callFrame) int { //OP_LE - cf := L.currentFrame + case OP_LE: A := int(inst>>18) & 0xff //GETA B := int(inst & 0x1ff) //GETB C := int(inst>>9) & 0x1ff //GETC @@ -527,24 +293,14 @@ func init() { if v == A { cf.Pc++ } - return 0 - }, - func(L *LState, inst uint32, baseframe *callFrame) int { //OP_TEST - reg := L.reg - cf := L.currentFrame - lbase := cf.LocalBase + case OP_TEST: A := int(inst>>18) & 0xff //GETA RA := lbase + A C := int(inst>>9) & 0x1ff //GETC if LVAsBool(reg.Get(RA)) == (C == 0) { cf.Pc++ } - return 0 - }, - func(L *LState, inst uint32, baseframe *callFrame) int { //OP_TESTSET - reg := L.reg - cf := L.currentFrame - lbase := cf.LocalBase + case OP_TESTSET: A := int(inst>>18) & 0xff //GETA RA := lbase + A B := int(inst & 0x1ff) //GETB @@ -554,12 +310,7 @@ func init() { } else { cf.Pc++ } - return 0 - }, - func(L *LState, inst uint32, baseframe *callFrame) int { //OP_CALL - reg := L.reg - cf := L.currentFrame - lbase := cf.LocalBase + case OP_CALL: A := int(inst>>18) & 0xff //GETA RA := lbase + A B := int(inst & 0x1ff) //GETB @@ -580,14 +331,9 @@ func init() { } // +inline-call L.pushCallFrame callFrame{Fn:callable,Pc:0,Base:RA,LocalBase:RA+1,ReturnBase:RA,NArgs:nargs,NRet:nret,Parent:cf,TailCall:0} lv meta if callable.IsG && callGFunction(L, false) { - return 1 + return } - return 0 - }, - func(L *LState, inst uint32, baseframe *callFrame) int { //OP_TAILCALL - reg := L.reg - cf := L.currentFrame - lbase := cf.LocalBase + case OP_TAILCALL: A := int(inst>>18) & 0xff //GETA RA := lbase + A B := int(inst & 0x1ff) //GETB @@ -622,10 +368,10 @@ func init() { TailCall: 0, }, lv, meta) if callGFunction(L, true) { - return 1 + return } if L.currentFrame == nil || L.currentFrame.Fn.IsG || luaframe == baseframe { - return 1 + return } } else { base := cf.Base @@ -647,12 +393,7 @@ func init() { cf.Base = base cf.LocalBase = base + (cf.LocalBase - lbase + 1) } - return 0 - }, - func(L *LState, inst uint32, baseframe *callFrame) int { //OP_RETURN - reg := L.reg - cf := L.currentFrame - lbase := cf.LocalBase + case OP_RETURN: A := int(inst>>18) & 0xff //GETA RA := lbase + A B := int(inst & 0x1ff) //GETB @@ -669,20 +410,15 @@ func init() { if L.Parent != nil && L.stack.Sp() == 1 { // +inline-call copyReturnValues L reg.Top() RA n B switchToParentThread(L, n, false, true) - return 1 + return } islast := baseframe == L.stack.Pop() || L.stack.IsEmpty() // +inline-call copyReturnValues L cf.ReturnBase RA n B L.currentFrame = L.stack.Last() if islast || L.currentFrame == nil || L.currentFrame.Fn.IsG { - return 1 + return } - return 0 - }, - func(L *LState, inst uint32, baseframe *callFrame) int { //OP_FORLOOP - reg := L.reg - cf := L.currentFrame - lbase := cf.LocalBase + case OP_FORLOOP: A := int(inst>>18) & 0xff //GETA RA := lbase + A if init, ok1 := reg.Get(RA).(LNumber); ok1 { @@ -707,12 +443,7 @@ func init() { } else { L.RaiseError("for statement init must be a number") } - return 0 - }, - func(L *LState, inst uint32, baseframe *callFrame) int { //OP_FORPREP - reg := L.reg - cf := L.currentFrame - lbase := cf.LocalBase + case OP_FORPREP: A := int(inst>>18) & 0xff //GETA RA := lbase + A Sbx := int(inst&0x3ffff) - opMaxArgSbx //GETSBX @@ -726,12 +457,7 @@ func init() { L.RaiseError("for statement init must be a number") } cf.Pc += Sbx - return 0 - }, - func(L *LState, inst uint32, baseframe *callFrame) int { //OP_TFORLOOP - reg := L.reg - cf := L.currentFrame - lbase := cf.LocalBase + case OP_TFORLOOP: A := int(inst>>18) & 0xff //GETA RA := lbase + A C := int(inst>>9) & 0x1ff //GETC @@ -747,12 +473,7 @@ func init() { cf.Pc += int(pc&0x3ffff) - opMaxArgSbx } cf.Pc++ - return 0 - }, - func(L *LState, inst uint32, baseframe *callFrame) int { //OP_SETLIST - reg := L.reg - cf := L.currentFrame - lbase := cf.LocalBase + case OP_SETLIST: A := int(inst>>18) & 0xff //GETA RA := lbase + A B := int(inst & 0x1ff) //GETB @@ -770,20 +491,11 @@ func init() { for i := 1; i <= nelem; i++ { table.RawSetInt(offset+i, reg.Get(RA+i)) } - return 0 - }, - func(L *LState, inst uint32, baseframe *callFrame) int { //OP_CLOSE - cf := L.currentFrame - lbase := cf.LocalBase + case OP_CLOSE: A := int(inst>>18) & 0xff //GETA RA := lbase + A // +inline-call L.closeUpvalues RA - return 0 - }, - func(L *LState, inst uint32, baseframe *callFrame) int { //OP_CLOSURE - reg := L.reg - cf := L.currentFrame - lbase := cf.LocalBase + case OP_CLOSURE: A := int(inst>>18) & 0xff //GETA RA := lbase + A Bx := int(inst & 0x3ffff) //GETBX @@ -801,12 +513,7 @@ func init() { closure.Upvalues[i] = cf.Fn.Upvalues[B] } } - return 0 - }, - func(L *LState, inst uint32, baseframe *callFrame) int { //OP_VARARG - reg := L.reg - cf := L.currentFrame - lbase := cf.LocalBase + case OP_VARARG: A := int(inst>>18) & 0xff //GETA RA := lbase + A B := int(inst & 0x1ff) //GETB @@ -820,35 +527,111 @@ func init() { nwant = nvarargs } // +inline-call reg.CopyRange RA cf.Base+nparams+1 cf.LocalBase nwant - return 0 - }, - func(L *LState, inst uint32, baseframe *callFrame) int { //OP_NOP - return 0 - }, + case OP_NOP: + } } + + L.RaiseError(L.ctx.Err().Error()) } -func opArith(L *LState, inst uint32, baseframe *callFrame) int { //OP_ADD, OP_SUB, OP_MUL, OP_DIV, OP_MOD, OP_POW - reg := L.reg - cf := L.currentFrame - lbase := cf.LocalBase - A := int(inst>>18) & 0xff //GETA - RA := lbase + A - opcode := int(inst >> 26) //GETOPCODE - B := int(inst & 0x1ff) //GETB - C := int(inst>>9) & 0x1ff //GETC - lhs := L.rkValue(B) - rhs := L.rkValue(C) - v1, ok1 := lhs.(LNumber) - v2, ok2 := rhs.(LNumber) - if ok1 && ok2 { - v := numberArith(L, opcode, LNumber(v1), LNumber(v2)) - // +inline-call reg.SetNumber RA v +// regv is the first target register to copy the return values to. +// It can be reg.top, indicating that the copied values are going into new registers, or it can be below reg.top +// Indicating that the values should be within the existing registers. +// b is the available number of return values + 1. +// n is the desired number of return values. +// If n more than the available return values then the extra values are set to nil. +// When this function returns the top of the registry will be set to regv+n. +func copyReturnValues(L *LState, regv, start, n, b int) { // +inline-start + if b == 1 { + // +inline-call L.reg.FillNil regv n } else { - v := objectArith(L, opcode, lhs, rhs) - // +inline-call reg.Set RA v + // +inline-call L.reg.CopyRange regv start -1 n + if b > 1 && n > (b-1) { + // +inline-call L.reg.FillNil regv+b-1 n-(b-1) + } } - return 0 +} // +inline-end + +func switchToParentThread(L *LState, nargs int, haserror bool, kill bool) { + parent := L.Parent + if parent == nil { + L.RaiseError("can not yield from outside of a coroutine") + } + L.G.CurrentThread = parent + L.Parent = nil + if !L.wrapped { + if haserror { + parent.Push(LFalse) + } else { + parent.Push(LTrue) + } + } + L.XMoveTo(parent, nargs) + L.stack.Pop() + offset := L.currentFrame.LocalBase - L.currentFrame.ReturnBase + L.currentFrame = L.stack.Last() + L.reg.SetTop(L.reg.Top() - offset) // remove 'yield' function(including tailcalled functions) + if kill { + L.kill() + } +} + +func callGFunction(L *LState, tailcall bool) bool { + frame := L.currentFrame + gfnret := frame.Fn.GFunction(L) + if tailcall { + L.currentFrame = L.RemoveCallerFrame() + } + + if gfnret < 0 { + switchToParentThread(L, L.GetTop(), false, false) + return true + } + + wantret := frame.NRet + if wantret == MultRet { + wantret = gfnret + } + + if tailcall && L.Parent != nil && L.stack.Sp() == 1 { + switchToParentThread(L, wantret, false, true) + return true + } + + // +inline-call L.reg.CopyRange frame.ReturnBase L.reg.Top()-gfnret -1 wantret + L.stack.Pop() + L.currentFrame = L.stack.Last() + return false +} + +func threadRun(L *LState) { + if L.stack.IsEmpty() { + return + } + + defer func() { + if rcv := recover(); rcv != nil { + var lv LValue + if v, ok := rcv.(*ApiError); ok { + lv = v.Object + } else { + lv = LString(fmt.Sprint(rcv)) + } + if parent := L.Parent; parent != nil { + if L.wrapped { + L.Push(lv) + parent.Panic(L) + } else { + L.SetTop(0) + L.Push(lv) + switchToParentThread(L, 1, true, true) + } + } else { + panic(rcv) + } + } + }() + mainLoop(L, nil) } func luaModulo(lhs, rhs LNumber) LNumber { diff --git a/state.go b/state.go index 292f93b4..fa50dcaf 100644 --- a/state.go +++ b/state.go @@ -1,5 +1,4 @@ package lua - //////////////////////////////////////////////////////// // This file was generated by go-inline. DO NOT EDIT. // //////////////////////////////////////////////////////// @@ -404,14 +403,14 @@ func (rg *registry) forceResize(newSize int) { } func (rg *registry) SetTop(topi int) { // +inline-start - // this section is inlined by go-inline - // source function is 'func (rg *registry) checkSize(requiredSize int) ' in '_state.go' - { - requiredSize := topi - if requiredSize > cap(rg.array) { - rg.resize(requiredSize) - } +// this section is inlined by go-inline +// source function is 'func (rg *registry) checkSize(requiredSize int) ' in '_state.go' +{ +requiredSize := topi + if requiredSize > cap(rg.array) { + rg.resize(requiredSize) } +} oldtopi := rg.top rg.top = topi for i := oldtopi; i < rg.top; i++ { @@ -436,14 +435,14 @@ func (rg *registry) Top() int { func (rg *registry) Push(v LValue) { newSize := rg.top + 1 - // this section is inlined by go-inline - // source function is 'func (rg *registry) checkSize(requiredSize int) ' in '_state.go' - { - requiredSize := newSize - if requiredSize > cap(rg.array) { - rg.resize(requiredSize) - } +// this section is inlined by go-inline +// source function is 'func (rg *registry) checkSize(requiredSize int) ' in '_state.go' +{ +requiredSize := newSize + if requiredSize > cap(rg.array) { + rg.resize(requiredSize) } +} rg.array[rg.top] = v rg.top++ } @@ -470,14 +469,14 @@ func (rg *registry) Get(reg int) LValue { // CopyRange should ideally be renamed to MoveRange. func (rg *registry) CopyRange(regv, start, limit, n int) { // +inline-start newSize := regv + n - // this section is inlined by go-inline - // source function is 'func (rg *registry) checkSize(requiredSize int) ' in '_state.go' - { - requiredSize := newSize - if requiredSize > cap(rg.array) { - rg.resize(requiredSize) - } +// this section is inlined by go-inline +// source function is 'func (rg *registry) checkSize(requiredSize int) ' in '_state.go' +{ +requiredSize := newSize + if requiredSize > cap(rg.array) { + rg.resize(requiredSize) } +} if limit == -1 || limit > rg.top { limit = rg.top } @@ -505,14 +504,14 @@ func (rg *registry) CopyRange(regv, start, limit, n int) { // +inline-start // FillNil fills the registry with nil values from regm to regm+n and then sets the registry top to regm+n func (rg *registry) FillNil(regm, n int) { // +inline-start newSize := regm + n - // this section is inlined by go-inline - // source function is 'func (rg *registry) checkSize(requiredSize int) ' in '_state.go' - { - requiredSize := newSize - if requiredSize > cap(rg.array) { - rg.resize(requiredSize) - } +// this section is inlined by go-inline +// source function is 'func (rg *registry) checkSize(requiredSize int) ' in '_state.go' +{ +requiredSize := newSize + if requiredSize > cap(rg.array) { + rg.resize(requiredSize) } +} for i := 0; i < n; i++ { rg.array[regm+i] = LNil } @@ -531,81 +530,81 @@ func (rg *registry) FillNil(regm, n int) { // +inline-start func (rg *registry) Insert(value LValue, reg int) { top := rg.Top() if reg >= top { - // this section is inlined by go-inline - // source function is 'func (rg *registry) Set(regi int, vali LValue) ' in '_state.go' - { - regi := reg - vali := value - newSize := regi + 1 - // this section is inlined by go-inline - // source function is 'func (rg *registry) checkSize(requiredSize int) ' in '_state.go' - { - requiredSize := newSize - if requiredSize > cap(rg.array) { - rg.resize(requiredSize) - } - } - rg.array[regi] = vali - if regi >= rg.top { - rg.top = regi + 1 - } - } +// this section is inlined by go-inline +// source function is 'func (rg *registry) Set(regi int, vali LValue) ' in '_state.go' +{ +regi := reg +vali := value + newSize := regi + 1 +// this section is inlined by go-inline +// source function is 'func (rg *registry) checkSize(requiredSize int) ' in '_state.go' +{ +requiredSize := newSize + if requiredSize > cap(rg.array) { + rg.resize(requiredSize) + } +} + rg.array[regi] = vali + if regi >= rg.top { + rg.top = regi + 1 + } +} return } top-- for ; top >= reg; top-- { // FIXME consider using copy() here if Insert() is called enough - // this section is inlined by go-inline - // source function is 'func (rg *registry) Set(regi int, vali LValue) ' in '_state.go' - { - regi := top + 1 - vali := rg.Get(top) - newSize := regi + 1 - // this section is inlined by go-inline - // source function is 'func (rg *registry) checkSize(requiredSize int) ' in '_state.go' - { - requiredSize := newSize - if requiredSize > cap(rg.array) { - rg.resize(requiredSize) - } - } - rg.array[regi] = vali - if regi >= rg.top { - rg.top = regi + 1 - } - } +// this section is inlined by go-inline +// source function is 'func (rg *registry) Set(regi int, vali LValue) ' in '_state.go' +{ +regi := top+1 +vali := rg.Get(top) + newSize := regi + 1 +// this section is inlined by go-inline +// source function is 'func (rg *registry) checkSize(requiredSize int) ' in '_state.go' +{ +requiredSize := newSize + if requiredSize > cap(rg.array) { + rg.resize(requiredSize) } - // this section is inlined by go-inline - // source function is 'func (rg *registry) Set(regi int, vali LValue) ' in '_state.go' - { - regi := reg - vali := value - newSize := regi + 1 - // this section is inlined by go-inline - // source function is 'func (rg *registry) checkSize(requiredSize int) ' in '_state.go' - { - requiredSize := newSize - if requiredSize > cap(rg.array) { - rg.resize(requiredSize) - } - } - rg.array[regi] = vali - if regi >= rg.top { - rg.top = regi + 1 - } +} + rg.array[regi] = vali + if regi >= rg.top { + rg.top = regi + 1 } +} + } +// this section is inlined by go-inline +// source function is 'func (rg *registry) Set(regi int, vali LValue) ' in '_state.go' +{ +regi := reg +vali := value + newSize := regi + 1 +// this section is inlined by go-inline +// source function is 'func (rg *registry) checkSize(requiredSize int) ' in '_state.go' +{ +requiredSize := newSize + if requiredSize > cap(rg.array) { + rg.resize(requiredSize) + } +} + rg.array[regi] = vali + if regi >= rg.top { + rg.top = regi + 1 + } +} } func (rg *registry) Set(regi int, vali LValue) { // +inline-start newSize := regi + 1 - // this section is inlined by go-inline - // source function is 'func (rg *registry) checkSize(requiredSize int) ' in '_state.go' - { - requiredSize := newSize - if requiredSize > cap(rg.array) { - rg.resize(requiredSize) - } +// this section is inlined by go-inline +// source function is 'func (rg *registry) checkSize(requiredSize int) ' in '_state.go' +{ +requiredSize := newSize + if requiredSize > cap(rg.array) { + rg.resize(requiredSize) } +} rg.array[regi] = vali if regi >= rg.top { rg.top = regi + 1 @@ -614,14 +613,14 @@ func (rg *registry) Set(regi int, vali LValue) { // +inline-start func (rg *registry) SetNumber(regi int, vali LNumber) { // +inline-start newSize := regi + 1 - // this section is inlined by go-inline - // source function is 'func (rg *registry) checkSize(requiredSize int) ' in '_state.go' - { - requiredSize := newSize - if requiredSize > cap(rg.array) { - rg.resize(requiredSize) - } +// this section is inlined by go-inline +// source function is 'func (rg *registry) checkSize(requiredSize int) ' in '_state.go' +{ +requiredSize := newSize + if requiredSize > cap(rg.array) { + rg.resize(requiredSize) } +} rg.array[regi] = rg.alloc.LNumber2I(vali) if regi >= rg.top { rg.top = regi + 1 @@ -676,7 +675,6 @@ func newLState(options Options) *LState { wrapped: false, uvcache: nil, hasErrorFunc: false, - mainLoop: mainLoop, ctx: nil, } if options.MinimizeStackMemory { @@ -1043,15 +1041,15 @@ func (ls *LState) initCallFrame(cf *callFrame) { // +inline-start if nargs < np { // default any missing arguments to nil newSize := cf.LocalBase + np - // this section is inlined by go-inline - // source function is 'func (rg *registry) checkSize(requiredSize int) ' in '_state.go' - { - rg := ls.reg - requiredSize := newSize - if requiredSize > cap(rg.array) { - rg.resize(requiredSize) - } - } +// this section is inlined by go-inline +// source function is 'func (rg *registry) checkSize(requiredSize int) ' in '_state.go' +{ +rg := ls.reg +requiredSize := newSize + if requiredSize > cap(rg.array) { + rg.resize(requiredSize) + } +} for i := nargs; i < np; i++ { ls.reg.array[cf.LocalBase+i] = LNil } @@ -1064,15 +1062,15 @@ func (ls *LState) initCallFrame(cf *callFrame) { // +inline-start nargs = int(proto.NumUsedRegisters) } newSize := cf.LocalBase + nargs - // this section is inlined by go-inline - // source function is 'func (rg *registry) checkSize(requiredSize int) ' in '_state.go' - { - rg := ls.reg - requiredSize := newSize - if requiredSize > cap(rg.array) { - rg.resize(requiredSize) - } - } +// this section is inlined by go-inline +// source function is 'func (rg *registry) checkSize(requiredSize int) ' in '_state.go' +{ +rg := ls.reg +requiredSize := newSize + if requiredSize > cap(rg.array) { + rg.resize(requiredSize) + } +} for i := np; i < nargs; i++ { ls.reg.array[cf.LocalBase+i] = LNil } @@ -1142,104 +1140,104 @@ func (ls *LState) pushCallFrame(cf callFrame, fn LValue, meta bool) { // +inline } ls.stack.Push(cf) newcf := ls.stack.Last() - // this section is inlined by go-inline - // source function is 'func (ls *LState) initCallFrame(cf *callFrame) ' in '_state.go' - { - cf := newcf - if cf.Fn.IsG { - ls.reg.SetTop(cf.LocalBase + cf.NArgs) - } else { - proto := cf.Fn.Proto - nargs := cf.NArgs - np := int(proto.NumParameters) - if nargs < np { - // default any missing arguments to nil - newSize := cf.LocalBase + np - // this section is inlined by go-inline - // source function is 'func (rg *registry) checkSize(requiredSize int) ' in '_state.go' - { - rg := ls.reg - requiredSize := newSize - if requiredSize > cap(rg.array) { - rg.resize(requiredSize) - } - } - for i := nargs; i < np; i++ { - ls.reg.array[cf.LocalBase+i] = LNil - } - nargs = np - ls.reg.top = newSize +// this section is inlined by go-inline +// source function is 'func (ls *LState) initCallFrame(cf *callFrame) ' in '_state.go' +{ +cf := newcf + if cf.Fn.IsG { + ls.reg.SetTop(cf.LocalBase + cf.NArgs) + } else { + proto := cf.Fn.Proto + nargs := cf.NArgs + np := int(proto.NumParameters) + if nargs < np { + // default any missing arguments to nil + newSize := cf.LocalBase + np +// this section is inlined by go-inline +// source function is 'func (rg *registry) checkSize(requiredSize int) ' in '_state.go' +{ +rg := ls.reg +requiredSize := newSize + if requiredSize > cap(rg.array) { + rg.resize(requiredSize) + } +} + for i := nargs; i < np; i++ { + ls.reg.array[cf.LocalBase+i] = LNil } + nargs = np + ls.reg.top = newSize + } - if (proto.IsVarArg & VarArgIsVarArg) == 0 { - if nargs < int(proto.NumUsedRegisters) { - nargs = int(proto.NumUsedRegisters) - } - newSize := cf.LocalBase + nargs - // this section is inlined by go-inline - // source function is 'func (rg *registry) checkSize(requiredSize int) ' in '_state.go' - { - rg := ls.reg - requiredSize := newSize - if requiredSize > cap(rg.array) { - rg.resize(requiredSize) - } - } - for i := np; i < nargs; i++ { - ls.reg.array[cf.LocalBase+i] = LNil - } - ls.reg.top = cf.LocalBase + int(proto.NumUsedRegisters) - } else { - /* swap vararg positions: - closure - namedparam1 <- lbase - namedparam2 - vararg1 - vararg2 - - TO - - closure - nil - nil - vararg1 - vararg2 - namedparam1 <- lbase - namedparam2 - */ - nvarargs := nargs - np - if nvarargs < 0 { - nvarargs = 0 - } + if (proto.IsVarArg & VarArgIsVarArg) == 0 { + if nargs < int(proto.NumUsedRegisters) { + nargs = int(proto.NumUsedRegisters) + } + newSize := cf.LocalBase + nargs +// this section is inlined by go-inline +// source function is 'func (rg *registry) checkSize(requiredSize int) ' in '_state.go' +{ +rg := ls.reg +requiredSize := newSize + if requiredSize > cap(rg.array) { + rg.resize(requiredSize) + } +} + for i := np; i < nargs; i++ { + ls.reg.array[cf.LocalBase+i] = LNil + } + ls.reg.top = cf.LocalBase + int(proto.NumUsedRegisters) + } else { + /* swap vararg positions: + closure + namedparam1 <- lbase + namedparam2 + vararg1 + vararg2 - ls.reg.SetTop(cf.LocalBase + nargs + np) - for i := 0; i < np; i++ { - //ls.reg.Set(cf.LocalBase+nargs+i, ls.reg.Get(cf.LocalBase+i)) - ls.reg.array[cf.LocalBase+nargs+i] = ls.reg.array[cf.LocalBase+i] - //ls.reg.Set(cf.LocalBase+i, LNil) - ls.reg.array[cf.LocalBase+i] = LNil - } + TO - if CompatVarArg { - ls.reg.SetTop(cf.LocalBase + nargs + np + 1) - if (proto.IsVarArg & VarArgNeedsArg) != 0 { - argtb := newLTable(nvarargs, 0) - for i := 0; i < nvarargs; i++ { - argtb.RawSetInt(i+1, ls.reg.Get(cf.LocalBase+np+i)) - } - argtb.RawSetString("n", LNumber(nvarargs)) - //ls.reg.Set(cf.LocalBase+nargs+np, argtb) - ls.reg.array[cf.LocalBase+nargs+np] = argtb - } else { - ls.reg.array[cf.LocalBase+nargs+np] = LNil + closure + nil + nil + vararg1 + vararg2 + namedparam1 <- lbase + namedparam2 + */ + nvarargs := nargs - np + if nvarargs < 0 { + nvarargs = 0 + } + + ls.reg.SetTop(cf.LocalBase + nargs + np) + for i := 0; i < np; i++ { + //ls.reg.Set(cf.LocalBase+nargs+i, ls.reg.Get(cf.LocalBase+i)) + ls.reg.array[cf.LocalBase+nargs+i] = ls.reg.array[cf.LocalBase+i] + //ls.reg.Set(cf.LocalBase+i, LNil) + ls.reg.array[cf.LocalBase+i] = LNil + } + + if CompatVarArg { + ls.reg.SetTop(cf.LocalBase + nargs + np + 1) + if (proto.IsVarArg & VarArgNeedsArg) != 0 { + argtb := newLTable(nvarargs, 0) + for i := 0; i < nvarargs; i++ { + argtb.RawSetInt(i+1, ls.reg.Get(cf.LocalBase+np+i)) } + argtb.RawSetString("n", LNumber(nvarargs)) + //ls.reg.Set(cf.LocalBase+nargs+np, argtb) + ls.reg.array[cf.LocalBase+nargs+np] = argtb + } else { + ls.reg.array[cf.LocalBase+nargs+np] = LNil } - cf.LocalBase += nargs - maxreg := cf.LocalBase + int(proto.NumUsedRegisters) - ls.reg.SetTop(maxreg) } + cf.LocalBase += nargs + maxreg := cf.LocalBase + int(proto.NumUsedRegisters) + ls.reg.SetTop(maxreg) } } +} ls.currentFrame = newcf } // +inline-end @@ -1264,9 +1262,9 @@ func (ls *LState) callR(nargs, nret, rbase int) { if ls.G.MainThread == nil { ls.G.MainThread = ls ls.G.CurrentThread = ls - ls.mainLoop(ls, nil) + mainLoop(ls, nil) } else { - ls.mainLoop(ls, ls.currentFrame) + mainLoop(ls, ls.currentFrame) } if nret != MultRet { ls.reg.SetTop(rbase + nret) @@ -1617,7 +1615,6 @@ func (ls *LState) NewThread() (*LState, context.CancelFunc) { thread.Env = ls.Env var f context.CancelFunc = nil if ls.ctx != nil { - thread.mainLoop = mainLoopWithContext thread.ctx, f = context.WithCancel(ls.ctx) thread.ctxCancelFn = f } @@ -2257,9 +2254,8 @@ func (ls *LState) SetMx(mx int) { }() } -// SetContext set a context ctx to this LState. The provided ctx must be non-nil. +// SetContext set a context ctx to this LState. func (ls *LState) SetContext(ctx context.Context) { - ls.mainLoop = mainLoopWithContext ls.ctx = ctx } @@ -2271,7 +2267,6 @@ func (ls *LState) Context() context.Context { // RemoveContext removes the context associated with this LState and returns this context. func (ls *LState) RemoveContext() context.Context { oldctx := ls.ctx - ls.mainLoop = mainLoop ls.ctx = nil return oldctx } @@ -2304,3 +2299,4 @@ func (ls *LState) RemoveCallerFrame() *callFrame { /* }}} */ // + diff --git a/value.go b/value.go index 4156e9d5..3044f1b4 100644 --- a/value.go +++ b/value.go @@ -192,7 +192,6 @@ type LState struct { wrapped bool uvcache *Upvalue hasErrorFunc bool - mainLoop func(*LState, *callFrame) ctx context.Context ctxCancelFn context.CancelFunc } diff --git a/vm.go b/vm.go index 97335a75..4d96c004 100644 --- a/vm.go +++ b/vm.go @@ -1,5 +1,4 @@ package lua - //////////////////////////////////////////////////////// // This file was generated by go-inline. DO NOT EDIT. // //////////////////////////////////////////////////////// @@ -11,9 +10,6 @@ import ( ) func mainLoop(L *LState, baseframe *callFrame) { - var inst uint32 - var cf *callFrame - if L.stack.IsEmpty() { return } @@ -24,340 +20,65 @@ func mainLoop(L *LState, baseframe *callFrame) { return } - for { - cf = L.currentFrame - inst = cf.Fn.Proto.Code[cf.Pc] - cf.Pc++ - if jumpTable[int(inst>>26)](L, inst, baseframe) == 1 { - return - } - } -} - -func mainLoopWithContext(L *LState, baseframe *callFrame) { - var inst uint32 - var cf *callFrame - - if L.stack.IsEmpty() { - return - } - - L.currentFrame = L.stack.Last() - if L.currentFrame.Fn.IsG { - callGFunction(L, false) - return - } - - for { - cf = L.currentFrame - inst = cf.Fn.Proto.Code[cf.Pc] + reg := L.reg + for L.ctx == nil || L.ctx.Err() == nil { + cf := L.currentFrame + inst := cf.Fn.Proto.Code[cf.Pc] + lbase := cf.LocalBase cf.Pc++ - select { - case <-L.ctx.Done(): - L.RaiseError(L.ctx.Err().Error()) - return - default: - if jumpTable[int(inst>>26)](L, inst, baseframe) == 1 { - return - } - } - } -} - -// regv is the first target register to copy the return values to. -// It can be reg.top, indicating that the copied values are going into new registers, or it can be below reg.top -// Indicating that the values should be within the existing registers. -// b is the available number of return values + 1. -// n is the desired number of return values. -// If n more than the available return values then the extra values are set to nil. -// When this function returns the top of the registry will be set to regv+n. -func copyReturnValues(L *LState, regv, start, n, b int) { // +inline-start - if b == 1 { - // this section is inlined by go-inline - // source function is 'func (rg *registry) FillNil(regm, n int) ' in '_state.go' - { - rg := L.reg - regm := regv - newSize := regm + n - // this section is inlined by go-inline - // source function is 'func (rg *registry) checkSize(requiredSize int) ' in '_state.go' - { - requiredSize := newSize - if requiredSize > cap(rg.array) { - rg.resize(requiredSize) - } - } - for i := 0; i < n; i++ { - rg.array[regm+i] = LNil - } - // values beyond top don't need to be valid LValues, so setting them to nil is fine - // setting them to nil rather than LNil lets us invoke the golang memclr opto - oldtop := rg.top - rg.top = regm + n - if rg.top < oldtop { - nilRange := rg.array[rg.top:oldtop] - for i := range nilRange { - nilRange[i] = nil - } - } - } - } else { - // this section is inlined by go-inline - // source function is 'func (rg *registry) CopyRange(regv, start, limit, n int) ' in '_state.go' - { - rg := L.reg - limit := -1 - newSize := regv + n - // this section is inlined by go-inline - // source function is 'func (rg *registry) checkSize(requiredSize int) ' in '_state.go' - { - requiredSize := newSize - if requiredSize > cap(rg.array) { - rg.resize(requiredSize) - } - } - if limit == -1 || limit > rg.top { - limit = rg.top - } - for i := 0; i < n; i++ { - srcIdx := start + i - if srcIdx >= limit || srcIdx < 0 { - rg.array[regv+i] = LNil - } else { - rg.array[regv+i] = rg.array[srcIdx] - } - } - - // values beyond top don't need to be valid LValues, so setting them to nil is fine - // setting them to nil rather than LNil lets us invoke the golang memclr opto - oldtop := rg.top - rg.top = regv + n - if rg.top < oldtop { - nilRange := rg.array[rg.top:oldtop] - for i := range nilRange { - nilRange[i] = nil - } - } - } - if b > 1 && n > (b-1) { - // this section is inlined by go-inline - // source function is 'func (rg *registry) FillNil(regm, n int) ' in '_state.go' - { - rg := L.reg - regm := regv + b - 1 - n := n - (b - 1) - newSize := regm + n - // this section is inlined by go-inline - // source function is 'func (rg *registry) checkSize(requiredSize int) ' in '_state.go' - { - requiredSize := newSize - if requiredSize > cap(rg.array) { - rg.resize(requiredSize) - } - } - for i := 0; i < n; i++ { - rg.array[regm+i] = LNil - } - // values beyond top don't need to be valid LValues, so setting them to nil is fine - // setting them to nil rather than LNil lets us invoke the golang memclr opto - oldtop := rg.top - rg.top = regm + n - if rg.top < oldtop { - nilRange := rg.array[rg.top:oldtop] - for i := range nilRange { - nilRange[i] = nil - } - } - } - } - } -} // +inline-end - -func switchToParentThread(L *LState, nargs int, haserror bool, kill bool) { - parent := L.Parent - if parent == nil { - L.RaiseError("can not yield from outside of a coroutine") - } - L.G.CurrentThread = parent - L.Parent = nil - if !L.wrapped { - if haserror { - parent.Push(LFalse) - } else { - parent.Push(LTrue) - } - } - L.XMoveTo(parent, nargs) - L.stack.Pop() - offset := L.currentFrame.LocalBase - L.currentFrame.ReturnBase - L.currentFrame = L.stack.Last() - L.reg.SetTop(L.reg.Top() - offset) // remove 'yield' function(including tailcalled functions) - if kill { - L.kill() - } -} - -func callGFunction(L *LState, tailcall bool) bool { - frame := L.currentFrame - gfnret := frame.Fn.GFunction(L) - if tailcall { - L.currentFrame = L.RemoveCallerFrame() - } - - if gfnret < 0 { - switchToParentThread(L, L.GetTop(), false, false) - return true - } - - wantret := frame.NRet - if wantret == MultRet { - wantret = gfnret - } - - if tailcall && L.Parent != nil && L.stack.Sp() == 1 { - switchToParentThread(L, wantret, false, true) - return true - } - - // this section is inlined by go-inline - // source function is 'func (rg *registry) CopyRange(regv, start, limit, n int) ' in '_state.go' - { - rg := L.reg - regv := frame.ReturnBase - start := L.reg.Top() - gfnret - limit := -1 - n := wantret - newSize := regv + n - // this section is inlined by go-inline - // source function is 'func (rg *registry) checkSize(requiredSize int) ' in '_state.go' - { - requiredSize := newSize - if requiredSize > cap(rg.array) { - rg.resize(requiredSize) - } - } - if limit == -1 || limit > rg.top { - limit = rg.top - } - for i := 0; i < n; i++ { - srcIdx := start + i - if srcIdx >= limit || srcIdx < 0 { - rg.array[regv+i] = LNil - } else { - rg.array[regv+i] = rg.array[srcIdx] - } - } - - // values beyond top don't need to be valid LValues, so setting them to nil is fine - // setting them to nil rather than LNil lets us invoke the golang memclr opto - oldtop := rg.top - rg.top = regv + n - if rg.top < oldtop { - nilRange := rg.array[rg.top:oldtop] - for i := range nilRange { - nilRange[i] = nil - } - } - } - L.stack.Pop() - L.currentFrame = L.stack.Last() - return false -} -func threadRun(L *LState) { - if L.stack.IsEmpty() { - return - } - - defer func() { - if rcv := recover(); rcv != nil { - var lv LValue - if v, ok := rcv.(*ApiError); ok { - lv = v.Object - } else { - lv = LString(fmt.Sprint(rcv)) - } - if parent := L.Parent; parent != nil { - if L.wrapped { - L.Push(lv) - parent.Panic(L) - } else { - L.SetTop(0) - L.Push(lv) - switchToParentThread(L, 1, true, true) - } - } else { - panic(rcv) - } - } - }() - L.mainLoop(L, nil) -} - -type instFunc func(*LState, uint32, *callFrame) int - -var jumpTable [opCodeMax + 1]instFunc - -func init() { - jumpTable = [opCodeMax + 1]instFunc{ - func(L *LState, inst uint32, baseframe *callFrame) int { //OP_MOVE - reg := L.reg - cf := L.currentFrame - lbase := cf.LocalBase + opcode := int(inst >> 26) + switch opcode { + case OP_MOVE: A := int(inst>>18) & 0xff //GETA RA := lbase + A B := int(inst & 0x1ff) //GETB v := reg.Get(lbase + B) - // this section is inlined by go-inline - // source function is 'func (rg *registry) Set(regi int, vali LValue) ' in '_state.go' - { - rg := reg - regi := RA - vali := v - newSize := regi + 1 - // this section is inlined by go-inline - // source function is 'func (rg *registry) checkSize(requiredSize int) ' in '_state.go' - { - requiredSize := newSize - if requiredSize > cap(rg.array) { - rg.resize(requiredSize) - } - } - rg.array[regi] = vali - if regi >= rg.top { - rg.top = regi + 1 - } - } - return 0 - }, - func(L *LState, inst uint32, baseframe *callFrame) int { //OP_MOVEN - reg := L.reg - cf := L.currentFrame - lbase := cf.LocalBase +// this section is inlined by go-inline +// source function is 'func (rg *registry) Set(regi int, vali LValue) ' in '_state.go' +{ +rg := reg +regi := RA +vali := v + newSize := regi + 1 +// this section is inlined by go-inline +// source function is 'func (rg *registry) checkSize(requiredSize int) ' in '_state.go' +{ +requiredSize := newSize + if requiredSize > cap(rg.array) { + rg.resize(requiredSize) + } +} + rg.array[regi] = vali + if regi >= rg.top { + rg.top = regi + 1 + } +} + case OP_MOVEN: A := int(inst>>18) & 0xff //GETA B := int(inst & 0x1ff) //GETB C := int(inst>>9) & 0x1ff //GETC v := reg.Get(lbase + B) - // this section is inlined by go-inline - // source function is 'func (rg *registry) Set(regi int, vali LValue) ' in '_state.go' - { - rg := reg - regi := lbase + A - vali := v - newSize := regi + 1 - // this section is inlined by go-inline - // source function is 'func (rg *registry) checkSize(requiredSize int) ' in '_state.go' - { - requiredSize := newSize - if requiredSize > cap(rg.array) { - rg.resize(requiredSize) - } - } - rg.array[regi] = vali - if regi >= rg.top { - rg.top = regi + 1 - } - } +// this section is inlined by go-inline +// source function is 'func (rg *registry) Set(regi int, vali LValue) ' in '_state.go' +{ +rg := reg +regi := lbase+A +vali := v + newSize := regi + 1 +// this section is inlined by go-inline +// source function is 'func (rg *registry) checkSize(requiredSize int) ' in '_state.go' +{ +requiredSize := newSize + if requiredSize > cap(rg.array) { + rg.resize(requiredSize) + } +} + rg.array[regi] = vali + if regi >= rg.top { + rg.top = regi + 1 + } +} code := cf.Fn.Proto.Code pc := cf.Pc for i := 0; i < C; i++ { @@ -366,479 +87,458 @@ func init() { A = int(inst>>18) & 0xff //GETA B = int(inst & 0x1ff) //GETB v := reg.Get(lbase + B) - // this section is inlined by go-inline - // source function is 'func (rg *registry) Set(regi int, vali LValue) ' in '_state.go' - { - rg := reg - regi := lbase + A - vali := v - newSize := regi + 1 - // this section is inlined by go-inline - // source function is 'func (rg *registry) checkSize(requiredSize int) ' in '_state.go' - { - requiredSize := newSize - if requiredSize > cap(rg.array) { - rg.resize(requiredSize) - } - } - rg.array[regi] = vali - if regi >= rg.top { - rg.top = regi + 1 - } - } +// this section is inlined by go-inline +// source function is 'func (rg *registry) Set(regi int, vali LValue) ' in '_state.go' +{ +rg := reg +regi := lbase+A +vali := v + newSize := regi + 1 +// this section is inlined by go-inline +// source function is 'func (rg *registry) checkSize(requiredSize int) ' in '_state.go' +{ +requiredSize := newSize + if requiredSize > cap(rg.array) { + rg.resize(requiredSize) + } +} + rg.array[regi] = vali + if regi >= rg.top { + rg.top = regi + 1 + } +} } cf.Pc = pc - return 0 - }, - func(L *LState, inst uint32, baseframe *callFrame) int { //OP_LOADK - reg := L.reg - cf := L.currentFrame - lbase := cf.LocalBase + case OP_LOADK: A := int(inst>>18) & 0xff //GETA RA := lbase + A Bx := int(inst & 0x3ffff) //GETBX v := cf.Fn.Proto.Constants[Bx] - // this section is inlined by go-inline - // source function is 'func (rg *registry) Set(regi int, vali LValue) ' in '_state.go' - { - rg := reg - regi := RA - vali := v - newSize := regi + 1 - // this section is inlined by go-inline - // source function is 'func (rg *registry) checkSize(requiredSize int) ' in '_state.go' - { - requiredSize := newSize - if requiredSize > cap(rg.array) { - rg.resize(requiredSize) - } - } - rg.array[regi] = vali - if regi >= rg.top { - rg.top = regi + 1 - } - } - return 0 - }, - func(L *LState, inst uint32, baseframe *callFrame) int { //OP_LOADBOOL - reg := L.reg - cf := L.currentFrame - lbase := cf.LocalBase +// this section is inlined by go-inline +// source function is 'func (rg *registry) Set(regi int, vali LValue) ' in '_state.go' +{ +rg := reg +regi := RA +vali := v + newSize := regi + 1 +// this section is inlined by go-inline +// source function is 'func (rg *registry) checkSize(requiredSize int) ' in '_state.go' +{ +requiredSize := newSize + if requiredSize > cap(rg.array) { + rg.resize(requiredSize) + } +} + rg.array[regi] = vali + if regi >= rg.top { + rg.top = regi + 1 + } +} + case OP_LOADBOOL: A := int(inst>>18) & 0xff //GETA RA := lbase + A B := int(inst & 0x1ff) //GETB C := int(inst>>9) & 0x1ff //GETC if B != 0 { - // this section is inlined by go-inline - // source function is 'func (rg *registry) Set(regi int, vali LValue) ' in '_state.go' - { - rg := reg - regi := RA - vali := LTrue - newSize := regi + 1 - // this section is inlined by go-inline - // source function is 'func (rg *registry) checkSize(requiredSize int) ' in '_state.go' - { - requiredSize := newSize - if requiredSize > cap(rg.array) { - rg.resize(requiredSize) - } - } - rg.array[regi] = vali - if regi >= rg.top { - rg.top = regi + 1 - } - } +// this section is inlined by go-inline +// source function is 'func (rg *registry) Set(regi int, vali LValue) ' in '_state.go' +{ +rg := reg +regi := RA +vali := LTrue + newSize := regi + 1 +// this section is inlined by go-inline +// source function is 'func (rg *registry) checkSize(requiredSize int) ' in '_state.go' +{ +requiredSize := newSize + if requiredSize > cap(rg.array) { + rg.resize(requiredSize) + } +} + rg.array[regi] = vali + if regi >= rg.top { + rg.top = regi + 1 + } +} } else { - // this section is inlined by go-inline - // source function is 'func (rg *registry) Set(regi int, vali LValue) ' in '_state.go' - { - rg := reg - regi := RA - vali := LFalse - newSize := regi + 1 - // this section is inlined by go-inline - // source function is 'func (rg *registry) checkSize(requiredSize int) ' in '_state.go' - { - requiredSize := newSize - if requiredSize > cap(rg.array) { - rg.resize(requiredSize) - } - } - rg.array[regi] = vali - if regi >= rg.top { - rg.top = regi + 1 - } - } +// this section is inlined by go-inline +// source function is 'func (rg *registry) Set(regi int, vali LValue) ' in '_state.go' +{ +rg := reg +regi := RA +vali := LFalse + newSize := regi + 1 +// this section is inlined by go-inline +// source function is 'func (rg *registry) checkSize(requiredSize int) ' in '_state.go' +{ +requiredSize := newSize + if requiredSize > cap(rg.array) { + rg.resize(requiredSize) + } +} + rg.array[regi] = vali + if regi >= rg.top { + rg.top = regi + 1 + } +} } if C != 0 { cf.Pc++ } - return 0 - }, - func(L *LState, inst uint32, baseframe *callFrame) int { //OP_LOADNIL - reg := L.reg - cf := L.currentFrame - lbase := cf.LocalBase + case OP_LOADNIL: A := int(inst>>18) & 0xff //GETA RA := lbase + A B := int(inst & 0x1ff) //GETB for i := RA; i <= lbase+B; i++ { - // this section is inlined by go-inline - // source function is 'func (rg *registry) Set(regi int, vali LValue) ' in '_state.go' - { - rg := reg - regi := i - vali := LNil - newSize := regi + 1 - // this section is inlined by go-inline - // source function is 'func (rg *registry) checkSize(requiredSize int) ' in '_state.go' - { - requiredSize := newSize - if requiredSize > cap(rg.array) { - rg.resize(requiredSize) - } - } - rg.array[regi] = vali - if regi >= rg.top { - rg.top = regi + 1 - } - } +// this section is inlined by go-inline +// source function is 'func (rg *registry) Set(regi int, vali LValue) ' in '_state.go' +{ +rg := reg +regi := i +vali := LNil + newSize := regi + 1 +// this section is inlined by go-inline +// source function is 'func (rg *registry) checkSize(requiredSize int) ' in '_state.go' +{ +requiredSize := newSize + if requiredSize > cap(rg.array) { + rg.resize(requiredSize) + } +} + rg.array[regi] = vali + if regi >= rg.top { + rg.top = regi + 1 + } +} } - return 0 - }, - func(L *LState, inst uint32, baseframe *callFrame) int { //OP_GETUPVAL - reg := L.reg - cf := L.currentFrame - lbase := cf.LocalBase + case OP_GETUPVAL: A := int(inst>>18) & 0xff //GETA RA := lbase + A B := int(inst & 0x1ff) //GETB v := cf.Fn.Upvalues[B].Value() - // this section is inlined by go-inline - // source function is 'func (rg *registry) Set(regi int, vali LValue) ' in '_state.go' - { - rg := reg - regi := RA - vali := v - newSize := regi + 1 - // this section is inlined by go-inline - // source function is 'func (rg *registry) checkSize(requiredSize int) ' in '_state.go' - { - requiredSize := newSize - if requiredSize > cap(rg.array) { - rg.resize(requiredSize) - } - } - rg.array[regi] = vali - if regi >= rg.top { - rg.top = regi + 1 - } - } - return 0 - }, - func(L *LState, inst uint32, baseframe *callFrame) int { //OP_GETGLOBAL - reg := L.reg - cf := L.currentFrame - lbase := cf.LocalBase +// this section is inlined by go-inline +// source function is 'func (rg *registry) Set(regi int, vali LValue) ' in '_state.go' +{ +rg := reg +regi := RA +vali := v + newSize := regi + 1 +// this section is inlined by go-inline +// source function is 'func (rg *registry) checkSize(requiredSize int) ' in '_state.go' +{ +requiredSize := newSize + if requiredSize > cap(rg.array) { + rg.resize(requiredSize) + } +} + rg.array[regi] = vali + if regi >= rg.top { + rg.top = regi + 1 + } +} + case OP_GETGLOBAL: A := int(inst>>18) & 0xff //GETA RA := lbase + A Bx := int(inst & 0x3ffff) //GETBX //reg.Set(RA, L.getField(cf.Fn.Env, cf.Fn.Proto.Constants[Bx])) v := L.getFieldString(cf.Fn.Env, cf.Fn.Proto.stringConstants[Bx]) - // this section is inlined by go-inline - // source function is 'func (rg *registry) Set(regi int, vali LValue) ' in '_state.go' - { - rg := reg - regi := RA - vali := v - newSize := regi + 1 - // this section is inlined by go-inline - // source function is 'func (rg *registry) checkSize(requiredSize int) ' in '_state.go' - { - requiredSize := newSize - if requiredSize > cap(rg.array) { - rg.resize(requiredSize) - } - } - rg.array[regi] = vali - if regi >= rg.top { - rg.top = regi + 1 - } - } - return 0 - }, - func(L *LState, inst uint32, baseframe *callFrame) int { //OP_GETTABLE - reg := L.reg - cf := L.currentFrame - lbase := cf.LocalBase +// this section is inlined by go-inline +// source function is 'func (rg *registry) Set(regi int, vali LValue) ' in '_state.go' +{ +rg := reg +regi := RA +vali := v + newSize := regi + 1 +// this section is inlined by go-inline +// source function is 'func (rg *registry) checkSize(requiredSize int) ' in '_state.go' +{ +requiredSize := newSize + if requiredSize > cap(rg.array) { + rg.resize(requiredSize) + } +} + rg.array[regi] = vali + if regi >= rg.top { + rg.top = regi + 1 + } +} + case OP_GETTABLE: A := int(inst>>18) & 0xff //GETA RA := lbase + A B := int(inst & 0x1ff) //GETB C := int(inst>>9) & 0x1ff //GETC v := L.getField(reg.Get(lbase+B), L.rkValue(C)) - // this section is inlined by go-inline - // source function is 'func (rg *registry) Set(regi int, vali LValue) ' in '_state.go' - { - rg := reg - regi := RA - vali := v - newSize := regi + 1 - // this section is inlined by go-inline - // source function is 'func (rg *registry) checkSize(requiredSize int) ' in '_state.go' - { - requiredSize := newSize - if requiredSize > cap(rg.array) { - rg.resize(requiredSize) - } - } - rg.array[regi] = vali - if regi >= rg.top { - rg.top = regi + 1 - } - } - return 0 - }, - func(L *LState, inst uint32, baseframe *callFrame) int { //OP_GETTABLEKS - reg := L.reg - cf := L.currentFrame - lbase := cf.LocalBase +// this section is inlined by go-inline +// source function is 'func (rg *registry) Set(regi int, vali LValue) ' in '_state.go' +{ +rg := reg +regi := RA +vali := v + newSize := regi + 1 +// this section is inlined by go-inline +// source function is 'func (rg *registry) checkSize(requiredSize int) ' in '_state.go' +{ +requiredSize := newSize + if requiredSize > cap(rg.array) { + rg.resize(requiredSize) + } +} + rg.array[regi] = vali + if regi >= rg.top { + rg.top = regi + 1 + } +} + case OP_GETTABLEKS: A := int(inst>>18) & 0xff //GETA RA := lbase + A B := int(inst & 0x1ff) //GETB C := int(inst>>9) & 0x1ff //GETC v := L.getFieldString(reg.Get(lbase+B), L.rkString(C)) - // this section is inlined by go-inline - // source function is 'func (rg *registry) Set(regi int, vali LValue) ' in '_state.go' - { - rg := reg - regi := RA - vali := v - newSize := regi + 1 - // this section is inlined by go-inline - // source function is 'func (rg *registry) checkSize(requiredSize int) ' in '_state.go' - { - requiredSize := newSize - if requiredSize > cap(rg.array) { - rg.resize(requiredSize) - } - } - rg.array[regi] = vali - if regi >= rg.top { - rg.top = regi + 1 - } - } - return 0 - }, - func(L *LState, inst uint32, baseframe *callFrame) int { //OP_SETGLOBAL - reg := L.reg - cf := L.currentFrame - lbase := cf.LocalBase +// this section is inlined by go-inline +// source function is 'func (rg *registry) Set(regi int, vali LValue) ' in '_state.go' +{ +rg := reg +regi := RA +vali := v + newSize := regi + 1 +// this section is inlined by go-inline +// source function is 'func (rg *registry) checkSize(requiredSize int) ' in '_state.go' +{ +requiredSize := newSize + if requiredSize > cap(rg.array) { + rg.resize(requiredSize) + } +} + rg.array[regi] = vali + if regi >= rg.top { + rg.top = regi + 1 + } +} + case OP_SETGLOBAL: A := int(inst>>18) & 0xff //GETA RA := lbase + A Bx := int(inst & 0x3ffff) //GETBX //L.setField(cf.Fn.Env, cf.Fn.Proto.Constants[Bx], reg.Get(RA)) L.setFieldString(cf.Fn.Env, cf.Fn.Proto.stringConstants[Bx], reg.Get(RA)) - return 0 - }, - func(L *LState, inst uint32, baseframe *callFrame) int { //OP_SETUPVAL - reg := L.reg - cf := L.currentFrame - lbase := cf.LocalBase + case OP_SETUPVAL: A := int(inst>>18) & 0xff //GETA RA := lbase + A B := int(inst & 0x1ff) //GETB cf.Fn.Upvalues[B].SetValue(reg.Get(RA)) - return 0 - }, - func(L *LState, inst uint32, baseframe *callFrame) int { //OP_SETTABLE - reg := L.reg - cf := L.currentFrame - lbase := cf.LocalBase + case OP_SETTABLE: A := int(inst>>18) & 0xff //GETA RA := lbase + A B := int(inst & 0x1ff) //GETB C := int(inst>>9) & 0x1ff //GETC L.setField(reg.Get(RA), L.rkValue(B), L.rkValue(C)) - return 0 - }, - func(L *LState, inst uint32, baseframe *callFrame) int { //OP_SETTABLEKS - reg := L.reg - cf := L.currentFrame - lbase := cf.LocalBase + case OP_SETTABLEKS: A := int(inst>>18) & 0xff //GETA RA := lbase + A B := int(inst & 0x1ff) //GETB C := int(inst>>9) & 0x1ff //GETC L.setFieldString(reg.Get(RA), L.rkString(B), L.rkValue(C)) - return 0 - }, - func(L *LState, inst uint32, baseframe *callFrame) int { //OP_NEWTABLE - reg := L.reg - cf := L.currentFrame - lbase := cf.LocalBase + case OP_NEWTABLE: A := int(inst>>18) & 0xff //GETA RA := lbase + A B := int(inst & 0x1ff) //GETB C := int(inst>>9) & 0x1ff //GETC v := newLTable(B, C) - // this section is inlined by go-inline - // source function is 'func (rg *registry) Set(regi int, vali LValue) ' in '_state.go' - { - rg := reg - regi := RA - vali := v - newSize := regi + 1 - // this section is inlined by go-inline - // source function is 'func (rg *registry) checkSize(requiredSize int) ' in '_state.go' - { - requiredSize := newSize - if requiredSize > cap(rg.array) { - rg.resize(requiredSize) - } - } - rg.array[regi] = vali - if regi >= rg.top { - rg.top = regi + 1 - } - } - return 0 - }, - func(L *LState, inst uint32, baseframe *callFrame) int { //OP_SELF - reg := L.reg - cf := L.currentFrame - lbase := cf.LocalBase +// this section is inlined by go-inline +// source function is 'func (rg *registry) Set(regi int, vali LValue) ' in '_state.go' +{ +rg := reg +regi := RA +vali := v + newSize := regi + 1 +// this section is inlined by go-inline +// source function is 'func (rg *registry) checkSize(requiredSize int) ' in '_state.go' +{ +requiredSize := newSize + if requiredSize > cap(rg.array) { + rg.resize(requiredSize) + } +} + rg.array[regi] = vali + if regi >= rg.top { + rg.top = regi + 1 + } +} + case OP_SELF: A := int(inst>>18) & 0xff //GETA RA := lbase + A B := int(inst & 0x1ff) //GETB C := int(inst>>9) & 0x1ff //GETC selfobj := reg.Get(lbase + B) v := L.getFieldString(selfobj, L.rkString(C)) - // this section is inlined by go-inline - // source function is 'func (rg *registry) Set(regi int, vali LValue) ' in '_state.go' - { - rg := reg - regi := RA - vali := v - newSize := regi + 1 - // this section is inlined by go-inline - // source function is 'func (rg *registry) checkSize(requiredSize int) ' in '_state.go' - { - requiredSize := newSize - if requiredSize > cap(rg.array) { - rg.resize(requiredSize) - } - } - rg.array[regi] = vali - if regi >= rg.top { - rg.top = regi + 1 - } - } - // this section is inlined by go-inline - // source function is 'func (rg *registry) Set(regi int, vali LValue) ' in '_state.go' - { - rg := reg - regi := RA + 1 - vali := selfobj - newSize := regi + 1 - // this section is inlined by go-inline - // source function is 'func (rg *registry) checkSize(requiredSize int) ' in '_state.go' - { - requiredSize := newSize - if requiredSize > cap(rg.array) { - rg.resize(requiredSize) - } - } - rg.array[regi] = vali - if regi >= rg.top { - rg.top = regi + 1 - } +// this section is inlined by go-inline +// source function is 'func (rg *registry) Set(regi int, vali LValue) ' in '_state.go' +{ +rg := reg +regi := RA +vali := v + newSize := regi + 1 +// this section is inlined by go-inline +// source function is 'func (rg *registry) checkSize(requiredSize int) ' in '_state.go' +{ +requiredSize := newSize + if requiredSize > cap(rg.array) { + rg.resize(requiredSize) + } +} + rg.array[regi] = vali + if regi >= rg.top { + rg.top = regi + 1 + } +} +// this section is inlined by go-inline +// source function is 'func (rg *registry) Set(regi int, vali LValue) ' in '_state.go' +{ +rg := reg +regi := RA+1 +vali := selfobj + newSize := regi + 1 +// this section is inlined by go-inline +// source function is 'func (rg *registry) checkSize(requiredSize int) ' in '_state.go' +{ +requiredSize := newSize + if requiredSize > cap(rg.array) { + rg.resize(requiredSize) + } +} + rg.array[regi] = vali + if regi >= rg.top { + rg.top = regi + 1 + } +} + case OP_ADD, OP_SUB, OP_MUL, OP_DIV, OP_MOD, OP_POW: + A := int(inst>>18) & 0xff //GETA + RA := lbase + A + B := int(inst & 0x1ff) //GETB + C := int(inst>>9) & 0x1ff //GETC + lhs := L.rkValue(B) + rhs := L.rkValue(C) + v1, ok1 := lhs.(LNumber) + v2, ok2 := rhs.(LNumber) + if ok1 && ok2 { + v := numberArith(L, opcode, LNumber(v1), LNumber(v2)) +// this section is inlined by go-inline +// source function is 'func (rg *registry) SetNumber(regi int, vali LNumber) ' in '_state.go' +{ +rg := reg +regi := RA +vali := v + newSize := regi + 1 +// this section is inlined by go-inline +// source function is 'func (rg *registry) checkSize(requiredSize int) ' in '_state.go' +{ +requiredSize := newSize + if requiredSize > cap(rg.array) { + rg.resize(requiredSize) + } +} + rg.array[regi] = rg.alloc.LNumber2I(vali) + if regi >= rg.top { + rg.top = regi + 1 + } +} + } else { + v := objectArith(L, opcode, lhs, rhs) +// this section is inlined by go-inline +// source function is 'func (rg *registry) Set(regi int, vali LValue) ' in '_state.go' +{ +rg := reg +regi := RA +vali := v + newSize := regi + 1 +// this section is inlined by go-inline +// source function is 'func (rg *registry) checkSize(requiredSize int) ' in '_state.go' +{ +requiredSize := newSize + if requiredSize > cap(rg.array) { + rg.resize(requiredSize) + } +} + rg.array[regi] = vali + if regi >= rg.top { + rg.top = regi + 1 + } +} } - return 0 - }, - opArith, // OP_ADD - opArith, // OP_SUB - opArith, // OP_MUL - opArith, // OP_DIV - opArith, // OP_MOD - opArith, // OP_POW - func(L *LState, inst uint32, baseframe *callFrame) int { //OP_UNM - reg := L.reg - cf := L.currentFrame - lbase := cf.LocalBase + + case OP_UNM: A := int(inst>>18) & 0xff //GETA RA := lbase + A B := int(inst & 0x1ff) //GETB unaryv := L.rkValue(B) if nm, ok := unaryv.(LNumber); ok { - // this section is inlined by go-inline - // source function is 'func (rg *registry) Set(regi int, vali LValue) ' in '_state.go' - { - rg := reg - regi := RA - vali := -nm - newSize := regi + 1 - // this section is inlined by go-inline - // source function is 'func (rg *registry) checkSize(requiredSize int) ' in '_state.go' - { - requiredSize := newSize - if requiredSize > cap(rg.array) { - rg.resize(requiredSize) - } - } - rg.array[regi] = vali - if regi >= rg.top { - rg.top = regi + 1 - } - } +// this section is inlined by go-inline +// source function is 'func (rg *registry) Set(regi int, vali LValue) ' in '_state.go' +{ +rg := reg +regi := RA +vali := -nm + newSize := regi + 1 +// this section is inlined by go-inline +// source function is 'func (rg *registry) checkSize(requiredSize int) ' in '_state.go' +{ +requiredSize := newSize + if requiredSize > cap(rg.array) { + rg.resize(requiredSize) + } +} + rg.array[regi] = vali + if regi >= rg.top { + rg.top = regi + 1 + } +} } else { op := L.metaOp1(unaryv, "__unm") if op.Type() == LTFunction { reg.Push(op) reg.Push(unaryv) L.Call(1, 1) - // this section is inlined by go-inline - // source function is 'func (rg *registry) Set(regi int, vali LValue) ' in '_state.go' - { - rg := reg - regi := RA - vali := reg.Pop() - newSize := regi + 1 - // this section is inlined by go-inline - // source function is 'func (rg *registry) checkSize(requiredSize int) ' in '_state.go' - { - requiredSize := newSize - if requiredSize > cap(rg.array) { - rg.resize(requiredSize) - } - } - rg.array[regi] = vali - if regi >= rg.top { - rg.top = regi + 1 - } - } +// this section is inlined by go-inline +// source function is 'func (rg *registry) Set(regi int, vali LValue) ' in '_state.go' +{ +rg := reg +regi := RA +vali := reg.Pop() + newSize := regi + 1 +// this section is inlined by go-inline +// source function is 'func (rg *registry) checkSize(requiredSize int) ' in '_state.go' +{ +requiredSize := newSize + if requiredSize > cap(rg.array) { + rg.resize(requiredSize) + } +} + rg.array[regi] = vali + if regi >= rg.top { + rg.top = regi + 1 + } +} } else if str, ok1 := unaryv.(LString); ok1 { if num, err := parseNumber(string(str)); err == nil { - // this section is inlined by go-inline - // source function is 'func (rg *registry) Set(regi int, vali LValue) ' in '_state.go' - { - rg := reg - regi := RA - vali := -num - newSize := regi + 1 - // this section is inlined by go-inline - // source function is 'func (rg *registry) checkSize(requiredSize int) ' in '_state.go' - { - requiredSize := newSize - if requiredSize > cap(rg.array) { - rg.resize(requiredSize) - } - } - rg.array[regi] = vali - if regi >= rg.top { - rg.top = regi + 1 - } - } +// this section is inlined by go-inline +// source function is 'func (rg *registry) Set(regi int, vali LValue) ' in '_state.go' +{ +rg := reg +regi := RA +vali := -num + newSize := regi + 1 +// this section is inlined by go-inline +// source function is 'func (rg *registry) checkSize(requiredSize int) ' in '_state.go' +{ +requiredSize := newSize + if requiredSize > cap(rg.array) { + rg.resize(requiredSize) + } +} + rg.array[regi] = vali + if regi >= rg.top { + rg.top = regi + 1 + } +} } else { L.RaiseError("__unm undefined") } @@ -846,89 +546,79 @@ func init() { L.RaiseError("__unm undefined") } } - return 0 - }, - func(L *LState, inst uint32, baseframe *callFrame) int { //OP_NOT - reg := L.reg - cf := L.currentFrame - lbase := cf.LocalBase + case OP_NOT: A := int(inst>>18) & 0xff //GETA RA := lbase + A B := int(inst & 0x1ff) //GETB if LVIsFalse(reg.Get(lbase + B)) { - // this section is inlined by go-inline - // source function is 'func (rg *registry) Set(regi int, vali LValue) ' in '_state.go' - { - rg := reg - regi := RA - vali := LTrue - newSize := regi + 1 - // this section is inlined by go-inline - // source function is 'func (rg *registry) checkSize(requiredSize int) ' in '_state.go' - { - requiredSize := newSize - if requiredSize > cap(rg.array) { - rg.resize(requiredSize) - } - } - rg.array[regi] = vali - if regi >= rg.top { - rg.top = regi + 1 - } - } +// this section is inlined by go-inline +// source function is 'func (rg *registry) Set(regi int, vali LValue) ' in '_state.go' +{ +rg := reg +regi := RA +vali := LTrue + newSize := regi + 1 +// this section is inlined by go-inline +// source function is 'func (rg *registry) checkSize(requiredSize int) ' in '_state.go' +{ +requiredSize := newSize + if requiredSize > cap(rg.array) { + rg.resize(requiredSize) + } +} + rg.array[regi] = vali + if regi >= rg.top { + rg.top = regi + 1 + } +} } else { - // this section is inlined by go-inline - // source function is 'func (rg *registry) Set(regi int, vali LValue) ' in '_state.go' - { - rg := reg - regi := RA - vali := LFalse - newSize := regi + 1 - // this section is inlined by go-inline - // source function is 'func (rg *registry) checkSize(requiredSize int) ' in '_state.go' - { - requiredSize := newSize - if requiredSize > cap(rg.array) { - rg.resize(requiredSize) - } - } - rg.array[regi] = vali - if regi >= rg.top { - rg.top = regi + 1 - } - } +// this section is inlined by go-inline +// source function is 'func (rg *registry) Set(regi int, vali LValue) ' in '_state.go' +{ +rg := reg +regi := RA +vali := LFalse + newSize := regi + 1 +// this section is inlined by go-inline +// source function is 'func (rg *registry) checkSize(requiredSize int) ' in '_state.go' +{ +requiredSize := newSize + if requiredSize > cap(rg.array) { + rg.resize(requiredSize) + } +} + rg.array[regi] = vali + if regi >= rg.top { + rg.top = regi + 1 + } +} } - return 0 - }, - func(L *LState, inst uint32, baseframe *callFrame) int { //OP_LEN - reg := L.reg - cf := L.currentFrame - lbase := cf.LocalBase + case OP_LEN: A := int(inst>>18) & 0xff //GETA RA := lbase + A B := int(inst & 0x1ff) //GETB switch lv := L.rkValue(B).(type) { case LString: - // this section is inlined by go-inline - // source function is 'func (rg *registry) SetNumber(regi int, vali LNumber) ' in '_state.go' - { - rg := reg - regi := RA - vali := LNumber(len(lv)) - newSize := regi + 1 - // this section is inlined by go-inline - // source function is 'func (rg *registry) checkSize(requiredSize int) ' in '_state.go' - { - requiredSize := newSize - if requiredSize > cap(rg.array) { - rg.resize(requiredSize) - } - } - rg.array[regi] = rg.alloc.LNumber2I(vali) - if regi >= rg.top { - rg.top = regi + 1 - } - } +// this section is inlined by go-inline +// source function is 'func (rg *registry) SetNumber(regi int, vali LNumber) ' in '_state.go' +{ +rg := reg +regi := RA +vali := LNumber(len(lv)) + newSize := regi + 1 +// this section is inlined by go-inline +// source function is 'func (rg *registry) checkSize(requiredSize int) ' in '_state.go' +{ +requiredSize := newSize + if requiredSize > cap(rg.array) { + rg.resize(requiredSize) + } +} + rg.array[regi] = rg.alloc.LNumber2I(vali) + if regi >= rg.top { + rg.top = regi + 1 + } +} default: op := L.metaOp1(lv, "__len") if op.Type() == LTFunction { @@ -938,79 +628,74 @@ func init() { ret := reg.Pop() if ret.Type() == LTNumber { v, _ := ret.(LNumber) - // this section is inlined by go-inline - // source function is 'func (rg *registry) SetNumber(regi int, vali LNumber) ' in '_state.go' - { - rg := reg - regi := RA - vali := v - newSize := regi + 1 - // this section is inlined by go-inline - // source function is 'func (rg *registry) checkSize(requiredSize int) ' in '_state.go' - { - requiredSize := newSize - if requiredSize > cap(rg.array) { - rg.resize(requiredSize) - } - } - rg.array[regi] = rg.alloc.LNumber2I(vali) - if regi >= rg.top { - rg.top = regi + 1 - } - } +// this section is inlined by go-inline +// source function is 'func (rg *registry) SetNumber(regi int, vali LNumber) ' in '_state.go' +{ +rg := reg +regi := RA +vali := v + newSize := regi + 1 +// this section is inlined by go-inline +// source function is 'func (rg *registry) checkSize(requiredSize int) ' in '_state.go' +{ +requiredSize := newSize + if requiredSize > cap(rg.array) { + rg.resize(requiredSize) + } +} + rg.array[regi] = rg.alloc.LNumber2I(vali) + if regi >= rg.top { + rg.top = regi + 1 + } +} } else { - // this section is inlined by go-inline - // source function is 'func (rg *registry) Set(regi int, vali LValue) ' in '_state.go' - { - rg := reg - regi := RA - vali := ret - newSize := regi + 1 - // this section is inlined by go-inline - // source function is 'func (rg *registry) checkSize(requiredSize int) ' in '_state.go' - { - requiredSize := newSize - if requiredSize > cap(rg.array) { - rg.resize(requiredSize) - } - } - rg.array[regi] = vali - if regi >= rg.top { - rg.top = regi + 1 - } - } +// this section is inlined by go-inline +// source function is 'func (rg *registry) Set(regi int, vali LValue) ' in '_state.go' +{ +rg := reg +regi := RA +vali := ret + newSize := regi + 1 +// this section is inlined by go-inline +// source function is 'func (rg *registry) checkSize(requiredSize int) ' in '_state.go' +{ +requiredSize := newSize + if requiredSize > cap(rg.array) { + rg.resize(requiredSize) + } +} + rg.array[regi] = vali + if regi >= rg.top { + rg.top = regi + 1 + } +} } } else if lv.Type() == LTTable { - // this section is inlined by go-inline - // source function is 'func (rg *registry) SetNumber(regi int, vali LNumber) ' in '_state.go' - { - rg := reg - regi := RA - vali := LNumber(lv.(*LTable).Len()) - newSize := regi + 1 - // this section is inlined by go-inline - // source function is 'func (rg *registry) checkSize(requiredSize int) ' in '_state.go' - { - requiredSize := newSize - if requiredSize > cap(rg.array) { - rg.resize(requiredSize) - } - } - rg.array[regi] = rg.alloc.LNumber2I(vali) - if regi >= rg.top { - rg.top = regi + 1 - } - } +// this section is inlined by go-inline +// source function is 'func (rg *registry) SetNumber(regi int, vali LNumber) ' in '_state.go' +{ +rg := reg +regi := RA +vali := LNumber(lv.(*LTable).Len()) + newSize := regi + 1 +// this section is inlined by go-inline +// source function is 'func (rg *registry) checkSize(requiredSize int) ' in '_state.go' +{ +requiredSize := newSize + if requiredSize > cap(rg.array) { + rg.resize(requiredSize) + } +} + rg.array[regi] = rg.alloc.LNumber2I(vali) + if regi >= rg.top { + rg.top = regi + 1 + } +} } else { L.RaiseError("__len undefined") } } - return 0 - }, - func(L *LState, inst uint32, baseframe *callFrame) int { //OP_CONCAT - reg := L.reg - cf := L.currentFrame - lbase := cf.LocalBase + case OP_CONCAT: A := int(inst>>18) & 0xff //GETA RA := lbase + A B := int(inst & 0x1ff) //GETB @@ -1018,36 +703,30 @@ func init() { RC := lbase + C RB := lbase + B v := stringConcat(L, RC-RB+1, RC) - // this section is inlined by go-inline - // source function is 'func (rg *registry) Set(regi int, vali LValue) ' in '_state.go' - { - rg := reg - regi := RA - vali := v - newSize := regi + 1 - // this section is inlined by go-inline - // source function is 'func (rg *registry) checkSize(requiredSize int) ' in '_state.go' - { - requiredSize := newSize - if requiredSize > cap(rg.array) { - rg.resize(requiredSize) - } - } - rg.array[regi] = vali - if regi >= rg.top { - rg.top = regi + 1 - } - } - return 0 - }, - func(L *LState, inst uint32, baseframe *callFrame) int { //OP_JMP - cf := L.currentFrame +// this section is inlined by go-inline +// source function is 'func (rg *registry) Set(regi int, vali LValue) ' in '_state.go' +{ +rg := reg +regi := RA +vali := v + newSize := regi + 1 +// this section is inlined by go-inline +// source function is 'func (rg *registry) checkSize(requiredSize int) ' in '_state.go' +{ +requiredSize := newSize + if requiredSize > cap(rg.array) { + rg.resize(requiredSize) + } +} + rg.array[regi] = vali + if regi >= rg.top { + rg.top = regi + 1 + } +} + case OP_JMP: Sbx := int(inst&0x3ffff) - opMaxArgSbx //GETSBX cf.Pc += Sbx - return 0 - }, - func(L *LState, inst uint32, baseframe *callFrame) int { //OP_EQ - cf := L.currentFrame + case OP_EQ: A := int(inst>>18) & 0xff //GETA B := int(inst & 0x1ff) //GETB C := int(inst>>9) & 0x1ff //GETC @@ -1059,10 +738,7 @@ func init() { if v == A { cf.Pc++ } - return 0 - }, - func(L *LState, inst uint32, baseframe *callFrame) int { //OP_LT - cf := L.currentFrame + case OP_LT: A := int(inst>>18) & 0xff //GETA B := int(inst & 0x1ff) //GETB C := int(inst>>9) & 0x1ff //GETC @@ -1074,10 +750,7 @@ func init() { if v == A { cf.Pc++ } - return 0 - }, - func(L *LState, inst uint32, baseframe *callFrame) int { //OP_LE - cf := L.currentFrame + case OP_LE: A := int(inst>>18) & 0xff //GETA B := int(inst & 0x1ff) //GETB C := int(inst>>9) & 0x1ff //GETC @@ -1117,58 +790,43 @@ func init() { if v == A { cf.Pc++ } - return 0 - }, - func(L *LState, inst uint32, baseframe *callFrame) int { //OP_TEST - reg := L.reg - cf := L.currentFrame - lbase := cf.LocalBase + case OP_TEST: A := int(inst>>18) & 0xff //GETA RA := lbase + A C := int(inst>>9) & 0x1ff //GETC if LVAsBool(reg.Get(RA)) == (C == 0) { cf.Pc++ } - return 0 - }, - func(L *LState, inst uint32, baseframe *callFrame) int { //OP_TESTSET - reg := L.reg - cf := L.currentFrame - lbase := cf.LocalBase + case OP_TESTSET: A := int(inst>>18) & 0xff //GETA RA := lbase + A B := int(inst & 0x1ff) //GETB C := int(inst>>9) & 0x1ff //GETC if value := reg.Get(lbase + B); LVAsBool(value) != (C == 0) { - // this section is inlined by go-inline - // source function is 'func (rg *registry) Set(regi int, vali LValue) ' in '_state.go' - { - rg := reg - regi := RA - vali := value - newSize := regi + 1 - // this section is inlined by go-inline - // source function is 'func (rg *registry) checkSize(requiredSize int) ' in '_state.go' - { - requiredSize := newSize - if requiredSize > cap(rg.array) { - rg.resize(requiredSize) - } - } - rg.array[regi] = vali - if regi >= rg.top { - rg.top = regi + 1 - } - } +// this section is inlined by go-inline +// source function is 'func (rg *registry) Set(regi int, vali LValue) ' in '_state.go' +{ +rg := reg +regi := RA +vali := value + newSize := regi + 1 +// this section is inlined by go-inline +// source function is 'func (rg *registry) checkSize(requiredSize int) ' in '_state.go' +{ +requiredSize := newSize + if requiredSize > cap(rg.array) { + rg.resize(requiredSize) + } +} + rg.array[regi] = vali + if regi >= rg.top { + rg.top = regi + 1 + } +} } else { cf.Pc++ } - return 0 - }, - func(L *LState, inst uint32, baseframe *callFrame) int { //OP_CALL - reg := L.reg - cf := L.currentFrame - lbase := cf.LocalBase + case OP_CALL: A := int(inst>>18) & 0xff //GETA RA := lbase + A B := int(inst & 0x1ff) //GETB @@ -1187,133 +845,128 @@ func init() { } else { callable, meta = L.metaCall(lv) } - // this section is inlined by go-inline - // source function is 'func (ls *LState) pushCallFrame(cf callFrame, fn LValue, meta bool) ' in '_state.go' - { - ls := L - cf := callFrame{Fn: callable, Pc: 0, Base: RA, LocalBase: RA + 1, ReturnBase: RA, NArgs: nargs, NRet: nret, Parent: cf, TailCall: 0} - fn := lv - if meta { - cf.NArgs++ - ls.reg.Insert(fn, cf.LocalBase) - } - if cf.Fn == nil { - ls.RaiseError("attempt to call a non-function object") - } - if ls.stack.IsFull() { - ls.RaiseError("stack overflow") - } - ls.stack.Push(cf) - newcf := ls.stack.Last() - // this section is inlined by go-inline - // source function is 'func (ls *LState) initCallFrame(cf *callFrame) ' in '_state.go' - { - cf := newcf - if cf.Fn.IsG { - ls.reg.SetTop(cf.LocalBase + cf.NArgs) - } else { - proto := cf.Fn.Proto - nargs := cf.NArgs - np := int(proto.NumParameters) - if nargs < np { - // default any missing arguments to nil - newSize := cf.LocalBase + np - // this section is inlined by go-inline - // source function is 'func (rg *registry) checkSize(requiredSize int) ' in '_state.go' - { - rg := ls.reg - requiredSize := newSize - if requiredSize > cap(rg.array) { - rg.resize(requiredSize) - } - } - for i := nargs; i < np; i++ { - ls.reg.array[cf.LocalBase+i] = LNil - } - nargs = np - ls.reg.top = newSize - } +// this section is inlined by go-inline +// source function is 'func (ls *LState) pushCallFrame(cf callFrame, fn LValue, meta bool) ' in '_state.go' +{ +ls := L +cf := callFrame{Fn:callable,Pc:0,Base:RA,LocalBase:RA+1,ReturnBase:RA,NArgs:nargs,NRet:nret,Parent:cf,TailCall:0} +fn := lv + if meta { + cf.NArgs++ + ls.reg.Insert(fn, cf.LocalBase) + } + if cf.Fn == nil { + ls.RaiseError("attempt to call a non-function object") + } + if ls.stack.IsFull() { + ls.RaiseError("stack overflow") + } + ls.stack.Push(cf) + newcf := ls.stack.Last() +// this section is inlined by go-inline +// source function is 'func (ls *LState) initCallFrame(cf *callFrame) ' in '_state.go' +{ +cf := newcf + if cf.Fn.IsG { + ls.reg.SetTop(cf.LocalBase + cf.NArgs) + } else { + proto := cf.Fn.Proto + nargs := cf.NArgs + np := int(proto.NumParameters) + if nargs < np { + // default any missing arguments to nil + newSize := cf.LocalBase + np +// this section is inlined by go-inline +// source function is 'func (rg *registry) checkSize(requiredSize int) ' in '_state.go' +{ +rg := ls.reg +requiredSize := newSize + if requiredSize > cap(rg.array) { + rg.resize(requiredSize) + } +} + for i := nargs; i < np; i++ { + ls.reg.array[cf.LocalBase+i] = LNil + } + nargs = np + ls.reg.top = newSize + } - if (proto.IsVarArg & VarArgIsVarArg) == 0 { - if nargs < int(proto.NumUsedRegisters) { - nargs = int(proto.NumUsedRegisters) - } - newSize := cf.LocalBase + nargs - // this section is inlined by go-inline - // source function is 'func (rg *registry) checkSize(requiredSize int) ' in '_state.go' - { - rg := ls.reg - requiredSize := newSize - if requiredSize > cap(rg.array) { - rg.resize(requiredSize) - } - } - for i := np; i < nargs; i++ { - ls.reg.array[cf.LocalBase+i] = LNil - } - ls.reg.top = cf.LocalBase + int(proto.NumUsedRegisters) - } else { - /* swap vararg positions: - closure - namedparam1 <- lbase - namedparam2 - vararg1 - vararg2 + if (proto.IsVarArg & VarArgIsVarArg) == 0 { + if nargs < int(proto.NumUsedRegisters) { + nargs = int(proto.NumUsedRegisters) + } + newSize := cf.LocalBase + nargs +// this section is inlined by go-inline +// source function is 'func (rg *registry) checkSize(requiredSize int) ' in '_state.go' +{ +rg := ls.reg +requiredSize := newSize + if requiredSize > cap(rg.array) { + rg.resize(requiredSize) + } +} + for i := np; i < nargs; i++ { + ls.reg.array[cf.LocalBase+i] = LNil + } + ls.reg.top = cf.LocalBase + int(proto.NumUsedRegisters) + } else { + /* swap vararg positions: + closure + namedparam1 <- lbase + namedparam2 + vararg1 + vararg2 - TO + TO - closure - nil - nil - vararg1 - vararg2 - namedparam1 <- lbase - namedparam2 - */ - nvarargs := nargs - np - if nvarargs < 0 { - nvarargs = 0 - } + closure + nil + nil + vararg1 + vararg2 + namedparam1 <- lbase + namedparam2 + */ + nvarargs := nargs - np + if nvarargs < 0 { + nvarargs = 0 + } - ls.reg.SetTop(cf.LocalBase + nargs + np) - for i := 0; i < np; i++ { - //ls.reg.Set(cf.LocalBase+nargs+i, ls.reg.Get(cf.LocalBase+i)) - ls.reg.array[cf.LocalBase+nargs+i] = ls.reg.array[cf.LocalBase+i] - //ls.reg.Set(cf.LocalBase+i, LNil) - ls.reg.array[cf.LocalBase+i] = LNil - } + ls.reg.SetTop(cf.LocalBase + nargs + np) + for i := 0; i < np; i++ { + //ls.reg.Set(cf.LocalBase+nargs+i, ls.reg.Get(cf.LocalBase+i)) + ls.reg.array[cf.LocalBase+nargs+i] = ls.reg.array[cf.LocalBase+i] + //ls.reg.Set(cf.LocalBase+i, LNil) + ls.reg.array[cf.LocalBase+i] = LNil + } - if CompatVarArg { - ls.reg.SetTop(cf.LocalBase + nargs + np + 1) - if (proto.IsVarArg & VarArgNeedsArg) != 0 { - argtb := newLTable(nvarargs, 0) - for i := 0; i < nvarargs; i++ { - argtb.RawSetInt(i+1, ls.reg.Get(cf.LocalBase+np+i)) - } - argtb.RawSetString("n", LNumber(nvarargs)) - //ls.reg.Set(cf.LocalBase+nargs+np, argtb) - ls.reg.array[cf.LocalBase+nargs+np] = argtb - } else { - ls.reg.array[cf.LocalBase+nargs+np] = LNil - } - } - cf.LocalBase += nargs - maxreg := cf.LocalBase + int(proto.NumUsedRegisters) - ls.reg.SetTop(maxreg) - } + if CompatVarArg { + ls.reg.SetTop(cf.LocalBase + nargs + np + 1) + if (proto.IsVarArg & VarArgNeedsArg) != 0 { + argtb := newLTable(nvarargs, 0) + for i := 0; i < nvarargs; i++ { + argtb.RawSetInt(i+1, ls.reg.Get(cf.LocalBase+np+i)) } + argtb.RawSetString("n", LNumber(nvarargs)) + //ls.reg.Set(cf.LocalBase+nargs+np, argtb) + ls.reg.array[cf.LocalBase+nargs+np] = argtb + } else { + ls.reg.array[cf.LocalBase+nargs+np] = LNil } - ls.currentFrame = newcf } + cf.LocalBase += nargs + maxreg := cf.LocalBase + int(proto.NumUsedRegisters) + ls.reg.SetTop(maxreg) + } + } +} + ls.currentFrame = newcf +} if callable.IsG && callGFunction(L, false) { - return 1 + return } - return 0 - }, - func(L *LState, inst uint32, baseframe *callFrame) int { //OP_TAILCALL - reg := L.reg - cf := L.currentFrame - lbase := cf.LocalBase + case OP_TAILCALL: A := int(inst>>18) & 0xff //GETA RA := lbase + A B := int(inst & 0x1ff) //GETB @@ -1333,26 +986,26 @@ func init() { if callable == nil { L.RaiseError("attempt to call a non-function object") } - // this section is inlined by go-inline - // source function is 'func (ls *LState) closeUpvalues(idx int) ' in '_state.go' - { - ls := L - idx := lbase - if ls.uvcache != nil { - var prev *Upvalue - for uv := ls.uvcache; uv != nil; uv = uv.next { - if uv.index >= idx { - if prev != nil { - prev.next = nil - } else { - ls.uvcache = nil - } - uv.Close() - } - prev = uv - } +// this section is inlined by go-inline +// source function is 'func (ls *LState) closeUpvalues(idx int) ' in '_state.go' +{ +ls := L +idx := lbase + if ls.uvcache != nil { + var prev *Upvalue + for uv := ls.uvcache; uv != nil; uv = uv.next { + if uv.index >= idx { + if prev != nil { + prev.next = nil + } else { + ls.uvcache = nil } + uv.Close() } + prev = uv + } + } +} if callable.IsG { luaframe := cf L.pushCallFrame(callFrame{ @@ -1367,10 +1020,10 @@ func init() { TailCall: 0, }, lv, meta) if callGFunction(L, true) { - return 1 + return } if L.currentFrame == nil || L.currentFrame.Fn.IsG || luaframe == baseframe { - return 1 + return } } else { base := cf.Base @@ -1387,176 +1040,171 @@ func init() { cf.NArgs++ L.reg.Insert(lv, cf.LocalBase) } - // this section is inlined by go-inline - // source function is 'func (ls *LState) initCallFrame(cf *callFrame) ' in '_state.go' - { - ls := L - if cf.Fn.IsG { - ls.reg.SetTop(cf.LocalBase + cf.NArgs) - } else { - proto := cf.Fn.Proto - nargs := cf.NArgs - np := int(proto.NumParameters) - if nargs < np { - // default any missing arguments to nil - newSize := cf.LocalBase + np - // this section is inlined by go-inline - // source function is 'func (rg *registry) checkSize(requiredSize int) ' in '_state.go' - { - rg := ls.reg - requiredSize := newSize - if requiredSize > cap(rg.array) { - rg.resize(requiredSize) - } - } - for i := nargs; i < np; i++ { - ls.reg.array[cf.LocalBase+i] = LNil - } - nargs = np - ls.reg.top = newSize - } +// this section is inlined by go-inline +// source function is 'func (ls *LState) initCallFrame(cf *callFrame) ' in '_state.go' +{ +ls := L + if cf.Fn.IsG { + ls.reg.SetTop(cf.LocalBase + cf.NArgs) + } else { + proto := cf.Fn.Proto + nargs := cf.NArgs + np := int(proto.NumParameters) + if nargs < np { + // default any missing arguments to nil + newSize := cf.LocalBase + np +// this section is inlined by go-inline +// source function is 'func (rg *registry) checkSize(requiredSize int) ' in '_state.go' +{ +rg := ls.reg +requiredSize := newSize + if requiredSize > cap(rg.array) { + rg.resize(requiredSize) + } +} + for i := nargs; i < np; i++ { + ls.reg.array[cf.LocalBase+i] = LNil + } + nargs = np + ls.reg.top = newSize + } - if (proto.IsVarArg & VarArgIsVarArg) == 0 { - if nargs < int(proto.NumUsedRegisters) { - nargs = int(proto.NumUsedRegisters) - } - newSize := cf.LocalBase + nargs - // this section is inlined by go-inline - // source function is 'func (rg *registry) checkSize(requiredSize int) ' in '_state.go' - { - rg := ls.reg - requiredSize := newSize - if requiredSize > cap(rg.array) { - rg.resize(requiredSize) - } - } - for i := np; i < nargs; i++ { - ls.reg.array[cf.LocalBase+i] = LNil - } - ls.reg.top = cf.LocalBase + int(proto.NumUsedRegisters) - } else { - /* swap vararg positions: - closure - namedparam1 <- lbase - namedparam2 - vararg1 - vararg2 + if (proto.IsVarArg & VarArgIsVarArg) == 0 { + if nargs < int(proto.NumUsedRegisters) { + nargs = int(proto.NumUsedRegisters) + } + newSize := cf.LocalBase + nargs +// this section is inlined by go-inline +// source function is 'func (rg *registry) checkSize(requiredSize int) ' in '_state.go' +{ +rg := ls.reg +requiredSize := newSize + if requiredSize > cap(rg.array) { + rg.resize(requiredSize) + } +} + for i := np; i < nargs; i++ { + ls.reg.array[cf.LocalBase+i] = LNil + } + ls.reg.top = cf.LocalBase + int(proto.NumUsedRegisters) + } else { + /* swap vararg positions: + closure + namedparam1 <- lbase + namedparam2 + vararg1 + vararg2 - TO + TO - closure - nil - nil - vararg1 - vararg2 - namedparam1 <- lbase - namedparam2 - */ - nvarargs := nargs - np - if nvarargs < 0 { - nvarargs = 0 - } + closure + nil + nil + vararg1 + vararg2 + namedparam1 <- lbase + namedparam2 + */ + nvarargs := nargs - np + if nvarargs < 0 { + nvarargs = 0 + } - ls.reg.SetTop(cf.LocalBase + nargs + np) - for i := 0; i < np; i++ { - //ls.reg.Set(cf.LocalBase+nargs+i, ls.reg.Get(cf.LocalBase+i)) - ls.reg.array[cf.LocalBase+nargs+i] = ls.reg.array[cf.LocalBase+i] - //ls.reg.Set(cf.LocalBase+i, LNil) - ls.reg.array[cf.LocalBase+i] = LNil - } + ls.reg.SetTop(cf.LocalBase + nargs + np) + for i := 0; i < np; i++ { + //ls.reg.Set(cf.LocalBase+nargs+i, ls.reg.Get(cf.LocalBase+i)) + ls.reg.array[cf.LocalBase+nargs+i] = ls.reg.array[cf.LocalBase+i] + //ls.reg.Set(cf.LocalBase+i, LNil) + ls.reg.array[cf.LocalBase+i] = LNil + } - if CompatVarArg { - ls.reg.SetTop(cf.LocalBase + nargs + np + 1) - if (proto.IsVarArg & VarArgNeedsArg) != 0 { - argtb := newLTable(nvarargs, 0) - for i := 0; i < nvarargs; i++ { - argtb.RawSetInt(i+1, ls.reg.Get(cf.LocalBase+np+i)) - } - argtb.RawSetString("n", LNumber(nvarargs)) - //ls.reg.Set(cf.LocalBase+nargs+np, argtb) - ls.reg.array[cf.LocalBase+nargs+np] = argtb - } else { - ls.reg.array[cf.LocalBase+nargs+np] = LNil - } - } - cf.LocalBase += nargs - maxreg := cf.LocalBase + int(proto.NumUsedRegisters) - ls.reg.SetTop(maxreg) - } + if CompatVarArg { + ls.reg.SetTop(cf.LocalBase + nargs + np + 1) + if (proto.IsVarArg & VarArgNeedsArg) != 0 { + argtb := newLTable(nvarargs, 0) + for i := 0; i < nvarargs; i++ { + argtb.RawSetInt(i+1, ls.reg.Get(cf.LocalBase+np+i)) } + argtb.RawSetString("n", LNumber(nvarargs)) + //ls.reg.Set(cf.LocalBase+nargs+np, argtb) + ls.reg.array[cf.LocalBase+nargs+np] = argtb + } else { + ls.reg.array[cf.LocalBase+nargs+np] = LNil } - // this section is inlined by go-inline - // source function is 'func (rg *registry) CopyRange(regv, start, limit, n int) ' in '_state.go' - { - rg := L.reg - regv := base - start := RA - limit := -1 - n := reg.Top() - RA - 1 - newSize := regv + n - // this section is inlined by go-inline - // source function is 'func (rg *registry) checkSize(requiredSize int) ' in '_state.go' - { - requiredSize := newSize - if requiredSize > cap(rg.array) { - rg.resize(requiredSize) - } - } - if limit == -1 || limit > rg.top { - limit = rg.top - } - for i := 0; i < n; i++ { - srcIdx := start + i - if srcIdx >= limit || srcIdx < 0 { - rg.array[regv+i] = LNil - } else { - rg.array[regv+i] = rg.array[srcIdx] - } - } + } + cf.LocalBase += nargs + maxreg := cf.LocalBase + int(proto.NumUsedRegisters) + ls.reg.SetTop(maxreg) + } + } +} +// this section is inlined by go-inline +// source function is 'func (rg *registry) CopyRange(regv, start, limit, n int) ' in '_state.go' +{ +rg := L.reg +regv := base +start := RA +limit := -1 +n := reg.Top()-RA-1 + newSize := regv + n +// this section is inlined by go-inline +// source function is 'func (rg *registry) checkSize(requiredSize int) ' in '_state.go' +{ +requiredSize := newSize + if requiredSize > cap(rg.array) { + rg.resize(requiredSize) + } +} + if limit == -1 || limit > rg.top { + limit = rg.top + } + for i := 0; i < n; i++ { + srcIdx := start + i + if srcIdx >= limit || srcIdx < 0 { + rg.array[regv+i] = LNil + } else { + rg.array[regv+i] = rg.array[srcIdx] + } + } - // values beyond top don't need to be valid LValues, so setting them to nil is fine - // setting them to nil rather than LNil lets us invoke the golang memclr opto - oldtop := rg.top - rg.top = regv + n - if rg.top < oldtop { - nilRange := rg.array[rg.top:oldtop] - for i := range nilRange { - nilRange[i] = nil - } - } - } + // values beyond top don't need to be valid LValues, so setting them to nil is fine + // setting them to nil rather than LNil lets us invoke the golang memclr opto + oldtop := rg.top + rg.top = regv + n + if rg.top < oldtop { + nilRange := rg.array[rg.top:oldtop] + for i := range nilRange { + nilRange[i] = nil + } + } +} cf.Base = base cf.LocalBase = base + (cf.LocalBase - lbase + 1) } - return 0 - }, - func(L *LState, inst uint32, baseframe *callFrame) int { //OP_RETURN - reg := L.reg - cf := L.currentFrame - lbase := cf.LocalBase + case OP_RETURN: A := int(inst>>18) & 0xff //GETA RA := lbase + A B := int(inst & 0x1ff) //GETB - // this section is inlined by go-inline - // source function is 'func (ls *LState) closeUpvalues(idx int) ' in '_state.go' - { - ls := L - idx := lbase - if ls.uvcache != nil { - var prev *Upvalue - for uv := ls.uvcache; uv != nil; uv = uv.next { - if uv.index >= idx { - if prev != nil { - prev.next = nil - } else { - ls.uvcache = nil - } - uv.Close() - } - prev = uv - } +// this section is inlined by go-inline +// source function is 'func (ls *LState) closeUpvalues(idx int) ' in '_state.go' +{ +ls := L +idx := lbase + if ls.uvcache != nil { + var prev *Upvalue + for uv := ls.uvcache; uv != nil; uv = uv.next { + if uv.index >= idx { + if prev != nil { + prev.next = nil + } else { + ls.uvcache = nil } + uv.Close() } + prev = uv + } + } +} nret := B - 1 if B == 0 { nret = reg.Top() - RA @@ -1567,232 +1215,227 @@ func init() { } if L.Parent != nil && L.stack.Sp() == 1 { - // this section is inlined by go-inline - // source function is 'func copyReturnValues(L *LState, regv, start, n, b int) ' in '_vm.go' - { - regv := reg.Top() - start := RA - b := B - if b == 1 { - // this section is inlined by go-inline - // source function is 'func (rg *registry) FillNil(regm, n int) ' in '_state.go' - { - rg := L.reg - regm := regv - newSize := regm + n - // this section is inlined by go-inline - // source function is 'func (rg *registry) checkSize(requiredSize int) ' in '_state.go' - { - requiredSize := newSize - if requiredSize > cap(rg.array) { - rg.resize(requiredSize) - } - } - for i := 0; i < n; i++ { - rg.array[regm+i] = LNil - } - // values beyond top don't need to be valid LValues, so setting them to nil is fine - // setting them to nil rather than LNil lets us invoke the golang memclr opto - oldtop := rg.top - rg.top = regm + n - if rg.top < oldtop { - nilRange := rg.array[rg.top:oldtop] - for i := range nilRange { - nilRange[i] = nil - } - } - } - } else { - // this section is inlined by go-inline - // source function is 'func (rg *registry) CopyRange(regv, start, limit, n int) ' in '_state.go' - { - rg := L.reg - limit := -1 - newSize := regv + n - // this section is inlined by go-inline - // source function is 'func (rg *registry) checkSize(requiredSize int) ' in '_state.go' - { - requiredSize := newSize - if requiredSize > cap(rg.array) { - rg.resize(requiredSize) - } - } - if limit == -1 || limit > rg.top { - limit = rg.top - } - for i := 0; i < n; i++ { - srcIdx := start + i - if srcIdx >= limit || srcIdx < 0 { - rg.array[regv+i] = LNil - } else { - rg.array[regv+i] = rg.array[srcIdx] - } - } +// this section is inlined by go-inline +// source function is 'func copyReturnValues(L *LState, regv, start, n, b int) ' in '_vm.go' +{ +regv := reg.Top() +start := RA +b := B + if b == 1 { +// this section is inlined by go-inline +// source function is 'func (rg *registry) FillNil(regm, n int) ' in '_state.go' +{ +rg := L.reg +regm := regv + newSize := regm + n +// this section is inlined by go-inline +// source function is 'func (rg *registry) checkSize(requiredSize int) ' in '_state.go' +{ +requiredSize := newSize + if requiredSize > cap(rg.array) { + rg.resize(requiredSize) + } +} + for i := 0; i < n; i++ { + rg.array[regm+i] = LNil + } + // values beyond top don't need to be valid LValues, so setting them to nil is fine + // setting them to nil rather than LNil lets us invoke the golang memclr opto + oldtop := rg.top + rg.top = regm + n + if rg.top < oldtop { + nilRange := rg.array[rg.top:oldtop] + for i := range nilRange { + nilRange[i] = nil + } + } +} + } else { +// this section is inlined by go-inline +// source function is 'func (rg *registry) CopyRange(regv, start, limit, n int) ' in '_state.go' +{ +rg := L.reg +limit := -1 + newSize := regv + n +// this section is inlined by go-inline +// source function is 'func (rg *registry) checkSize(requiredSize int) ' in '_state.go' +{ +requiredSize := newSize + if requiredSize > cap(rg.array) { + rg.resize(requiredSize) + } +} + if limit == -1 || limit > rg.top { + limit = rg.top + } + for i := 0; i < n; i++ { + srcIdx := start + i + if srcIdx >= limit || srcIdx < 0 { + rg.array[regv+i] = LNil + } else { + rg.array[regv+i] = rg.array[srcIdx] + } + } - // values beyond top don't need to be valid LValues, so setting them to nil is fine - // setting them to nil rather than LNil lets us invoke the golang memclr opto - oldtop := rg.top - rg.top = regv + n - if rg.top < oldtop { - nilRange := rg.array[rg.top:oldtop] - for i := range nilRange { - nilRange[i] = nil - } - } - } - if b > 1 && n > (b-1) { - // this section is inlined by go-inline - // source function is 'func (rg *registry) FillNil(regm, n int) ' in '_state.go' - { - rg := L.reg - regm := regv + b - 1 - n := n - (b - 1) - newSize := regm + n - // this section is inlined by go-inline - // source function is 'func (rg *registry) checkSize(requiredSize int) ' in '_state.go' - { - requiredSize := newSize - if requiredSize > cap(rg.array) { - rg.resize(requiredSize) - } - } - for i := 0; i < n; i++ { - rg.array[regm+i] = LNil - } - // values beyond top don't need to be valid LValues, so setting them to nil is fine - // setting them to nil rather than LNil lets us invoke the golang memclr opto - oldtop := rg.top - rg.top = regm + n - if rg.top < oldtop { - nilRange := rg.array[rg.top:oldtop] - for i := range nilRange { - nilRange[i] = nil - } - } - } - } - } - } + // values beyond top don't need to be valid LValues, so setting them to nil is fine + // setting them to nil rather than LNil lets us invoke the golang memclr opto + oldtop := rg.top + rg.top = regv + n + if rg.top < oldtop { + nilRange := rg.array[rg.top:oldtop] + for i := range nilRange { + nilRange[i] = nil + } + } +} + if b > 1 && n > (b-1) { +// this section is inlined by go-inline +// source function is 'func (rg *registry) FillNil(regm, n int) ' in '_state.go' +{ +rg := L.reg +regm := regv+b-1 +n := n-(b-1) + newSize := regm + n +// this section is inlined by go-inline +// source function is 'func (rg *registry) checkSize(requiredSize int) ' in '_state.go' +{ +requiredSize := newSize + if requiredSize > cap(rg.array) { + rg.resize(requiredSize) + } +} + for i := 0; i < n; i++ { + rg.array[regm+i] = LNil + } + // values beyond top don't need to be valid LValues, so setting them to nil is fine + // setting them to nil rather than LNil lets us invoke the golang memclr opto + oldtop := rg.top + rg.top = regm + n + if rg.top < oldtop { + nilRange := rg.array[rg.top:oldtop] + for i := range nilRange { + nilRange[i] = nil + } + } +} + } + } +} switchToParentThread(L, n, false, true) - return 1 + return } islast := baseframe == L.stack.Pop() || L.stack.IsEmpty() - // this section is inlined by go-inline - // source function is 'func copyReturnValues(L *LState, regv, start, n, b int) ' in '_vm.go' - { - regv := cf.ReturnBase - start := RA - b := B - if b == 1 { - // this section is inlined by go-inline - // source function is 'func (rg *registry) FillNil(regm, n int) ' in '_state.go' - { - rg := L.reg - regm := regv - newSize := regm + n - // this section is inlined by go-inline - // source function is 'func (rg *registry) checkSize(requiredSize int) ' in '_state.go' - { - requiredSize := newSize - if requiredSize > cap(rg.array) { - rg.resize(requiredSize) - } - } - for i := 0; i < n; i++ { - rg.array[regm+i] = LNil - } - // values beyond top don't need to be valid LValues, so setting them to nil is fine - // setting them to nil rather than LNil lets us invoke the golang memclr opto - oldtop := rg.top - rg.top = regm + n - if rg.top < oldtop { - nilRange := rg.array[rg.top:oldtop] - for i := range nilRange { - nilRange[i] = nil - } - } - } - } else { - // this section is inlined by go-inline - // source function is 'func (rg *registry) CopyRange(regv, start, limit, n int) ' in '_state.go' - { - rg := L.reg - limit := -1 - newSize := regv + n - // this section is inlined by go-inline - // source function is 'func (rg *registry) checkSize(requiredSize int) ' in '_state.go' - { - requiredSize := newSize - if requiredSize > cap(rg.array) { - rg.resize(requiredSize) - } - } - if limit == -1 || limit > rg.top { - limit = rg.top - } - for i := 0; i < n; i++ { - srcIdx := start + i - if srcIdx >= limit || srcIdx < 0 { - rg.array[regv+i] = LNil - } else { - rg.array[regv+i] = rg.array[srcIdx] - } - } +// this section is inlined by go-inline +// source function is 'func copyReturnValues(L *LState, regv, start, n, b int) ' in '_vm.go' +{ +regv := cf.ReturnBase +start := RA +b := B + if b == 1 { +// this section is inlined by go-inline +// source function is 'func (rg *registry) FillNil(regm, n int) ' in '_state.go' +{ +rg := L.reg +regm := regv + newSize := regm + n +// this section is inlined by go-inline +// source function is 'func (rg *registry) checkSize(requiredSize int) ' in '_state.go' +{ +requiredSize := newSize + if requiredSize > cap(rg.array) { + rg.resize(requiredSize) + } +} + for i := 0; i < n; i++ { + rg.array[regm+i] = LNil + } + // values beyond top don't need to be valid LValues, so setting them to nil is fine + // setting them to nil rather than LNil lets us invoke the golang memclr opto + oldtop := rg.top + rg.top = regm + n + if rg.top < oldtop { + nilRange := rg.array[rg.top:oldtop] + for i := range nilRange { + nilRange[i] = nil + } + } +} + } else { +// this section is inlined by go-inline +// source function is 'func (rg *registry) CopyRange(regv, start, limit, n int) ' in '_state.go' +{ +rg := L.reg +limit := -1 + newSize := regv + n +// this section is inlined by go-inline +// source function is 'func (rg *registry) checkSize(requiredSize int) ' in '_state.go' +{ +requiredSize := newSize + if requiredSize > cap(rg.array) { + rg.resize(requiredSize) + } +} + if limit == -1 || limit > rg.top { + limit = rg.top + } + for i := 0; i < n; i++ { + srcIdx := start + i + if srcIdx >= limit || srcIdx < 0 { + rg.array[regv+i] = LNil + } else { + rg.array[regv+i] = rg.array[srcIdx] + } + } - // values beyond top don't need to be valid LValues, so setting them to nil is fine - // setting them to nil rather than LNil lets us invoke the golang memclr opto - oldtop := rg.top - rg.top = regv + n - if rg.top < oldtop { - nilRange := rg.array[rg.top:oldtop] - for i := range nilRange { - nilRange[i] = nil - } - } - } - if b > 1 && n > (b-1) { - // this section is inlined by go-inline - // source function is 'func (rg *registry) FillNil(regm, n int) ' in '_state.go' - { - rg := L.reg - regm := regv + b - 1 - n := n - (b - 1) - newSize := regm + n - // this section is inlined by go-inline - // source function is 'func (rg *registry) checkSize(requiredSize int) ' in '_state.go' - { - requiredSize := newSize - if requiredSize > cap(rg.array) { - rg.resize(requiredSize) - } - } - for i := 0; i < n; i++ { - rg.array[regm+i] = LNil - } - // values beyond top don't need to be valid LValues, so setting them to nil is fine - // setting them to nil rather than LNil lets us invoke the golang memclr opto - oldtop := rg.top - rg.top = regm + n - if rg.top < oldtop { - nilRange := rg.array[rg.top:oldtop] - for i := range nilRange { - nilRange[i] = nil - } - } - } - } - } - } + // values beyond top don't need to be valid LValues, so setting them to nil is fine + // setting them to nil rather than LNil lets us invoke the golang memclr opto + oldtop := rg.top + rg.top = regv + n + if rg.top < oldtop { + nilRange := rg.array[rg.top:oldtop] + for i := range nilRange { + nilRange[i] = nil + } + } +} + if b > 1 && n > (b-1) { +// this section is inlined by go-inline +// source function is 'func (rg *registry) FillNil(regm, n int) ' in '_state.go' +{ +rg := L.reg +regm := regv+b-1 +n := n-(b-1) + newSize := regm + n +// this section is inlined by go-inline +// source function is 'func (rg *registry) checkSize(requiredSize int) ' in '_state.go' +{ +requiredSize := newSize + if requiredSize > cap(rg.array) { + rg.resize(requiredSize) + } +} + for i := 0; i < n; i++ { + rg.array[regm+i] = LNil + } + // values beyond top don't need to be valid LValues, so setting them to nil is fine + // setting them to nil rather than LNil lets us invoke the golang memclr opto + oldtop := rg.top + rg.top = regm + n + if rg.top < oldtop { + nilRange := rg.array[rg.top:oldtop] + for i := range nilRange { + nilRange[i] = nil + } + } +} + } + } +} L.currentFrame = L.stack.Last() if islast || L.currentFrame == nil || L.currentFrame.Fn.IsG { - return 1 + return } - return 0 - }, - func(L *LState, inst uint32, baseframe *callFrame) int { //OP_FORLOOP - reg := L.reg - cf := L.currentFrame - lbase := cf.LocalBase + case OP_FORLOOP: A := int(inst>>18) & 0xff //GETA RA := lbase + A if init, ok1 := reg.Get(RA).(LNumber); ok1 { @@ -1800,80 +1443,80 @@ func init() { if step, ok3 := reg.Get(RA + 2).(LNumber); ok3 { init += step v := LNumber(init) - // this section is inlined by go-inline - // source function is 'func (rg *registry) SetNumber(regi int, vali LNumber) ' in '_state.go' - { - rg := reg - regi := RA - vali := v - newSize := regi + 1 - // this section is inlined by go-inline - // source function is 'func (rg *registry) checkSize(requiredSize int) ' in '_state.go' - { - requiredSize := newSize - if requiredSize > cap(rg.array) { - rg.resize(requiredSize) - } - } - rg.array[regi] = rg.alloc.LNumber2I(vali) - if regi >= rg.top { - rg.top = regi + 1 - } - } +// this section is inlined by go-inline +// source function is 'func (rg *registry) SetNumber(regi int, vali LNumber) ' in '_state.go' +{ +rg := reg +regi := RA +vali := v + newSize := regi + 1 +// this section is inlined by go-inline +// source function is 'func (rg *registry) checkSize(requiredSize int) ' in '_state.go' +{ +requiredSize := newSize + if requiredSize > cap(rg.array) { + rg.resize(requiredSize) + } +} + rg.array[regi] = rg.alloc.LNumber2I(vali) + if regi >= rg.top { + rg.top = regi + 1 + } +} if (step > 0 && init <= limit) || (step <= 0 && init >= limit) { Sbx := int(inst&0x3ffff) - opMaxArgSbx //GETSBX cf.Pc += Sbx - // this section is inlined by go-inline - // source function is 'func (rg *registry) SetNumber(regi int, vali LNumber) ' in '_state.go' - { - rg := reg - regi := RA + 3 - vali := v - newSize := regi + 1 - // this section is inlined by go-inline - // source function is 'func (rg *registry) checkSize(requiredSize int) ' in '_state.go' - { - requiredSize := newSize - if requiredSize > cap(rg.array) { - rg.resize(requiredSize) - } - } - rg.array[regi] = rg.alloc.LNumber2I(vali) - if regi >= rg.top { - rg.top = regi + 1 - } - } +// this section is inlined by go-inline +// source function is 'func (rg *registry) SetNumber(regi int, vali LNumber) ' in '_state.go' +{ +rg := reg +regi := RA+3 +vali := v + newSize := regi + 1 +// this section is inlined by go-inline +// source function is 'func (rg *registry) checkSize(requiredSize int) ' in '_state.go' +{ +requiredSize := newSize + if requiredSize > cap(rg.array) { + rg.resize(requiredSize) + } +} + rg.array[regi] = rg.alloc.LNumber2I(vali) + if regi >= rg.top { + rg.top = regi + 1 + } +} } else { - // this section is inlined by go-inline - // source function is 'func (rg *registry) SetTop(topi int) ' in '_state.go' - { - rg := reg - topi := RA + 1 - // this section is inlined by go-inline - // source function is 'func (rg *registry) checkSize(requiredSize int) ' in '_state.go' - { - requiredSize := topi - if requiredSize > cap(rg.array) { - rg.resize(requiredSize) - } - } - oldtopi := rg.top - rg.top = topi - for i := oldtopi; i < rg.top; i++ { - rg.array[i] = LNil - } - // values beyond top don't need to be valid LValues, so setting them to nil is fine - // setting them to nil rather than LNil lets us invoke the golang memclr opto - if rg.top < oldtopi { - nilRange := rg.array[rg.top:oldtopi] - for i := range nilRange { - nilRange[i] = nil - } - } - //for i := rg.top; i < oldtop; i++ { - // rg.array[i] = LNil - //} - } +// this section is inlined by go-inline +// source function is 'func (rg *registry) SetTop(topi int) ' in '_state.go' +{ +rg := reg +topi := RA+1 +// this section is inlined by go-inline +// source function is 'func (rg *registry) checkSize(requiredSize int) ' in '_state.go' +{ +requiredSize := topi + if requiredSize > cap(rg.array) { + rg.resize(requiredSize) + } +} + oldtopi := rg.top + rg.top = topi + for i := oldtopi; i < rg.top; i++ { + rg.array[i] = LNil + } + // values beyond top don't need to be valid LValues, so setting them to nil is fine + // setting them to nil rather than LNil lets us invoke the golang memclr opto + if rg.top < oldtopi { + nilRange := rg.array[rg.top:oldtopi] + for i := range nilRange { + nilRange[i] = nil + } + } + //for i := rg.top; i < oldtop; i++ { + // rg.array[i] = LNil + //} +} } } else { L.RaiseError("for statement step must be a number") @@ -1884,37 +1527,32 @@ func init() { } else { L.RaiseError("for statement init must be a number") } - return 0 - }, - func(L *LState, inst uint32, baseframe *callFrame) int { //OP_FORPREP - reg := L.reg - cf := L.currentFrame - lbase := cf.LocalBase + case OP_FORPREP: A := int(inst>>18) & 0xff //GETA RA := lbase + A Sbx := int(inst&0x3ffff) - opMaxArgSbx //GETSBX if init, ok1 := reg.Get(RA).(LNumber); ok1 { if step, ok2 := reg.Get(RA + 2).(LNumber); ok2 { - // this section is inlined by go-inline - // source function is 'func (rg *registry) SetNumber(regi int, vali LNumber) ' in '_state.go' - { - rg := reg - regi := RA - vali := LNumber(init - step) - newSize := regi + 1 - // this section is inlined by go-inline - // source function is 'func (rg *registry) checkSize(requiredSize int) ' in '_state.go' - { - requiredSize := newSize - if requiredSize > cap(rg.array) { - rg.resize(requiredSize) - } - } - rg.array[regi] = rg.alloc.LNumber2I(vali) - if regi >= rg.top { - rg.top = regi + 1 - } - } +// this section is inlined by go-inline +// source function is 'func (rg *registry) SetNumber(regi int, vali LNumber) ' in '_state.go' +{ +rg := reg +regi := RA +vali := LNumber(init-step) + newSize := regi + 1 +// this section is inlined by go-inline +// source function is 'func (rg *registry) checkSize(requiredSize int) ' in '_state.go' +{ +requiredSize := newSize + if requiredSize > cap(rg.array) { + rg.resize(requiredSize) + } +} + rg.array[regi] = rg.alloc.LNumber2I(vali) + if regi >= rg.top { + rg.top = regi + 1 + } +} } else { L.RaiseError("for statement step must be a number") } @@ -1922,138 +1560,128 @@ func init() { L.RaiseError("for statement init must be a number") } cf.Pc += Sbx - return 0 - }, - func(L *LState, inst uint32, baseframe *callFrame) int { //OP_TFORLOOP - reg := L.reg - cf := L.currentFrame - lbase := cf.LocalBase + case OP_TFORLOOP: A := int(inst>>18) & 0xff //GETA RA := lbase + A C := int(inst>>9) & 0x1ff //GETC nret := C - // this section is inlined by go-inline - // source function is 'func (rg *registry) SetTop(topi int) ' in '_state.go' - { - rg := reg - topi := RA + 3 + 2 - // this section is inlined by go-inline - // source function is 'func (rg *registry) checkSize(requiredSize int) ' in '_state.go' - { - requiredSize := topi - if requiredSize > cap(rg.array) { - rg.resize(requiredSize) - } - } - oldtopi := rg.top - rg.top = topi - for i := oldtopi; i < rg.top; i++ { - rg.array[i] = LNil - } - // values beyond top don't need to be valid LValues, so setting them to nil is fine - // setting them to nil rather than LNil lets us invoke the golang memclr opto - if rg.top < oldtopi { - nilRange := rg.array[rg.top:oldtopi] - for i := range nilRange { - nilRange[i] = nil - } - } - //for i := rg.top; i < oldtop; i++ { - // rg.array[i] = LNil - //} - } - // this section is inlined by go-inline - // source function is 'func (rg *registry) Set(regi int, vali LValue) ' in '_state.go' - { - rg := reg - regi := RA + 3 + 2 - vali := reg.Get(RA + 2) - newSize := regi + 1 - // this section is inlined by go-inline - // source function is 'func (rg *registry) checkSize(requiredSize int) ' in '_state.go' - { - requiredSize := newSize - if requiredSize > cap(rg.array) { - rg.resize(requiredSize) - } - } - rg.array[regi] = vali - if regi >= rg.top { - rg.top = regi + 1 - } - } - // this section is inlined by go-inline - // source function is 'func (rg *registry) Set(regi int, vali LValue) ' in '_state.go' - { - rg := reg - regi := RA + 3 + 1 - vali := reg.Get(RA + 1) - newSize := regi + 1 - // this section is inlined by go-inline - // source function is 'func (rg *registry) checkSize(requiredSize int) ' in '_state.go' - { - requiredSize := newSize - if requiredSize > cap(rg.array) { - rg.resize(requiredSize) - } - } - rg.array[regi] = vali - if regi >= rg.top { - rg.top = regi + 1 - } - } - // this section is inlined by go-inline - // source function is 'func (rg *registry) Set(regi int, vali LValue) ' in '_state.go' - { - rg := reg - regi := RA + 3 - vali := reg.Get(RA) - newSize := regi + 1 - // this section is inlined by go-inline - // source function is 'func (rg *registry) checkSize(requiredSize int) ' in '_state.go' - { - requiredSize := newSize - if requiredSize > cap(rg.array) { - rg.resize(requiredSize) - } - } - rg.array[regi] = vali - if regi >= rg.top { - rg.top = regi + 1 - } - } +// this section is inlined by go-inline +// source function is 'func (rg *registry) SetTop(topi int) ' in '_state.go' +{ +rg := reg +topi := RA+3+2 +// this section is inlined by go-inline +// source function is 'func (rg *registry) checkSize(requiredSize int) ' in '_state.go' +{ +requiredSize := topi + if requiredSize > cap(rg.array) { + rg.resize(requiredSize) + } +} + oldtopi := rg.top + rg.top = topi + for i := oldtopi; i < rg.top; i++ { + rg.array[i] = LNil + } + // values beyond top don't need to be valid LValues, so setting them to nil is fine + // setting them to nil rather than LNil lets us invoke the golang memclr opto + if rg.top < oldtopi { + nilRange := rg.array[rg.top:oldtopi] + for i := range nilRange { + nilRange[i] = nil + } + } + //for i := rg.top; i < oldtop; i++ { + // rg.array[i] = LNil + //} +} +// this section is inlined by go-inline +// source function is 'func (rg *registry) Set(regi int, vali LValue) ' in '_state.go' +{ +rg := reg +regi := RA+3+2 +vali := reg.Get(RA+2) + newSize := regi + 1 +// this section is inlined by go-inline +// source function is 'func (rg *registry) checkSize(requiredSize int) ' in '_state.go' +{ +requiredSize := newSize + if requiredSize > cap(rg.array) { + rg.resize(requiredSize) + } +} + rg.array[regi] = vali + if regi >= rg.top { + rg.top = regi + 1 + } +} +// this section is inlined by go-inline +// source function is 'func (rg *registry) Set(regi int, vali LValue) ' in '_state.go' +{ +rg := reg +regi := RA+3+1 +vali := reg.Get(RA+1) + newSize := regi + 1 +// this section is inlined by go-inline +// source function is 'func (rg *registry) checkSize(requiredSize int) ' in '_state.go' +{ +requiredSize := newSize + if requiredSize > cap(rg.array) { + rg.resize(requiredSize) + } +} + rg.array[regi] = vali + if regi >= rg.top { + rg.top = regi + 1 + } +} +// this section is inlined by go-inline +// source function is 'func (rg *registry) Set(regi int, vali LValue) ' in '_state.go' +{ +rg := reg +regi := RA+3 +vali := reg.Get(RA) + newSize := regi + 1 +// this section is inlined by go-inline +// source function is 'func (rg *registry) checkSize(requiredSize int) ' in '_state.go' +{ +requiredSize := newSize + if requiredSize > cap(rg.array) { + rg.resize(requiredSize) + } +} + rg.array[regi] = vali + if regi >= rg.top { + rg.top = regi + 1 + } +} L.callR(2, nret, RA+3) if value := reg.Get(RA + 3); value != LNil { - // this section is inlined by go-inline - // source function is 'func (rg *registry) Set(regi int, vali LValue) ' in '_state.go' - { - rg := reg - regi := RA + 2 - vali := value - newSize := regi + 1 - // this section is inlined by go-inline - // source function is 'func (rg *registry) checkSize(requiredSize int) ' in '_state.go' - { - requiredSize := newSize - if requiredSize > cap(rg.array) { - rg.resize(requiredSize) - } - } - rg.array[regi] = vali - if regi >= rg.top { - rg.top = regi + 1 - } - } +// this section is inlined by go-inline +// source function is 'func (rg *registry) Set(regi int, vali LValue) ' in '_state.go' +{ +rg := reg +regi := RA+2 +vali := value + newSize := regi + 1 +// this section is inlined by go-inline +// source function is 'func (rg *registry) checkSize(requiredSize int) ' in '_state.go' +{ +requiredSize := newSize + if requiredSize > cap(rg.array) { + rg.resize(requiredSize) + } +} + rg.array[regi] = vali + if regi >= rg.top { + rg.top = regi + 1 + } +} pc := cf.Fn.Proto.Code[cf.Pc] cf.Pc += int(pc&0x3ffff) - opMaxArgSbx } cf.Pc++ - return 0 - }, - func(L *LState, inst uint32, baseframe *callFrame) int { //OP_SETLIST - reg := L.reg - cf := L.currentFrame - lbase := cf.LocalBase + case OP_SETLIST: A := int(inst>>18) & 0xff //GETA RA := lbase + A B := int(inst & 0x1ff) //GETB @@ -2071,64 +1699,55 @@ func init() { for i := 1; i <= nelem; i++ { table.RawSetInt(offset+i, reg.Get(RA+i)) } - return 0 - }, - func(L *LState, inst uint32, baseframe *callFrame) int { //OP_CLOSE - cf := L.currentFrame - lbase := cf.LocalBase + case OP_CLOSE: A := int(inst>>18) & 0xff //GETA RA := lbase + A - // this section is inlined by go-inline - // source function is 'func (ls *LState) closeUpvalues(idx int) ' in '_state.go' - { - ls := L - idx := RA - if ls.uvcache != nil { - var prev *Upvalue - for uv := ls.uvcache; uv != nil; uv = uv.next { - if uv.index >= idx { - if prev != nil { - prev.next = nil - } else { - ls.uvcache = nil - } - uv.Close() - } - prev = uv - } +// this section is inlined by go-inline +// source function is 'func (ls *LState) closeUpvalues(idx int) ' in '_state.go' +{ +ls := L +idx := RA + if ls.uvcache != nil { + var prev *Upvalue + for uv := ls.uvcache; uv != nil; uv = uv.next { + if uv.index >= idx { + if prev != nil { + prev.next = nil + } else { + ls.uvcache = nil } + uv.Close() } - return 0 - }, - func(L *LState, inst uint32, baseframe *callFrame) int { //OP_CLOSURE - reg := L.reg - cf := L.currentFrame - lbase := cf.LocalBase + prev = uv + } + } +} + case OP_CLOSURE: A := int(inst>>18) & 0xff //GETA RA := lbase + A Bx := int(inst & 0x3ffff) //GETBX proto := cf.Fn.Proto.FunctionPrototypes[Bx] closure := newLFunctionL(proto, cf.Fn.Env, int(proto.NumUpvalues)) - // this section is inlined by go-inline - // source function is 'func (rg *registry) Set(regi int, vali LValue) ' in '_state.go' - { - rg := reg - regi := RA - vali := closure - newSize := regi + 1 - // this section is inlined by go-inline - // source function is 'func (rg *registry) checkSize(requiredSize int) ' in '_state.go' - { - requiredSize := newSize - if requiredSize > cap(rg.array) { - rg.resize(requiredSize) - } - } - rg.array[regi] = vali - if regi >= rg.top { - rg.top = regi + 1 - } - } +// this section is inlined by go-inline +// source function is 'func (rg *registry) Set(regi int, vali LValue) ' in '_state.go' +{ +rg := reg +regi := RA +vali := closure + newSize := regi + 1 +// this section is inlined by go-inline +// source function is 'func (rg *registry) checkSize(requiredSize int) ' in '_state.go' +{ +requiredSize := newSize + if requiredSize > cap(rg.array) { + rg.resize(requiredSize) + } +} + rg.array[regi] = vali + if regi >= rg.top { + rg.top = regi + 1 + } +} for i := 0; i < int(proto.NumUpvalues); i++ { inst = cf.Fn.Proto.Code[cf.Pc] cf.Pc++ @@ -2140,12 +1759,7 @@ func init() { closure.Upvalues[i] = cf.Fn.Upvalues[B] } } - return 0 - }, - func(L *LState, inst uint32, baseframe *callFrame) int { //OP_VARARG - reg := L.reg - cf := L.currentFrame - lbase := cf.LocalBase + case OP_VARARG: A := int(inst>>18) & 0xff //GETA RA := lbase + A B := int(inst & 0x1ff) //GETB @@ -2158,113 +1772,281 @@ func init() { if B == 0 { nwant = nvarargs } - // this section is inlined by go-inline - // source function is 'func (rg *registry) CopyRange(regv, start, limit, n int) ' in '_state.go' - { - rg := reg - regv := RA - start := cf.Base + nparams + 1 - limit := cf.LocalBase - n := nwant - newSize := regv + n - // this section is inlined by go-inline - // source function is 'func (rg *registry) checkSize(requiredSize int) ' in '_state.go' - { - requiredSize := newSize - if requiredSize > cap(rg.array) { - rg.resize(requiredSize) - } - } - if limit == -1 || limit > rg.top { - limit = rg.top - } - for i := 0; i < n; i++ { - srcIdx := start + i - if srcIdx >= limit || srcIdx < 0 { - rg.array[regv+i] = LNil - } else { - rg.array[regv+i] = rg.array[srcIdx] - } - } +// this section is inlined by go-inline +// source function is 'func (rg *registry) CopyRange(regv, start, limit, n int) ' in '_state.go' +{ +rg := reg +regv := RA +start := cf.Base+nparams+1 +limit := cf.LocalBase +n := nwant + newSize := regv + n +// this section is inlined by go-inline +// source function is 'func (rg *registry) checkSize(requiredSize int) ' in '_state.go' +{ +requiredSize := newSize + if requiredSize > cap(rg.array) { + rg.resize(requiredSize) + } +} + if limit == -1 || limit > rg.top { + limit = rg.top + } + for i := 0; i < n; i++ { + srcIdx := start + i + if srcIdx >= limit || srcIdx < 0 { + rg.array[regv+i] = LNil + } else { + rg.array[regv+i] = rg.array[srcIdx] + } + } - // values beyond top don't need to be valid LValues, so setting them to nil is fine - // setting them to nil rather than LNil lets us invoke the golang memclr opto - oldtop := rg.top - rg.top = regv + n - if rg.top < oldtop { - nilRange := rg.array[rg.top:oldtop] - for i := range nilRange { - nilRange[i] = nil - } - } - } - return 0 - }, - func(L *LState, inst uint32, baseframe *callFrame) int { //OP_NOP - return 0 - }, + // values beyond top don't need to be valid LValues, so setting them to nil is fine + // setting them to nil rather than LNil lets us invoke the golang memclr opto + oldtop := rg.top + rg.top = regv + n + if rg.top < oldtop { + nilRange := rg.array[rg.top:oldtop] + for i := range nilRange { + nilRange[i] = nil + } } } + case OP_NOP: + } + } -func opArith(L *LState, inst uint32, baseframe *callFrame) int { //OP_ADD, OP_SUB, OP_MUL, OP_DIV, OP_MOD, OP_POW - reg := L.reg - cf := L.currentFrame - lbase := cf.LocalBase - A := int(inst>>18) & 0xff //GETA - RA := lbase + A - opcode := int(inst >> 26) //GETOPCODE - B := int(inst & 0x1ff) //GETB - C := int(inst>>9) & 0x1ff //GETC - lhs := L.rkValue(B) - rhs := L.rkValue(C) - v1, ok1 := lhs.(LNumber) - v2, ok2 := rhs.(LNumber) - if ok1 && ok2 { - v := numberArith(L, opcode, LNumber(v1), LNumber(v2)) - // this section is inlined by go-inline - // source function is 'func (rg *registry) SetNumber(regi int, vali LNumber) ' in '_state.go' - { - rg := reg - regi := RA - vali := v - newSize := regi + 1 - // this section is inlined by go-inline - // source function is 'func (rg *registry) checkSize(requiredSize int) ' in '_state.go' - { - requiredSize := newSize - if requiredSize > cap(rg.array) { - rg.resize(requiredSize) - } - } - rg.array[regi] = rg.alloc.LNumber2I(vali) - if regi >= rg.top { - rg.top = regi + 1 - } + L.RaiseError(L.ctx.Err().Error()) +} + +// regv is the first target register to copy the return values to. +// It can be reg.top, indicating that the copied values are going into new registers, or it can be below reg.top +// Indicating that the values should be within the existing registers. +// b is the available number of return values + 1. +// n is the desired number of return values. +// If n more than the available return values then the extra values are set to nil. +// When this function returns the top of the registry will be set to regv+n. +func copyReturnValues(L *LState, regv, start, n, b int) { // +inline-start + if b == 1 { +// this section is inlined by go-inline +// source function is 'func (rg *registry) FillNil(regm, n int) ' in '_state.go' +{ +rg := L.reg +regm := regv + newSize := regm + n +// this section is inlined by go-inline +// source function is 'func (rg *registry) checkSize(requiredSize int) ' in '_state.go' +{ +requiredSize := newSize + if requiredSize > cap(rg.array) { + rg.resize(requiredSize) + } +} + for i := 0; i < n; i++ { + rg.array[regm+i] = LNil + } + // values beyond top don't need to be valid LValues, so setting them to nil is fine + // setting them to nil rather than LNil lets us invoke the golang memclr opto + oldtop := rg.top + rg.top = regm + n + if rg.top < oldtop { + nilRange := rg.array[rg.top:oldtop] + for i := range nilRange { + nilRange[i] = nil } + } +} } else { - v := objectArith(L, opcode, lhs, rhs) - // this section is inlined by go-inline - // source function is 'func (rg *registry) Set(regi int, vali LValue) ' in '_state.go' - { - rg := reg - regi := RA - vali := v - newSize := regi + 1 - // this section is inlined by go-inline - // source function is 'func (rg *registry) checkSize(requiredSize int) ' in '_state.go' - { - requiredSize := newSize - if requiredSize > cap(rg.array) { - rg.resize(requiredSize) - } +// this section is inlined by go-inline +// source function is 'func (rg *registry) CopyRange(regv, start, limit, n int) ' in '_state.go' +{ +rg := L.reg +limit := -1 + newSize := regv + n +// this section is inlined by go-inline +// source function is 'func (rg *registry) checkSize(requiredSize int) ' in '_state.go' +{ +requiredSize := newSize + if requiredSize > cap(rg.array) { + rg.resize(requiredSize) + } +} + if limit == -1 || limit > rg.top { + limit = rg.top + } + for i := 0; i < n; i++ { + srcIdx := start + i + if srcIdx >= limit || srcIdx < 0 { + rg.array[regv+i] = LNil + } else { + rg.array[regv+i] = rg.array[srcIdx] + } + } + + // values beyond top don't need to be valid LValues, so setting them to nil is fine + // setting them to nil rather than LNil lets us invoke the golang memclr opto + oldtop := rg.top + rg.top = regv + n + if rg.top < oldtop { + nilRange := rg.array[rg.top:oldtop] + for i := range nilRange { + nilRange[i] = nil + } + } +} + if b > 1 && n > (b-1) { +// this section is inlined by go-inline +// source function is 'func (rg *registry) FillNil(regm, n int) ' in '_state.go' +{ +rg := L.reg +regm := regv+b-1 +n := n-(b-1) + newSize := regm + n +// this section is inlined by go-inline +// source function is 'func (rg *registry) checkSize(requiredSize int) ' in '_state.go' +{ +requiredSize := newSize + if requiredSize > cap(rg.array) { + rg.resize(requiredSize) + } +} + for i := 0; i < n; i++ { + rg.array[regm+i] = LNil + } + // values beyond top don't need to be valid LValues, so setting them to nil is fine + // setting them to nil rather than LNil lets us invoke the golang memclr opto + oldtop := rg.top + rg.top = regm + n + if rg.top < oldtop { + nilRange := rg.array[rg.top:oldtop] + for i := range nilRange { + nilRange[i] = nil + } + } +} + } + } +} // +inline-end + +func switchToParentThread(L *LState, nargs int, haserror bool, kill bool) { + parent := L.Parent + if parent == nil { + L.RaiseError("can not yield from outside of a coroutine") + } + L.G.CurrentThread = parent + L.Parent = nil + if !L.wrapped { + if haserror { + parent.Push(LFalse) + } else { + parent.Push(LTrue) + } + } + L.XMoveTo(parent, nargs) + L.stack.Pop() + offset := L.currentFrame.LocalBase - L.currentFrame.ReturnBase + L.currentFrame = L.stack.Last() + L.reg.SetTop(L.reg.Top() - offset) // remove 'yield' function(including tailcalled functions) + if kill { + L.kill() + } +} + +func callGFunction(L *LState, tailcall bool) bool { + frame := L.currentFrame + gfnret := frame.Fn.GFunction(L) + if tailcall { + L.currentFrame = L.RemoveCallerFrame() + } + + if gfnret < 0 { + switchToParentThread(L, L.GetTop(), false, false) + return true + } + + wantret := frame.NRet + if wantret == MultRet { + wantret = gfnret + } + + if tailcall && L.Parent != nil && L.stack.Sp() == 1 { + switchToParentThread(L, wantret, false, true) + return true + } + +// this section is inlined by go-inline +// source function is 'func (rg *registry) CopyRange(regv, start, limit, n int) ' in '_state.go' +{ +rg := L.reg +regv := frame.ReturnBase +start := L.reg.Top()-gfnret +limit := -1 +n := wantret + newSize := regv + n +// this section is inlined by go-inline +// source function is 'func (rg *registry) checkSize(requiredSize int) ' in '_state.go' +{ +requiredSize := newSize + if requiredSize > cap(rg.array) { + rg.resize(requiredSize) + } +} + if limit == -1 || limit > rg.top { + limit = rg.top + } + for i := 0; i < n; i++ { + srcIdx := start + i + if srcIdx >= limit || srcIdx < 0 { + rg.array[regv+i] = LNil + } else { + rg.array[regv+i] = rg.array[srcIdx] + } + } + + // values beyond top don't need to be valid LValues, so setting them to nil is fine + // setting them to nil rather than LNil lets us invoke the golang memclr opto + oldtop := rg.top + rg.top = regv + n + if rg.top < oldtop { + nilRange := rg.array[rg.top:oldtop] + for i := range nilRange { + nilRange[i] = nil + } + } +} + L.stack.Pop() + L.currentFrame = L.stack.Last() + return false +} + +func threadRun(L *LState) { + if L.stack.IsEmpty() { + return + } + + defer func() { + if rcv := recover(); rcv != nil { + var lv LValue + if v, ok := rcv.(*ApiError); ok { + lv = v.Object + } else { + lv = LString(fmt.Sprint(rcv)) } - rg.array[regi] = vali - if regi >= rg.top { - rg.top = regi + 1 + if parent := L.Parent; parent != nil { + if L.wrapped { + L.Push(lv) + parent.Panic(L) + } else { + L.SetTop(0) + L.Push(lv) + switchToParentThread(L, 1, true, true) + } + } else { + panic(rcv) } } - } - return 0 + }() + mainLoop(L, nil) } func luaModulo(lhs, rhs LNumber) LNumber { @@ -2463,3 +2245,4 @@ func objectRational(L *LState, lhs, rhs LValue, event string) int { } return -1 } +