vm: optimize ROLL/ROT, refactor common code

Add `Roll` method to Stack that doesn't pop and push values and use it for
ROLL and ROT.

1.4M->1.5M 100K block import test before:
real    3m44,292s
user    5m43,494s
sys     0m34,741s

After:
real    3m40,449s
user    5m42,701s
sys     0m35,500s
This commit is contained in:
Roman Khimov 2019-12-16 19:53:21 +03:00
parent 2627628387
commit 587cfc7c66
4 changed files with 108 additions and 13 deletions

View file

@ -389,6 +389,34 @@ func (s *Stack) Swap(n1, n2 int) error {
return nil
}
// Roll brings an item with the given index to the top of the stack, moving all
// the other elements down accordingly. It does all of that without popping and
// pushing elements.
func (s *Stack) Roll(n int) error {
if n < 0 {
return errors.New("negative index")
}
if n >= s.len {
return errors.New("too big index")
}
if n == 0 {
return nil
}
top := s.Peek(0)
e := s.Peek(n)
e.prev.next = e.next
e.next.prev = e.prev
top.prev = e
e.next = top
e.prev = &s.top
s.top.next = e
return nil
}
// popSigElements pops keys or signatures from the stack as needed for
// CHECKMULTISIG.
func (s *Stack) popSigElements() ([][]byte, error) {