forked from TrueCloudLab/neoneo-go
vm: simplify access to context, don't call Context() twice
Avoid going through Value(), avoid doing type casts twice for every instruction. name old time/op new time/op delta ScriptFibonacci-8 793µs ± 3% 736µs ± 1% -7.18% (p=0.000 n=10+9) ScriptNestedRefCount-8 1.09ms ± 1% 1.08ms ± 2% -0.96% (p=0.035 n=10+10) ScriptPushPop/4-8 1.51µs ± 3% 1.48µs ± 3% ~ (p=0.072 n=10+10) ScriptPushPop/16-8 3.76µs ± 1% 3.59µs ± 1% -4.56% (p=0.000 n=10+10) ScriptPushPop/128-8 25.0µs ± 1% 23.7µs ± 1% -5.28% (p=0.000 n=10+10) ScriptPushPop/1024-8 184µs ± 1% 176µs ± 2% -4.22% (p=0.000 n=9+9)
This commit is contained in:
parent
e09a0f3969
commit
bc31c97c32
2 changed files with 15 additions and 8 deletions
|
@ -286,8 +286,7 @@ func (v *VM) getContextScriptHash(n int) util.Uint160 {
|
||||||
return util.Uint160{}
|
return util.Uint160{}
|
||||||
}
|
}
|
||||||
element := istack.Peek(n)
|
element := istack.Peek(n)
|
||||||
ctxIface := element.Value()
|
ctx := element.value.(*Context)
|
||||||
ctx := ctxIface.(*Context)
|
|
||||||
return ctx.ScriptHash()
|
return ctx.ScriptHash()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
20
pkg/vm/vm.go
20
pkg/vm/vm.go
|
@ -322,7 +322,7 @@ func (v *VM) Context() *Context {
|
||||||
if v.istack.Len() == 0 {
|
if v.istack.Len() == 0 {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
return v.istack.Peek(0).Value().(*Context)
|
return v.istack.Peek(0).value.(*Context)
|
||||||
}
|
}
|
||||||
|
|
||||||
// PopResult is used to pop the first item of the evaluation stack. This allows
|
// PopResult is used to pop the first item of the evaluation stack. This allows
|
||||||
|
@ -360,6 +360,8 @@ func (v *VM) Ready() bool {
|
||||||
|
|
||||||
// Run starts the execution of the loaded program.
|
// Run starts the execution of the loaded program.
|
||||||
func (v *VM) Run() error {
|
func (v *VM) Run() error {
|
||||||
|
var ctx *Context
|
||||||
|
|
||||||
if !v.Ready() {
|
if !v.Ready() {
|
||||||
v.state = FaultState
|
v.state = FaultState
|
||||||
return errors.New("no program loaded")
|
return errors.New("no program loaded")
|
||||||
|
@ -372,6 +374,7 @@ func (v *VM) Run() error {
|
||||||
}
|
}
|
||||||
// HaltState (the default) or BreakState are safe to continue.
|
// HaltState (the default) or BreakState are safe to continue.
|
||||||
v.state = NoneState
|
v.state = NoneState
|
||||||
|
ctx = v.Context()
|
||||||
for {
|
for {
|
||||||
switch {
|
switch {
|
||||||
case v.state.HasFlag(FaultState):
|
case v.state.HasFlag(FaultState):
|
||||||
|
@ -382,7 +385,7 @@ func (v *VM) Run() error {
|
||||||
// Normal exit from this loop.
|
// Normal exit from this loop.
|
||||||
return nil
|
return nil
|
||||||
case v.state == NoneState:
|
case v.state == NoneState:
|
||||||
if err := v.Step(); err != nil {
|
if err := v.step(ctx); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
default:
|
default:
|
||||||
|
@ -390,7 +393,7 @@ func (v *VM) Run() error {
|
||||||
return errors.New("unknown state")
|
return errors.New("unknown state")
|
||||||
}
|
}
|
||||||
// check for breakpoint before executing the next instruction
|
// check for breakpoint before executing the next instruction
|
||||||
ctx := v.Context()
|
ctx = v.Context()
|
||||||
if ctx != nil && ctx.atBreakPoint() {
|
if ctx != nil && ctx.atBreakPoint() {
|
||||||
v.state = BreakState
|
v.state = BreakState
|
||||||
}
|
}
|
||||||
|
@ -400,6 +403,11 @@ func (v *VM) Run() error {
|
||||||
// Step 1 instruction in the program.
|
// Step 1 instruction in the program.
|
||||||
func (v *VM) Step() error {
|
func (v *VM) Step() error {
|
||||||
ctx := v.Context()
|
ctx := v.Context()
|
||||||
|
return v.step(ctx)
|
||||||
|
}
|
||||||
|
|
||||||
|
// step executes one instruction in given context.
|
||||||
|
func (v *VM) step(ctx *Context) error {
|
||||||
op, param, err := ctx.Next()
|
op, param, err := ctx.Next()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
v.state = FaultState
|
v.state = FaultState
|
||||||
|
@ -1285,7 +1293,7 @@ func (v *VM) execute(ctx *Context, op opcode.Opcode, parameter []byte) (err erro
|
||||||
}
|
}
|
||||||
|
|
||||||
case opcode.RET:
|
case opcode.RET:
|
||||||
oldCtx := v.istack.Pop().Value().(*Context)
|
oldCtx := v.istack.Pop().value.(*Context)
|
||||||
oldEstack := v.estack
|
oldEstack := v.estack
|
||||||
|
|
||||||
v.unloadContext(oldCtx)
|
v.unloadContext(oldCtx)
|
||||||
|
@ -1552,7 +1560,7 @@ func calcJumpOffset(ctx *Context, parameter []byte) (int, int, error) {
|
||||||
func (v *VM) handleException() {
|
func (v *VM) handleException() {
|
||||||
for pop := 0; pop < v.istack.Len(); pop++ {
|
for pop := 0; pop < v.istack.Len(); pop++ {
|
||||||
ictxv := v.istack.Peek(pop)
|
ictxv := v.istack.Peek(pop)
|
||||||
ictx := ictxv.Value().(*Context)
|
ictx := ictxv.value.(*Context)
|
||||||
for j := 0; j < ictx.tryStack.Len(); j++ {
|
for j := 0; j < ictx.tryStack.Len(); j++ {
|
||||||
e := ictx.tryStack.Peek(j)
|
e := ictx.tryStack.Peek(j)
|
||||||
ectx := e.Value().(*exceptionHandlingContext)
|
ectx := e.Value().(*exceptionHandlingContext)
|
||||||
|
@ -1562,7 +1570,7 @@ func (v *VM) handleException() {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
for i := 0; i < pop; i++ {
|
for i := 0; i < pop; i++ {
|
||||||
ctx := v.istack.Pop().Value().(*Context)
|
ctx := v.istack.Pop().value.(*Context)
|
||||||
v.unloadContext(ctx)
|
v.unloadContext(ctx)
|
||||||
}
|
}
|
||||||
if ectx.State == eTry && ectx.HasCatch() {
|
if ectx.State == eTry && ectx.HasCatch() {
|
||||||
|
|
Loading…
Add table
Reference in a new issue