Merge pull request #2122 from nspcc-dev/vm-microopt
VM-related microoptimizations
This commit is contained in:
commit
3360c4a0d8
6 changed files with 37 additions and 27 deletions
|
@ -48,14 +48,20 @@ type Context struct {
|
||||||
VM *vm.VM
|
VM *vm.VM
|
||||||
Functions []Function
|
Functions []Function
|
||||||
getContract func(dao.DAO, util.Uint160) (*state.Contract, error)
|
getContract func(dao.DAO, util.Uint160) (*state.Contract, error)
|
||||||
|
baseExecFee int64
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewContext returns new interop context.
|
// NewContext returns new interop context.
|
||||||
func NewContext(trigger trigger.Type, bc blockchainer.Blockchainer, d dao.DAO,
|
func NewContext(trigger trigger.Type, bc blockchainer.Blockchainer, d dao.DAO,
|
||||||
getContract func(dao.DAO, util.Uint160) (*state.Contract, error), natives []Contract,
|
getContract func(dao.DAO, util.Uint160) (*state.Contract, error), natives []Contract,
|
||||||
block *block.Block, tx *transaction.Transaction, log *zap.Logger) *Context {
|
block *block.Block, tx *transaction.Transaction, log *zap.Logger) *Context {
|
||||||
|
baseExecFee := int64(DefaultBaseExecFee)
|
||||||
dao := d.GetWrapped()
|
dao := d.GetWrapped()
|
||||||
nes := make([]state.NotificationEvent, 0)
|
nes := make([]state.NotificationEvent, 0)
|
||||||
|
|
||||||
|
if bc != nil && (block == nil || block.Index != 0) {
|
||||||
|
baseExecFee = bc.GetPolicer().GetBaseExecFee()
|
||||||
|
}
|
||||||
return &Context{
|
return &Context{
|
||||||
Chain: bc,
|
Chain: bc,
|
||||||
Network: uint32(bc.GetConfig().Magic),
|
Network: uint32(bc.GetConfig().Magic),
|
||||||
|
@ -69,6 +75,7 @@ func NewContext(trigger trigger.Type, bc blockchainer.Blockchainer, d dao.DAO,
|
||||||
// Functions is a slice of interops sorted by ID.
|
// Functions is a slice of interops sorted by ID.
|
||||||
Functions: []Function{},
|
Functions: []Function{},
|
||||||
getContract: getContract,
|
getContract: getContract,
|
||||||
|
baseExecFee: baseExecFee,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -254,10 +261,7 @@ func (ic *Context) GetFunction(id uint32) *Function {
|
||||||
|
|
||||||
// BaseExecFee represents factor to multiply syscall prices with.
|
// BaseExecFee represents factor to multiply syscall prices with.
|
||||||
func (ic *Context) BaseExecFee() int64 {
|
func (ic *Context) BaseExecFee() int64 {
|
||||||
if ic.Chain == nil || (ic.Block != nil && ic.Block.Index == 0) {
|
return ic.baseExecFee
|
||||||
return DefaultBaseExecFee
|
|
||||||
}
|
|
||||||
return ic.Chain.GetPolicer().GetBaseExecFee()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// SyscallHandler handles syscall with id.
|
// SyscallHandler handles syscall with id.
|
||||||
|
|
|
@ -5,6 +5,7 @@ import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
|
"github.com/nspcc-dev/neo-go/internal/fakechain"
|
||||||
"github.com/nspcc-dev/neo-go/pkg/config/netmode"
|
"github.com/nspcc-dev/neo-go/pkg/config/netmode"
|
||||||
"github.com/nspcc-dev/neo-go/pkg/core/dao"
|
"github.com/nspcc-dev/neo-go/pkg/core/dao"
|
||||||
"github.com/nspcc-dev/neo-go/pkg/core/fee"
|
"github.com/nspcc-dev/neo-go/pkg/core/fee"
|
||||||
|
@ -67,12 +68,15 @@ func initCheckMultisigVMNoArgs(container *transaction.Transaction) *vm.VM {
|
||||||
buf[0] = byte(opcode.SYSCALL)
|
buf[0] = byte(opcode.SYSCALL)
|
||||||
binary.LittleEndian.PutUint32(buf[1:], neoCryptoCheckMultisigID)
|
binary.LittleEndian.PutUint32(buf[1:], neoCryptoCheckMultisigID)
|
||||||
|
|
||||||
ic := &interop.Context{
|
ic := interop.NewContext(
|
||||||
Network: uint32(netmode.UnitTestNet),
|
trigger.Verification,
|
||||||
Trigger: trigger.Verification,
|
fakechain.NewFakeChain(),
|
||||||
Container: container,
|
dao.NewSimple(storage.NewMemoryStore(), false),
|
||||||
Functions: Interops,
|
nil, nil, nil,
|
||||||
}
|
container,
|
||||||
|
nil)
|
||||||
|
ic.Container = container
|
||||||
|
ic.Functions = Interops
|
||||||
v := ic.SpawnVM()
|
v := ic.SpawnVM()
|
||||||
v.LoadScript(buf)
|
v.LoadScript(buf)
|
||||||
return v
|
return v
|
||||||
|
|
|
@ -7,5 +7,5 @@ import (
|
||||||
|
|
||||||
// GetPrice returns a price for executing op with the provided parameter.
|
// GetPrice returns a price for executing op with the provided parameter.
|
||||||
func (ic *Context) GetPrice(op opcode.Opcode, parameter []byte) int64 {
|
func (ic *Context) GetPrice(op opcode.Opcode, parameter []byte) int64 {
|
||||||
return fee.Opcode(ic.BaseExecFee(), op)
|
return fee.Opcode(ic.baseExecFee, op)
|
||||||
}
|
}
|
||||||
|
|
|
@ -26,7 +26,7 @@ func (s *Slot) init(n int) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (v *VM) newSlot(n int) *Slot {
|
func (v *VM) newSlot(n int) *Slot {
|
||||||
s := newSlot(v.refs)
|
s := newSlot(&v.refs)
|
||||||
s.init(n)
|
s.init(n)
|
||||||
return s
|
return s
|
||||||
}
|
}
|
||||||
|
|
|
@ -162,13 +162,15 @@ func NewStack(n string) *Stack {
|
||||||
}
|
}
|
||||||
|
|
||||||
func newStack(n string, refc *refCounter) *Stack {
|
func newStack(n string, refc *refCounter) *Stack {
|
||||||
s := &Stack{
|
s := new(Stack)
|
||||||
name: n,
|
initStack(s, n, refc)
|
||||||
refs: refc,
|
return s
|
||||||
}
|
}
|
||||||
|
func initStack(s *Stack, n string, refc *refCounter) {
|
||||||
|
s.name = n
|
||||||
|
s.refs = refc
|
||||||
s.top.next = &s.top
|
s.top.next = &s.top
|
||||||
s.top.prev = &s.top
|
s.top.prev = &s.top
|
||||||
return s
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Clear clears all elements on the stack and set its length to 0.
|
// Clear clears all elements on the stack and set its length to 0.
|
||||||
|
|
20
pkg/vm/vm.go
20
pkg/vm/vm.go
|
@ -68,12 +68,12 @@ type VM struct {
|
||||||
// callback to get interop price
|
// callback to get interop price
|
||||||
getPrice func(opcode.Opcode, []byte) int64
|
getPrice func(opcode.Opcode, []byte) int64
|
||||||
|
|
||||||
istack *Stack // invocation stack.
|
istack Stack // invocation stack.
|
||||||
estack *Stack // execution stack.
|
estack *Stack // execution stack.
|
||||||
|
|
||||||
uncaughtException stackitem.Item // exception being handled
|
uncaughtException stackitem.Item // exception being handled
|
||||||
|
|
||||||
refs *refCounter
|
refs refCounter
|
||||||
|
|
||||||
gasConsumed int64
|
gasConsumed int64
|
||||||
GasLimit int64
|
GasLimit int64
|
||||||
|
@ -99,15 +99,15 @@ func New() *VM {
|
||||||
func NewWithTrigger(t trigger.Type) *VM {
|
func NewWithTrigger(t trigger.Type) *VM {
|
||||||
vm := &VM{
|
vm := &VM{
|
||||||
state: NoneState,
|
state: NoneState,
|
||||||
istack: newStack("invocation", nil),
|
|
||||||
refs: newRefCounter(),
|
|
||||||
trigger: t,
|
trigger: t,
|
||||||
|
|
||||||
SyscallHandler: defaultSyscallHandler,
|
SyscallHandler: defaultSyscallHandler,
|
||||||
Invocations: make(map[util.Uint160]int),
|
Invocations: make(map[util.Uint160]int),
|
||||||
}
|
}
|
||||||
|
|
||||||
vm.estack = newStack("evaluation", vm.refs)
|
vm.refs.items = make(map[stackitem.Item]int)
|
||||||
|
initStack(&vm.istack, "invocation", nil)
|
||||||
|
vm.estack = newStack("evaluation", &vm.refs)
|
||||||
return vm
|
return vm
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -135,7 +135,7 @@ func (v *VM) Estack() *Stack {
|
||||||
|
|
||||||
// Istack returns the invocation stack so interop hooks can utilize this.
|
// Istack returns the invocation stack so interop hooks can utilize this.
|
||||||
func (v *VM) Istack() *Stack {
|
func (v *VM) Istack() *Stack {
|
||||||
return v.istack
|
return &v.istack
|
||||||
}
|
}
|
||||||
|
|
||||||
// LoadArgs loads in the arguments used in the Mian entry point.
|
// LoadArgs loads in the arguments used in the Mian entry point.
|
||||||
|
@ -281,11 +281,11 @@ func (v *VM) LoadScript(b []byte) {
|
||||||
func (v *VM) LoadScriptWithFlags(b []byte, f callflag.CallFlag) {
|
func (v *VM) LoadScriptWithFlags(b []byte, f callflag.CallFlag) {
|
||||||
v.checkInvocationStackSize()
|
v.checkInvocationStackSize()
|
||||||
ctx := NewContextWithParams(b, 0, -1, 0)
|
ctx := NewContextWithParams(b, 0, -1, 0)
|
||||||
v.estack = newStack("evaluation", v.refs)
|
v.estack = newStack("evaluation", &v.refs)
|
||||||
ctx.estack = v.estack
|
ctx.estack = v.estack
|
||||||
ctx.tryStack = newStack("exception", nil)
|
ctx.tryStack = newStack("exception", nil)
|
||||||
ctx.callFlag = f
|
ctx.callFlag = f
|
||||||
ctx.static = newSlot(v.refs)
|
ctx.static = newSlot(&v.refs)
|
||||||
ctx.callingScriptHash = v.GetCurrentScriptHash()
|
ctx.callingScriptHash = v.GetCurrentScriptHash()
|
||||||
v.istack.PushVal(ctx)
|
v.istack.PushVal(ctx)
|
||||||
}
|
}
|
||||||
|
@ -340,7 +340,7 @@ func (v *VM) PopResult() interface{} {
|
||||||
func (v *VM) Stack(n string) string {
|
func (v *VM) Stack(n string) string {
|
||||||
var s *Stack
|
var s *Stack
|
||||||
if n == "istack" {
|
if n == "istack" {
|
||||||
s = v.istack
|
s = &v.istack
|
||||||
}
|
}
|
||||||
if n == "estack" {
|
if n == "estack" {
|
||||||
s = v.estack
|
s = v.estack
|
||||||
|
@ -1786,7 +1786,7 @@ func (v *VM) GetCallingScriptHash() util.Uint160 {
|
||||||
|
|
||||||
// GetEntryScriptHash implements ScriptHashGetter interface.
|
// GetEntryScriptHash implements ScriptHashGetter interface.
|
||||||
func (v *VM) GetEntryScriptHash() util.Uint160 {
|
func (v *VM) GetEntryScriptHash() util.Uint160 {
|
||||||
return v.getContextScriptHash(v.Istack().Len() - 1)
|
return v.getContextScriptHash(v.istack.len - 1)
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetCurrentScriptHash implements ScriptHashGetter interface.
|
// GetCurrentScriptHash implements ScriptHashGetter interface.
|
||||||
|
|
Loading…
Reference in a new issue