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