From fe0ec91636b89c3293b6cb629b0accfc84b838da Mon Sep 17 00:00:00 2001 From: Roman Khimov Date: Thu, 15 Oct 2020 16:10:48 +0300 Subject: [PATCH 1/3] vm: optimize reversing items on the stack Before: BenchmarkOpcodes/REVERSE3/null-8 10000 335 ns/op BenchmarkOpcodes/REVERSE3/integer-8 10000 355 ns/op BenchmarkOpcodes/REVERSE3/big_bytes-8 10000 344 ns/op BenchmarkOpcodes/REVERSE4/null-8 10000 353 ns/op BenchmarkOpcodes/REVERSE4/integer-8 10000 336 ns/op BenchmarkOpcodes/REVERSE4/big_bytes-8 10000 324 ns/op BenchmarkOpcodes/REVERSEN/5/null-8 10000 350 ns/op BenchmarkOpcodes/REVERSEN/5/integer-8 10000 358 ns/op BenchmarkOpcodes/REVERSEN/5/big_bytes-8 10000 351 ns/op BenchmarkOpcodes/REVERSEN/1024/null-8 10000 982413 ns/op BenchmarkOpcodes/REVERSEN/1024/integer-8 10000 994926 ns/op BenchmarkOpcodes/REVERSEN/1024/big_bytes-8 10000 992951 ns/op After: BenchmarkOpcodes/REVERSE3/null-8 10000 241 ns/op BenchmarkOpcodes/REVERSE3/integer-8 10000 255 ns/op BenchmarkOpcodes/REVERSE3/big_bytes-8 10000 249 ns/op BenchmarkOpcodes/REVERSE4/null-8 10000 249 ns/op BenchmarkOpcodes/REVERSE4/integer-8 10000 267 ns/op BenchmarkOpcodes/REVERSE4/big_bytes-8 10000 292 ns/op BenchmarkOpcodes/REVERSEN/5/null-8 10000 337 ns/op BenchmarkOpcodes/REVERSEN/5/integer-8 10000 327 ns/op BenchmarkOpcodes/REVERSEN/5/big_bytes-8 10000 293 ns/op BenchmarkOpcodes/REVERSEN/1024/null-8 10000 5414 ns/op BenchmarkOpcodes/REVERSEN/1024/integer-8 10000 5487 ns/op BenchmarkOpcodes/REVERSEN/1024/big_bytes-8 10000 5609 ns/op --- pkg/vm/stack.go | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/pkg/vm/stack.go b/pkg/vm/stack.go index 62f45022a..1b1130f53 100644 --- a/pkg/vm/stack.go +++ b/pkg/vm/stack.go @@ -351,10 +351,11 @@ func (s *Stack) ReverseTop(n int) error { return nil } - for i, j := 0, n-1; i < j; { - s.swap(i, j) - i++ - j-- + a, b := s.Peek(0), s.Peek(n-1) + for i := 0; i < n/2; i++ { + a.value, b.value = b.value, a.value + a = a.Next() + b = b.Prev() } return nil } From 3d8434a50c6d463974429f25d21fec8bbaa93a0f Mon Sep 17 00:00:00 2001 From: Roman Khimov Date: Thu, 15 Oct 2020 16:11:26 +0300 Subject: [PATCH 2/3] vm: fix invocation stack checks It should be done on every new context push. --- pkg/vm/vm.go | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/pkg/vm/vm.go b/pkg/vm/vm.go index 9d22a96f1..33be7df7b 100644 --- a/pkg/vm/vm.go +++ b/pkg/vm/vm.go @@ -273,6 +273,7 @@ func (v *VM) LoadScript(b []byte) { // LoadScriptWithFlags loads script and sets call flag to f. func (v *VM) LoadScriptWithFlags(b []byte, f smartcontract.CallFlag) { + v.checkInvocationStackSize() ctx := NewContext(b) v.estack = v.newItemStack("estack") ctx.estack = v.estack @@ -1226,7 +1227,6 @@ func (v *VM) execute(ctx *Context, op opcode.Opcode, parameter []byte) (err erro } case opcode.CALL, opcode.CALLL: - v.checkInvocationStackSize() // Note: jump offset must be calculated regarding to new context, // but it is cloned and thus has the same script and instruction pointer. v.call(ctx, v.getJumpOffset(ctx, parameter)) @@ -1476,6 +1476,7 @@ func (v *VM) Call(ctx *Context, offset int) { // affect the invocation counter and is only being used by vm // package. func (v *VM) call(ctx *Context, offset int) { + v.checkInvocationStackSize() newCtx := ctx.Copy() newCtx.CheckReturn = NoCheck newCtx.local = nil From 27a01c7759e66933d61abe20fb8437a96279caa7 Mon Sep 17 00:00:00 2001 From: Roman Khimov Date: Thu, 15 Oct 2020 16:12:03 +0300 Subject: [PATCH 3/3] vm: optimize stack traversal on exception handling Before: BenchmarkOpcodes/THROW/0/1-8 10000 506 ns/op BenchmarkOpcodes/THROW/0/16-8 10000 524 ns/op BenchmarkOpcodes/THROW/255/0-8 10000 49363 ns/op BenchmarkOpcodes/THROW/1023/0-8 10000 1628480 ns/op After: BenchmarkOpcodes/THROW/0/1-8 10000 575 ns/op BenchmarkOpcodes/THROW/0/16-8 10000 516 ns/op BenchmarkOpcodes/THROW/255/0-8 10000 8290 ns/op BenchmarkOpcodes/THROW/1023/0-8 10000 34605 ns/op --- pkg/vm/vm.go | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/pkg/vm/vm.go b/pkg/vm/vm.go index 33be7df7b..a39c27365 100644 --- a/pkg/vm/vm.go +++ b/pkg/vm/vm.go @@ -1521,7 +1521,8 @@ func (v *VM) calcJumpOffset(ctx *Context, parameter []byte) (int, int, error) { func (v *VM) handleException() { pop := 0 - ictx := v.istack.Peek(0).Value().(*Context) + ictxv := v.istack.Peek(0) + ictx := ictxv.Value().(*Context) for ictx != nil { e := ictx.tryStack.Peek(0) for e != nil { @@ -1547,7 +1548,8 @@ func (v *VM) handleException() { return } pop++ - ictx = v.istack.Peek(pop).Value().(*Context) + ictxv = ictxv.Next() + ictx = ictxv.Value().(*Context) } }