aboutsummaryrefslogtreecommitdiffstats
path: root/core
diff options
context:
space:
mode:
authorJeffrey Wilcke <geffobscura@gmail.com>2016-01-21 22:29:58 +0800
committerJeffrey Wilcke <jeffrey@ethereum.org>2016-03-23 07:04:00 +0800
commit342ae7ce7dfd7a0eab2dd06bfa65199825279f05 (patch)
tree4d90314e50e137bcd8ee837cbb396fee40e2bb4b /core
parent2855a93ede6e9437d05a82c2397d48744621db9b (diff)
downloaddexon-342ae7ce7dfd7a0eab2dd06bfa65199825279f05.tar
dexon-342ae7ce7dfd7a0eab2dd06bfa65199825279f05.tar.gz
dexon-342ae7ce7dfd7a0eab2dd06bfa65199825279f05.tar.bz2
dexon-342ae7ce7dfd7a0eab2dd06bfa65199825279f05.tar.lz
dexon-342ae7ce7dfd7a0eab2dd06bfa65199825279f05.tar.xz
dexon-342ae7ce7dfd7a0eab2dd06bfa65199825279f05.tar.zst
dexon-342ae7ce7dfd7a0eab2dd06bfa65199825279f05.zip
core, core/vm, tests: changed the initialisation behaviour of the EVM
The EVM was previously initialised and created for every CALL, CALLCODE, DELEGATECALL and CREATE. This PR changes this behaviour so that the same EVM can be used through the session and beyond as long as the Environment sticks around.
Diffstat (limited to 'core')
-rw-r--r--core/execution.go4
-rw-r--r--core/vm/common.go14
-rw-r--r--core/vm/environment.go4
-rw-r--r--core/vm/instructions.go1
-rw-r--r--core/vm/jit_test.go8
-rw-r--r--core/vm/jump_table.go12
-rw-r--r--core/vm/jump_table_test.go4
-rw-r--r--core/vm/runtime/env.go8
-rw-r--r--core/vm/vm.go13
-rw-r--r--core/vm/vm_jit_fake.go2
-rw-r--r--core/vm_env.go6
11 files changed, 34 insertions, 42 deletions
diff --git a/core/execution.go b/core/execution.go
index 24c0c93ae..d90dceafc 100644
--- a/core/execution.go
+++ b/core/execution.go
@@ -60,7 +60,7 @@ func Create(env vm.Environment, caller vm.ContractRef, code []byte, gas, gasPric
}
func exec(env vm.Environment, caller vm.ContractRef, address, codeAddr *common.Address, input, code []byte, gas, gasPrice, value *big.Int) (ret []byte, addr common.Address, err error) {
- evm := vm.NewVm(env)
+ evm := env.Vm()
// Depth check execution. Fail if we're trying to execute above the
// limit.
if env.Depth() > int(params.CallCreateDepth.Int64()) {
@@ -136,7 +136,7 @@ func exec(env vm.Environment, caller vm.ContractRef, address, codeAddr *common.A
}
func execDelegateCall(env vm.Environment, caller vm.ContractRef, originAddr, toAddr, codeAddr *common.Address, input, code []byte, gas, gasPrice, value *big.Int) (ret []byte, addr common.Address, err error) {
- evm := vm.NewVm(env)
+ evm := env.Vm()
// Depth check execution. Fail if we're trying to execute above the
// limit.
if env.Depth() > int(params.CallCreateDepth.Int64()) {
diff --git a/core/vm/common.go b/core/vm/common.go
index 395ed0471..f73bc1527 100644
--- a/core/vm/common.go
+++ b/core/vm/common.go
@@ -21,7 +21,6 @@ import (
"math/big"
"github.com/ethereum/go-ethereum/common"
- "github.com/ethereum/go-ethereum/logger/glog"
"github.com/ethereum/go-ethereum/params"
)
@@ -51,19 +50,6 @@ var (
max = big.NewInt(math.MaxInt64) // Maximum 64 bit integer
)
-// NewVm returns a new VM based on the Environment
-func NewVm(env Environment) VirtualMachine {
- switch env.VmType() {
- case JitVmTy:
- return NewJitVm(env)
- default:
- glog.V(0).Infoln("unsupported vm type %d", env.VmType())
- fallthrough
- case StdVmTy:
- return New(env)
- }
-}
-
// calculates the memory size required for a step
func calcMemSize(off, l *big.Int) *big.Int {
if l.Cmp(common.Big0) == 0 {
diff --git a/core/vm/environment.go b/core/vm/environment.go
index d5d21a45b..3c530962b 100644
--- a/core/vm/environment.go
+++ b/core/vm/environment.go
@@ -58,10 +58,8 @@ type Environment interface {
AddStructLog(StructLog)
// Returns all coalesced structured logs
StructLogs() []StructLog
-
// Type of the VM
- VmType() Type
-
+ Vm() *Vm
// Current calling depth
Depth() int
SetDepth(i int)
diff --git a/core/vm/instructions.go b/core/vm/instructions.go
index 1e1086b13..c4b4339a2 100644
--- a/core/vm/instructions.go
+++ b/core/vm/instructions.go
@@ -597,7 +597,6 @@ func opDelegateCall(instr instruction, pc *uint64, env Environment, contract *Co
toAddr := common.BigToAddress(to)
args := memory.Get(inOffset.Int64(), inSize.Int64())
ret, err := env.DelegateCall(contract, toAddr, args, gas, contract.Price)
-
if err != nil {
stack.push(new(big.Int))
} else {
diff --git a/core/vm/jit_test.go b/core/vm/jit_test.go
index 19261827b..5fac0156f 100644
--- a/core/vm/jit_test.go
+++ b/core/vm/jit_test.go
@@ -154,7 +154,7 @@ func runVmBench(test vmBench, b *testing.B) {
context := NewContract(sender, sender, big.NewInt(100), big.NewInt(10000), big.NewInt(0))
context.Code = test.code
context.CodeAddr = &common.Address{}
- _, err := New(env).Run(context, test.input)
+ _, err := env.Vm().Run(context, test.input)
if err != nil {
b.Error(err)
b.FailNow()
@@ -165,12 +165,16 @@ func runVmBench(test vmBench, b *testing.B) {
type Env struct {
gasLimit *big.Int
depth int
+ evm *Vm
}
func NewEnv() *Env {
- return &Env{big.NewInt(10000), 0}
+ env := &Env{gasLimit: big.NewInt(10000), depth: 0}
+ env.evm = EVM(env)
+ return env
}
+func (self *Env) Vm() *Vm { return self.evm }
func (self *Env) Origin() common.Address { return common.Address{} }
func (self *Env) BlockNumber() *big.Int { return big.NewInt(0) }
func (self *Env) AddStructLog(log StructLog) {
diff --git a/core/vm/jump_table.go b/core/vm/jump_table.go
index 37d7bb160..8297d3e1d 100644
--- a/core/vm/jump_table.go
+++ b/core/vm/jump_table.go
@@ -13,19 +13,15 @@ type jumpPtr struct {
type vmJumpTable [256]jumpPtr
-func (jt vmJumpTable) init(blockNumber *big.Int) {
+func newJumpTable(blockNumber *big.Int) vmJumpTable {
+ var jumpTable vmJumpTable
+
// when initialising a new VM execution we must first check the homestead
// changes.
if params.IsHomestead(blockNumber) {
jumpTable[DELEGATECALL] = jumpPtr{opDelegateCall, true}
- } else {
- jumpTable[DELEGATECALL] = jumpPtr{nil, false}
}
-}
-var jumpTable vmJumpTable
-
-func init() {
jumpTable[ADD] = jumpPtr{opAdd, true}
jumpTable[SUB] = jumpPtr{opSub, true}
jumpTable[MUL] = jumpPtr{opMul, true}
@@ -156,4 +152,6 @@ func init() {
jumpTable[JUMP] = jumpPtr{nil, true}
jumpTable[JUMPI] = jumpPtr{nil, true}
jumpTable[STOP] = jumpPtr{nil, true}
+
+ return jumpTable
}
diff --git a/core/vm/jump_table_test.go b/core/vm/jump_table_test.go
index 98d34bef2..2ed1b26fc 100644
--- a/core/vm/jump_table_test.go
+++ b/core/vm/jump_table_test.go
@@ -10,13 +10,13 @@ import (
func TestInit(t *testing.T) {
params.HomesteadBlock = big.NewInt(1)
- jumpTable.init(big.NewInt(0))
+ jumpTable := newJumpTable(big.NewInt(0))
if jumpTable[DELEGATECALL].valid {
t.Error("Expected DELEGATECALL not to be present")
}
for _, n := range []int64{1, 2, 100} {
- jumpTable.init(big.NewInt(n))
+ jumpTable := newJumpTable(big.NewInt(n))
if !jumpTable[DELEGATECALL].valid {
t.Error("Expected DELEGATECALL to be present for block", n)
}
diff --git a/core/vm/runtime/env.go b/core/vm/runtime/env.go
index 77519df81..e9bf828ea 100644
--- a/core/vm/runtime/env.go
+++ b/core/vm/runtime/env.go
@@ -41,11 +41,13 @@ type Env struct {
logs []vm.StructLog
getHashFn func(uint64) common.Hash
+
+ evm *vm.Vm
}
// NewEnv returns a new vm.Environment
func NewEnv(cfg *Config, state *state.StateDB) vm.Environment {
- return &Env{
+ env := &Env{
state: state,
origin: cfg.Origin,
coinbase: cfg.Coinbase,
@@ -54,6 +56,9 @@ func NewEnv(cfg *Config, state *state.StateDB) vm.Environment {
difficulty: cfg.Difficulty,
gasLimit: cfg.GasLimit,
}
+ env.evm = vm.EVM(env)
+
+ return env
}
func (self *Env) StructLogs() []vm.StructLog {
@@ -64,6 +69,7 @@ func (self *Env) AddStructLog(log vm.StructLog) {
self.logs = append(self.logs, log)
}
+func (self *Env) Vm() *vm.Vm { return self.evm }
func (self *Env) Origin() common.Address { return self.origin }
func (self *Env) BlockNumber() *big.Int { return self.number }
func (self *Env) Coinbase() common.Address { return self.coinbase }
diff --git a/core/vm/vm.go b/core/vm/vm.go
index 95d27c64c..26df8aef4 100644
--- a/core/vm/vm.go
+++ b/core/vm/vm.go
@@ -30,15 +30,12 @@ import (
// Vm is an EVM and implements VirtualMachine
type Vm struct {
- env Environment
+ env Environment
+ jumpTable vmJumpTable
}
-// New returns a new Vm
-func New(env Environment) *Vm {
- // init the jump table. Also prepares the homestead changes
- jumpTable.init(env.BlockNumber())
-
- return &Vm{env: env}
+func EVM(env Environment) *Vm {
+ return &Vm{env: env, jumpTable: newJumpTable(env.BlockNumber())}
}
// Run loops and evaluates the contract's code with the given input data
@@ -169,7 +166,7 @@ func (self *Vm) Run(contract *Contract, input []byte) (ret []byte, err error) {
mem.Resize(newMemSize.Uint64())
// Add a log message
self.log(pc, op, contract.Gas, cost, mem, stack, contract, nil)
- if opPtr := jumpTable[op]; opPtr.valid {
+ if opPtr := self.jumpTable[op]; opPtr.valid {
if opPtr.fn != nil {
opPtr.fn(instruction{}, &pc, self.env, contract, mem, stack)
} else {
diff --git a/core/vm/vm_jit_fake.go b/core/vm/vm_jit_fake.go
index 456fcb8d4..192f3615d 100644
--- a/core/vm/vm_jit_fake.go
+++ b/core/vm/vm_jit_fake.go
@@ -22,5 +22,5 @@ import "fmt"
func NewJitVm(env Environment) VirtualMachine {
fmt.Printf("Warning! EVM JIT not enabled.\n")
- return New(env)
+ return EVM(env)
}
diff --git a/core/vm_env.go b/core/vm_env.go
index 7b9a1a0f9..0fab4a090 100644
--- a/core/vm_env.go
+++ b/core/vm_env.go
@@ -51,10 +51,11 @@ type VMEnv struct {
getHashFn func(uint64) common.Hash
// structured logging
logs []vm.StructLog
+ evm *vm.Vm
}
func NewEnv(state *state.StateDB, chain *BlockChain, msg Message, header *types.Header) *VMEnv {
- return &VMEnv{
+ env := &VMEnv{
chain: chain,
state: state,
header: header,
@@ -62,8 +63,11 @@ func NewEnv(state *state.StateDB, chain *BlockChain, msg Message, header *types.
typ: vm.StdVmTy,
getHashFn: GetHashFn(header.ParentHash, chain),
}
+ env.evm = vm.EVM(env)
+ return env
}
+func (self *VMEnv) Vm() *vm.Vm { return self.evm }
func (self *VMEnv) Origin() common.Address { f, _ := self.msg.From(); return f }
func (self *VMEnv) BlockNumber() *big.Int { return self.header.Number }
func (self *VMEnv) Coinbase() common.Address { return self.header.Coinbase }