Add pushtoarraykwsplat instruction to avoid unnecessary array allocation

This is designed to replace the newarraykwsplat instruction, which is
no longer used in the parse.y compiler after this commit.  This avoids
an unnecessary array allocation in the case where ARGSCAT is followed
by LIST with keyword:

```ruby
a = []
kw = {}
[*a, 1, **kw]
```

Previous Instructions:

```
0000 newarray                               0                         (   1)[Li]
0002 setlocal_WC_0                          a@0
0004 newhash                                0                         (   2)[Li]
0006 setlocal_WC_0                          kw@1
0008 getlocal_WC_0                          a@0                       (   3)[Li]
0010 splatarray                             true
0012 putobject_INT2FIX_1_
0013 putspecialobject                       1
0015 newhash                                0
0017 getlocal_WC_0                          kw@1
0019 opt_send_without_block                 <calldata!mid:core#hash_merge_kwd, argc:2, ARGS_SIMPLE>
0021 newarraykwsplat                        2
0023 concattoarray
0024 leave
```

New Instructions:

```
0000 newarray                               0                         (   1)[Li]
0002 setlocal_WC_0                          a@0
0004 newhash                                0                         (   2)[Li]
0006 setlocal_WC_0                          kw@1
0008 getlocal_WC_0                          a@0                       (   3)[Li]
0010 splatarray                             true
0012 putobject_INT2FIX_1_
0013 pushtoarray                            1
0015 putspecialobject                       1
0017 newhash                                0
0019 getlocal_WC_0                          kw@1
0021 opt_send_without_block                 <calldata!mid:core#hash_merge_kwd, argc:2, ARGS_SIMPLE>
0023 pushtoarraykwsplat
0024 leave
```

pushtoarraykwsplat is designed to be simpler than newarraykwsplat.
It does not take a variable number of arguments from the stack, it
pops the top of the stack, and appends it to the second from the top,
unless the top of the stack is an empty hash.

During this work, I found the ARGSPUSH followed by HASH with keyword
did not compile correctly, as it pushed the generated hash to the
array even if the hash was empty.  This fixes the behavior, to use
pushtoarraykwsplat instead of pushtoarray in that case:

```ruby
a = []
kw = {}
[*a, **kw]

[{}] # Before

[] # After
```

This does not remove the newarraykwsplat instruction, as it is still
referenced in the prism compiler (which should be updated similar
to this), YJIT (only in the bindings, it does not appear to be
implemented), and RJIT (in a couple comments).  After those are
updated, the newarraykwsplat instruction should be removed.
This commit is contained in:
Jeremy Evans 2024-01-30 10:31:27 -08:00
parent 2e2e3d89af
commit 77c1233f79
5 changed files with 236 additions and 193 deletions

View File

