forked from TrueCloudLab/neoneo-go
vm: count initial Null slot variables as well
Match C# behavior. Thanks to @ixje for finding this.
This commit is contained in:
parent
18d627e7f7
commit
0d93b353e6
5 changed files with 20 additions and 15 deletions
|
@ -56,11 +56,11 @@ func opParamSlotsPushVM(op opcode.Opcode, param []byte, sslot int, slotloc int,
|
|||
return nil
|
||||
}
|
||||
if sslot != 0 {
|
||||
v.Context().static.init(sslot)
|
||||
v.Context().static.init(sslot, &v.refs)
|
||||
}
|
||||
if slotloc != 0 && slotarg != 0 {
|
||||
v.Context().local.init(slotloc)
|
||||
v.Context().arguments.init(slotarg)
|
||||
v.Context().local.init(slotloc, &v.refs)
|
||||
v.Context().arguments.init(slotarg, &v.refs)
|
||||
}
|
||||
for i := range items {
|
||||
item, ok := items[i].(stackitem.Item)
|
||||
|
|
|
@ -10,11 +10,12 @@ import (
|
|||
type slot []stackitem.Item
|
||||
|
||||
// init sets static slot size to n. It is intended to be used only by INITSSLOT.
|
||||
func (s *slot) init(n int) {
|
||||
func (s *slot) init(n int, rc *refCounter) {
|
||||
if *s != nil {
|
||||
panic("already initialized")
|
||||
}
|
||||
*s = make([]stackitem.Item, n)
|
||||
*rc += refCounter(n) // Virtual "Null" elements.
|
||||
}
|
||||
|
||||
// Set sets i-th storage slot.
|
||||
|
@ -26,6 +27,8 @@ func (s slot) Set(i int, item stackitem.Item, refs *refCounter) {
|
|||
s[i] = item
|
||||
if old != nil {
|
||||
refs.Remove(old)
|
||||
} else {
|
||||
*refs-- // Not really existing, but counted Null element.
|
||||
}
|
||||
refs.Add(item)
|
||||
}
|
||||
|
@ -38,8 +41,8 @@ func (s slot) Get(i int) stackitem.Item {
|
|||
return stackitem.Null{}
|
||||
}
|
||||
|
||||
// Clear removes all slot variables from the reference counter.
|
||||
func (s slot) Clear(refs *refCounter) {
|
||||
// ClearRefs removes all slot variables from the reference counter.
|
||||
func (s slot) ClearRefs(refs *refCounter) {
|
||||
for _, item := range s {
|
||||
refs.Remove(item)
|
||||
}
|
||||
|
|
|
@ -13,8 +13,9 @@ func TestSlot_Get(t *testing.T) {
|
|||
var s slot
|
||||
require.Panics(t, func() { s.Size() })
|
||||
|
||||
s.init(3)
|
||||
s.init(3, rc)
|
||||
require.Equal(t, 3, s.Size())
|
||||
require.Equal(t, 3, int(*rc))
|
||||
|
||||
// Null is the default
|
||||
item := s.Get(2)
|
||||
|
@ -22,4 +23,5 @@ func TestSlot_Get(t *testing.T) {
|
|||
|
||||
s.Set(1, stackitem.NewBigInteger(big.NewInt(42)), rc)
|
||||
require.Equal(t, stackitem.NewBigInteger(big.NewInt(42)), s.Get(1))
|
||||
require.Equal(t, 3, int(*rc))
|
||||
}
|
||||
|
|
12
pkg/vm/vm.go
12
pkg/vm/vm.go
|
@ -616,7 +616,7 @@ func (v *VM) execute(ctx *Context, op opcode.Opcode, parameter []byte) (err erro
|
|||
if parameter[0] == 0 {
|
||||
panic("zero argument")
|
||||
}
|
||||
ctx.static.init(int(parameter[0]))
|
||||
ctx.static.init(int(parameter[0]), &v.refs)
|
||||
|
||||
case opcode.INITSLOT:
|
||||
if ctx.local != nil || ctx.arguments != nil {
|
||||
|
@ -626,11 +626,11 @@ func (v *VM) execute(ctx *Context, op opcode.Opcode, parameter []byte) (err erro
|
|||
panic("zero argument")
|
||||
}
|
||||
if parameter[0] > 0 {
|
||||
ctx.local.init(int(parameter[0]))
|
||||
ctx.local.init(int(parameter[0]), &v.refs)
|
||||
}
|
||||
if parameter[1] > 0 {
|
||||
sz := int(parameter[1])
|
||||
ctx.arguments.init(sz)
|
||||
ctx.arguments.init(sz, &v.refs)
|
||||
for i := 0; i < sz; i++ {
|
||||
ctx.arguments.Set(i, v.estack.Pop().Item(), &v.refs)
|
||||
}
|
||||
|
@ -1582,14 +1582,14 @@ func (v *VM) execute(ctx *Context, op opcode.Opcode, parameter []byte) (err erro
|
|||
|
||||
func (v *VM) unloadContext(ctx *Context) {
|
||||
if ctx.local != nil {
|
||||
ctx.local.Clear(&v.refs)
|
||||
ctx.local.ClearRefs(&v.refs)
|
||||
}
|
||||
if ctx.arguments != nil {
|
||||
ctx.arguments.Clear(&v.refs)
|
||||
ctx.arguments.ClearRefs(&v.refs)
|
||||
}
|
||||
currCtx := v.Context()
|
||||
if ctx.static != nil && currCtx != nil && ctx.static != currCtx.static {
|
||||
ctx.static.Clear(&v.refs)
|
||||
ctx.static.ClearRefs(&v.refs)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -387,8 +387,8 @@ func TestStackLimit(t *testing.T) {
|
|||
inst opcode.Opcode
|
||||
size int
|
||||
}{
|
||||
{opcode.PUSH2, 1},
|
||||
{opcode.NEWARRAY, 3}, // array + 2 items
|
||||
{opcode.PUSH2, 2}, // 1 from INITSSLOT and 1 for integer 2
|
||||
{opcode.NEWARRAY, 4}, // array + 2 items
|
||||
{opcode.STSFLD0, 3},
|
||||
{opcode.LDSFLD0, 4},
|
||||
{opcode.NEWMAP, 5},
|
||||
|
|
Loading…
Reference in a new issue