Commit graph

70 commits

Author SHA1 Message Date
Roman Khimov
930653418d vm: rework stack as a simple slice
Double-linked list is quite expensive to manage especially given that it
requires microallocations for each Element. It can be replaced by simple slice
which is much more effective for simple push/pop operations that are very
typical in a VM. I've worried a little about more complex operations like
XDROP/1024 or REVERSEN/1024 because these require copying quite substantial
number of elements, but turns out these work fine too.

At the moment Element is kept as a convenient wrapper for Bytes/BigInt/Bool/etc
methods, but it can be changed in future. Many other potential optimizations
are also possible now.

Complex scripts:
name                    old time/op    new time/op    delta
ScriptFibonacci-8         1.11ms ± 2%    0.85ms ± 2%  -23.40%  (p=0.000 n=10+10)
ScriptNestedRefCount-8    1.46ms ± 2%    1.16ms ± 1%  -20.65%  (p=0.000 n=10+10)
ScriptPushPop/4-8         1.81µs ± 1%    1.54µs ± 4%  -14.96%  (p=0.000 n=8+10)
ScriptPushPop/16-8        4.88µs ± 2%    3.91µs ± 2%  -19.87%  (p=0.000 n=9+9)
ScriptPushPop/128-8       31.9µs ± 9%    26.7µs ± 3%  -16.28%  (p=0.000 n=9+8)
ScriptPushPop/1024-8       235µs ± 1%     192µs ± 3%  -18.31%  (p=0.000 n=9+10)

name                    old alloc/op   new alloc/op   delta
ScriptFibonacci-8          392kB ± 0%     123kB ± 0%  -68.68%  (p=0.000 n=8+8)
ScriptNestedRefCount-8     535kB ± 0%     266kB ± 0%  -50.38%  (p=0.000 n=6+10)
ScriptPushPop/4-8           352B ± 0%      160B ± 0%  -54.55%  (p=0.000 n=10+10)
ScriptPushPop/16-8        1.41kB ± 0%    0.64kB ± 0%  -54.55%  (p=0.000 n=10+10)
ScriptPushPop/128-8       11.3kB ± 0%     8.7kB ± 0%  -22.73%  (p=0.000 n=10+10)
ScriptPushPop/1024-8      90.1kB ± 0%    73.2kB ± 0%  -18.75%  (p=0.000 n=10+10)

name                    old allocs/op  new allocs/op  delta
ScriptFibonacci-8          9.14k ± 0%     3.53k ± 0%  -61.41%  (p=0.000 n=10+10)
ScriptNestedRefCount-8     17.4k ± 0%     11.8k ± 0%  -32.35%  (p=0.000 n=10+10)
ScriptPushPop/4-8           12.0 ± 0%       8.0 ± 0%  -33.33%  (p=0.000 n=10+10)
ScriptPushPop/16-8          48.0 ± 0%      32.0 ± 0%  -33.33%  (p=0.000 n=10+10)
ScriptPushPop/128-8          384 ± 0%       259 ± 0%  -32.55%  (p=0.000 n=10+10)
ScriptPushPop/1024-8       3.07k ± 0%     2.05k ± 0%  -33.14%  (p=0.000 n=10+10)

Some stack-management opcodes:

