neo-project/neo-vm

Efficient way to pass Map type to contract method? OpCode.PACKMAP?

Closed this issue · 1 comments

ixje commented

With Map being a valid ContractParameterType I looked at how to pass one to a smart contract method. The solution I came up with seems very verbose and inefficient, in pseudo code

emit(OpCode.NEWMAP)
for _ in map_size:
    emit(OpCode.DUP)
for key, value in map:
    emit_push(key)
    emit_push(value)
    emit(OpCode.SETITEM)

So we need to duplicate the new map as many times as there are key value pairs, and then call SETITEM that many times. That's a lot of instructions. Am I missing a better way of doing this, or isn't there any? If there isn't, how about a new opcode e.g. PACKMAP

                case OpCode.PACKMAP:
                {
                    int size = (int)Pop().GetInteger();
                    Map map = new(ReferenceCounter);
                    for (int i = 0; i < size; i++)
                    {
                        StackItem value = Pop();
                        PrimitiveType key = Pop<PrimitiveType>();
                        map[key] = value;
                    }
                    Push(map);
                    break;
                }

@ixje please take a look to #443