@@ -3741,6 +3741,10 @@ function VirtualMachine:getLength(...)
37413741 return select (" #" , ... )
37423742end
37433743
3744+ local function pack (...)
3745+ return select (" #" , ... ), { ... }
3746+ end
3747+
37443748function VirtualMachine :pushClosure (closure )
37453749 closure = {
37463750 nupvalues = closure .nupvalues or 0 ,
@@ -3786,8 +3790,7 @@ function VirtualMachine:executeClosure(...)
37863790 stack [paramIdx - 1 ] = params [paramIdx ]
37873791 end
37883792 if isVararg then
3789- vararg = { select (numparams + 1 , ... ) }
3790- varargLen = self :getLength (unpack (vararg ))
3793+ varargLen , vararg = pack (select (numparams + 1 , ... ))
37913794 stack [numparams ] = vararg -- Implicit "arg" argument.
37923795 end
37933796
@@ -4010,48 +4013,28 @@ function VirtualMachine:executeClosure(...)
40104013 -- Call a closure (function) with arguments and handle returns.
40114014 elseif opcode == " CALL" then
40124015 local func = stack [a ]
4013- local args = {}
4014- local nArgs
40154016 if b ~= USE_CURRENT_TOP then
4016- nArgs = b - 1
4017- for index = 1 , nArgs do
4018- table.insert (args , stack [a + index ])
4019- end
4020- else
4021- nArgs = top - (a + 1 )
4022- for index = a + 1 , top - 1 do
4023- table.insert (args , stack [index ])
4024- end
4017+ top = a + b
40254018 end
40264019
4027- local returns = { func (unpack (args )) }
4020+ local nReturns , returns = pack ( func (unpack (stack , a + 1 , top - 1 )))
40284021
40294022 if c ~= USE_CURRENT_TOP then
4030- for index = 0 , c - 2 do
4031- stack [a + index ] = returns [index + 1 ]
4032- end
4023+ nReturns = c - 1
40334024 else
40344025 -- Multi-return: push all results onto the stack.
4035- local nReturns = self :getLength (unpack (returns ))
40364026 top = a + nReturns
4037- for index = 1 , nReturns do
4038- stack [ a + index - 1 ] = returns [ index ]
4039- end
4027+ end
4028+ for index = 1 , nReturns do
4029+ stack [ a + index - 1 ] = returns [ index ]
40404030 end
40414031
40424032 -- OP_TAILCALL [A, B, C] return R(A)(R(A+1), ... ,R(A+B-1))
40434033 -- Perform a tail call to a closure (function).
40444034 elseif opcode == " TAILCALL" then
40454035 local func = stack [a ]
4046- local args = {}
40474036 if b ~= USE_CURRENT_TOP then
4048- for reg = a + 1 , a + b - 1 do
4049- table.insert (args , stack [reg ])
4050- end
4051- else
4052- for reg = a + 1 , a + top do
4053- table.insert (args , stack [reg ])
4054- end
4037+ top = a + b
40554038 end
40564039
40574040 -- Continuation of original implementation:
@@ -4068,23 +4051,16 @@ function VirtualMachine:executeClosure(...)
40684051 -- Since TAILCALL always comes before RETURN,
40694052 -- we can just return the function call results directly.
40704053
4071- return func (unpack (args ))
4054+ return func (unpack (stack , a + 1 , top - 1 ))
40724055
40734056 -- OP_RETURN [A, B] return R(A), ... ,R(A+B-2)
40744057 -- Return values from function call.
40754058 elseif opcode == " RETURN" then
4076- local returns = {}
4077- if b == USE_CURRENT_TOP then
4078- for reg = a , top do
4079- table.insert (returns , stack [reg ])
4080- end
4081- else
4082- for reg = a , a + b - 2 do
4083- table.insert (returns , stack [reg ])
4084- end
4059+ if b ~= USE_CURRENT_TOP then
4060+ top = a + b - 1
40854061 end
40864062
4087- return unpack (returns )
4063+ return unpack (stack , a , top - 1 )
40884064
40894065 -- OP_FORLOOP [A, sBx] R(A)+=R(A+2)
40904066 -- if R(A) <?= R(A+1) then { pc+=sBx R(A+3)=R(A) }
@@ -4251,10 +4227,10 @@ function VirtualMachine:executeClosure(...)
42514227 -- of code.
42524228 stack [a ] = function (...)
42534229 self :pushClosure (tClosure )
4254- local returns = { self :executeClosure (... ) }
4230+ local nReturns , returns = pack ( self :executeClosure (... ))
42554231 self :pushClosure (closure )
42564232
4257- return unpack (returns )
4233+ return unpack (returns , 1 , nReturns )
42584234 end
42594235
42604236 -- OP_VARARG [A, B] R(A), R(A+1), ..., R(A+B-1) = vararg
0 commit comments