以太坊原始碼分析(28)core-vm-stack-memory原始碼分析
vm使用了stack.go裡面的物件Stack來作為虛擬機器的堆疊。memory代表了虛擬機器裡面使用的記憶體物件。
## stack
比較簡單,就是用1024個big.Int的定長陣列來作為堆疊的儲存。
構造
// 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
}
func newstack() *Stack {
return &Stack{data: make([]*big.Int, 0, 1024)}
}
push操作
func (st *Stack) push(d *big.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)
}
func (st *Stack) pushN(ds ...*big.Int) {
st.data = append(st.data, ds...)
}
pop操作
func (st *Stack) pop() (ret *big.Int) { //從最末尾取出。
ret = st.data[len(st.data)-1]
st.data = st.data[:len(st.data)-1]
return
}
交換元素的值操作,還有這種操作?
func (st *Stack) swap(n int) { 交換堆疊頂的元素和離棧頂n距離的元素的值。
st.data[st.len()-n], st.data[st.len()-1] = st.data[st.len()-1], st.data[st.len()-n]
}
dup操作 像複製指定位置的值到堆頂
func (st *Stack) dup(pool *intPool, n int) {
st.push(pool.get().Set(st.data[st.len()-n]))
}
peek 操作. 偷看棧頂元素
func (st *Stack) peek() *big.Int {
return st.data[st.len()-1]
}
Back 偷看指定位置的元素
// Back returns the n'th item in stack
func (st *Stack) Back(n int) *big.Int {
return st.data[st.len()-n-1]
}
require 保證堆疊元素的數量要大於等於n.
func (st *Stack) require(n int) error {
if st.len() < n {
return fmt.Errorf("stack underflow (%d <=> %d)", len(st.data), n)
}
return nil
}
## intpool
非常簡單. 就是256大小的 big.int的池,用來加速bit.Int的分配
var checkVal = big.NewInt(-42)
const poolLimit = 256
// intPool is a pool of big integers that
// can be reused for all big.Int operations.
type intPool struct {
pool *Stack
}
func newIntPool() *intPool {
return &intPool{pool: newstack()}
}
func (p *intPool) get() *big.Int {
if p.pool.len() > 0 {
return p.pool.pop()
}
return new(big.Int)
}
func (p *intPool) put(is ...*big.Int) {
if len(p.pool.data) > poolLimit {
return
}
for _, i := range is {
// verifyPool is a build flag. Pool verification makes sure the integrity
// of the integer pool by comparing values to a default value.
if verifyPool {
i.Set(checkVal)
}
p.pool.push(i)
}
}
## memory
構造, memory的儲存就是byte[]. 還有一個lastGasCost的記錄.
type Memory struct {
store []byte
lastGasCost uint64
}
func NewMemory() *Memory {
return &Memory{}
}
使用首先需要使用Resize分配空間
// Resize resizes the memory to size
func (m *Memory) Resize(size uint64) {
if uint64(m.Len()) < size {
m.store = append(m.store, make([]byte, size-uint64(m.Len()))...)
}
}
然後使用Set來設定值
// Set sets offset + size to value
func (m *Memory) Set(offset, size uint64, value []byte) {
// length of store may never be less than offset + size.
// The store should be resized PRIOR to setting the memory
if size > uint64(len(m.store)) {
panic("INVALID memory: store empty")
}
// It's possible the offset is greater than 0 and size equals 0. This is because
// the calcMemSize (common.go) could potentially return 0 when size is zero (NO-OP)
if size > 0 {
copy(m.store[offset:offset+size], value)
}
}
Get來取值, 一個是獲取拷貝, 一個是獲取指標.
// Get returns offset + size as a new slice
func (self *Memory) Get(offset, size int64) (cpy []byte) {
if size == 0 {
return nil
}
if len(self.store) > int(offset) {
cpy = make([]byte, size)
copy(cpy, self.store[offset:offset+size])
return
}
return
}
// GetPtr returns the offset + size
func (self *Memory) GetPtr(offset, size int64) []byte {
if size == 0 {
return nil
}
if len(self.store) > int(offset) {
return self.store[offset : offset+size]
}
return nil
}
## 一些額外的幫助函式 在stack_table.go裡面
func makeStackFunc(pop, push int) stackValidationFunc {
return func(stack *Stack) error {
if err := stack.require(pop); err != nil {
return err
}
if stack.len()+push-pop > int(params.StackLimit) {
return fmt.Errorf("stack limit reached %d (%d)", stack.len(), params.StackLimit)
}
return nil
}
}
func makeDupStackFunc(n int) stackValidationFunc {
return makeStackFunc(n, n+1)
}
func makeSwapStackFunc(n int) stackValidationFunc {
return makeStackFunc(n, n)
}
網址:http://www.qukuailianxueyuan.io/
欲領取造幣技術與全套虛擬機器資料
區塊鏈技術交流QQ群:756146052 備註:CSDN
尹成學院微信:備註:CSDN
相關文章
- 以太坊原始碼分析(36)ethdb原始碼分析原始碼
- 以太坊原始碼分析(38)event原始碼分析原始碼
- 以太坊原始碼分析(41)hashimoto原始碼分析原始碼
- 以太坊原始碼分析(43)node原始碼分析原始碼
- 以太坊原始碼分析(51)rpc原始碼分析原始碼RPC
- 以太坊原始碼分析(52)trie原始碼分析原始碼
- 以太坊原始碼分析(13)RPC分析原始碼RPC
- 以太坊原始碼分析(35)eth-fetcher原始碼分析原始碼
- 以太坊原始碼分析(20)core-bloombits原始碼分析原始碼OOM
- 以太坊原始碼分析(24)core-state原始碼分析原始碼
- 以太坊原始碼分析(29)core-vm原始碼分析原始碼
- 以太坊原始碼分析(34)eth-downloader原始碼分析原始碼
- 以太坊原始碼分析(37)eth以太坊協議分析原始碼協議
- 以太坊原始碼分析(18)以太坊交易執行分析原始碼
- 以太坊原始碼分析(5)accounts程式碼分析原始碼
- 以太坊交易池原始碼分析原始碼
- 以太坊原始碼分析(23)core-state-process原始碼分析原始碼
- 以太坊原始碼分析(31)eth-downloader-peer原始碼分析原始碼
- 以太坊原始碼分析(32)eth-downloader-peer原始碼分析原始碼
- 以太坊原始碼分析(33)eth-downloader-statesync原始碼分析原始碼
- 以太坊原始碼分析(8)區塊分析原始碼
- 以太坊原始碼分析(9)cmd包分析原始碼
- 以太坊原始碼分析(16)挖礦分析原始碼
- 以太坊原始碼分析(26)core-txpool交易池原始碼分析原始碼
- 以太坊原始碼分析(27)core-vm-jumptable-instruction原始碼分析原始碼Struct
- 以太坊原始碼分析(30)eth-bloombits和filter原始碼分析原始碼OOMFilter
- 以太坊原始碼分析(10)CMD深入分析原始碼
- 以太坊原始碼分析(12)交易資料分析原始碼
- 以太坊原始碼分析(19)core-blockchain分析原始碼Blockchain
- 以太坊原始碼分析(44)p2p-database.go原始碼分析原始碼DatabaseGo
- 以太坊原始碼分析(45)p2p-dial.go原始碼分析原始碼Go
- 以太坊原始碼分析(46)p2p-peer.go原始碼分析原始碼Go
- 以太坊原始碼分析(48)p2p-server.go原始碼分析原始碼ServerGo
- 以太坊原始碼分析(49)p2p-table.go原始碼分析原始碼Go
- 以太坊原始碼分析(50)p2p-udp.go原始碼分析原始碼UDPGo
- 以太坊原始碼分析(52)以太坊fast sync演算法原始碼AST演算法
- 以太坊原始碼分析(39)geth啟動流程分析原始碼
- 以太坊原始碼分析(6)accounts賬戶管理分析原始碼