@@ -40,6 +40,7 @@ type VM struct {
40
40
Stack []any
41
41
Scopes []* Scope
42
42
Variables []any
43
+ reflectArgs []reflect.Value
43
44
MemoryBudget uint
44
45
ip int
45
46
memory uint
@@ -82,6 +83,10 @@ func (vm *VM) Run(program *Program, env any) (_ any, err error) {
82
83
if vm .MemoryBudget == 0 {
83
84
vm .MemoryBudget = conf .DefaultMemoryBudget
84
85
}
86
+ if vm .reflectArgs != nil {
87
+ clearSlice (vm .reflectArgs )
88
+ }
89
+
85
90
vm .memory = 0
86
91
vm .ip = 0
87
92
@@ -336,15 +341,25 @@ func (vm *VM) Run(program *Program, env any) (_ any, err error) {
336
341
case OpCall :
337
342
fn := reflect .ValueOf (vm .pop ())
338
343
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
+ }
346
360
}
347
361
}
362
+
348
363
out := fn .Call (in )
349
364
if len (out ) == 2 && out [1 ].Type () == errorType && ! out [1 ].IsNil () {
350
365
panic (out [1 ].Interface ().(error ))
0 commit comments