diff --git a/src/core/org/luaj/vm2/LuaClosure.java b/src/core/org/luaj/vm2/LuaClosure.java index 46a3556f..a2a0658a 100644 --- a/src/core/org/luaj/vm2/LuaClosure.java +++ b/src/core/org/luaj/vm2/LuaClosure.java @@ -23,6 +23,9 @@ import org.luaj.vm2.lib.DebugLib.CallFrame; +import java.util.ArrayList; +import java.util.List; + /** * Extension of {@link LuaFunction} which executes lua bytecode. *

@@ -128,44 +131,98 @@ public LuaClosure checkclosure() { public String tojstring() { return "function: " + p.toString(); } - + + + private List stackPool = new ArrayList<>(); private LuaValue[] getNewStack() { + if (stackPool.isEmpty()) { + return getNewStackRaw(); + } else { + return stackPool.remove(stackPool.size() - 1); + } + } + + private LuaValue[] getNewStackRaw() { int max = p.maxstacksize; LuaValue[] stack = new LuaValue[max]; System.arraycopy(NILS, 0, stack, 0, max); return stack; } + + private void releaseStack(LuaValue[] stack) { + System.arraycopy(NILS, 0, stack, 0, stack.length); + stackPool.add(stack); + } public final LuaValue call() { LuaValue[] stack = getNewStack(); - return execute(stack,NONE).arg1(); + LuaValue result = execute(stack,NONE).arg1(); + releaseStack(stack); + return result; } public final LuaValue call(LuaValue arg) { LuaValue[] stack = getNewStack(); + LuaValue result; switch ( p.numparams ) { - default: stack[0]=arg; return execute(stack,NONE).arg1(); - case 0: return execute(stack,arg).arg1(); + default: + stack[0]=arg; + result = execute(stack,NONE).arg1(); + break; + case 0: + result = execute(stack,arg).arg1(); + break; } + releaseStack(stack); + return result; } public final LuaValue call(LuaValue arg1, LuaValue arg2) { LuaValue[] stack = getNewStack(); + LuaValue result; switch ( p.numparams ) { - default: stack[0]=arg1; stack[1]=arg2; return execute(stack,NONE).arg1(); - case 1: stack[0]=arg1; return execute(stack,arg2).arg1(); - case 0: return execute(stack,p.is_vararg!=0? varargsOf(arg1,arg2): NONE).arg1(); + default: + stack[0]=arg1; + stack[1]=arg2; + result = execute(stack,NONE).arg1(); + break; + case 1: + stack[0]=arg1; + result = execute(stack,arg2).arg1(); + break; + case 0: + result = execute(stack,p.is_vararg!=0 ? varargsOf(arg1,arg2) : NONE).arg1(); + break; } + releaseStack(stack); + return result; } public final LuaValue call(LuaValue arg1, LuaValue arg2, LuaValue arg3) { LuaValue[] stack = getNewStack(); + LuaValue result; switch ( p.numparams ) { - default: stack[0]=arg1; stack[1]=arg2; stack[2]=arg3; return execute(stack,NONE).arg1(); - case 2: stack[0]=arg1; stack[1]=arg2; return execute(stack,arg3).arg1(); - case 1: stack[0]=arg1; return execute(stack,p.is_vararg!=0? varargsOf(arg2,arg3): NONE).arg1(); - case 0: return execute(stack,p.is_vararg!=0? varargsOf(arg1,arg2,arg3): NONE).arg1(); + default: + stack[0]=arg1; + stack[1]=arg2; + stack[2]=arg3; + result = execute(stack,NONE).arg1(); + break; + case 2: + stack[0]=arg1; + stack[1]=arg2; + result = execute(stack,arg3).arg1(); + break; + case 1: + stack[0]=arg1; + result = execute(stack,p.is_vararg!=0 ? varargsOf(arg2,arg3) : NONE).arg1(); + break; + case 0: + result = execute(stack,p.is_vararg!=0 ? varargsOf(arg1,arg2,arg3) : NONE).arg1(); + break; } + releaseStack(stack); + return result; } public final Varargs invoke(Varargs varargs) { @@ -176,7 +233,11 @@ public final Varargs onInvoke(Varargs varargs) { LuaValue[] stack = getNewStack(); for ( int i=0; i