@@ -40,6 +40,7 @@ type VM struct {
4040 Stack []any
4141 Scopes []* Scope
4242 Variables []any
43+ reflectArgs []reflect.Value
4344 MemoryBudget uint
4445 ip int
4546 memory uint
@@ -82,6 +83,10 @@ func (vm *VM) Run(program *Program, env any) (_ any, err error) {
8283 if vm .MemoryBudget == 0 {
8384 vm .MemoryBudget = conf .DefaultMemoryBudget
8485 }
86+ if vm .reflectArgs != nil {
87+ clearSlice (vm .reflectArgs )
88+ }
89+
8590 vm .memory = 0
8691 vm .ip = 0
8792
@@ -336,15 +341,25 @@ func (vm *VM) Run(program *Program, env any) (_ any, err error) {
336341 case OpCall :
337342 fn := reflect .ValueOf (vm .pop ())
338343 size := arg
339- in := make ([]reflect.Value , size )
340- for i := int (size ) - 1 ; i >= 0 ; i -- {
341- param := vm .pop ()
342- if param == nil {
343- in [i ] = reflect .Zero (fn .Type ().In (i ))
344- } else {
345- in [i ] = reflect .ValueOf (param )
344+ if len (vm .reflectArgs ) < size {
345+ vm .reflectArgs = make ([]reflect.Value , size )
346+ }
347+ var in []reflect.Value
348+ if size > 0 {
349+ in = vm .reflectArgs [:size ]
350+ // pop in bulk
351+ stackTail := vm .Stack [len (vm .Stack )- size :]
352+ vm .Stack = vm .Stack [:len (vm .Stack )- size ]
353+ for i := range stackTail {
354+ param := stackTail [i ]
355+ if param == nil {
356+ in [i ] = reflect .Zero (fn .Type ().In (i ))
357+ } else {
358+ in [i ] = reflect .ValueOf (param )
359+ }
346360 }
347361 }
362+
348363 out := fn .Call (in )
349364 if len (out ) == 2 && out [1 ].Type () == errorType && ! out [1 ].IsNil () {
350365 panic (out [1 ].Interface ().(error ))
0 commit comments