name                                 old time/op    new time/op    delta
Opcodes/XDROP/0/1-8                     255ns ± 9%     273ns ±11%    +6.92%  (p=0.016 n=11+10)
Opcodes/XDROP/0/1024-8                  362ns ± 2%     365ns ± 8%      ~     (p=0.849 n=10+11)
Opcodes/XDROP/1024/1024-8              3.20µs ± 2%    1.99µs ±12%   -37.69%  (p=0.000 n=11+11)
Opcodes/XDROP/2047/2048-8              6.55µs ± 3%    1.75µs ± 5%   -73.26%  (p=0.000 n=10+11)
Opcodes/DUP/null-8                      414ns ± 6%     245ns ±12%   -40.88%  (p=0.000 n=11+11)
Opcodes/DUP/boolean-8                   411ns ± 8%     245ns ± 6%   -40.31%  (p=0.000 n=11+11)
Opcodes/DUP/integer/small-8             684ns ± 8%     574ns ± 3%   -16.02%  (p=0.000 n=11+10)
Opcodes/DUP/integer/big-8               675ns ± 6%     601ns ±10%   -10.98%  (p=0.000 n=11+11)
Opcodes/DUP/bytearray/small-8           675ns ±10%     566ns ±10%   -16.22%  (p=0.000 n=11+11)
Opcodes/DUP/bytearray/big-8            6.39µs ±11%    6.13µs ± 3%      ~     (p=0.148 n=10+10)
Opcodes/DUP/buffer/small-8              412ns ± 5%     261ns ± 8%   -36.55%  (p=0.000 n=9+11)
Opcodes/DUP/buffer/big-8                586ns ±10%     337ns ± 7%   -42.53%  (p=0.000 n=11+11)
Opcodes/DUP/struct/small-8              458ns ±12%     256ns ±12%   -44.09%  (p=0.000 n=11+11)
Opcodes/DUP/struct/big-8                489ns ± 7%     274ns ± 5%   -44.06%  (p=0.000 n=10+10)
Opcodes/DUP/pointer-8                   586ns ± 7%     494ns ± 7%   -15.67%  (p=0.000 n=11+11)
Opcodes/OVER/null-8                     450ns ±14%     264ns ±10%   -41.30%  (p=0.000 n=11+11)
Opcodes/OVER/boolean-8                  450ns ±14%     264ns ±10%   -41.31%  (p=0.000 n=11+11)
Opcodes/OVER/integer/small-8            716ns ± 9%     604ns ± 6%   -15.65%  (p=0.000 n=11+11)
Opcodes/OVER/integer/big-8              696ns ± 5%     634ns ± 6%    -8.89%  (p=0.000 n=10+11)
Opcodes/OVER/bytearray/small-8          693ns ± 1%     539ns ± 9%   -22.18%  (p=0.000 n=9+10)
Opcodes/OVER/bytearray/big-8           6.33µs ± 2%    6.16µs ± 4%    -2.79%  (p=0.004 n=8+10)
Opcodes/OVER/buffer/small-8             415ns ± 4%     263ns ± 8%   -36.76%  (p=0.000 n=9+11)
Opcodes/OVER/buffer/big-8               587ns ± 5%     342ns ± 7%   -41.70%  (p=0.000 n=11+11)
Opcodes/OVER/struct/small-8             446ns ±14%     257ns ± 8%   -42.42%  (p=0.000 n=11+11)
Opcodes/OVER/struct/big-8               607ns ±26%     278ns ± 7%   -54.25%  (p=0.000 n=11+11)
Opcodes/OVER/pointer-8                  645ns ±12%     476ns ±10%   -26.21%  (p=0.000 n=11+11)
Opcodes/PICK/2/null-8                   460ns ±11%     264ns ± 9%   -42.68%  (p=0.000 n=11+11)
Opcodes/PICK/2/boolean-8                460ns ± 4%     260ns ± 4%   -43.37%  (p=0.000 n=8+11)
Opcodes/PICK/2/integer/small-8          725ns ± 7%     557ns ± 4%   -23.19%  (p=0.000 n=11+10)
Opcodes/PICK/2/integer/big-8            722ns ±12%     582ns ± 6%   -19.51%  (p=0.000 n=11+11)
Opcodes/PICK/2/bytearray/small-8        705ns ± 6%     545ns ± 4%   -22.69%  (p=0.000 n=11+11)
Opcodes/PICK/2/bytearray/big-8         7.17µs ±36%    6.37µs ± 8%      ~     (p=0.065 n=11+11)
Opcodes/PICK/2/buffer/small-8           427ns ± 8%     253ns ± 8%   -40.82%  (p=0.000 n=11+11)
Opcodes/PICK/2/buffer/big-8             590ns ± 3%     331ns ± 6%   -43.83%  (p=0.000 n=11+11)
Opcodes/PICK/2/struct/small-8           428ns ± 8%     254ns ± 7%   -40.64%  (p=0.000 n=11+11)
Opcodes/PICK/2/struct/big-8             489ns ±15%     283ns ± 7%   -42.11%  (p=0.000 n=11+11)
Opcodes/PICK/2/pointer-8                553ns ± 7%     414ns ± 8%   -25.18%  (p=0.000 n=11+11)
Opcodes/PICK/1024/null-8                531ns ± 4%     327ns ± 6%   -38.49%  (p=0.000 n=10+10)
Opcodes/PICK/1024/boolean-8             527ns ± 5%     318ns ± 5%   -39.78%  (p=0.000 n=11+9)
Opcodes/PICK/1024/integer/small-8       861ns ± 4%     683ns ± 4%   -20.66%  (p=0.000 n=11+11)
Opcodes/PICK/1024/integer/big-8         882ns ± 4%    1060ns ±47%      ~     (p=0.748 n=11+11)
Opcodes/PICK/1024/bytearray/small-8     850ns ± 4%     671ns ± 5%   -21.12%  (p=0.000 n=10+11)
Opcodes/PICK/1024/bytearray/big-8      6.32µs ±26%    6.75µs ± 4%    +6.86%  (p=0.019 n=10+11)
Opcodes/PICK/1024/buffer/small-8        530ns ± 6%     324ns ± 5%   -38.86%  (p=0.000 n=10+11)
Opcodes/PICK/1024/buffer/big-8          570ns ± 4%     417ns ±45%   -26.82%  (p=0.001 n=11+10)
Opcodes/PICK/1024/struct/small-8      1.11µs ±122%    0.34µs ±11%   -69.38%  (p=0.000 n=11+10)
Opcodes/PICK/1024/pointer-8             693ns ± 5%     568ns ±31%   -18.10%  (p=0.002 n=10+10)
Opcodes/TUCK/null-8                     450ns ±10%     275ns ± 8%   -38.93%  (p=0.000 n=11+11)
Opcodes/TUCK/boolean-8                  449ns ±13%     268ns ± 9%   -40.16%  (p=0.000 n=11+10)
Opcodes/TUCK/integer/small-8            716ns ± 7%     599ns ± 7%   -16.30%  (p=0.000 n=11+11)
Opcodes/TUCK/integer/big-8              718ns ± 8%     613ns ±11%   -14.55%  (p=0.000 n=11+11)
Opcodes/TUCK/bytearray/small-8          700ns ±12%     558ns ± 7%   -20.39%  (p=0.000 n=11+11)
Opcodes/TUCK/bytearray/big-8           5.88µs ± 7%    6.37µs ± 3%    +8.31%  (p=0.000 n=10+11)
Opcodes/TUCK/buffer/small-8             425ns ± 6%     258ns ±12%   -39.28%  (p=0.000 n=11+11)
Opcodes/TUCK/buffer/big-8               553ns ±19%     334ns ± 6%   -39.57%  (p=0.000 n=11+11)
Opcodes/TUCK/struct/small-8             474ns ± 3%     263ns ±12%   -44.51%  (p=0.000 n=10+11)
Opcodes/TUCK/struct/big-8               641ns ±24%     284ns ± 8%   -55.63%  (p=0.000 n=11+11)
Opcodes/TUCK/pointer-8                  635ns ±13%     468ns ±16%   -26.31%  (p=0.000 n=11+11)
Opcodes/SWAP/null-8                     227ns ±31%     212ns ±11%      ~     (p=0.847 n=11+11)
Opcodes/SWAP/integer-8                  233ns ±32%     210ns ±14%      ~     (p=0.072 n=10+11)
Opcodes/SWAP/big_bytes-8                263ns ±39%     211ns ±11%      ~     (p=0.056 n=11+11)
Opcodes/ROT/null-8                      308ns ±68%     223ns ±12%      ~     (p=0.519 n=11+11)
Opcodes/ROT/integer-8                   226ns ±25%     228ns ± 9%      ~     (p=0.705 n=10+11)
Opcodes/ROT/big_bytes-8                 215ns ±18%     218ns ± 7%      ~     (p=0.756 n=10+11)
Opcodes/ROLL/4/null-8                   269ns ±10%     295ns ± 9%    +9.42%  (p=0.002 n=10+11)
Opcodes/ROLL/4/integer-8                344ns ±48%     280ns ± 2%      ~     (p=0.882 n=11+9)
Opcodes/ROLL/4/big_bytes-8              276ns ±13%     288ns ± 4%    +4.38%  (p=0.046 n=9+11)
Opcodes/ROLL/1024/null-8               4.21µs ±70%    1.01µs ± 9%   -76.15%  (p=0.000 n=11+11)
Opcodes/ROLL/1024/integer-8            4.78µs ±82%    0.71µs ± 3%   -85.06%  (p=0.000 n=11+11)
Opcodes/ROLL/1024/big_bytes-8          3.28µs ± 5%    1.35µs ±36%   -58.91%  (p=0.000 n=9+11)
Opcodes/REVERSE3/null-8                 219ns ± 9%     224ns ± 9%      ~     (p=0.401 n=11+11)
Opcodes/REVERSE3/integer-8              261ns ±28%     220ns ± 6%   -15.67%  (p=0.015 n=11+11)
Opcodes/REVERSE3/big_bytes-8            245ns ±31%     218ns ± 7%      ~     (p=0.051 n=10+11)
Opcodes/REVERSE4/null-8                 223ns ±10%     218ns ± 6%      ~     (p=0.300 n=11+11)
Opcodes/REVERSE4/integer-8              233ns ±10%     220ns ± 7%    -5.74%  (p=0.016 n=11+11)
Opcodes/REVERSE4/big_bytes-8            225ns ±10%     220ns ± 7%      ~     (p=0.157 n=10+11)
Opcodes/REVERSEN/5/null-8               281ns ±12%     277ns ± 4%      ~     (p=0.847 n=11+11)
Opcodes/REVERSEN/5/integer-8            280ns ±11%     275ns ± 5%      ~     (p=0.243 n=11+11)
Opcodes/REVERSEN/5/big_bytes-8          283ns ± 9%     276ns ± 7%      ~     (p=0.133 n=11+11)
Opcodes/REVERSEN/1024/null-8           4.85µs ± 6%    1.94µs ± 6%   -60.07%  (p=0.000 n=10+11)
Opcodes/REVERSEN/1024/integer-8        4.97µs ± 7%    1.99µs ±22%   -59.88%  (p=0.000 n=11+11)
Opcodes/REVERSEN/1024/big_bytes-8      5.11µs ±10%    2.00µs ± 4%   -60.87%  (p=0.000 n=10+9)
Opcodes/PACK/1-8                       1.22µs ± 7%    0.95µs ± 6%   -22.17%  (p=0.000 n=10+11)
Opcodes/PACK/255-8                     11.1µs ± 4%    10.2µs ± 6%    -7.96%  (p=0.000 n=11+11)
Opcodes/PACK/1024-8                    38.9µs ± 4%    37.4µs ± 9%      ~     (p=0.173 n=10+11)
Opcodes/UNPACK/1-8                     1.32µs ±34%    0.96µs ± 6%   -27.57%  (p=0.000 n=10+11)
Opcodes/UNPACK/255-8                   27.2µs ±14%    16.0µs ±13%   -41.04%  (p=0.000 n=11+11)
Opcodes/UNPACK/1024-8                   102µs ±10%      64µs ±16%   -37.33%  (p=0.000 n=10+11)

