github.com/n1ghtfa1l/go-vnt@v0.6.4-alpha.6/core/wavm/gas/gas.go (about) 1 // Copyright 2019 The go-vnt Authors 2 // This file is part of the go-vnt library. 3 // 4 // The go-vnt 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 go-vnt 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 go-vnt library. If not, see <http://www.gnu.org/licenses/>. 16 17 package gas 18 19 import ( 20 "sort" 21 22 "github.com/vntchain/go-vnt/common" 23 "github.com/vntchain/go-vnt/core/wavm/internal/stack" 24 "github.com/vntchain/go-vnt/core/wavm/utils" 25 "github.com/vntchain/vnt-wasm/disasm" 26 "github.com/vntchain/vnt-wasm/wasm" 27 ops "github.com/vntchain/vnt-wasm/wasm/operators" 28 ) 29 30 type BlockEntry struct { 31 /// Index of the first instruction (aka `Opcode`) in the block. 32 starPos int 33 /// Sum of costs of all instructions until end of the block. 34 cost uint64 35 index []int 36 } 37 38 type BlockEntrys []*BlockEntry 39 40 func (block BlockEntrys) Len() int { return len(block) } 41 func (block BlockEntrys) Less(i, j int) bool { return block[i].starPos-block[j].starPos < 0 } 42 func (block BlockEntrys) Swap(i, j int) { block[i], block[j] = block[j], block[i] } 43 44 type Counter struct { 45 /// All blocks in the order of theirs start position. 46 blocks BlockEntrys 47 48 // Stack of blocks. Each element is an index to a `self.blocks` vector. 49 stack *stack.Stack 50 } 51 52 func NewCounter() *Counter { 53 return &Counter{ 54 blocks: BlockEntrys{}, 55 stack: &stack.Stack{}, 56 } 57 } 58 59 func (counter *Counter) Begin(cursor int) { 60 blockIdx := len(counter.blocks) 61 counter.blocks = append(counter.blocks, &BlockEntry{ 62 starPos: cursor, 63 cost: 1, 64 index: []int{}, 65 }) 66 counter.stack.Push(uint64(blockIdx)) 67 } 68 69 func (counter *Counter) Finalize() { 70 counter.stack.Pop() 71 } 72 73 func (counter *Counter) Increment(value uint64, index int) { 74 // var top uint64 75 // if counter.stack.Len() == 0 { 76 // top = 0 77 // } else { 78 // top = counter.stack.Top() 79 // } 80 top := counter.stack.Top() 81 82 topBlock := counter.blocks[top] 83 topBlock.cost = topBlock.cost + value 84 topBlock.index = append(topBlock.index, index) 85 } 86 87 func InjectCounter(disassembly []disasm.Instr, module *wasm.Module, rule Gas) []disasm.Instr { 88 _, _, gasIndex := utils.GetIndex(module) 89 if gasIndex == -1 { 90 return disassembly 91 } 92 counter := NewCounter() 93 counter.Begin(0) 94 for i, instr := range disassembly { 95 switch instr.Op.Code { 96 case ops.Block, ops.Loop, ops.If: 97 //instruction_cost = rules.process(instruction)?; 98 // instrCost := 1 //instr的gas消耗规则 99 // counter.Increment(uint32(instrCost), i) 100 101 // Begin new block. The cost of the following opcodes until `End` or `Else` will 102 // be included into this block. 103 counter.Begin(i + 1) 104 case ops.Br, ops.BrIf, ops.BrTable: 105 counter.Finalize() 106 // instrCost := 1 //instr的gas消耗规则 107 // counter.Increment(uint32(instrCost), i) 108 counter.Begin(i + 1) 109 case ops.End: 110 counter.Finalize() 111 case ops.Else: 112 counter.Finalize() 113 counter.Begin(i + 1) 114 default: 115 instrCost := rule.GasCost(instr.Op.Code) 116 counter.Increment(instrCost, i) 117 } 118 } 119 120 for _, v := range counter.blocks { 121 if len(v.index) > 0 { 122 v.starPos = v.index[0] 123 } 124 } 125 sort.Sort(counter.blocks) 126 offset := 0 127 for _, v := range counter.blocks { 128 pos := v.starPos + offset 129 constOp, _ := ops.New(ops.I64Const) 130 constInstr := disasm.Instr{Op: constOp, Immediates: []interface{}{int64(v.cost)}} 131 callOp, _ := ops.New(ops.Call) 132 callInstr := disasm.Instr{Op: callOp, Immediates: []interface{}{uint32(gasIndex)}} 133 //disassembly=append(disassembly[0:pos],) 134 res := common.Insert(disassembly, pos, []disasm.Instr{callInstr}) 135 disassembly = res.([]disasm.Instr) 136 res = common.Insert(disassembly, pos, []disasm.Instr{constInstr}) 137 disassembly = res.([]disasm.Instr) 138 offset += 2 139 } 140 return disassembly 141 }