mirror of
https://github.com/ethereum/go-ethereum.git
synced 2026-07-25 22:26:42 +00:00
wip
This commit is contained in:
parent
50281f1d17
commit
f80d102fe4
6 changed files with 103 additions and 31 deletions
|
|
@ -18,6 +18,7 @@ package common
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"bytes"
|
"bytes"
|
||||||
|
"math/big"
|
||||||
"testing"
|
"testing"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
@ -87,3 +88,37 @@ func TestBigCopy(t *testing.T) {
|
||||||
t.Error("Got", zbytes)
|
t.Error("Got", zbytes)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var benchSize = 1000
|
||||||
|
|
||||||
|
func BenchmarkBitLen(b *testing.B) {
|
||||||
|
tests := make([]*big.Int, 0, benchSize)
|
||||||
|
for i := 0; i < benchSize; i++ {
|
||||||
|
tests = append(tests, big.NewInt(int64(i)))
|
||||||
|
}
|
||||||
|
|
||||||
|
b.ResetTimer()
|
||||||
|
|
||||||
|
for i := 0; i < b.N; i++ {
|
||||||
|
for j := 0; j < benchSize; j++ {
|
||||||
|
_ = tests[j].BitLen()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var bigzero = new(big.Int)
|
||||||
|
|
||||||
|
func BenchmarkCmp(b *testing.B) {
|
||||||
|
tests := make([]*big.Int, 0, benchSize)
|
||||||
|
for i := 0; i < benchSize; i++ {
|
||||||
|
tests = append(tests, big.NewInt(int64(i)))
|
||||||
|
}
|
||||||
|
|
||||||
|
b.ResetTimer()
|
||||||
|
|
||||||
|
for i := 0; i < b.N; i++ {
|
||||||
|
for j := 0; j < benchSize; j++ {
|
||||||
|
_ = tests[j].Cmp(bigzero)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -85,6 +85,7 @@ func (s *State) Read(address common.Address) (object *StateObject, inCache bool)
|
||||||
stateObject := s.StateObjects[address]
|
stateObject := s.StateObjects[address]
|
||||||
if stateObject == nil && s.parent != nil {
|
if stateObject == nil && s.parent != nil {
|
||||||
stateObject, _ = s.parent.Read(address)
|
stateObject, _ = s.parent.Read(address)
|
||||||
|
s.StateObjects[address] = stateObject
|
||||||
} else if stateObject != nil {
|
} else if stateObject != nil {
|
||||||
inCache = true
|
inCache = true
|
||||||
}
|
}
|
||||||
|
|
@ -107,6 +108,7 @@ func (s *State) Read(address common.Address) (object *StateObject, inCache bool)
|
||||||
glog.Errorf("can't decode object at %x: %v", address[:], err)
|
glog.Errorf("can't decode object at %x: %v", address[:], err)
|
||||||
return nil, false
|
return nil, false
|
||||||
}
|
}
|
||||||
|
s.StateObjects[address] = stateObject
|
||||||
|
|
||||||
return stateObject, false
|
return stateObject, false
|
||||||
}
|
}
|
||||||
|
|
@ -126,9 +128,9 @@ func (s *State) loadStateObject(stateObject *StateObject) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *State) GetOrNewStateObject(address common.Address) *StateObject {
|
func (s *State) GetOrNewStateObject(address common.Address) *StateObject {
|
||||||
stateObject, inCache := s.Read(address)
|
stateObject, _ := s.Read(address)
|
||||||
if stateObject != nil {
|
if stateObject != nil {
|
||||||
if !inCache || !s.localStateObjects[address] {
|
if !s.localStateObjects[address] {
|
||||||
stateObject = stateObject.Copy()
|
stateObject = stateObject.Copy()
|
||||||
s.StateObjects[address] = stateObject
|
s.StateObjects[address] = stateObject
|
||||||
s.localStateObjects[address] = true
|
s.localStateObjects[address] = true
|
||||||
|
|
@ -161,9 +163,10 @@ func (s *State) GetOrNewStateObject(address common.Address) *StateObject {
|
||||||
*/
|
*/
|
||||||
|
|
||||||
func (s *State) GetStateObject(address common.Address) *StateObject {
|
func (s *State) GetStateObject(address common.Address) *StateObject {
|
||||||
account, inCache := s.Read(address)
|
account, _ := s.Read(address)
|
||||||
if account != nil {
|
if account != nil {
|
||||||
if !inCache {
|
if s.StateObjects[address] == nil {
|
||||||
|
//if !inCache {
|
||||||
s.StateObjects[address] = account
|
s.StateObjects[address] = account
|
||||||
}
|
}
|
||||||
return account
|
return account
|
||||||
|
|
@ -189,7 +192,13 @@ func (s *State) CreateStateObject(address common.Address) *StateObject {
|
||||||
return stateObject
|
return stateObject
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var bigzero = new(big.Int)
|
||||||
|
|
||||||
func (s *State) SubBalance(address common.Address, amount *big.Int) {
|
func (s *State) SubBalance(address common.Address, amount *big.Int) {
|
||||||
|
if amount.Cmp(bigzero) == 0 {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
stateObject := s.GetOrNewStateObject(address)
|
stateObject := s.GetOrNewStateObject(address)
|
||||||
if stateObject != nil {
|
if stateObject != nil {
|
||||||
stateObject.SubBalance(amount)
|
stateObject.SubBalance(amount)
|
||||||
|
|
@ -197,6 +206,10 @@ func (s *State) SubBalance(address common.Address, amount *big.Int) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *State) AddBalance(address common.Address, amount *big.Int) {
|
func (s *State) AddBalance(address common.Address, amount *big.Int) {
|
||||||
|
if amount.Cmp(bigzero) == 0 {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
stateObject := s.GetOrNewStateObject(address)
|
stateObject := s.GetOrNewStateObject(address)
|
||||||
if stateObject != nil {
|
if stateObject != nil {
|
||||||
stateObject.AddBalance(amount)
|
stateObject.AddBalance(amount)
|
||||||
|
|
|
||||||
|
|
@ -142,7 +142,7 @@ func opMul(instr instruction, pc *uint64, env *Environment, contract *Contract,
|
||||||
|
|
||||||
func opDiv(instr instruction, pc *uint64, env *Environment, contract *Contract, memory *Memory, stack *Stack) {
|
func opDiv(instr instruction, pc *uint64, env *Environment, contract *Contract, memory *Memory, stack *Stack) {
|
||||||
x, y := stack.pop(), stack.pop()
|
x, y := stack.pop(), stack.pop()
|
||||||
if y.Cmp(common.Big0) != 0 {
|
if y.BitLen() != 0 {
|
||||||
stack.push(U256(x.Div(x, y)))
|
stack.push(U256(x.Div(x, y)))
|
||||||
} else {
|
} else {
|
||||||
stack.push(new(big.Int))
|
stack.push(new(big.Int))
|
||||||
|
|
|
||||||
|
|
@ -20,7 +20,6 @@ import (
|
||||||
"math/big"
|
"math/big"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/ethereum/go-ethereum/common"
|
|
||||||
"github.com/ethereum/go-ethereum/logger"
|
"github.com/ethereum/go-ethereum/logger"
|
||||||
"github.com/ethereum/go-ethereum/logger/glog"
|
"github.com/ethereum/go-ethereum/logger/glog"
|
||||||
)
|
)
|
||||||
|
|
@ -86,8 +85,6 @@ func OptimiseProgram(program *Program) {
|
||||||
statsJump++
|
statsJump++
|
||||||
|
|
||||||
load = nil
|
load = nil
|
||||||
case instr.op == EXTCODESIZE:
|
|
||||||
program.instructions[i] = codesize{}
|
|
||||||
default:
|
default:
|
||||||
// create a new N pushes segment
|
// create a new N pushes segment
|
||||||
if len(load) > 1 {
|
if len(load) > 1 {
|
||||||
|
|
@ -100,22 +97,6 @@ func OptimiseProgram(program *Program) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
type codesize struct {
|
|
||||||
size *big.Int
|
|
||||||
}
|
|
||||||
|
|
||||||
func (instr codesize) do(program *Program, pc *uint64, env *Environment, contract *Contract, memory *Memory, stack *Stack) ([]byte, error) {
|
|
||||||
if instr.size == nil {
|
|
||||||
addr := common.BigToAddress(stack.pop())
|
|
||||||
instr.size = big.NewInt(int64(len(env.Db().GetCode(addr))))
|
|
||||||
}
|
|
||||||
stack.push(instr.size)
|
|
||||||
return nil, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (codesize) Op() OpCode { return EXTCODESIZE }
|
|
||||||
func (codesize) halts() bool { return false }
|
|
||||||
|
|
||||||
// makePushSeg creates a new push segment from N amount of push instructions
|
// makePushSeg creates a new push segment from N amount of push instructions
|
||||||
func makePushSeg(instrs []instruction) (pushSeg, int) {
|
func makePushSeg(instrs []instruction) (pushSeg, int) {
|
||||||
var (
|
var (
|
||||||
|
|
|
||||||
|
|
@ -26,6 +26,7 @@ import (
|
||||||
// initialised objects.
|
// initialised objects.
|
||||||
type Stack struct {
|
type Stack struct {
|
||||||
data []*big.Int
|
data []*big.Int
|
||||||
|
count int
|
||||||
}
|
}
|
||||||
|
|
||||||
func newstack() *Stack {
|
func newstack() *Stack {
|
||||||
|
|
@ -40,16 +41,21 @@ func (st *Stack) push(d *big.Int) {
|
||||||
// NOTE push limit (1024) is checked in baseCheck
|
// NOTE push limit (1024) is checked in baseCheck
|
||||||
//stackItem := new(big.Int).Set(d)
|
//stackItem := new(big.Int).Set(d)
|
||||||
//st.data = append(st.data, stackItem)
|
//st.data = append(st.data, stackItem)
|
||||||
st.data = append(st.data, d)
|
//st.data = append(st.data, d)
|
||||||
|
st.data = append(st.data[:st.count], d)
|
||||||
|
st.count++
|
||||||
}
|
}
|
||||||
func (st *Stack) pushN(ds ...*big.Int) {
|
func (st *Stack) pushN(ds ...*big.Int) {
|
||||||
st.data = append(st.data, ds...)
|
st.data = append(st.data[:st.count], ds...)
|
||||||
|
st.count += len(ds)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (st *Stack) pop() (ret *big.Int) {
|
func (st *Stack) pop() *big.Int {
|
||||||
ret = st.data[len(st.data)-1]
|
//ret = st.data[len(st.data)-1]
|
||||||
st.data = st.data[:len(st.data)-1]
|
//st.data = st.data[:len(st.data)-1]
|
||||||
return
|
|
||||||
|
st.count--
|
||||||
|
return st.data[st.count]
|
||||||
}
|
}
|
||||||
|
|
||||||
func (st *Stack) len() int {
|
func (st *Stack) len() int {
|
||||||
|
|
|
||||||
|
|
@ -18,6 +18,7 @@ package vm
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"sort"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/ethereum/go-ethereum/crypto"
|
"github.com/ethereum/go-ethereum/crypto"
|
||||||
|
|
@ -103,6 +104,18 @@ func (evm *EVM) Run(contract *Contract, input []byte) ([]byte, error) {
|
||||||
return nil, fmt.Errorf("Unexpected return using program %x", codehash)
|
return nil, fmt.Errorf("Unexpected return using program %x", codehash)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type stats struct {
|
||||||
|
op OpCode
|
||||||
|
dura time.Duration
|
||||||
|
callCount uint64
|
||||||
|
}
|
||||||
|
|
||||||
|
type statsList []stats
|
||||||
|
|
||||||
|
func (sl statsList) Len() int { return len(sl) }
|
||||||
|
func (sl statsList) Less(i, j int) bool { return sl[i].dura < sl[j].dura }
|
||||||
|
func (sl statsList) Swap(i, j int) { sl[i], sl[j] = sl[j], sl[i] }
|
||||||
|
|
||||||
func (evm *EVM) runProgram(program *Program, contract *Contract, input []byte) ([]byte, error) {
|
func (evm *EVM) runProgram(program *Program, contract *Contract, input []byte) ([]byte, error) {
|
||||||
contract.Input = input
|
contract.Input = input
|
||||||
|
|
||||||
|
|
@ -112,7 +125,23 @@ func (evm *EVM) runProgram(program *Program, contract *Contract, input []byte) (
|
||||||
mem = NewMemory()
|
mem = NewMemory()
|
||||||
stack = newstack()
|
stack = newstack()
|
||||||
env = evm.env
|
env = evm.env
|
||||||
|
stats = make(map[OpCode]stats)
|
||||||
)
|
)
|
||||||
|
defer func() {
|
||||||
|
fmt.Println("stats for program")
|
||||||
|
i := 0
|
||||||
|
sl := make(statsList, len(stats))
|
||||||
|
for op, stat := range stats {
|
||||||
|
stat.op = op
|
||||||
|
sl[i] = stat
|
||||||
|
i++
|
||||||
|
}
|
||||||
|
|
||||||
|
sort.Sort(sort.Reverse(sl))
|
||||||
|
for _, stat := range sl {
|
||||||
|
fmt.Printf("%v: call count: %d duration: %v\n", stat.op, stat.callCount, stat.dura)
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
|
||||||
if glog.V(logger.Debug) {
|
if glog.V(logger.Debug) {
|
||||||
glog.Infof("running JIT program %x\n", program.Id[:4])
|
glog.Infof("running JIT program %x\n", program.Id[:4])
|
||||||
|
|
@ -127,11 +156,19 @@ func (evm *EVM) runProgram(program *Program, contract *Contract, input []byte) (
|
||||||
instrCount++
|
instrCount++
|
||||||
|
|
||||||
instr := program.instructions[pc]
|
instr := program.instructions[pc]
|
||||||
|
|
||||||
|
tstart := time.Now()
|
||||||
|
stat := stats[instr.Op()]
|
||||||
|
|
||||||
|
stat.callCount++
|
||||||
if instr.Op() == DELEGATECALL && !homestead {
|
if instr.Op() == DELEGATECALL && !homestead {
|
||||||
return nil, fmt.Errorf("Invalid opcode 0x%x", instr.Op())
|
return nil, fmt.Errorf("Invalid opcode 0x%x", instr.Op())
|
||||||
}
|
}
|
||||||
|
|
||||||
ret, err := instr.do(program, &pc, env, contract, mem, stack)
|
ret, err := instr.do(program, &pc, env, contract, mem, stack)
|
||||||
|
stat.dura += time.Since(tstart)
|
||||||
|
|
||||||
|
stats[instr.Op()] = stat
|
||||||
if err != nil {
|
if err != nil {
|
||||||
//gas := new(big.Int).SetUint64(contract.gas64)
|
//gas := new(big.Int).SetUint64(contract.gas64)
|
||||||
//evm.cfg.Tracer.CaptureState(evm.env, pc, instr.Op(), gas, cost, mem, stack, contract, evm.env.Depth(), err)
|
//evm.cfg.Tracer.CaptureState(evm.env, pc, instr.Op(), gas, cost, mem, stack, contract, evm.env.Depth(), err)
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue