vm: optimize SWAP instruction, refactor common code

Add `Swap` method to the Stack and use it for both SWAP and XSWAP. Avoid
element popping and pushing (and associated accounting costs).

1.4M->1.5M 100K block import test before:
real    3m51,885s
user    5m54,744s
sys     0m38,444s

After:
real    3m44,292s
user    5m43,494s
sys     0m34,741s
This commit is contained in:
Roman Khimov 2019-12-16 19:02:40 +03:00
parent b78896f2e1
commit 2627628387
4 changed files with 115 additions and 30 deletions

View file

@ -2,6 +2,7 @@ package vm
import (
"encoding/json"
"errors"
"fmt"
"math/big"
@ -371,6 +372,23 @@ func (s *Stack) IterBack(f func(*Element)) {
}
}
// Swap swaps two elements on the stack without popping and pushing them.
func (s *Stack) Swap(n1, n2 int) error {
if n1 < 0 || n2 < 0 {
return errors.New("negative index")
}
if n1 >= s.len || n2 >= s.len {
return errors.New("too big index")
}
if n1 == n2 {
return nil
}
a := s.Peek(n1)
b := s.Peek(n2)
a.value, b.value = b.value, a.value
return nil
}
// popSigElements pops keys or signatures from the stack as needed for
// CHECKMULTISIG.
func (s *Stack) popSigElements() ([][]byte, error) {