github.com/amazechain/amc@v0.1.3/internal/vm/stack/stack.go (about) 1 // Copyright 2023 The AmazeChain Authors 2 // This file is part of the AmazeChain library. 3 // 4 // The AmazeChain library is free software: you can redistribute it and/or modify 5 // it under the terms of the GNU Lesser General Public License as published by 6 // the Free Software Foundation, either version 3 of the License, or 7 // (at your option) any later version. 8 // 9 // The AmazeChain library is distributed in the hope that it will be useful, 10 // but WITHOUT ANY WARRANTY; without even the implied warranty of 11 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 // GNU Lesser General Public License for more details. 13 // 14 // You should have received a copy of the GNU Lesser General Public License 15 // along with the AmazeChain library. If not, see <http://www.gnu.org/licenses/>. 16 package stack 17 18 import ( 19 "fmt" 20 "github.com/amazechain/amc/log" 21 "sync" 22 23 "github.com/holiman/uint256" 24 ) 25 26 var stackPool = sync.Pool{ 27 New: func() interface{} { 28 return &Stack{Data: make([]uint256.Int, 0, 16)} 29 }, 30 } 31 32 // Stack is an object for basic stack operations. Items popped to the stack are 33 // expected to be changed and modified. stack does not take care of adding newly 34 // initialised objects. 35 type Stack struct { 36 Data []uint256.Int 37 } 38 39 func New() *Stack { 40 stack, ok := stackPool.Get().(*Stack) 41 if !ok { 42 log.Error("Type assertion failure", "err", "cannot get Stack pointer from stackPool") 43 } 44 return stack 45 } 46 47 func (st *Stack) Push(d *uint256.Int) { 48 // NOTE push limit (1024) is checked in baseCheck 49 st.Data = append(st.Data, *d) 50 } 51 52 func (st *Stack) PushN(ds ...uint256.Int) { 53 // FIXME: Is there a way to pass args by pointers. 54 st.Data = append(st.Data, ds...) 55 } 56 57 func (st *Stack) Pop() (ret uint256.Int) { 58 ret = st.Data[len(st.Data)-1] 59 st.Data = st.Data[:len(st.Data)-1] 60 return 61 } 62 63 func (st *Stack) Cap() int { 64 return cap(st.Data) 65 } 66 67 func (st *Stack) Swap(n int) { 68 st.Data[st.Len()-n], st.Data[st.Len()-1] = st.Data[st.Len()-1], st.Data[st.Len()-n] 69 } 70 71 func (st *Stack) Dup(n int) { 72 st.Push(&st.Data[st.Len()-n]) 73 } 74 75 func (st *Stack) Peek() *uint256.Int { 76 return &st.Data[st.Len()-1] 77 } 78 79 // Back returns the n'th item in stack 80 func (st *Stack) Back(n int) *uint256.Int { 81 return &st.Data[st.Len()-n-1] 82 } 83 84 func (st *Stack) Reset() { 85 st.Data = st.Data[:0] 86 } 87 88 func (st *Stack) Len() int { 89 return len(st.Data) 90 } 91 92 // Print dumps the content of the stack 93 func (st *Stack) Print() { 94 fmt.Println("### stack ###") 95 if len(st.Data) > 0 { 96 for i, val := range st.Data { 97 fmt.Printf("%-3d %v\n", i, val) 98 } 99 } else { 100 fmt.Println("-- empty --") 101 } 102 fmt.Println("#############") 103 } 104 105 func ReturnNormalStack(s *Stack) { 106 s.Data = s.Data[:0] 107 stackPool.Put(s) 108 } 109 110 var rStackPool = sync.Pool{ 111 New: func() interface{} { 112 return &ReturnStack{data: make([]uint32, 0, 10)} 113 }, 114 } 115 116 func ReturnRStack(rs *ReturnStack) { 117 rs.data = rs.data[:0] 118 rStackPool.Put(rs) 119 } 120 121 // ReturnStack is an object for basic return stack operations. 122 type ReturnStack struct { 123 data []uint32 124 } 125 126 func NewReturnStack() *ReturnStack { 127 rStack, ok := rStackPool.Get().(*ReturnStack) 128 if !ok { 129 log.Error("Type assertion failure", "err", "cannot get ReturnStack pointer from rStackPool") 130 } 131 return rStack 132 } 133 134 func (st *ReturnStack) Push(d uint32) { 135 st.data = append(st.data, d) 136 } 137 138 // A uint32 is sufficient as for code below 4.2G 139 func (st *ReturnStack) Pop() (ret uint32) { 140 ret = st.data[len(st.data)-1] 141 st.data = st.data[:len(st.data)-1] 142 return 143 } 144 145 func (st *ReturnStack) Data() []uint32 { 146 return st.data 147 }