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 (
|
||||
"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)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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))
|
||||
|
|
|
|||
|
|
@ -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 (
|
||||
|
|
|
|||
|
|
@ -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 {
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
Loading…
Reference in a new issue