name                                 old alloc/op   new alloc/op   delta
Opcodes/XDROP/0/1-8                     0.00B          0.00B           ~     (all equal)
Opcodes/XDROP/0/1024-8                  0.00B          0.00B           ~     (all equal)
Opcodes/XDROP/1024/1024-8               0.00B          0.00B           ~     (all equal)
Opcodes/XDROP/2047/2048-8               0.00B          0.00B           ~     (all equal)
Opcodes/DUP/null-8                      48.0B ± 0%      0.0B       -100.00%  (p=0.000 n=11+11)
Opcodes/DUP/boolean-8                   48.0B ± 0%      0.0B       -100.00%  (p=0.000 n=11+11)
Opcodes/DUP/integer/small-8             96.0B ± 0%     48.0B ± 0%   -50.00%  (p=0.000 n=11+11)
Opcodes/DUP/integer/big-8                104B ± 0%       56B ± 0%   -46.15%  (p=0.000 n=11+11)
Opcodes/DUP/bytearray/small-8           88.0B ± 0%     40.0B ± 0%   -54.55%  (p=0.000 n=11+11)
Opcodes/DUP/bytearray/big-8            65.6kB ± 0%    65.6kB ± 0%    -0.07%  (p=0.000 n=10+9)
Opcodes/DUP/buffer/small-8              48.0B ± 0%      0.0B       -100.00%  (p=0.000 n=11+11)
Opcodes/DUP/buffer/big-8                48.0B ± 0%      0.0B       -100.00%  (p=0.000 n=11+11)
Opcodes/DUP/struct/small-8              48.0B ± 0%      0.0B       -100.00%  (p=0.000 n=11+11)
Opcodes/DUP/struct/big-8                48.0B ± 0%      0.0B       -100.00%  (p=0.000 n=11+11)
Opcodes/DUP/pointer-8                    112B ± 0%       64B ± 0%   -42.86%  (p=0.000 n=11+11)
Opcodes/OVER/null-8                     48.0B ± 0%      0.0B       -100.00%  (p=0.000 n=11+11)
Opcodes/OVER/boolean-8                  48.0B ± 0%      0.0B       -100.00%  (p=0.000 n=11+11)
Opcodes/OVER/integer/small-8            96.0B ± 0%     48.0B ± 0%   -50.00%  (p=0.000 n=11+11)
Opcodes/OVER/integer/big-8               104B ± 0%       56B ± 0%   -46.15%  (p=0.000 n=11+11)
Opcodes/OVER/bytearray/small-8          88.0B ± 0%     40.0B ± 0%   -54.55%  (p=0.000 n=11+11)
Opcodes/OVER/bytearray/big-8           65.6kB ± 0%    65.6kB ± 0%    -0.07%  (p=0.000 n=9+11)
Opcodes/OVER/buffer/small-8             48.0B ± 0%      0.0B       -100.00%  (p=0.000 n=11+11)
Opcodes/OVER/buffer/big-8               48.0B ± 0%      0.0B       -100.00%  (p=0.000 n=11+11)
Opcodes/OVER/struct/small-8             48.0B ± 0%      0.0B       -100.00%  (p=0.000 n=11+11)
Opcodes/OVER/struct/big-8               48.0B ± 0%      0.0B       -100.00%  (p=0.000 n=11+11)
Opcodes/OVER/pointer-8                   112B ± 0%       64B ± 0%   -42.86%  (p=0.000 n=11+11)
Opcodes/PICK/2/null-8                   48.0B ± 0%      0.0B       -100.00%  (p=0.000 n=11+11)
Opcodes/PICK/2/boolean-8                48.0B ± 0%      0.0B       -100.00%  (p=0.000 n=11+11)
Opcodes/PICK/2/integer/small-8          96.0B ± 0%     48.0B ± 0%   -50.00%  (p=0.000 n=11+11)
Opcodes/PICK/2/integer/big-8             104B ± 0%       56B ± 0%   -46.15%  (p=0.000 n=11+11)
Opcodes/PICK/2/bytearray/small-8        88.0B ± 0%     40.0B ± 0%   -54.55%  (p=0.000 n=11+11)
Opcodes/PICK/2/bytearray/big-8         65.6kB ± 0%    65.6kB ± 0%    -0.07%  (p=0.001 n=9+11)
Opcodes/PICK/2/buffer/small-8           48.0B ± 0%      0.0B       -100.00%  (p=0.000 n=11+11)
Opcodes/PICK/2/buffer/big-8             48.0B ± 0%      0.0B       -100.00%  (p=0.000 n=11+11)
Opcodes/PICK/2/struct/small-8           48.0B ± 0%      0.0B       -100.00%  (p=0.000 n=11+11)
Opcodes/PICK/2/struct/big-8             48.0B ± 0%      0.0B       -100.00%  (p=0.000 n=11+11)
Opcodes/PICK/2/pointer-8                 112B ± 0%       64B ± 0%   -42.86%  (p=0.000 n=11+11)
Opcodes/PICK/1024/null-8                48.0B ± 0%      0.0B       -100.00%  (p=0.000 n=11+11)
Opcodes/PICK/1024/boolean-8             48.0B ± 0%      0.0B       -100.00%  (p=0.000 n=11+11)
Opcodes/PICK/1024/integer/small-8       96.0B ± 0%     48.0B ± 0%   -50.00%  (p=0.000 n=11+11)
Opcodes/PICK/1024/integer/big-8          104B ± 0%       56B ± 0%   -46.15%  (p=0.000 n=11+11)
Opcodes/PICK/1024/bytearray/small-8     88.0B ± 0%     40.0B ± 0%   -54.55%  (p=0.000 n=11+11)
Opcodes/PICK/1024/bytearray/big-8      65.6kB ± 0%    65.6kB ± 0%    -0.07%  (p=0.000 n=11+11)
Opcodes/PICK/1024/buffer/small-8        48.0B ± 0%      0.0B       -100.00%  (p=0.000 n=11+11)
Opcodes/PICK/1024/buffer/big-8          48.0B ± 0%      0.0B       -100.00%  (p=0.000 n=11+11)
Opcodes/PICK/1024/struct/small-8        48.0B ± 0%      0.0B       -100.00%  (p=0.000 n=11+11)
Opcodes/PICK/1024/pointer-8              112B ± 0%       64B ± 0%   -42.86%  (p=0.000 n=11+11)
Opcodes/TUCK/null-8                     48.0B ± 0%      0.0B       -100.00%  (p=0.000 n=11+11)
Opcodes/TUCK/boolean-8                  48.0B ± 0%      0.0B       -100.00%  (p=0.000 n=11+11)
Opcodes/TUCK/integer/small-8            96.0B ± 0%     48.0B ± 0%   -50.00%  (p=0.000 n=11+11)
Opcodes/TUCK/integer/big-8               104B ± 0%       56B ± 0%   -46.15%  (p=0.000 n=11+11)
Opcodes/TUCK/bytearray/small-8          88.0B ± 0%     40.0B ± 0%   -54.55%  (p=0.000 n=11+11)
Opcodes/TUCK/bytearray/big-8           65.6kB ± 0%    65.6kB ± 0%    -0.07%  (p=0.000 n=10+11)
Opcodes/TUCK/buffer/small-8             48.0B ± 0%      0.0B       -100.00%  (p=0.000 n=11+11)
Opcodes/TUCK/buffer/big-8               48.0B ± 0%      0.0B       -100.00%  (p=0.000 n=11+11)
Opcodes/TUCK/struct/small-8             48.0B ± 0%      0.0B       -100.00%  (p=0.000 n=11+11)
Opcodes/TUCK/struct/big-8               48.0B ± 0%      0.0B       -100.00%  (p=0.000 n=11+11)
Opcodes/TUCK/pointer-8                   112B ± 0%       64B ± 0%   -42.86%  (p=0.000 n=11+11)
Opcodes/SWAP/null-8                     0.00B          0.00B           ~     (all equal)
Opcodes/SWAP/integer-8                  0.00B          0.00B           ~     (all equal)
Opcodes/SWAP/big_bytes-8                0.00B          0.00B           ~     (all equal)
Opcodes/ROT/null-8                      0.00B          0.00B           ~     (all equal)
Opcodes/ROT/integer-8                   0.00B          0.00B           ~     (all equal)
Opcodes/ROT/big_bytes-8                 0.00B          0.00B           ~     (all equal)
Opcodes/ROLL/4/null-8                   0.00B          0.00B           ~     (all equal)
Opcodes/ROLL/4/integer-8                0.00B          0.00B           ~     (all equal)
Opcodes/ROLL/4/big_bytes-8              0.00B          0.00B           ~     (all equal)
Opcodes/ROLL/1024/null-8                0.00B          0.00B           ~     (all equal)
Opcodes/ROLL/1024/integer-8             0.00B          0.00B           ~     (all equal)
Opcodes/ROLL/1024/big_bytes-8           0.00B          0.00B           ~     (all equal)
Opcodes/REVERSE3/null-8                 0.00B          0.00B           ~     (all equal)
Opcodes/REVERSE3/integer-8              0.00B          0.00B           ~     (all equal)
Opcodes/REVERSE3/big_bytes-8            0.00B          0.00B           ~     (all equal)
Opcodes/REVERSE4/null-8                 0.00B          0.00B           ~     (all equal)
Opcodes/REVERSE4/integer-8              0.00B          0.00B           ~     (all equal)
Opcodes/REVERSE4/big_bytes-8            0.00B          0.00B           ~     (all equal)
Opcodes/REVERSEN/5/null-8               0.00B          0.00B           ~     (all equal)
Opcodes/REVERSEN/5/integer-8            0.00B          0.00B           ~     (all equal)
Opcodes/REVERSEN/5/big_bytes-8          0.00B          0.00B           ~     (all equal)
Opcodes/REVERSEN/1024/null-8            0.00B          0.00B           ~     (all equal)
Opcodes/REVERSEN/1024/integer-8         0.00B          0.00B           ~     (all equal)
Opcodes/REVERSEN/1024/big_bytes-8       0.00B          0.00B           ~     (all equal)
Opcodes/PACK/1-8                         144B ± 0%       96B ± 0%   -33.33%  (p=0.000 n=11+11)
Opcodes/PACK/255-8                     4.22kB ± 0%    4.18kB ± 0%    -1.14%  (p=0.000 n=11+11)
Opcodes/PACK/1024-8                    16.5kB ± 0%    16.5kB ± 0%    -0.29%  (p=0.000 n=11+11)
Opcodes/UNPACK/1-8                       168B ± 0%       72B ± 0%   -57.14%  (p=0.000 n=11+11)
Opcodes/UNPACK/255-8                   12.4kB ± 0%     7.8kB ± 0%   -37.28%  (p=0.000 n=11+11)
Opcodes/UNPACK/1024-8                  49.3kB ± 0%    52.8kB ± 0%    +7.18%  (p=0.000 n=11+11)

