Skip to content

Commit 1e5e3d8

Browse files
committed
optimize and reuse reflect call arguments allocation
1 parent 2fb1f53 commit 1e5e3d8

File tree

1 file changed

+22
-7
lines changed

1 file changed

+22
-7
lines changed

vm/vm.go

Lines changed: 22 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -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

Comments
 (0)