aboutsummaryrefslogtreecommitdiff
path: root/core/vm/stack.go
diff options
context:
space:
mode:
Diffstat (limited to 'core/vm/stack.go')
-rw-r--r--core/vm/stack.go84
1 files changed, 60 insertions, 24 deletions
diff --git a/core/vm/stack.go b/core/vm/stack.go
index 4c1b9e8..af27d65 100644
--- a/core/vm/stack.go
+++ b/core/vm/stack.go
@@ -18,36 +18,48 @@ package vm
import (
"fmt"
- "math/big"
+ "sync"
+
+ "github.com/holiman/uint256"
)
+var stackPool = sync.Pool{
+ New: func() interface{} {
+ return &Stack{data: make([]uint256.Int, 0, 16)}
+ },
+}
+
// Stack is an object for basic stack operations. Items popped to the stack are
// expected to be changed and modified. stack does not take care of adding newly
// initialised objects.
type Stack struct {
- data []*big.Int
+ data []uint256.Int
}
func newstack() *Stack {
- return &Stack{data: make([]*big.Int, 0, 1024)}
+ return stackPool.Get().(*Stack)
}
-// Data returns the underlying big.Int array.
-func (st *Stack) Data() []*big.Int {
+func returnStack(s *Stack) {
+ s.data = s.data[:0]
+ stackPool.Put(s)
+}
+
+// Data returns the underlying uint256.Int array.
+func (st *Stack) Data() []uint256.Int {
return st.data
}
-func (st *Stack) push(d *big.Int) {
+func (st *Stack) push(d *uint256.Int) {
// NOTE push limit (1024) is checked in baseCheck
- //stackItem := new(big.Int).Set(d)
- //st.data = append(st.data, stackItem)
- st.data = append(st.data, d)
+ st.data = append(st.data, *d)
}
-func (st *Stack) pushN(ds ...*big.Int) {
+func (st *Stack) pushN(ds ...uint256.Int) {
+ // FIXME: Is there a way to pass args by pointers.
st.data = append(st.data, ds...)
}
-func (st *Stack) pop() (ret *big.Int) {
+func (st *Stack) pop() (ret uint256.Int) {
ret = st.data[len(st.data)-1]
st.data = st.data[:len(st.data)-1]
return
@@ -61,24 +73,17 @@ func (st *Stack) swap(n int) {
st.data[st.len()-n], st.data[st.len()-1] = st.data[st.len()-1], st.data[st.len()-n]
}
-func (st *Stack) dup(pool *intPool, n int) {
- st.push(pool.get().Set(st.data[st.len()-n]))
+func (st *Stack) dup(n int) {
+ st.push(&st.data[st.len()-n])
}
-func (st *Stack) peek() *big.Int {
- return st.data[st.len()-1]
+func (st *Stack) peek() *uint256.Int {
+ return &st.data[st.len()-1]
}
// Back returns the n'th item in stack
-func (st *Stack) Back(n int) *big.Int {
- return st.data[st.len()-n-1]
-}
-
-func (st *Stack) require(n int) error {
- if st.len() < n {
- return fmt.Errorf("stack underflow (%d <=> %d)", len(st.data), n)
- }
- return nil
+func (st *Stack) Back(n int) *uint256.Int {
+ return &st.data[st.len()-n-1]
}
// Print dumps the content of the stack
@@ -93,3 +98,34 @@ func (st *Stack) Print() {
}
fmt.Println("#############")
}
+
+var rStackPool = sync.Pool{
+ New: func() interface{} {
+ return &ReturnStack{data: make([]uint32, 0, 10)}
+ },
+}
+
+// ReturnStack is an object for basic return stack operations.
+type ReturnStack struct {
+ data []uint32
+}
+
+func newReturnStack() *ReturnStack {
+ return rStackPool.Get().(*ReturnStack)
+}
+
+func returnRStack(rs *ReturnStack) {
+ rs.data = rs.data[:0]
+ rStackPool.Put(rs)
+}
+
+func (st *ReturnStack) push(d uint32) {
+ st.data = append(st.data, d)
+}
+
+// A uint32 is sufficient as for code below 4.2G
+func (st *ReturnStack) pop() (ret uint32) {
+ ret = st.data[len(st.data)-1]
+ st.data = st.data[:len(st.data)-1]
+ return
+}