@ -92,7 +92,7 @@ tests = [
[ 'intern', %q{ :"#{true}" }, ],
[ 'newarray', %q{ ["true"][0] }, ],
[ 'newarraykwsplat', %q{ [**{x:'true'}][0][:x] }, ],
[ 'pushtoarraykwsplat', %q{ [**{x:'true'}][0][:x] }, ],
[ 'duparray', %q{ [ true ][0] }, ],
[ 'expandarray', %q{ y = [ true, false, nil ]; x, = y; x }, ],
[ 'expandarray', %q{ y = [ true, false, nil ]; x, *z = y; x }, ],

View File

@ -4813,12 +4813,12 @@ compile_array(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *node, int pop
* putobject [1,2,3,...,100] (<- hidden array); concattoarray;
* push z; pushtoarray 1;
*
* - If the last element is a keyword, newarraykwsplat should be emitted
* to check and remove empty keyword arguments hash from array.
* - If the last element is a keyword, pushtoarraykwsplat should be emitted
* to only push it onto the array if it is not empty
* (Note: a keyword is NODE_HASH which is not static_literal_node_p.)
*
* [1,2,3,**kw] =>
* putobject 1; putobject 2; putobject 3; push kw; newarraykwsplat
* putobject 1; putobject 2; putobject 3; newarray 3; ...; pushtoarraykwsplat kw
*/
const int max_stack_len = 0x100;
@ -4873,15 +4873,22 @@ compile_array(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *node, int pop
EXPECT_NODE("compile_array", node, NODE_LIST, -1);
}
NO_CHECK(COMPILE_(ret, "array element", RNODE_LIST(node)->nd_head, 0));
stack_len++;
if (!RNODE_LIST(node)->nd_next && keyword_node_p(RNODE_LIST(node)->nd_head)) {
/* Reached the end, and the last element is a keyword */
ADD_INSN1(ret, line_node, newarraykwsplat, INT2FIX(stack_len));
if (!first_chunk) ADD_INSN(ret, line_node, concattoarray);
/* Create array or push existing non-keyword elements onto array */
if (stack_len == 0 && first_chunk) {
ADD_INSN1(ret, line_node, newarray, INT2FIX(0));
}
else {
FLUSH_CHUNK;
}
NO_CHECK(COMPILE_(ret, "array element", RNODE_LIST(node)->nd_head, 0));
ADD_INSN(ret, line_node, pushtoarraykwsplat);
return 1;
}
else {
NO_CHECK(COMPILE_(ret, "array element", RNODE_LIST(node)->nd_head, 0));
stack_len++;
}
/* If there are many pushed elements, flush them to avoid stack overflow */
if (stack_len >= max_stack_len) FLUSH_CHUNK;
@ -10426,13 +10433,18 @@ iseq_compile_each0(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *const no
else {
CHECK(COMPILE(ret, "argspush head", RNODE_ARGSPUSH(node)->nd_head));
const NODE *body_node = RNODE_ARGSPUSH(node)->nd_body;
if (static_literal_node_p(body_node, iseq, false)) {
if (keyword_node_p(body_node)) {
CHECK(COMPILE_(ret, "array element", body_node, FALSE));
ADD_INSN(ret, node, pushtoarraykwsplat);
}
else if (static_literal_node_p(body_node, iseq, false)) {
ADD_INSN1(ret, body_node, putobject, static_literal_value(body_node, iseq));
ADD_INSN1(ret, node, pushtoarray, INT2FIX(1));
}
else {
CHECK(COMPILE_(ret, "array element", body_node, FALSE));
ADD_INSN1(ret, node, pushtoarray, INT2FIX(1));
}
ADD_INSN1(ret, node, pushtoarray, INT2FIX(1));
}
break;
}

View File

@ -462,6 +462,20 @@ newarraykwsplat
}
}
/* push hash onto array unless the hash is empty (as empty keyword
splats should be ignored).
*/
DEFINE_INSN
pushtoarraykwsplat
()
(VALUE ary, VALUE hash)
(VALUE ary)
{
if (!RHASH_EMPTY_P(hash)) {
rb_ary_push(ary, hash);
}
}
/* dup array */
DEFINE_INSN
duparray

View File

@ -233,6 +233,7 @@ class TestSyntax < Test::Unit::TestCase
def test_array_kwsplat_hash
kw = {}
h = {a: 1}
a = []
assert_equal([], [**{}])
assert_equal([], [**kw])
assert_equal([h], [**h])
@ -247,6 +248,20 @@ class TestSyntax < Test::Unit::TestCase
assert_equal([1, kw], [1, kw])
assert_equal([1, h], [1, h])
assert_equal([], [*a, **{}])
assert_equal([], [*a, **kw])
assert_equal([h], [*a, **h])
assert_equal([{}], [*a, {}])
assert_equal([kw], [*a, kw])
assert_equal([h], [*a, h])
assert_equal([1], [1, *a, **{}])
assert_equal([1], [1, *a, **kw])
assert_equal([1, h], [1, *a, **h])
assert_equal([1, {}], [1, *a, {}])
assert_equal([1, kw], [1, *a, kw])
assert_equal([1, h], [1, *a, h])
assert_equal([], [**kw, **kw])
assert_equal([], [**kw, **{}, **kw])
assert_equal([1], [1, **kw, **{}, **kw])

View File

@ -731,187 +731,189 @@ pub const YARVINSN_toregexp: ruby_vminsn_type = 24;
pub const YARVINSN_intern: ruby_vminsn_type = 25;
pub const YARVINSN_newarray: ruby_vminsn_type = 26;
pub const YARVINSN_newarraykwsplat: ruby_vminsn_type = 27;
pub const YARVINSN_duparray: ruby_vminsn_type = 28;
pub const YARVINSN_duphash: ruby_vminsn_type = 29;
pub const YARVINSN_expandarray: ruby_vminsn_type = 30;
pub const YARVINSN_concatarray: ruby_vminsn_type = 31;
pub const YARVINSN_concattoarray: ruby_vminsn_type = 32;
pub const YARVINSN_pushtoarray: ruby_vminsn_type = 33;
pub const YARVINSN_splatarray: ruby_vminsn_type = 34;
pub const YARVINSN_splatkw: ruby_vminsn_type = 35;
pub const YARVINSN_newhash: ruby_vminsn_type = 36;
pub const YARVINSN_newrange: ruby_vminsn_type = 37;
pub const YARVINSN_pop: ruby_vminsn_type = 38;
pub const YARVINSN_dup: ruby_vminsn_type = 39;
pub const YARVINSN_dupn: ruby_vminsn_type = 40;
pub const YARVINSN_swap: ruby_vminsn_type = 41;
pub const YARVINSN_opt_reverse: ruby_vminsn_type = 42;
pub const YARVINSN_topn: ruby_vminsn_type = 43;
pub const YARVINSN_setn: ruby_vminsn_type = 44;
pub const YARVINSN_adjuststack: ruby_vminsn_type = 45;
pub const YARVINSN_defined: ruby_vminsn_type = 46;
pub const YARVINSN_definedivar: ruby_vminsn_type = 47;
pub const YARVINSN_checkmatch: ruby_vminsn_type = 48;
pub const YARVINSN_checkkeyword: ruby_vminsn_type = 49;
pub const YARVINSN_checktype: ruby_vminsn_type = 50;
pub const YARVINSN_defineclass: ruby_vminsn_type = 51;
pub const YARVINSN_definemethod: ruby_vminsn_type = 52;
pub const YARVINSN_definesmethod: ruby_vminsn_type = 53;
pub const YARVINSN_send: ruby_vminsn_type = 54;
pub const YARVINSN_opt_send_without_block: ruby_vminsn_type = 55;
pub const YARVINSN_objtostring: ruby_vminsn_type = 56;
pub const YARVINSN_opt_str_freeze: ruby_vminsn_type = 57;
pub const YARVINSN_opt_nil_p: ruby_vminsn_type = 58;
pub const YARVINSN_opt_str_uminus: ruby_vminsn_type = 59;
pub const YARVINSN_opt_newarray_send: ruby_vminsn_type = 60;
pub const YARVINSN_invokesuper: ruby_vminsn_type = 61;
pub const YARVINSN_invokeblock: ruby_vminsn_type = 62;
pub const YARVINSN_leave: ruby_vminsn_type = 63;
pub const YARVINSN_throw: ruby_vminsn_type = 64;
pub const YARVINSN_jump: ruby_vminsn_type = 65;
pub const YARVINSN_branchif: ruby_vminsn_type = 66;
pub const YARVINSN_branchunless: ruby_vminsn_type = 67;
pub const YARVINSN_branchnil: ruby_vminsn_type = 68;
pub const YARVINSN_once: ruby_vminsn_type = 69;
pub const YARVINSN_opt_case_dispatch: ruby_vminsn_type = 70;
pub const YARVINSN_opt_plus: ruby_vminsn_type = 71;
pub const YARVINSN_opt_minus: ruby_vminsn_type = 72;
pub const YARVINSN_opt_mult: ruby_vminsn_type = 73;
pub const YARVINSN_opt_div: ruby_vminsn_type = 74;
pub const YARVINSN_opt_mod: ruby_vminsn_type = 75;
pub const YARVINSN_opt_eq: ruby_vminsn_type = 76;
pub const YARVINSN_opt_neq: ruby_vminsn_type = 77;
pub const YARVINSN_opt_lt: ruby_vminsn_type = 78;
pub const YARVINSN_opt_le: ruby_vminsn_type = 79;
pub const YARVINSN_opt_gt: ruby_vminsn_type = 80;
pub const YARVINSN_opt_ge: ruby_vminsn_type = 81;
pub const YARVINSN_opt_ltlt: ruby_vminsn_type = 82;
pub const YARVINSN_opt_and: ruby_vminsn_type = 83;
pub const YARVINSN_opt_or: ruby_vminsn_type = 84;
pub const YARVINSN_opt_aref: ruby_vminsn_type = 85;
pub const YARVINSN_opt_aset: ruby_vminsn_type = 86;
pub const YARVINSN_opt_aset_with: ruby_vminsn_type = 87;
pub const YARVINSN_opt_aref_with: ruby_vminsn_type = 88;
pub const YARVINSN_opt_length: ruby_vminsn_type = 89;
pub const YARVINSN_opt_size: ruby_vminsn_type = 90;
pub const YARVINSN_opt_empty_p: ruby_vminsn_type = 91;
pub const YARVINSN_opt_succ: ruby_vminsn_type = 92;
pub const YARVINSN_opt_not: ruby_vminsn_type = 93;
pub const YARVINSN_opt_regexpmatch2: ruby_vminsn_type = 94;
pub const YARVINSN_invokebuiltin: ruby_vminsn_type = 95;
pub const YARVINSN_opt_invokebuiltin_delegate: ruby_vminsn_type = 96;
pub const YARVINSN_opt_invokebuiltin_delegate_leave: ruby_vminsn_type = 97;
pub const YARVINSN_getlocal_WC_0: ruby_vminsn_type = 98;
pub const YARVINSN_getlocal_WC_1: ruby_vminsn_type = 99;
pub const YARVINSN_setlocal_WC_0: ruby_vminsn_type = 100;
pub const YARVINSN_setlocal_WC_1: ruby_vminsn_type = 101;
pub const YARVINSN_putobject_INT2FIX_0_: ruby_vminsn_type = 102;
pub const YARVINSN_putobject_INT2FIX_1_: ruby_vminsn_type = 103;
pub const YARVINSN_trace_nop: ruby_vminsn_type = 104;
pub const YARVINSN_trace_getlocal: ruby_vminsn_type = 105;
pub const YARVINSN_trace_setlocal: ruby_vminsn_type = 106;
pub const YARVINSN_trace_getblockparam: ruby_vminsn_type = 107;
pub const YARVINSN_trace_setblockparam: ruby_vminsn_type = 108;
pub const YARVINSN_trace_getblockparamproxy: ruby_vminsn_type = 109;
pub const YARVINSN_trace_getspecial: ruby_vminsn_type = 110;
pub const YARVINSN_trace_setspecial: ruby_vminsn_type = 111;
pub const YARVINSN_trace_getinstancevariable: ruby_vminsn_type = 112;
pub const YARVINSN_trace_setinstancevariable: ruby_vminsn_type = 113;
pub const YARVINSN_trace_getclassvariable: ruby_vminsn_type = 114;
pub const YARVINSN_trace_setclassvariable: ruby_vminsn_type = 115;
pub const YARVINSN_trace_opt_getconstant_path: ruby_vminsn_type = 116;
pub const YARVINSN_trace_getconstant: ruby_vminsn_type = 117;
pub const YARVINSN_trace_setconstant: ruby_vminsn_type = 118;
pub const YARVINSN_trace_getglobal: ruby_vminsn_type = 119;
pub const YARVINSN_trace_setglobal: ruby_vminsn_type = 120;
pub const YARVINSN_trace_putnil: ruby_vminsn_type = 121;
pub const YARVINSN_trace_putself: ruby_vminsn_type = 122;
pub const YARVINSN_trace_putobject: ruby_vminsn_type = 123;
pub const YARVINSN_trace_putspecialobject: ruby_vminsn_type = 124;
pub const YARVINSN_trace_putstring: ruby_vminsn_type = 125;
pub const YARVINSN_trace_concatstrings: ruby_vminsn_type = 126;
pub const YARVINSN_trace_anytostring: ruby_vminsn_type = 127;
pub const YARVINSN_trace_toregexp: ruby_vminsn_type = 128;
pub const YARVINSN_trace_intern: ruby_vminsn_type = 129;
pub const YARVINSN_trace_newarray: ruby_vminsn_type = 130;
pub const YARVINSN_trace_newarraykwsplat: ruby_vminsn_type = 131;
pub const YARVINSN_trace_duparray: ruby_vminsn_type = 132;
pub const YARVINSN_trace_duphash: ruby_vminsn_type = 133;
pub const YARVINSN_trace_expandarray: ruby_vminsn_type = 134;
pub const YARVINSN_trace_concatarray: ruby_vminsn_type = 135;
pub const YARVINSN_trace_concattoarray: ruby_vminsn_type = 136;
pub const YARVINSN_trace_pushtoarray: ruby_vminsn_type = 137;
pub const YARVINSN_trace_splatarray: ruby_vminsn_type = 138;
pub const YARVINSN_trace_splatkw: ruby_vminsn_type = 139;
pub const YARVINSN_trace_newhash: ruby_vminsn_type = 140;
pub const YARVINSN_trace_newrange: ruby_vminsn_type = 141;
pub const YARVINSN_trace_pop: ruby_vminsn_type = 142;
pub const YARVINSN_trace_dup: ruby_vminsn_type = 143;
pub const YARVINSN_trace_dupn: ruby_vminsn_type = 144;
pub const YARVINSN_trace_swap: ruby_vminsn_type = 145;
pub const YARVINSN_trace_opt_reverse: ruby_vminsn_type = 146;
pub const YARVINSN_trace_topn: ruby_vminsn_type = 147;
pub const YARVINSN_trace_setn: ruby_vminsn_type = 148;
pub const YARVINSN_trace_adjuststack: ruby_vminsn_type = 149;
pub const YARVINSN_trace_defined: ruby_vminsn_type = 150;
pub const YARVINSN_trace_definedivar: ruby_vminsn_type = 151;
pub const YARVINSN_trace_checkmatch: ruby_vminsn_type = 152;
pub const YARVINSN_trace_checkkeyword: ruby_vminsn_type = 153;
pub const YARVINSN_trace_checktype: ruby_vminsn_type = 154;
pub const YARVINSN_trace_defineclass: ruby_vminsn_type = 155;
pub const YARVINSN_trace_definemethod: ruby_vminsn_type = 156;
pub const YARVINSN_trace_definesmethod: ruby_vminsn_type = 157;
pub const YARVINSN_trace_send: ruby_vminsn_type = 158;
pub const YARVINSN_trace_opt_send_without_block: ruby_vminsn_type = 159;
pub const YARVINSN_trace_objtostring: ruby_vminsn_type = 160;
pub const YARVINSN_trace_opt_str_freeze: ruby_vminsn_type = 161;
pub const YARVINSN_trace_opt_nil_p: ruby_vminsn_type = 162;
pub const YARVINSN_trace_opt_str_uminus: ruby_vminsn_type = 163;
pub const YARVINSN_trace_opt_newarray_send: ruby_vminsn_type = 164;
pub const YARVINSN_trace_invokesuper: ruby_vminsn_type = 165;
pub const YARVINSN_trace_invokeblock: ruby_vminsn_type = 166;
pub const YARVINSN_trace_leave: ruby_vminsn_type = 167;
pub const YARVINSN_trace_throw: ruby_vminsn_type = 168;
pub const YARVINSN_trace_jump: ruby_vminsn_type = 169;
pub const YARVINSN_trace_branchif: ruby_vminsn_type = 170;
pub const YARVINSN_trace_branchunless: ruby_vminsn_type = 171;
pub const YARVINSN_trace_branchnil: ruby_vminsn_type = 172;
pub const YARVINSN_trace_once: ruby_vminsn_type = 173;
pub const YARVINSN_trace_opt_case_dispatch: ruby_vminsn_type = 174;
pub const YARVINSN_trace_opt_plus: ruby_vminsn_type = 175;
pub const YARVINSN_trace_opt_minus: ruby_vminsn_type = 176;
pub const YARVINSN_trace_opt_mult: ruby_vminsn_type = 177;
pub const YARVINSN_trace_opt_div: ruby_vminsn_type = 178;
pub const YARVINSN_trace_opt_mod: ruby_vminsn_type = 179;
pub const YARVINSN_trace_opt_eq: ruby_vminsn_type = 180;
pub const YARVINSN_trace_opt_neq: ruby_vminsn_type = 181;
pub const YARVINSN_trace_opt_lt: ruby_vminsn_type = 182;
pub const YARVINSN_trace_opt_le: ruby_vminsn_type = 183;
pub const YARVINSN_trace_opt_gt: ruby_vminsn_type = 184;
pub const YARVINSN_trace_opt_ge: ruby_vminsn_type = 185;
pub const YARVINSN_trace_opt_ltlt: ruby_vminsn_type = 186;
pub const YARVINSN_trace_opt_and: ruby_vminsn_type = 187;
pub const YARVINSN_trace_opt_or: ruby_vminsn_type = 188;
pub const YARVINSN_trace_opt_aref: ruby_vminsn_type = 189;
pub const YARVINSN_trace_opt_aset: ruby_vminsn_type = 190;
pub const YARVINSN_trace_opt_aset_with: ruby_vminsn_type = 191;
pub const YARVINSN_trace_opt_aref_with: ruby_vminsn_type = 192;
pub const YARVINSN_trace_opt_length: ruby_vminsn_type = 193;
pub const YARVINSN_trace_opt_size: ruby_vminsn_type = 194;
pub const YARVINSN_trace_opt_empty_p: ruby_vminsn_type = 195;
pub const YARVINSN_trace_opt_succ: ruby_vminsn_type = 196;
pub const YARVINSN_trace_opt_not: ruby_vminsn_type = 197;
pub const YARVINSN_trace_opt_regexpmatch2: ruby_vminsn_type = 198;
pub const YARVINSN_trace_invokebuiltin: ruby_vminsn_type = 199;
pub const YARVINSN_trace_opt_invokebuiltin_delegate: ruby_vminsn_type = 200;
pub const YARVINSN_trace_opt_invokebuiltin_delegate_leave: ruby_vminsn_type = 201;
pub const YARVINSN_trace_getlocal_WC_0: ruby_vminsn_type = 202;
pub const YARVINSN_trace_getlocal_WC_1: ruby_vminsn_type = 203;
pub const YARVINSN_trace_setlocal_WC_0: ruby_vminsn_type = 204;
pub const YARVINSN_trace_setlocal_WC_1: ruby_vminsn_type = 205;
pub const YARVINSN_trace_putobject_INT2FIX_0_: ruby_vminsn_type = 206;
pub const YARVINSN_trace_putobject_INT2FIX_1_: ruby_vminsn_type = 207;
pub const VM_INSTRUCTION_SIZE: ruby_vminsn_type = 208;
pub const YARVINSN_pushtoarraykwsplat: ruby_vminsn_type = 28;
pub const YARVINSN_duparray: ruby_vminsn_type = 29;
pub const YARVINSN_duphash: ruby_vminsn_type = 30;
pub const YARVINSN_expandarray: ruby_vminsn_type = 31;
pub const YARVINSN_concatarray: ruby_vminsn_type = 32;
pub const YARVINSN_concattoarray: ruby_vminsn_type = 33;
pub const YARVINSN_pushtoarray: ruby_vminsn_type = 34;
pub const YARVINSN_splatarray: ruby_vminsn_type = 35;
pub const YARVINSN_splatkw: ruby_vminsn_type = 36;
pub const YARVINSN_newhash: ruby_vminsn_type = 37;
pub const YARVINSN_newrange: ruby_vminsn_type = 38;
pub const YARVINSN_pop: ruby_vminsn_type = 39;
pub const YARVINSN_dup: ruby_vminsn_type = 40;
pub const YARVINSN_dupn: ruby_vminsn_type = 41;
pub const YARVINSN_swap: ruby_vminsn_type = 42;
pub const YARVINSN_opt_reverse: ruby_vminsn_type = 43;
pub const YARVINSN_topn: ruby_vminsn_type = 44;
pub const YARVINSN_setn: ruby_vminsn_type = 45;
pub const YARVINSN_adjuststack: ruby_vminsn_type = 46;
pub const YARVINSN_defined: ruby_vminsn_type = 47;
pub const YARVINSN_definedivar: ruby_vminsn_type = 48;
pub const YARVINSN_checkmatch: ruby_vminsn_type = 49;
pub const YARVINSN_checkkeyword: ruby_vminsn_type = 50;
pub const YARVINSN_checktype: ruby_vminsn_type = 51;
pub const YARVINSN_defineclass: ruby_vminsn_type = 52;
pub const YARVINSN_definemethod: ruby_vminsn_type = 53;
pub const YARVINSN_definesmethod: ruby_vminsn_type = 54;
pub const YARVINSN_send: ruby_vminsn_type = 55;
pub const YARVINSN_opt_send_without_block: ruby_vminsn_type = 56;
pub const YARVINSN_objtostring: ruby_vminsn_type = 57;
pub const YARVINSN_opt_str_freeze: ruby_vminsn_type = 58;
pub const YARVINSN_opt_nil_p: ruby_vminsn_type = 59;
pub const YARVINSN_opt_str_uminus: ruby_vminsn_type = 60;
pub const YARVINSN_opt_newarray_send: ruby_vminsn_type = 61;
pub const YARVINSN_invokesuper: ruby_vminsn_type = 62;
pub const YARVINSN_invokeblock: ruby_vminsn_type = 63;
pub const YARVINSN_leave: ruby_vminsn_type = 64;
pub const YARVINSN_throw: ruby_vminsn_type = 65;
pub const YARVINSN_jump: ruby_vminsn_type = 66;
pub const YARVINSN_branchif: ruby_vminsn_type = 67;
pub const YARVINSN_branchunless: ruby_vminsn_type = 68;
pub const YARVINSN_branchnil: ruby_vminsn_type = 69;
pub const YARVINSN_once: ruby_vminsn_type = 70;
pub const YARVINSN_opt_case_dispatch: ruby_vminsn_type = 71;
pub const YARVINSN_opt_plus: ruby_vminsn_type = 72;
pub const YARVINSN_opt_minus: ruby_vminsn_type = 73;
pub const YARVINSN_opt_mult: ruby_vminsn_type = 74;
pub const YARVINSN_opt_div: ruby_vminsn_type = 75;
pub const YARVINSN_opt_mod: ruby_vminsn_type = 76;
pub const YARVINSN_opt_eq: ruby_vminsn_type = 77;
pub const YARVINSN_opt_neq: ruby_vminsn_type = 78;
pub const YARVINSN_opt_lt: ruby_vminsn_type = 79;
pub const YARVINSN_opt_le: ruby_vminsn_type = 80;
pub const YARVINSN_opt_gt: ruby_vminsn_type = 81;
pub const YARVINSN_opt_ge: ruby_vminsn_type = 82;
pub const YARVINSN_opt_ltlt: ruby_vminsn_type = 83;
pub const YARVINSN_opt_and: ruby_vminsn_type = 84;
pub const YARVINSN_opt_or: ruby_vminsn_type = 85;
pub const YARVINSN_opt_aref: ruby_vminsn_type = 86;
pub const YARVINSN_opt_aset: ruby_vminsn_type = 87;
pub const YARVINSN_opt_aset_with: ruby_vminsn_type = 88;
pub const YARVINSN_opt_aref_with: ruby_vminsn_type = 89;
pub const YARVINSN_opt_length: ruby_vminsn_type = 90;
pub const YARVINSN_opt_size: ruby_vminsn_type = 91;
pub const YARVINSN_opt_empty_p: ruby_vminsn_type = 92;
pub const YARVINSN_opt_succ: ruby_vminsn_type = 93;
pub const YARVINSN_opt_not: ruby_vminsn_type = 94;
pub const YARVINSN_opt_regexpmatch2: ruby_vminsn_type = 95;
pub const YARVINSN_invokebuiltin: ruby_vminsn_type = 96;
pub const YARVINSN_opt_invokebuiltin_delegate: ruby_vminsn_type = 97;
pub const YARVINSN_opt_invokebuiltin_delegate_leave: ruby_vminsn_type = 98;
pub const YARVINSN_getlocal_WC_0: ruby_vminsn_type = 99;
pub const YARVINSN_getlocal_WC_1: ruby_vminsn_type = 100;
pub const YARVINSN_setlocal_WC_0: ruby_vminsn_type = 101;
pub const YARVINSN_setlocal_WC_1: ruby_vminsn_type = 102;
pub const YARVINSN_putobject_INT2FIX_0_: ruby_vminsn_type = 103;
pub const YARVINSN_putobject_INT2FIX_1_: ruby_vminsn_type = 104;
pub const YARVINSN_trace_nop: ruby_vminsn_type = 105;
pub const YARVINSN_trace_getlocal: ruby_vminsn_type = 106;
pub const YARVINSN_trace_setlocal: ruby_vminsn_type = 107;
pub const YARVINSN_trace_getblockparam: ruby_vminsn_type = 108;
pub const YARVINSN_trace_setblockparam: ruby_vminsn_type = 109;
pub const YARVINSN_trace_getblockparamproxy: ruby_vminsn_type = 110;
pub const YARVINSN_trace_getspecial: ruby_vminsn_type = 111;
pub const YARVINSN_trace_setspecial: ruby_vminsn_type = 112;
pub const YARVINSN_trace_getinstancevariable: ruby_vminsn_type = 113;
pub const YARVINSN_trace_setinstancevariable: ruby_vminsn_type = 114;
pub const YARVINSN_trace_getclassvariable: ruby_vminsn_type = 115;
pub const YARVINSN_trace_setclassvariable: ruby_vminsn_type = 116;
pub const YARVINSN_trace_opt_getconstant_path: ruby_vminsn_type = 117;
pub const YARVINSN_trace_getconstant: ruby_vminsn_type = 118;
pub const YARVINSN_trace_setconstant: ruby_vminsn_type = 119;
pub const YARVINSN_trace_getglobal: ruby_vminsn_type = 120;
pub const YARVINSN_trace_setglobal: ruby_vminsn_type = 121;
pub const YARVINSN_trace_putnil: ruby_vminsn_type = 122;
pub const YARVINSN_trace_putself: ruby_vminsn_type = 123;
pub const YARVINSN_trace_putobject: ruby_vminsn_type = 124;
pub const YARVINSN_trace_putspecialobject: ruby_vminsn_type = 125;
pub const YARVINSN_trace_putstring: ruby_vminsn_type = 126;
pub const YARVINSN_trace_concatstrings: ruby_vminsn_type = 127;
pub const YARVINSN_trace_anytostring: ruby_vminsn_type = 128;
pub const YARVINSN_trace_toregexp: ruby_vminsn_type = 129;
pub const YARVINSN_trace_intern: ruby_vminsn_type = 130;
pub const YARVINSN_trace_newarray: ruby_vminsn_type = 131;
pub const YARVINSN_trace_newarraykwsplat: ruby_vminsn_type = 132;
pub const YARVINSN_trace_pushtoarraykwsplat: ruby_vminsn_type = 133;
pub const YARVINSN_trace_duparray: ruby_vminsn_type = 134;
pub const YARVINSN_trace_duphash: ruby_vminsn_type = 135;
pub const YARVINSN_trace_expandarray: ruby_vminsn_type = 136;
pub const YARVINSN_trace_concatarray: ruby_vminsn_type = 137;
pub const YARVINSN_trace_concattoarray: ruby_vminsn_type = 138;
pub const YARVINSN_trace_pushtoarray: ruby_vminsn_type = 139;
pub const YARVINSN_trace_splatarray: ruby_vminsn_type = 140;
pub const YARVINSN_trace_splatkw: ruby_vminsn_type = 141;
pub const YARVINSN_trace_newhash: ruby_vminsn_type = 142;
pub const YARVINSN_trace_newrange: ruby_vminsn_type = 143;
pub const YARVINSN_trace_pop: ruby_vminsn_type = 144;
pub const YARVINSN_trace_dup: ruby_vminsn_type = 145;
pub const YARVINSN_trace_dupn: ruby_vminsn_type = 146;
pub const YARVINSN_trace_swap: ruby_vminsn_type = 147;
pub const YARVINSN_trace_opt_reverse: ruby_vminsn_type = 148;
pub const YARVINSN_trace_topn: ruby_vminsn_type = 149;
pub const YARVINSN_trace_setn: ruby_vminsn_type = 150;
pub const YARVINSN_trace_adjuststack: ruby_vminsn_type = 151;
pub const YARVINSN_trace_defined: ruby_vminsn_type = 152;
pub const YARVINSN_trace_definedivar: ruby_vminsn_type = 153;
pub const YARVINSN_trace_checkmatch: ruby_vminsn_type = 154;
pub const YARVINSN_trace_checkkeyword: ruby_vminsn_type = 155;
pub const YARVINSN_trace_checktype: ruby_vminsn_type = 156;
pub const YARVINSN_trace_defineclass: ruby_vminsn_type = 157;
pub const YARVINSN_trace_definemethod: ruby_vminsn_type = 158;
pub const YARVINSN_trace_definesmethod: ruby_vminsn_type = 159;
pub const YARVINSN_trace_send: ruby_vminsn_type = 160;
pub const YARVINSN_trace_opt_send_without_block: ruby_vminsn_type = 161;
pub const YARVINSN_trace_objtostring: ruby_vminsn_type = 162;
pub const YARVINSN_trace_opt_str_freeze: ruby_vminsn_type = 163;
pub const YARVINSN_trace_opt_nil_p: ruby_vminsn_type = 164;
pub const YARVINSN_trace_opt_str_uminus: ruby_vminsn_type = 165;
pub const YARVINSN_trace_opt_newarray_send: ruby_vminsn_type = 166;
pub const YARVINSN_trace_invokesuper: ruby_vminsn_type = 167;
pub const YARVINSN_trace_invokeblock: ruby_vminsn_type = 168;
pub const YARVINSN_trace_leave: ruby_vminsn_type = 169;
pub const YARVINSN_trace_throw: ruby_vminsn_type = 170;
pub const YARVINSN_trace_jump: ruby_vminsn_type = 171;
pub const YARVINSN_trace_branchif: ruby_vminsn_type = 172;
pub const YARVINSN_trace_branchunless: ruby_vminsn_type = 173;
pub const YARVINSN_trace_branchnil: ruby_vminsn_type = 174;
pub const YARVINSN_trace_once: ruby_vminsn_type = 175;
pub const YARVINSN_trace_opt_case_dispatch: ruby_vminsn_type = 176;
pub const YARVINSN_trace_opt_plus: ruby_vminsn_type = 177;
pub const YARVINSN_trace_opt_minus: ruby_vminsn_type = 178;
pub const YARVINSN_trace_opt_mult: ruby_vminsn_type = 179;
pub const YARVINSN_trace_opt_div: ruby_vminsn_type = 180;
pub const YARVINSN_trace_opt_mod: ruby_vminsn_type = 181;
pub const YARVINSN_trace_opt_eq: ruby_vminsn_type = 182;
pub const YARVINSN_trace_opt_neq: ruby_vminsn_type = 183;
pub const YARVINSN_trace_opt_lt: ruby_vminsn_type = 184;
pub const YARVINSN_trace_opt_le: ruby_vminsn_type = 185;
pub const YARVINSN_trace_opt_gt: ruby_vminsn_type = 186;
pub const YARVINSN_trace_opt_ge: ruby_vminsn_type = 187;
pub const YARVINSN_trace_opt_ltlt: ruby_vminsn_type = 188;
pub const YARVINSN_trace_opt_and: ruby_vminsn_type = 189;
pub const YARVINSN_trace_opt_or: ruby_vminsn_type = 190;
pub const YARVINSN_trace_opt_aref: ruby_vminsn_type = 191;
pub const YARVINSN_trace_opt_aset: ruby_vminsn_type = 192;
pub const YARVINSN_trace_opt_aset_with: ruby_vminsn_type = 193;
pub const YARVINSN_trace_opt_aref_with: ruby_vminsn_type = 194;
pub const YARVINSN_trace_opt_length: ruby_vminsn_type = 195;
pub const YARVINSN_trace_opt_size: ruby_vminsn_type = 196;
pub const YARVINSN_trace_opt_empty_p: ruby_vminsn_type = 197;
pub const YARVINSN_trace_opt_succ: ruby_vminsn_type = 198;
pub const YARVINSN_trace_opt_not: ruby_vminsn_type = 199;
pub const YARVINSN_trace_opt_regexpmatch2: ruby_vminsn_type = 200;
pub const YARVINSN_trace_invokebuiltin: ruby_vminsn_type = 201;
pub const YARVINSN_trace_opt_invokebuiltin_delegate: ruby_vminsn_type = 202;
pub const YARVINSN_trace_opt_invokebuiltin_delegate_leave: ruby_vminsn_type = 203;
pub const YARVINSN_trace_getlocal_WC_0: ruby_vminsn_type = 204;
pub const YARVINSN_trace_getlocal_WC_1: ruby_vminsn_type = 205;
pub const YARVINSN_trace_setlocal_WC_0: ruby_vminsn_type = 206;
pub const YARVINSN_trace_setlocal_WC_1: ruby_vminsn_type = 207;
pub const YARVINSN_trace_putobject_INT2FIX_0_: ruby_vminsn_type = 208;
pub const YARVINSN_trace_putobject_INT2FIX_1_: ruby_vminsn_type = 209;
pub const VM_INSTRUCTION_SIZE: ruby_vminsn_type = 210;
pub type ruby_vminsn_type = u32;
pub type rb_iseq_callback = ::std::option::Option<
unsafe extern "C" fn(arg1: *const rb_iseq_t, arg2: *mut ::std::os::raw::c_void),