mirror of
https://github.com/nspcc-dev/neo-go.git
synced 2024-11-22 09:29:38 +00:00
vm: implement POPITEM opcode
This commit is contained in:
parent
7d937827e3
commit
324107b31e
5 changed files with 52 additions and 4 deletions
|
@ -195,6 +195,7 @@ var coefficients = map[opcode.Opcode]int64{
|
||||||
opcode.REVERSEITEMS: 1 << 13,
|
opcode.REVERSEITEMS: 1 << 13,
|
||||||
opcode.REMOVE: 1 << 4,
|
opcode.REMOVE: 1 << 4,
|
||||||
opcode.CLEARITEMS: 1 << 4,
|
opcode.CLEARITEMS: 1 << 4,
|
||||||
|
opcode.POPITEM: 1 << 4,
|
||||||
opcode.ISNULL: 1 << 1,
|
opcode.ISNULL: 1 << 1,
|
||||||
opcode.ISTYPE: 1 << 1,
|
opcode.ISTYPE: 1 << 1,
|
||||||
opcode.CONVERT: 1 << 11,
|
opcode.CONVERT: 1 << 11,
|
||||||
|
|
|
@ -212,6 +212,7 @@ const (
|
||||||
REVERSEITEMS Opcode = 0xD1
|
REVERSEITEMS Opcode = 0xD1
|
||||||
REMOVE Opcode = 0xD2
|
REMOVE Opcode = 0xD2
|
||||||
CLEARITEMS Opcode = 0xD3
|
CLEARITEMS Opcode = 0xD3
|
||||||
|
POPITEM Opcode = 0xD4
|
||||||
|
|
||||||
// Types
|
// Types
|
||||||
ISNULL Opcode = 0xD8
|
ISNULL Opcode = 0xD8
|
||||||
|
|
|
@ -192,12 +192,13 @@ func _() {
|
||||||
_ = x[REVERSEITEMS-209]
|
_ = x[REVERSEITEMS-209]
|
||||||
_ = x[REMOVE-210]
|
_ = x[REMOVE-210]
|
||||||
_ = x[CLEARITEMS-211]
|
_ = x[CLEARITEMS-211]
|
||||||
|
_ = x[POPITEM-212]
|
||||||
_ = x[ISNULL-216]
|
_ = x[ISNULL-216]
|
||||||
_ = x[ISTYPE-217]
|
_ = x[ISTYPE-217]
|
||||||
_ = x[CONVERT-219]
|
_ = x[CONVERT-219]
|
||||||
}
|
}
|
||||||
|
|
||||||
const _Opcode_name = "PUSHINT8PUSHINT16PUSHINT32PUSHINT64PUSHINT128PUSHINT256PUSHAPUSHNULLPUSHDATA1PUSHDATA2PUSHDATA4PUSHM1PUSH0PUSH1PUSH2PUSH3PUSH4PUSH5PUSH6PUSH7PUSH8PUSH9PUSH10PUSH11PUSH12PUSH13PUSH14PUSH15PUSH16NOPJMPJMP_LJMPIFJMPIF_LJMPIFNOTJMPIFNOT_LJMPEQJMPEQ_LJMPNEJMPNE_LJMPGTJMPGT_LJMPGEJMPGE_LJMPLTJMPLT_LJMPLEJMPLE_LCALLCALL_LCALLACALLTABORTASSERTTHROWTRYTRY_LENDTRYENDTRY_LENDFINALLYRETSYSCALLDEPTHDROPNIPXDROPCLEARDUPOVERPICKTUCKSWAPROTROLLREVERSE3REVERSE4REVERSENINITSSLOTINITSLOTLDSFLD0LDSFLD1LDSFLD2LDSFLD3LDSFLD4LDSFLD5LDSFLD6LDSFLDSTSFLD0STSFLD1STSFLD2STSFLD3STSFLD4STSFLD5STSFLD6STSFLDLDLOC0LDLOC1LDLOC2LDLOC3LDLOC4LDLOC5LDLOC6LDLOCSTLOC0STLOC1STLOC2STLOC3STLOC4STLOC5STLOC6STLOCLDARG0LDARG1LDARG2LDARG3LDARG4LDARG5LDARG6LDARGSTARG0STARG1STARG2STARG3STARG4STARG5STARG6STARGNEWBUFFERMEMCPYCATSUBSTRLEFTRIGHTINVERTANDORXOREQUALNOTEQUALSIGNABSNEGATEINCDECADDSUBMULDIVMODSHLSHRNOTBOOLANDBOOLORNZNUMEQUALNUMNOTEQUALLTLTEGTGTEMINMAXWITHINPACKUNPACKNEWARRAY0NEWARRAYNEWARRAY_TNEWSTRUCT0NEWSTRUCTNEWMAPSIZEHASKEYKEYSVALUESPICKITEMAPPENDSETITEMREVERSEITEMSREMOVECLEARITEMSISNULLISTYPECONVERT"
|
const _Opcode_name = "PUSHINT8PUSHINT16PUSHINT32PUSHINT64PUSHINT128PUSHINT256PUSHAPUSHNULLPUSHDATA1PUSHDATA2PUSHDATA4PUSHM1PUSH0PUSH1PUSH2PUSH3PUSH4PUSH5PUSH6PUSH7PUSH8PUSH9PUSH10PUSH11PUSH12PUSH13PUSH14PUSH15PUSH16NOPJMPJMP_LJMPIFJMPIF_LJMPIFNOTJMPIFNOT_LJMPEQJMPEQ_LJMPNEJMPNE_LJMPGTJMPGT_LJMPGEJMPGE_LJMPLTJMPLT_LJMPLEJMPLE_LCALLCALL_LCALLACALLTABORTASSERTTHROWTRYTRY_LENDTRYENDTRY_LENDFINALLYRETSYSCALLDEPTHDROPNIPXDROPCLEARDUPOVERPICKTUCKSWAPROTROLLREVERSE3REVERSE4REVERSENINITSSLOTINITSLOTLDSFLD0LDSFLD1LDSFLD2LDSFLD3LDSFLD4LDSFLD5LDSFLD6LDSFLDSTSFLD0STSFLD1STSFLD2STSFLD3STSFLD4STSFLD5STSFLD6STSFLDLDLOC0LDLOC1LDLOC2LDLOC3LDLOC4LDLOC5LDLOC6LDLOCSTLOC0STLOC1STLOC2STLOC3STLOC4STLOC5STLOC6STLOCLDARG0LDARG1LDARG2LDARG3LDARG4LDARG5LDARG6LDARGSTARG0STARG1STARG2STARG3STARG4STARG5STARG6STARGNEWBUFFERMEMCPYCATSUBSTRLEFTRIGHTINVERTANDORXOREQUALNOTEQUALSIGNABSNEGATEINCDECADDSUBMULDIVMODSHLSHRNOTBOOLANDBOOLORNZNUMEQUALNUMNOTEQUALLTLTEGTGTEMINMAXWITHINPACKUNPACKNEWARRAY0NEWARRAYNEWARRAY_TNEWSTRUCT0NEWSTRUCTNEWMAPSIZEHASKEYKEYSVALUESPICKITEMAPPENDSETITEMREVERSEITEMSREMOVECLEARITEMSPOPITEMISNULLISTYPECONVERT"
|
||||||
|
|
||||||
var _Opcode_map = map[Opcode]string{
|
var _Opcode_map = map[Opcode]string{
|
||||||
0: _Opcode_name[0:8],
|
0: _Opcode_name[0:8],
|
||||||
|
@ -382,9 +383,10 @@ var _Opcode_map = map[Opcode]string{
|
||||||
209: _Opcode_name[1033:1045],
|
209: _Opcode_name[1033:1045],
|
||||||
210: _Opcode_name[1045:1051],
|
210: _Opcode_name[1045:1051],
|
||||||
211: _Opcode_name[1051:1061],
|
211: _Opcode_name[1051:1061],
|
||||||
216: _Opcode_name[1061:1067],
|
212: _Opcode_name[1061:1068],
|
||||||
217: _Opcode_name[1067:1073],
|
216: _Opcode_name[1068:1074],
|
||||||
219: _Opcode_name[1073:1080],
|
217: _Opcode_name[1074:1080],
|
||||||
|
219: _Opcode_name[1080:1087],
|
||||||
}
|
}
|
||||||
|
|
||||||
func (i Opcode) String() string {
|
func (i Opcode) String() string {
|
||||||
|
|
14
pkg/vm/vm.go
14
pkg/vm/vm.go
|
@ -1216,6 +1216,20 @@ func (v *VM) execute(ctx *Context, op opcode.Opcode, parameter []byte) (err erro
|
||||||
panic("CLEARITEMS: invalid type")
|
panic("CLEARITEMS: invalid type")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
case opcode.POPITEM:
|
||||||
|
arr := v.estack.Pop().Item()
|
||||||
|
elems := arr.Value().([]stackitem.Item)
|
||||||
|
index := len(elems) - 1
|
||||||
|
elem := elems[index]
|
||||||
|
switch item := arr.(type) {
|
||||||
|
case *stackitem.Array:
|
||||||
|
item.Remove(index)
|
||||||
|
case *stackitem.Struct:
|
||||||
|
item.Remove(index)
|
||||||
|
}
|
||||||
|
v.refs.Remove(elem)
|
||||||
|
v.estack.PushVal(elem)
|
||||||
|
|
||||||
case opcode.SIZE:
|
case opcode.SIZE:
|
||||||
elem := v.estack.Pop()
|
elem := v.estack.Pop()
|
||||||
// Cause there is no native (byte) item type here, hence we need to check
|
// Cause there is no native (byte) item type here, hence we need to check
|
||||||
|
|
|
@ -2167,6 +2167,36 @@ func TestCLEARITEMS(t *testing.T) {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestPOPITEM(t *testing.T) {
|
||||||
|
testPOPITEM := func(t *testing.T, item, elem, arr interface{}) {
|
||||||
|
prog := makeProgram(opcode.DUP, opcode.POPITEM)
|
||||||
|
v := load(prog)
|
||||||
|
v.estack.PushVal(item)
|
||||||
|
|
||||||
|
runVM(t, v)
|
||||||
|
require.EqualValues(t, stackitem.Make(elem), v.estack.Pop().Item())
|
||||||
|
require.EqualValues(t, stackitem.Make(arr), v.estack.Pop().Item())
|
||||||
|
}
|
||||||
|
|
||||||
|
elems := []stackitem.Item{stackitem.Make(11), stackitem.Make(31)}
|
||||||
|
t.Run("Array", func(t *testing.T) {
|
||||||
|
testPOPITEM(t, stackitem.NewArray(elems), 31, elems[:1])
|
||||||
|
})
|
||||||
|
t.Run("Struct", func(t *testing.T) {
|
||||||
|
testPOPITEM(t, stackitem.NewStruct(elems), 31, elems[:1])
|
||||||
|
})
|
||||||
|
t.Run("0-length array", func(t *testing.T) {
|
||||||
|
prog := makeProgram(opcode.NEWARRAY0, opcode.POPITEM)
|
||||||
|
v := load(prog)
|
||||||
|
checkVMFailed(t, v)
|
||||||
|
})
|
||||||
|
t.Run("primitive type", func(t *testing.T) {
|
||||||
|
prog := makeProgram(opcode.PUSH4, opcode.POPITEM)
|
||||||
|
v := load(prog)
|
||||||
|
checkVMFailed(t, v)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
func TestSWAPGood(t *testing.T) {
|
func TestSWAPGood(t *testing.T) {
|
||||||
prog := makeProgram(opcode.SWAP)
|
prog := makeProgram(opcode.SWAP)
|
||||||
vm := load(prog)
|
vm := load(prog)
|
||||||
|
|
Loading…
Reference in a new issue