This commit is contained in:
Jeffrey Wilcke 2016-09-27 14:11:22 +02:00
parent 50281f1d17
commit f80d102fe4
6 changed files with 103 additions and 31 deletions

View file

@ -18,6 +18,7 @@ package common
import (
"bytes"
"math/big"
"testing"
)
@ -87,3 +88,37 @@ func TestBigCopy(t *testing.T) {
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)
}
}
}

View file

@ -85,6 +85,7 @@ func (s *State) Read(address common.Address) (object *StateObject, inCache bool)
stateObject := s.StateObjects[address]
if stateObject == nil && s.parent != nil {
stateObject, _ = s.parent.Read(address)
s.StateObjects[address] = stateObject
} else if stateObject != nil {
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)
return nil, false
}
s.StateObjects[address] = stateObject
return stateObject, false
}
@ -126,9 +128,9 @@ func (s *State) loadStateObject(stateObject *StateObject) {
}
func (s *State) GetOrNewStateObject(address common.Address) *StateObject {
stateObject, inCache := s.Read(address)
stateObject, _ := s.Read(address)
if stateObject != nil {
if !inCache || !s.localStateObjects[address] {
if !s.localStateObjects[address] {
stateObject = stateObject.Copy()
s.StateObjects[address] = stateObject
s.localStateObjects[address] = true
@ -161,9 +163,10 @@ func (s *State) GetOrNewStateObject(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 !inCache {
if s.StateObjects[address] == nil {
//if !inCache {
s.StateObjects[address] = account
}
return account
@ -189,7 +192,13 @@ func (s *State) CreateStateObject(address common.Address) *StateObject {
return stateObject
}
var bigzero = new(big.Int)
func (s *State) SubBalance(address common.Address, amount *big.Int) {
if amount.Cmp(bigzero) == 0 {
return
}
stateObject := s.GetOrNewStateObject(address)
if stateObject != nil {
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) {
if amount.Cmp(bigzero) == 0 {
return
}
stateObject := s.GetOrNewStateObject(address)
if stateObject != nil {
stateObject.AddBalance(amount)

View file

@ -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) {
x, y := stack.pop(), stack.pop()
if y.Cmp(common.Big0) != 0 {
if y.BitLen() != 0 {
stack.push(U256(x.Div(x, y)))
} else {
stack.push(new(big.Int))

View file

@ -20,7 +20,6 @@ import (
"math/big"
"time"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/logger"
"github.com/ethereum/go-ethereum/logger/glog"
)
@ -86,8 +85,6 @@ func OptimiseProgram(program *Program) {
statsJump++
load = nil
case instr.op == EXTCODESIZE:
program.instructions[i] = codesize{}
default:
// create a new N pushes segment
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
func makePushSeg(instrs []instruction) (pushSeg, int) {
var (

View file

@ -25,7 +25,8 @@ import (
// expected to be changed and modified. stack does not take care of adding newly
// initialised objects.
type Stack struct {
data []*big.Int
data []*big.Int
count int
}
func newstack() *Stack {
@ -40,16 +41,21 @@ 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)
//st.data = append(st.data, d)
st.data = append(st.data[:st.count], d)
st.count++
}
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) {
ret = st.data[len(st.data)-1]
st.data = st.data[:len(st.data)-1]
return
func (st *Stack) pop() *big.Int {
//ret = st.data[len(st.data)-1]
//st.data = st.data[:len(st.data)-1]
st.count--
return st.data[st.count]
}
func (st *Stack) len() int {

View file

@ -18,6 +18,7 @@ package vm
import (
"fmt"
"sort"
"time"
"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)
}
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) {
contract.Input = input
@ -112,7 +125,23 @@ func (evm *EVM) runProgram(program *Program, contract *Contract, input []byte) (
mem = NewMemory()
stack = newstack()
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) {
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++
instr := program.instructions[pc]
tstart := time.Now()
stat := stats[instr.Op()]
stat.callCount++
if instr.Op() == DELEGATECALL && !homestead {
return nil, fmt.Errorf("Invalid opcode 0x%x", instr.Op())
}
ret, err := instr.do(program, &pc, env, contract, mem, stack)
stat.dura += time.Since(tstart)
stats[instr.Op()] = stat
if err != nil {
//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)