name                                 old allocs/op  new allocs/op  delta
Opcodes/XDROP/0/1-8                      0.00           0.00           ~     (all equal)
Opcodes/XDROP/0/1024-8                   0.00           0.00           ~     (all equal)
Opcodes/XDROP/1024/1024-8                0.00           0.00           ~     (all equal)
Opcodes/XDROP/2047/2048-8                0.00           0.00           ~     (all equal)
Opcodes/DUP/null-8                       1.00 ± 0%      0.00       -100.00%  (p=0.000 n=11+11)
Opcodes/DUP/boolean-8                    1.00 ± 0%      0.00       -100.00%  (p=0.000 n=11+11)
Opcodes/DUP/integer/small-8              3.00 ± 0%      2.00 ± 0%   -33.33%  (p=0.000 n=11+11)
Opcodes/DUP/integer/big-8                3.00 ± 0%      2.00 ± 0%   -33.33%  (p=0.000 n=11+11)
Opcodes/DUP/bytearray/small-8            3.00 ± 0%      2.00 ± 0%   -33.33%  (p=0.000 n=11+11)
Opcodes/DUP/bytearray/big-8              3.00 ± 0%      2.00 ± 0%   -33.33%  (p=0.000 n=11+11)
Opcodes/DUP/buffer/small-8               1.00 ± 0%      0.00       -100.00%  (p=0.000 n=11+11)
Opcodes/DUP/buffer/big-8                 1.00 ± 0%      0.00       -100.00%  (p=0.000 n=11+11)
Opcodes/DUP/struct/small-8               1.00 ± 0%      0.00       -100.00%  (p=0.000 n=11+11)
Opcodes/DUP/struct/big-8                 1.00 ± 0%      0.00       -100.00%  (p=0.000 n=11+11)
Opcodes/DUP/pointer-8                    2.00 ± 0%      1.00 ± 0%   -50.00%  (p=0.000 n=11+11)
Opcodes/OVER/null-8                      1.00 ± 0%      0.00       -100.00%  (p=0.000 n=11+11)
Opcodes/OVER/boolean-8                   1.00 ± 0%      0.00       -100.00%  (p=0.000 n=11+11)
Opcodes/OVER/integer/small-8             3.00 ± 0%      2.00 ± 0%   -33.33%  (p=0.000 n=11+11)
Opcodes/OVER/integer/big-8               3.00 ± 0%      2.00 ± 0%   -33.33%  (p=0.000 n=11+11)
Opcodes/OVER/bytearray/small-8           3.00 ± 0%      2.00 ± 0%   -33.33%  (p=0.000 n=11+11)
Opcodes/OVER/bytearray/big-8             3.00 ± 0%      2.00 ± 0%   -33.33%  (p=0.000 n=11+11)
Opcodes/OVER/buffer/small-8              1.00 ± 0%      0.00       -100.00%  (p=0.000 n=11+11)
Opcodes/OVER/buffer/big-8                1.00 ± 0%      0.00       -100.00%  (p=0.000 n=11+11)
Opcodes/OVER/struct/small-8              1.00 ± 0%      0.00       -100.00%  (p=0.000 n=11+11)
Opcodes/OVER/struct/big-8                1.00 ± 0%      0.00       -100.00%  (p=0.000 n=11+11)
Opcodes/OVER/pointer-8                   2.00 ± 0%      1.00 ± 0%   -50.00%  (p=0.000 n=11+11)
Opcodes/PICK/2/null-8                    1.00 ± 0%      0.00       -100.00%  (p=0.000 n=11+11)
Opcodes/PICK/2/boolean-8                 1.00 ± 0%      0.00       -100.00%  (p=0.000 n=11+11)
Opcodes/PICK/2/integer/small-8           3.00 ± 0%      2.00 ± 0%   -33.33%  (p=0.000 n=11+11)
Opcodes/PICK/2/integer/big-8             3.00 ± 0%      2.00 ± 0%   -33.33%  (p=0.000 n=11+11)
Opcodes/PICK/2/bytearray/small-8         3.00 ± 0%      2.00 ± 0%   -33.33%  (p=0.000 n=11+11)
Opcodes/PICK/2/bytearray/big-8           3.00 ± 0%      2.00 ± 0%   -33.33%  (p=0.000 n=11+11)
Opcodes/PICK/2/buffer/small-8            1.00 ± 0%      0.00       -100.00%  (p=0.000 n=11+11)
Opcodes/PICK/2/buffer/big-8              1.00 ± 0%      0.00       -100.00%  (p=0.000 n=11+11)
Opcodes/PICK/2/struct/small-8            1.00 ± 0%      0.00       -100.00%  (p=0.000 n=11+11)
Opcodes/PICK/2/struct/big-8              1.00 ± 0%      0.00       -100.00%  (p=0.000 n=11+11)
Opcodes/PICK/2/pointer-8                 2.00 ± 0%      1.00 ± 0%   -50.00%  (p=0.000 n=11+11)
Opcodes/PICK/1024/null-8                 1.00 ± 0%      0.00       -100.00%  (p=0.000 n=11+11)
Opcodes/PICK/1024/boolean-8              1.00 ± 0%      0.00       -100.00%  (p=0.000 n=11+11)
Opcodes/PICK/1024/integer/small-8        3.00 ± 0%      2.00 ± 0%   -33.33%  (p=0.000 n=11+11)
Opcodes/PICK/1024/integer/big-8          3.00 ± 0%      2.00 ± 0%   -33.33%  (p=0.000 n=11+11)
Opcodes/PICK/1024/bytearray/small-8      3.00 ± 0%      2.00 ± 0%   -33.33%  (p=0.000 n=11+11)
Opcodes/PICK/1024/bytearray/big-8        3.00 ± 0%      2.00 ± 0%   -33.33%  (p=0.000 n=11+11)
Opcodes/PICK/1024/buffer/small-8         1.00 ± 0%      0.00       -100.00%  (p=0.000 n=11+11)
Opcodes/PICK/1024/buffer/big-8           1.00 ± 0%      0.00       -100.00%  (p=0.000 n=11+11)
Opcodes/PICK/1024/struct/small-8         1.00 ± 0%      0.00       -100.00%  (p=0.000 n=11+11)
Opcodes/PICK/1024/pointer-8              2.00 ± 0%      1.00 ± 0%   -50.00%  (p=0.000 n=11+11)
Opcodes/TUCK/null-8                      1.00 ± 0%      0.00       -100.00%  (p=0.000 n=11+11)
Opcodes/TUCK/boolean-8                   1.00 ± 0%      0.00       -100.00%  (p=0.000 n=11+11)
Opcodes/TUCK/integer/small-8             3.00 ± 0%      2.00 ± 0%   -33.33%  (p=0.000 n=11+11)
Opcodes/TUCK/integer/big-8               3.00 ± 0%      2.00 ± 0%   -33.33%  (p=0.000 n=11+11)
Opcodes/TUCK/bytearray/small-8           3.00 ± 0%      2.00 ± 0%   -33.33%  (p=0.000 n=11+11)
Opcodes/TUCK/bytearray/big-8             3.00 ± 0%      2.00 ± 0%   -33.33%  (p=0.000 n=11+11)
Opcodes/TUCK/buffer/small-8              1.00 ± 0%      0.00       -100.00%  (p=0.000 n=11+11)
Opcodes/TUCK/buffer/big-8                1.00 ± 0%      0.00       -100.00%  (p=0.000 n=11+11)
Opcodes/TUCK/struct/small-8              1.00 ± 0%      0.00       -100.00%  (p=0.000 n=11+11)
Opcodes/TUCK/struct/big-8                1.00 ± 0%      0.00       -100.00%  (p=0.000 n=11+11)
Opcodes/TUCK/pointer-8                   2.00 ± 0%      1.00 ± 0%   -50.00%  (p=0.000 n=11+11)
Opcodes/SWAP/null-8                      0.00           0.00           ~     (all equal)
Opcodes/SWAP/integer-8                   0.00           0.00           ~     (all equal)
Opcodes/SWAP/big_bytes-8                 0.00           0.00           ~     (all equal)
Opcodes/ROT/null-8                       0.00           0.00           ~     (all equal)
Opcodes/ROT/integer-8                    0.00           0.00           ~     (all equal)
Opcodes/ROT/big_bytes-8                  0.00           0.00           ~     (all equal)
Opcodes/ROLL/4/null-8                    0.00           0.00           ~     (all equal)
Opcodes/ROLL/4/integer-8                 0.00           0.00           ~     (all equal)
Opcodes/ROLL/4/big_bytes-8               0.00           0.00           ~     (all equal)
Opcodes/ROLL/1024/null-8                 0.00           0.00           ~     (all equal)
Opcodes/ROLL/1024/integer-8              0.00           0.00           ~     (all equal)
Opcodes/ROLL/1024/big_bytes-8            0.00           0.00           ~     (all equal)
Opcodes/REVERSE3/null-8                  0.00           0.00           ~     (all equal)
Opcodes/REVERSE3/integer-8               0.00           0.00           ~     (all equal)
Opcodes/REVERSE3/big_bytes-8             0.00           0.00           ~     (all equal)
Opcodes/REVERSE4/null-8                  0.00           0.00           ~     (all equal)
Opcodes/REVERSE4/integer-8               0.00           0.00           ~     (all equal)
Opcodes/REVERSE4/big_bytes-8             0.00           0.00           ~     (all equal)
Opcodes/REVERSEN/5/null-8                0.00           0.00           ~     (all equal)
Opcodes/REVERSEN/5/integer-8             0.00           0.00           ~     (all equal)
Opcodes/REVERSEN/5/big_bytes-8           0.00           0.00           ~     (all equal)
Opcodes/REVERSEN/1024/null-8             0.00           0.00           ~     (all equal)
Opcodes/REVERSEN/1024/integer-8          0.00           0.00           ~     (all equal)
Opcodes/REVERSEN/1024/big_bytes-8        0.00           0.00           ~     (all equal)
Opcodes/PACK/1-8                         5.00 ± 0%      4.00 ± 0%   -20.00%  (p=0.000 n=11+11)
Opcodes/PACK/255-8                       5.00 ± 0%      4.00 ± 0%   -20.00%  (p=0.000 n=11+11)
Opcodes/PACK/1024-8                      5.00 ± 0%      4.00 ± 0%   -20.00%  (p=0.000 n=11+11)
Opcodes/UNPACK/1-8                       5.00 ± 0%      3.00 ± 0%   -40.00%  (p=0.000 n=11+11)
Opcodes/UNPACK/255-8                      259 ± 0%         7 ± 0%   -97.30%  (p=0.000 n=11+11)
Opcodes/UNPACK/1024-8                   1.03k ± 0%     0.01k ± 0%   -98.93%  (p=0.000 n=11+11)
2021-08-24 15:28:14 +03:00
Roman Khimov
ed35cf8f12 vm: store exception stack in the context
Avoid allocating it.
2021-08-23 18:29:27 +03:00
Evgeniy Stratonikov
f5d1277bfd vm: do not copy parameter
Signed-off-by: Evgeniy Stratonikov <evgeniy@nspcc.ru>
2021-08-13 11:52:38 +03:00
Roman Khimov
b892db9976 vm: add instruction correctness check
See neo-project/neo-vm#392.
2021-02-09 22:31:26 +03:00
Evgeniy Stratonikov
49de8161ef core: implement LoadToken handler 2021-01-22 09:04:37 +03:00
Evgenii Stratonikov
bb706aa55b vm: implement CALLT opcode 2021-01-21 19:30:04 +03:00
Evgenii Stratonikov
1c0c331e25 core: update System.Contract.Call syscall
1. Remove `System.Contract.CallEx`.
2. Extend number of parameters.
3. Add return value count to `VM.Context`.
2021-01-14 18:23:36 +03:00
Evgenii Stratonikov
dbe81f9b80 smartcontract: move flags to a separate package 2021-01-14 17:52:09 +03:00
Evgenii Stratonikov
e903e40085 core: call from native contracts synchronously
Follow neo-project/neo#2130.
2020-12-10 16:43:46 +03:00
Evgenii Stratonikov
d7ffa89811 vmcli: set breakpoint before the instruction
Breakpoint should occur before actual instruction execution.
2020-12-02 10:49:37 +03:00
Roman Khimov
d93aa745bb contract: avoid going to the DB for entry scripts
This optimizes out DB access for non-deployed contracts under the assumption
that deployed ones are always loaded via `LoadScriptWithHash` (and if they're
not --- it's a bug anyway with the new hashing model) which actually is a very
popular case (every entry script does that).
2020-11-27 21:47:08 +03:00
Anna Shaleva
0f68528095 core: add callback to VM context 2020-11-25 18:37:29 +03:00
Evgenii Stratonikov
42ae226f9e native: use proper stack for result
When native method calls other contract result should be put
on the stack of current context. With oracles this problem wasn't
noticed because of void return type.
2020-11-24 12:17:28 +03:00
Anna Shaleva
fe1f0a7245 core: introduce CheckReturnState constants
At the moment we should have 3 possible options to check return state
during vm context unloading:
	* no check
	* ensure the stack is empty
	* ensure the stack is not empty

It is necessary to distinguish them because new _deploy method shouldn't
left anything on stack. Example: if we use _deploy method before some
ordinary contract method which returns one value. Without these changes
the contract invocation will fail due to 2 elements on stack left after
invocation (the first `null` element is from _deploy, the second element
is return-value from the ordinary contract method).
2020-10-13 19:14:44 +03:00
Roman Khimov
a7670303e8 stackitem: change Bool() to TryBool(), prepare for its failures 2020-08-21 20:55:20 +03:00
Evgenii Stratonikov
681e81420a vm: make (*Context).IP() return instruction pointer
It is misleading to return +1 in code, and user representation
can always be altered.
2020-08-21 08:44:32 +03:00
Evgenii Stratonikov
a080d24cf5 vm: fix debugger and add tests
1. `Run()` must be able to continue execution after a breakpoint.
2. VM must stop right before the breakpoint, not after.
3. Initial vm state is NONE, not HALT.
2020-08-18 11:26:27 +03:00
Evgenii Stratonikov
bf01599430 vm: check return value on context unload
When calling external contracts we expect exactly 1 value to be on
stack. For methods returning nothing, `Null` value is pushed, otherwise
it is an error.`
2020-08-10 11:52:33 +03:00
Evgenii Stratonikov
797324cb04 vm: support exceptions
Implement 3 new instructions: TRY,ENDTRY,ENDFINALLY.
1. TRY marks the start of the block where exceptions are catched.
    It has 2 arguments which are relative offsets of exception handler
    and the end of the whole try/catch construction.
2. ENDTRY denotes either end of try or catch block.
3. ENDFINALLY denotes end of finally block which is executed
    irregardless of whether an exception has occured.
2020-07-24 10:41:41 +03:00
Evgenii Stratonikov
58a594e3d4 vm: remove rvcount
It isn't used anymore.
2020-07-23 10:29:05 +03:00
Evgenii Stratonikov
261ff3c655 vm: remove alt.stack
It is no longer present in NEO3.
2020-07-22 13:20:31 +03:00
Roman Khimov
1bb26dcdc1 vm: fix INITSSLOT, it's context-wide, not VM-wide
It's tied to the current contract, not to VM.
2020-07-09 15:00:49 +03:00
Roman Khimov
a77357227a vm: fix caller's script hash returned from VM
Regular CALLs don't update it, only Contract.Call does. Fixes the following
mismatch on preview2 testnet:

file BlockStorage_100000/dump-block-49000.json: block 48644, changes number mismatch: 6 vs 4
2020-06-24 10:22:21 +03:00
Evgenii Stratonikov
f2f01a08c9 vm: move MaxArraySize and MaxItemSize to stackitem package 2020-06-16 11:32:16 +03:00
Evgenii Stratonikov
0dd00a49f5 core: specify require call flags in interop description
Related #1026, #1027, #1028, #1031.
2020-06-11 13:16:07 +03:00
Evgenii Stratonikov
bda94c74c3 vm: check calling flags on syscall invocation 2020-06-11 13:16:07 +03:00
Evgenii Stratonikov
5514b3f52f smartcontract,vm: remove DynamicInvoke feature
It doesn't exist in NEO3.
2020-06-11 10:45:25 +03:00
Anna Shaleva
783f5ecb01 vm: move StackItem to a separate package
closes #912
2020-06-08 13:27:08 +03:00
Roman Khimov
35b30ccfdf core: drop OLDPUSH1, it's no longer needed
Fixes #927.
2020-06-05 19:20:16 +03:00
Evgenii Stratonikov
0cb6dc47e4 vm: implement slot-related opcodes
1. Slot is a new mechanism for storing variables during execution
which is more convenient than alt.stack. This commit implements
support for slot opcodes in both vm and compiler.
2. Remove old alt.stack opcodes.
3. Do not process globals at the start of every function, but instead
load them single time at main.
2020-05-12 16:23:08 +03:00
Evgenii Stratonikov
1d3fb3d6f5 vm: implement PUSHA/CALLA opcodes 2020-05-12 12:56:51 +03:00
Evgenii Stratonikov
73c82584a3 vm,compiler: replace APPCALL with System.Contract.Call
Contract calls are performed via syscall System.Contract.Call
in NEO3. This implements this in compiler and removes APPCALL from the
VM.
2020-05-07 14:52:03 +03:00
Evgenii Stratonikov
115919aaf7 vm: process OLDPUSH1 at the context level
The only usecase for this opcode is single-byte verification scripts.
2020-05-06 13:00:00 +03:00
Anna Shaleva
5ece9922c1 vm: hide GetContextScriptHash() method
After adding ScriptHashGetter interface to vm, there's no need in
GetContextScriptHash() to be exported.
2020-05-04 11:53:31 +03:00
Anna Shaleva
9ecac14aee vm: fix bug in GetContextScriptHash()
v.Istack.Peek(n) can return nil pointer, so .Value() on this pointer
leads to panic here. Fixed by adding nil check.
2020-05-04 11:49:14 +03:00
Evgenii Stratonikov
7e98a2ffa0 vm: implements CONVERT opcode 2020-04-28 16:38:52 +03:00
Evgenii Stratonikov
be38798785 vm: move Bool method to the StackItem interface 2020-04-28 15:13:41 +03:00
Evgenii Stratonikov
7c3d7c0261 vm: implement NEWARRAYT opcode 2020-04-27 09:06:48 +03:00
Evgenii Stratonikov
d3b9aef8e2 vm: implement ISTYPE opcode
Also make StackItemType public and reorder it according to NEO3.
2020-04-27 09:01:26 +03:00
Evgenii Stratonikov
d6624a92ca vm: implement new JMP* and CALL* opcodes
In compiler JMP*_L opcodes are always used, as this requires less effort.
2020-04-24 10:16:41 +03:00
Evgenii Stratonikov
fba185cd99 vm: remove stack isolation opcodes
They are not present in NEO3 and will be creating additional difficulties
during future flow-control opcodes implementation.
2020-04-24 10:15:14 +03:00
Evgenii Stratonikov
008e6eb233 vm: implement new PUSH opcodes 2020-04-23 10:52:28 +03:00
Evgenii Stratonikov
ceff8736f2 vm: use ID-based syscalls
In NEO3 SYSCALL opcode has 4-byte ID parameter.
This commit removes support for string-based syscalls and
changes SYSCALL's parameter to be fixed 4-byte value.
2020-04-17 11:46:31 +03:00
Evgenii Stratonikov
b446753c57 core,vm: move get/putContextScriptHash to vm package 2020-04-16 15:54:52 +03:00
Evgenii Stratonikov
be407332b9 vm: add TryInteger() to StackItem interface
Conversion should be done in a StackItem, not in an Element.
2020-04-16 14:05:32 +03:00
Roman Khimov
1b5dd53e07
Merge pull request #746 from nspcc-dev/fix/equal
vm: implement EQUAL opcode properly

Fixes #745, #749.
2020-03-12 11:46:51 +03:00
Evgenii Stratonikov
dfc59129c7 vm: implement EQUAL opcode properly
When comparing elements of different types, conversions
should be performed. This commit implement custom equality
predicate for each stack item type.
2020-03-11 17:19:10 +03:00
Evgenii Stratonikov
5da82e8cf0 vm: add TryBytes() to StackItem interface
Conversion should be done in a StackItem, not in an Element.
2020-03-11 16:33:46 +03:00
Roman Khimov
8318adac56 vm: add support for dynamic invocations in APPCALL
Fixes #740.
2020-03-10 17:17:36 +03:00
Roman Khimov
e41d434a49 *: move all packages from CityOfZion to nspcc-dev 2020-03-03 17:21:42 +03:00