Optimized instruction for Array#freeze

If an Array which is empty or only using literals is frozen, we detect
this as a peephole optimization and change the instructions to be
`opt_ary_freeze`.

[Feature #20684]

Co-authored-by: Jean Boussier <byroot@ruby-lang.org>
This commit is contained in:
Étienne Barrié 2024-07-29 12:15:02 +02:00 коммит произвёл Jean Boussier
Родитель 63cbe3f6ac
Коммит a99707cd9c
10 изменённых файлов: 324 добавлений и 159 удалений

Просмотреть файл

@ -38,6 +38,7 @@
#include "ruby_assert.h"
VALUE rb_cArray;
VALUE rb_cArray_empty_frozen;
/* Flags of RArray
*
@ -8833,6 +8834,9 @@ Init_Array(void)
rb_define_method(rb_cArray, "freeze", rb_ary_freeze, 0);
rb_define_method(rb_cArray, "deconstruct", rb_ary_deconstruct, 0);
rb_cArray_empty_frozen = rb_ary_freeze(rb_ary_new());
rb_vm_register_global_object(rb_cArray_empty_frozen);
}
#include "array.rbinc"

Просмотреть файл

@ -3235,6 +3235,8 @@ ci_argc_set(const rb_iseq_t *iseq, const struct rb_callinfo *ci, int argc)
return nci;
}
#define vm_ci_simple(ci) (vm_ci_flag(ci) & VM_CALL_ARGS_SIMPLE)
static int
iseq_peephole_optimize(rb_iseq_t *iseq, LINK_ELEMENT *list, const int do_tailcallopt)
{
@ -3401,6 +3403,55 @@ iseq_peephole_optimize(rb_iseq_t *iseq, LINK_ELEMENT *list, const int do_tailcal
}
}
/*
* duparray [...]
* send <calldata!mid:freeze, argc:0, ARGS_SIMPLE>, nil
* =>
* opt_ary_freeze [...], <calldata!mid:freeze, argc:0, ARGS_SIMPLE>
*/
if (IS_INSN_ID(iobj, duparray)) {
LINK_ELEMENT *next = iobj->link.next;
if (IS_INSN(next) && (IS_INSN_ID(next, send))) {
const struct rb_callinfo *ci = (struct rb_callinfo *)OPERAND_AT(next, 0);
const rb_iseq_t *blockiseq = (rb_iseq_t *)OPERAND_AT(next, 1);
if (vm_ci_simple(ci) && vm_ci_argc(ci) == 0 && blockiseq == NULL && vm_ci_mid(ci) == idFreeze) {
VALUE ary = iobj->operands[0];
rb_obj_reveal(ary, rb_cArray);
iobj->insn_id = BIN(opt_ary_freeze);
iobj->operand_size = 2;
iobj->operands = compile_data_calloc2(iseq, iobj->operand_size, sizeof(VALUE));
iobj->operands[0] = ary;
iobj->operands[1] = (VALUE)ci;
ELEM_REMOVE(next);
}
}
}
/*
* newarray 0
* send <calldata!mid:freeze, argc:0, ARGS_SIMPLE>, nil
* =>
* opt_ary_freeze [], <calldata!mid:freeze, argc:0, ARGS_SIMPLE>
*/
if (IS_INSN_ID(iobj, newarray) && iobj->operands[0] == INT2FIX(0)) {
LINK_ELEMENT *next = iobj->link.next;
if (IS_INSN(next) && (IS_INSN_ID(next, send))) {
const struct rb_callinfo *ci = (struct rb_callinfo *)OPERAND_AT(next, 0);
const rb_iseq_t *blockiseq = (rb_iseq_t *)OPERAND_AT(next, 1);
if (vm_ci_simple(ci) && vm_ci_argc(ci) == 0 && blockiseq == NULL && vm_ci_mid(ci) == idFreeze) {
iobj->insn_id = BIN(opt_ary_freeze);
iobj->operand_size = 2;
iobj->operands = compile_data_calloc2(iseq, iobj->operand_size, sizeof(VALUE));
iobj->operands[0] = rb_cArray_empty_frozen;
iobj->operands[1] = (VALUE)ci;
ELEM_REMOVE(next);
}
}
}
if (IS_INSN_ID(iobj, branchif) ||
IS_INSN_ID(iobj, branchnil) ||
IS_INSN_ID(iobj, branchunless)) {
@ -3986,8 +4037,6 @@ insn_set_specialized_instruction(rb_iseq_t *iseq, INSN *iobj, int insn_id)
return COMPILE_OK;
}
#define vm_ci_simple(ci) (vm_ci_flag(ci) & VM_CALL_ARGS_SIMPLE)
static int
iseq_specialized_instruction(rb_iseq_t *iseq, INSN *iobj)
{

Просмотреть файл

@ -919,6 +919,21 @@ objtostring
}
}
DEFINE_INSN
opt_ary_freeze
(VALUE ary, CALL_DATA cd)
()
(VALUE val)
{
val = vm_opt_ary_freeze(ary, BOP_FREEZE, idFreeze);
if (UNDEF_P(val)) {
RUBY_DTRACE_CREATE_HOOK(ARRAY, RARRAY_LEN(ary));
PUSH(rb_ary_resurrect(ary));
CALL_SIMPLE_METHOD();
}
}
DEFINE_INSN
opt_str_freeze
(VALUE str, CALL_DATA cd)

Просмотреть файл

@ -37,6 +37,7 @@ size_t rb_ary_size_as_embedded(VALUE ary);
void rb_ary_make_embedded(VALUE ary);
bool rb_ary_embeddable_p(VALUE ary);
VALUE rb_ary_diff(VALUE ary1, VALUE ary2);
RUBY_EXTERN VALUE rb_cArray_empty_frozen;
static inline VALUE rb_ary_entry_internal(VALUE ary, long offset);
static inline bool ARY_PTR_USING_P(VALUE ary);

Просмотреть файл

@ -90,6 +90,7 @@ module RubyVM::RJIT
when :opt_send_without_block then opt_send_without_block(jit, ctx, asm)
when :objtostring then objtostring(jit, ctx, asm)
when :opt_str_freeze then opt_str_freeze(jit, ctx, asm)
when :opt_ary_freeze then opt_ary_freeze(jit, ctx, asm)
when :opt_nil_p then opt_nil_p(jit, ctx, asm)
# opt_str_uminus
when :opt_newarray_send then opt_newarray_send(jit, ctx, asm)
@ -1490,6 +1491,24 @@ module RubyVM::RJIT
end
end
# @param jit [RubyVM::RJIT::JITState]
# @param ctx [RubyVM::RJIT::Context]
# @param asm [RubyVM::RJIT::Assembler]
def opt_ary_freeze(jit, ctx, asm)
unless Invariants.assume_bop_not_redefined(jit, C::ARRAY_REDEFINED_OP_FLAG, C::BOP_FREEZE)
return CantCompile;
end
ary = jit.operand(0, ruby: true)
# Push the return value onto the stack
stack_ret = ctx.stack_push(Type::CArray)
asm.mov(:rax, to_value(ary))
asm.mov(stack_ret, :rax)
KeepCompiling
end
# @param jit [RubyVM::RJIT::JITState]
# @param ctx [RubyVM::RJIT::Context]
# @param asm [RubyVM::RJIT::Assembler]

Просмотреть файл

@ -749,6 +749,52 @@ class TestRubyOptimization < Test::Unit::TestCase
end
end
def test_peephole_array_freeze
code = "#{<<~'begin;'}\n#{<<~'end;'}"
begin;
[1].freeze
end;
iseq = RubyVM::InstructionSequence.compile(code)
insn = iseq.disasm
assert_match(/opt_ary_freeze/, insn)
assert_no_match(/duparray/, insn)
assert_no_match(/send/, insn)
assert_predicate([1].freeze, :frozen?)
assert_in_out_err([], <<~RUBY, [":ok"])
class Array
prepend Module.new {
def freeze
:ok
end
}
end
p [1].freeze
RUBY
end
def test_peephole_array_freeze_empty
code = "#{<<~'begin;'}\n#{<<~'end;'}"
begin;
[].freeze
end;
iseq = RubyVM::InstructionSequence.compile(code)
insn = iseq.disasm
assert_match(/opt_ary_freeze/, insn)
assert_no_match(/duparray/, insn)
assert_no_match(/send/, insn)
assert_predicate([].freeze, :frozen?)
assert_in_out_err([], <<~RUBY, [":ok"])
class Array
prepend Module.new {
def freeze
:ok
end
}
end
p [].freeze
RUBY
end
def test_branch_condition_backquote
bug = '[ruby-core:80740] [Bug #13444] redefined backquote should be called'
class << self

2
vm.c
Просмотреть файл

@ -2232,7 +2232,7 @@ vm_init_redefined_flag(void)
OP(EmptyP, EMPTY_P), (C(Array), C(String), C(Hash));
OP(Succ, SUCC), (C(Integer), C(String));
OP(EqTilde, MATCH), (C(Regexp), C(String));
OP(Freeze, FREEZE), (C(String));
OP(Freeze, FREEZE), (C(String), C(Array));
OP(UMinus, UMINUS), (C(String));
OP(Max, MAX), (C(Array));
OP(Min, MIN), (C(Array));

Просмотреть файл

@ -6109,6 +6109,17 @@ vm_objtostring(const rb_iseq_t *iseq, VALUE recv, CALL_DATA cd)
return Qundef;
}
static VALUE
vm_opt_ary_freeze(VALUE ary, int bop, ID id)
{
if (BASIC_OP_UNREDEFINED_P(bop, ARRAY_REDEFINED_OP_FLAG)) {
return ary;
}
else {
return Qundef;
}
}
static VALUE
vm_opt_str_freeze(VALUE str, int bop, ID id)
{

Просмотреть файл

@ -4187,6 +4187,23 @@ fn gen_opt_str_freeze(
Some(KeepCompiling)
}
fn gen_opt_ary_freeze(
jit: &mut JITState,
asm: &mut Assembler,
) -> Option<CodegenStatus> {
if !assume_bop_not_redefined(jit, asm, ARRAY_REDEFINED_OP_FLAG, BOP_FREEZE) {
return None;
}
let str = jit.get_arg(0);
// Push the return value onto the stack
let stack_ret = asm.stack_push(Type::CArray);
asm.mov(stack_ret, str.into());
Some(KeepCompiling)
}
fn gen_opt_str_uminus(
jit: &mut JITState,
asm: &mut Assembler,
@ -10228,6 +10245,7 @@ fn get_gen_fn(opcode: VALUE) -> Option<InsnGenFn> {
YARVINSN_opt_gt => Some(gen_opt_gt),
YARVINSN_opt_ge => Some(gen_opt_ge),
YARVINSN_opt_mod => Some(gen_opt_mod),
YARVINSN_opt_ary_freeze => Some(gen_opt_ary_freeze),
YARVINSN_opt_str_freeze => Some(gen_opt_str_freeze),
YARVINSN_opt_str_uminus => Some(gen_opt_str_uminus),
YARVINSN_opt_newarray_send => Some(gen_opt_newarray_send),

Просмотреть файл

@ -783,162 +783,164 @@ pub const YARVINSN_send: ruby_vminsn_type = 55;
pub const YARVINSN_sendforward: ruby_vminsn_type = 56;
pub const YARVINSN_opt_send_without_block: ruby_vminsn_type = 57;
pub const YARVINSN_objtostring: ruby_vminsn_type = 58;
pub const YARVINSN_opt_str_freeze: ruby_vminsn_type = 59;
pub const YARVINSN_opt_nil_p: ruby_vminsn_type = 60;
pub const YARVINSN_opt_str_uminus: ruby_vminsn_type = 61;
pub const YARVINSN_opt_newarray_send: ruby_vminsn_type = 62;
pub const YARVINSN_invokesuper: ruby_vminsn_type = 63;
pub const YARVINSN_invokesuperforward: ruby_vminsn_type = 64;
pub const YARVINSN_invokeblock: ruby_vminsn_type = 65;
pub const YARVINSN_leave: ruby_vminsn_type = 66;
pub const YARVINSN_throw: ruby_vminsn_type = 67;
pub const YARVINSN_jump: ruby_vminsn_type = 68;
pub const YARVINSN_branchif: ruby_vminsn_type = 69;
pub const YARVINSN_branchunless: ruby_vminsn_type = 70;
pub const YARVINSN_branchnil: ruby_vminsn_type = 71;
pub const YARVINSN_once: ruby_vminsn_type = 72;
pub const YARVINSN_opt_case_dispatch: ruby_vminsn_type = 73;
pub const YARVINSN_opt_plus: ruby_vminsn_type = 74;
pub const YARVINSN_opt_minus: ruby_vminsn_type = 75;
pub const YARVINSN_opt_mult: ruby_vminsn_type = 76;
pub const YARVINSN_opt_div: ruby_vminsn_type = 77;
pub const YARVINSN_opt_mod: ruby_vminsn_type = 78;
pub const YARVINSN_opt_eq: ruby_vminsn_type = 79;
pub const YARVINSN_opt_neq: ruby_vminsn_type = 80;
pub const YARVINSN_opt_lt: ruby_vminsn_type = 81;
pub const YARVINSN_opt_le: ruby_vminsn_type = 82;
pub const YARVINSN_opt_gt: ruby_vminsn_type = 83;
pub const YARVINSN_opt_ge: ruby_vminsn_type = 84;
pub const YARVINSN_opt_ltlt: ruby_vminsn_type = 85;
pub const YARVINSN_opt_and: ruby_vminsn_type = 86;
pub const YARVINSN_opt_or: ruby_vminsn_type = 87;
pub const YARVINSN_opt_aref: ruby_vminsn_type = 88;
pub const YARVINSN_opt_aset: ruby_vminsn_type = 89;
pub const YARVINSN_opt_aset_with: ruby_vminsn_type = 90;
pub const YARVINSN_opt_aref_with: ruby_vminsn_type = 91;
pub const YARVINSN_opt_length: ruby_vminsn_type = 92;
pub const YARVINSN_opt_size: ruby_vminsn_type = 93;
pub const YARVINSN_opt_empty_p: ruby_vminsn_type = 94;
pub const YARVINSN_opt_succ: ruby_vminsn_type = 95;
pub const YARVINSN_opt_not: ruby_vminsn_type = 96;
pub const YARVINSN_opt_regexpmatch2: ruby_vminsn_type = 97;
pub const YARVINSN_invokebuiltin: ruby_vminsn_type = 98;
pub const YARVINSN_opt_invokebuiltin_delegate: ruby_vminsn_type = 99;
pub const YARVINSN_opt_invokebuiltin_delegate_leave: ruby_vminsn_type = 100;
pub const YARVINSN_getlocal_WC_0: ruby_vminsn_type = 101;
pub const YARVINSN_getlocal_WC_1: ruby_vminsn_type = 102;
pub const YARVINSN_setlocal_WC_0: ruby_vminsn_type = 103;
pub const YARVINSN_setlocal_WC_1: ruby_vminsn_type = 104;
pub const YARVINSN_putobject_INT2FIX_0_: ruby_vminsn_type = 105;
pub const YARVINSN_putobject_INT2FIX_1_: ruby_vminsn_type = 106;
pub const YARVINSN_trace_nop: ruby_vminsn_type = 107;
pub const YARVINSN_trace_getlocal: ruby_vminsn_type = 108;
pub const YARVINSN_trace_setlocal: ruby_vminsn_type = 109;
pub const YARVINSN_trace_getblockparam: ruby_vminsn_type = 110;
pub const YARVINSN_trace_setblockparam: ruby_vminsn_type = 111;
pub const YARVINSN_trace_getblockparamproxy: ruby_vminsn_type = 112;
pub const YARVINSN_trace_getspecial: ruby_vminsn_type = 113;
pub const YARVINSN_trace_setspecial: ruby_vminsn_type = 114;
pub const YARVINSN_trace_getinstancevariable: ruby_vminsn_type = 115;
pub const YARVINSN_trace_setinstancevariable: ruby_vminsn_type = 116;
pub const YARVINSN_trace_getclassvariable: ruby_vminsn_type = 117;
pub const YARVINSN_trace_setclassvariable: ruby_vminsn_type = 118;
pub const YARVINSN_trace_opt_getconstant_path: ruby_vminsn_type = 119;
pub const YARVINSN_trace_getconstant: ruby_vminsn_type = 120;
pub const YARVINSN_trace_setconstant: ruby_vminsn_type = 121;
pub const YARVINSN_trace_getglobal: ruby_vminsn_type = 122;
pub const YARVINSN_trace_setglobal: ruby_vminsn_type = 123;
pub const YARVINSN_trace_putnil: ruby_vminsn_type = 124;
pub const YARVINSN_trace_putself: ruby_vminsn_type = 125;
pub const YARVINSN_trace_putobject: ruby_vminsn_type = 126;
pub const YARVINSN_trace_putspecialobject: ruby_vminsn_type = 127;
pub const YARVINSN_trace_putstring: ruby_vminsn_type = 128;
pub const YARVINSN_trace_putchilledstring: ruby_vminsn_type = 129;
pub const YARVINSN_trace_concatstrings: ruby_vminsn_type = 130;
pub const YARVINSN_trace_anytostring: ruby_vminsn_type = 131;
pub const YARVINSN_trace_toregexp: ruby_vminsn_type = 132;
pub const YARVINSN_trace_intern: ruby_vminsn_type = 133;
pub const YARVINSN_trace_newarray: ruby_vminsn_type = 134;
pub const YARVINSN_trace_pushtoarraykwsplat: ruby_vminsn_type = 135;
pub const YARVINSN_trace_duparray: ruby_vminsn_type = 136;
pub const YARVINSN_trace_duphash: ruby_vminsn_type = 137;
pub const YARVINSN_trace_expandarray: ruby_vminsn_type = 138;
pub const YARVINSN_trace_concatarray: ruby_vminsn_type = 139;
pub const YARVINSN_trace_concattoarray: ruby_vminsn_type = 140;
pub const YARVINSN_trace_pushtoarray: ruby_vminsn_type = 141;
pub const YARVINSN_trace_splatarray: ruby_vminsn_type = 142;
pub const YARVINSN_trace_splatkw: ruby_vminsn_type = 143;
pub const YARVINSN_trace_newhash: ruby_vminsn_type = 144;
pub const YARVINSN_trace_newrange: ruby_vminsn_type = 145;
pub const YARVINSN_trace_pop: ruby_vminsn_type = 146;
pub const YARVINSN_trace_dup: ruby_vminsn_type = 147;
pub const YARVINSN_trace_dupn: ruby_vminsn_type = 148;
pub const YARVINSN_trace_swap: ruby_vminsn_type = 149;
pub const YARVINSN_trace_opt_reverse: ruby_vminsn_type = 150;
pub const YARVINSN_trace_topn: ruby_vminsn_type = 151;
pub const YARVINSN_trace_setn: ruby_vminsn_type = 152;
pub const YARVINSN_trace_adjuststack: ruby_vminsn_type = 153;
pub const YARVINSN_trace_defined: ruby_vminsn_type = 154;
pub const YARVINSN_trace_definedivar: ruby_vminsn_type = 155;
pub const YARVINSN_trace_checkmatch: ruby_vminsn_type = 156;
pub const YARVINSN_trace_checkkeyword: ruby_vminsn_type = 157;
pub const YARVINSN_trace_checktype: ruby_vminsn_type = 158;
pub const YARVINSN_trace_defineclass: ruby_vminsn_type = 159;
pub const YARVINSN_trace_definemethod: ruby_vminsn_type = 160;
pub const YARVINSN_trace_definesmethod: ruby_vminsn_type = 161;
pub const YARVINSN_trace_send: ruby_vminsn_type = 162;
pub const YARVINSN_trace_sendforward: ruby_vminsn_type = 163;
pub const YARVINSN_trace_opt_send_without_block: ruby_vminsn_type = 164;
pub const YARVINSN_trace_objtostring: ruby_vminsn_type = 165;
pub const YARVINSN_trace_opt_str_freeze: ruby_vminsn_type = 166;
pub const YARVINSN_trace_opt_nil_p: ruby_vminsn_type = 167;
pub const YARVINSN_trace_opt_str_uminus: ruby_vminsn_type = 168;
pub const YARVINSN_trace_opt_newarray_send: ruby_vminsn_type = 169;
pub const YARVINSN_trace_invokesuper: ruby_vminsn_type = 170;
pub const YARVINSN_trace_invokesuperforward: ruby_vminsn_type = 171;
pub const YARVINSN_trace_invokeblock: ruby_vminsn_type = 172;
pub const YARVINSN_trace_leave: ruby_vminsn_type = 173;
pub const YARVINSN_trace_throw: ruby_vminsn_type = 174;
pub const YARVINSN_trace_jump: ruby_vminsn_type = 175;
pub const YARVINSN_trace_branchif: ruby_vminsn_type = 176;
pub const YARVINSN_trace_branchunless: ruby_vminsn_type = 177;
pub const YARVINSN_trace_branchnil: ruby_vminsn_type = 178;
pub const YARVINSN_trace_once: ruby_vminsn_type = 179;
pub const YARVINSN_trace_opt_case_dispatch: ruby_vminsn_type = 180;
pub const YARVINSN_trace_opt_plus: ruby_vminsn_type = 181;
pub const YARVINSN_trace_opt_minus: ruby_vminsn_type = 182;
pub const YARVINSN_trace_opt_mult: ruby_vminsn_type = 183;
pub const YARVINSN_trace_opt_div: ruby_vminsn_type = 184;
pub const YARVINSN_trace_opt_mod: ruby_vminsn_type = 185;
pub const YARVINSN_trace_opt_eq: ruby_vminsn_type = 186;
pub const YARVINSN_trace_opt_neq: ruby_vminsn_type = 187;
pub const YARVINSN_trace_opt_lt: ruby_vminsn_type = 188;
pub const YARVINSN_trace_opt_le: ruby_vminsn_type = 189;
pub const YARVINSN_trace_opt_gt: ruby_vminsn_type = 190;
pub const YARVINSN_trace_opt_ge: ruby_vminsn_type = 191;
pub const YARVINSN_trace_opt_ltlt: ruby_vminsn_type = 192;
pub const YARVINSN_trace_opt_and: ruby_vminsn_type = 193;
pub const YARVINSN_trace_opt_or: ruby_vminsn_type = 194;
pub const YARVINSN_trace_opt_aref: ruby_vminsn_type = 195;
pub const YARVINSN_trace_opt_aset: ruby_vminsn_type = 196;
pub const YARVINSN_trace_opt_aset_with: ruby_vminsn_type = 197;
pub const YARVINSN_trace_opt_aref_with: ruby_vminsn_type = 198;
pub const YARVINSN_trace_opt_length: ruby_vminsn_type = 199;
pub const YARVINSN_trace_opt_size: ruby_vminsn_type = 200;
pub const YARVINSN_trace_opt_empty_p: ruby_vminsn_type = 201;
pub const YARVINSN_trace_opt_succ: ruby_vminsn_type = 202;
pub const YARVINSN_trace_opt_not: ruby_vminsn_type = 203;
pub const YARVINSN_trace_opt_regexpmatch2: ruby_vminsn_type = 204;
pub const YARVINSN_trace_invokebuiltin: ruby_vminsn_type = 205;
pub const YARVINSN_trace_opt_invokebuiltin_delegate: ruby_vminsn_type = 206;
pub const YARVINSN_trace_opt_invokebuiltin_delegate_leave: ruby_vminsn_type = 207;
pub const YARVINSN_trace_getlocal_WC_0: ruby_vminsn_type = 208;
pub const YARVINSN_trace_getlocal_WC_1: ruby_vminsn_type = 209;
pub const YARVINSN_trace_setlocal_WC_0: ruby_vminsn_type = 210;
pub const YARVINSN_trace_setlocal_WC_1: ruby_vminsn_type = 211;
pub const YARVINSN_trace_putobject_INT2FIX_0_: ruby_vminsn_type = 212;
pub const YARVINSN_trace_putobject_INT2FIX_1_: ruby_vminsn_type = 213;
pub const VM_INSTRUCTION_SIZE: ruby_vminsn_type = 214;
pub const YARVINSN_opt_ary_freeze: ruby_vminsn_type = 59;
pub const YARVINSN_opt_str_freeze: ruby_vminsn_type = 60;
pub const YARVINSN_opt_nil_p: ruby_vminsn_type = 61;
pub const YARVINSN_opt_str_uminus: ruby_vminsn_type = 62;
pub const YARVINSN_opt_newarray_send: ruby_vminsn_type = 63;
pub const YARVINSN_invokesuper: ruby_vminsn_type = 64;
pub const YARVINSN_invokesuperforward: ruby_vminsn_type = 65;
pub const YARVINSN_invokeblock: ruby_vminsn_type = 66;
pub const YARVINSN_leave: ruby_vminsn_type = 67;
pub const YARVINSN_throw: ruby_vminsn_type = 68;
pub const YARVINSN_jump: ruby_vminsn_type = 69;
pub const YARVINSN_branchif: ruby_vminsn_type = 70;
pub const YARVINSN_branchunless: ruby_vminsn_type = 71;
pub const YARVINSN_branchnil: ruby_vminsn_type = 72;
pub const YARVINSN_once: ruby_vminsn_type = 73;
pub const YARVINSN_opt_case_dispatch: ruby_vminsn_type = 74;
pub const YARVINSN_opt_plus: ruby_vminsn_type = 75;
pub const YARVINSN_opt_minus: ruby_vminsn_type = 76;
pub const YARVINSN_opt_mult: ruby_vminsn_type = 77;
pub const YARVINSN_opt_div: ruby_vminsn_type = 78;
pub const YARVINSN_opt_mod: ruby_vminsn_type = 79;
pub const YARVINSN_opt_eq: ruby_vminsn_type = 80;
pub const YARVINSN_opt_neq: ruby_vminsn_type = 81;
pub const YARVINSN_opt_lt: ruby_vminsn_type = 82;
pub const YARVINSN_opt_le: ruby_vminsn_type = 83;
pub const YARVINSN_opt_gt: ruby_vminsn_type = 84;
pub const YARVINSN_opt_ge: ruby_vminsn_type = 85;
pub const YARVINSN_opt_ltlt: ruby_vminsn_type = 86;
pub const YARVINSN_opt_and: ruby_vminsn_type = 87;
pub const YARVINSN_opt_or: ruby_vminsn_type = 88;
pub const YARVINSN_opt_aref: ruby_vminsn_type = 89;
pub const YARVINSN_opt_aset: ruby_vminsn_type = 90;
pub const YARVINSN_opt_aset_with: ruby_vminsn_type = 91;
pub const YARVINSN_opt_aref_with: ruby_vminsn_type = 92;
pub const YARVINSN_opt_length: ruby_vminsn_type = 93;
pub const YARVINSN_opt_size: ruby_vminsn_type = 94;
pub const YARVINSN_opt_empty_p: ruby_vminsn_type = 95;
pub const YARVINSN_opt_succ: ruby_vminsn_type = 96;
pub const YARVINSN_opt_not: ruby_vminsn_type = 97;
pub const YARVINSN_opt_regexpmatch2: ruby_vminsn_type = 98;
pub const YARVINSN_invokebuiltin: ruby_vminsn_type = 99;
pub const YARVINSN_opt_invokebuiltin_delegate: ruby_vminsn_type = 100;
pub const YARVINSN_opt_invokebuiltin_delegate_leave: ruby_vminsn_type = 101;
pub const YARVINSN_getlocal_WC_0: ruby_vminsn_type = 102;
pub const YARVINSN_getlocal_WC_1: ruby_vminsn_type = 103;
pub const YARVINSN_setlocal_WC_0: ruby_vminsn_type = 104;
pub const YARVINSN_setlocal_WC_1: ruby_vminsn_type = 105;
pub const YARVINSN_putobject_INT2FIX_0_: ruby_vminsn_type = 106;
pub const YARVINSN_putobject_INT2FIX_1_: ruby_vminsn_type = 107;
pub const YARVINSN_trace_nop: ruby_vminsn_type = 108;
pub const YARVINSN_trace_getlocal: ruby_vminsn_type = 109;
pub const YARVINSN_trace_setlocal: ruby_vminsn_type = 110;
pub const YARVINSN_trace_getblockparam: ruby_vminsn_type = 111;
pub const YARVINSN_trace_setblockparam: ruby_vminsn_type = 112;
pub const YARVINSN_trace_getblockparamproxy: ruby_vminsn_type = 113;
pub const YARVINSN_trace_getspecial: ruby_vminsn_type = 114;
pub const YARVINSN_trace_setspecial: ruby_vminsn_type = 115;
pub const YARVINSN_trace_getinstancevariable: ruby_vminsn_type = 116;
pub const YARVINSN_trace_setinstancevariable: ruby_vminsn_type = 117;
pub const YARVINSN_trace_getclassvariable: ruby_vminsn_type = 118;
pub const YARVINSN_trace_setclassvariable: ruby_vminsn_type = 119;
pub const YARVINSN_trace_opt_getconstant_path: ruby_vminsn_type = 120;
pub const YARVINSN_trace_getconstant: ruby_vminsn_type = 121;
pub const YARVINSN_trace_setconstant: ruby_vminsn_type = 122;
pub const YARVINSN_trace_getglobal: ruby_vminsn_type = 123;
pub const YARVINSN_trace_setglobal: ruby_vminsn_type = 124;
pub const YARVINSN_trace_putnil: ruby_vminsn_type = 125;
pub const YARVINSN_trace_putself: ruby_vminsn_type = 126;
pub const YARVINSN_trace_putobject: ruby_vminsn_type = 127;
pub const YARVINSN_trace_putspecialobject: ruby_vminsn_type = 128;
pub const YARVINSN_trace_putstring: ruby_vminsn_type = 129;
pub const YARVINSN_trace_putchilledstring: ruby_vminsn_type = 130;
pub const YARVINSN_trace_concatstrings: ruby_vminsn_type = 131;
pub const YARVINSN_trace_anytostring: ruby_vminsn_type = 132;
pub const YARVINSN_trace_toregexp: ruby_vminsn_type = 133;
pub const YARVINSN_trace_intern: ruby_vminsn_type = 134;
pub const YARVINSN_trace_newarray: ruby_vminsn_type = 135;
pub const YARVINSN_trace_pushtoarraykwsplat: ruby_vminsn_type = 136;
pub const YARVINSN_trace_duparray: ruby_vminsn_type = 137;
pub const YARVINSN_trace_duphash: ruby_vminsn_type = 138;
pub const YARVINSN_trace_expandarray: ruby_vminsn_type = 139;
pub const YARVINSN_trace_concatarray: ruby_vminsn_type = 140;
pub const YARVINSN_trace_concattoarray: ruby_vminsn_type = 141;
pub const YARVINSN_trace_pushtoarray: ruby_vminsn_type = 142;
pub const YARVINSN_trace_splatarray: ruby_vminsn_type = 143;
pub const YARVINSN_trace_splatkw: ruby_vminsn_type = 144;
pub const YARVINSN_trace_newhash: ruby_vminsn_type = 145;
pub const YARVINSN_trace_newrange: ruby_vminsn_type = 146;
pub const YARVINSN_trace_pop: ruby_vminsn_type = 147;
pub const YARVINSN_trace_dup: ruby_vminsn_type = 148;
pub const YARVINSN_trace_dupn: ruby_vminsn_type = 149;
pub const YARVINSN_trace_swap: ruby_vminsn_type = 150;
pub const YARVINSN_trace_opt_reverse: ruby_vminsn_type = 151;
pub const YARVINSN_trace_topn: ruby_vminsn_type = 152;
pub const YARVINSN_trace_setn: ruby_vminsn_type = 153;
pub const YARVINSN_trace_adjuststack: ruby_vminsn_type = 154;
pub const YARVINSN_trace_defined: ruby_vminsn_type = 155;
pub const YARVINSN_trace_definedivar: ruby_vminsn_type = 156;
pub const YARVINSN_trace_checkmatch: ruby_vminsn_type = 157;
pub const YARVINSN_trace_checkkeyword: ruby_vminsn_type = 158;
pub const YARVINSN_trace_checktype: ruby_vminsn_type = 159;
pub const YARVINSN_trace_defineclass: ruby_vminsn_type = 160;
pub const YARVINSN_trace_definemethod: ruby_vminsn_type = 161;
pub const YARVINSN_trace_definesmethod: ruby_vminsn_type = 162;
pub const YARVINSN_trace_send: ruby_vminsn_type = 163;
pub const YARVINSN_trace_sendforward: ruby_vminsn_type = 164;
pub const YARVINSN_trace_opt_send_without_block: ruby_vminsn_type = 165;
pub const YARVINSN_trace_objtostring: ruby_vminsn_type = 166;
pub const YARVINSN_trace_opt_ary_freeze: ruby_vminsn_type = 167;
pub const YARVINSN_trace_opt_str_freeze: ruby_vminsn_type = 168;
pub const YARVINSN_trace_opt_nil_p: ruby_vminsn_type = 169;
pub const YARVINSN_trace_opt_str_uminus: ruby_vminsn_type = 170;
pub const YARVINSN_trace_opt_newarray_send: ruby_vminsn_type = 171;
pub const YARVINSN_trace_invokesuper: ruby_vminsn_type = 172;
pub const YARVINSN_trace_invokesuperforward: ruby_vminsn_type = 173;
pub const YARVINSN_trace_invokeblock: ruby_vminsn_type = 174;
pub const YARVINSN_trace_leave: ruby_vminsn_type = 175;
pub const YARVINSN_trace_throw: ruby_vminsn_type = 176;
pub const YARVINSN_trace_jump: ruby_vminsn_type = 177;
pub const YARVINSN_trace_branchif: ruby_vminsn_type = 178;
pub const YARVINSN_trace_branchunless: ruby_vminsn_type = 179;
pub const YARVINSN_trace_branchnil: ruby_vminsn_type = 180;
pub const YARVINSN_trace_once: ruby_vminsn_type = 181;
pub const YARVINSN_trace_opt_case_dispatch: ruby_vminsn_type = 182;
pub const YARVINSN_trace_opt_plus: ruby_vminsn_type = 183;
pub const YARVINSN_trace_opt_minus: ruby_vminsn_type = 184;
pub const YARVINSN_trace_opt_mult: ruby_vminsn_type = 185;
pub const YARVINSN_trace_opt_div: ruby_vminsn_type = 186;
pub const YARVINSN_trace_opt_mod: ruby_vminsn_type = 187;
pub const YARVINSN_trace_opt_eq: ruby_vminsn_type = 188;
pub const YARVINSN_trace_opt_neq: ruby_vminsn_type = 189;
pub const YARVINSN_trace_opt_lt: ruby_vminsn_type = 190;
pub const YARVINSN_trace_opt_le: ruby_vminsn_type = 191;
pub const YARVINSN_trace_opt_gt: ruby_vminsn_type = 192;
pub const YARVINSN_trace_opt_ge: ruby_vminsn_type = 193;
pub const YARVINSN_trace_opt_ltlt: ruby_vminsn_type = 194;
pub const YARVINSN_trace_opt_and: ruby_vminsn_type = 195;
pub const YARVINSN_trace_opt_or: ruby_vminsn_type = 196;
pub const YARVINSN_trace_opt_aref: ruby_vminsn_type = 197;
pub const YARVINSN_trace_opt_aset: ruby_vminsn_type = 198;
pub const YARVINSN_trace_opt_aset_with: ruby_vminsn_type = 199;
pub const YARVINSN_trace_opt_aref_with: ruby_vminsn_type = 200;
pub const YARVINSN_trace_opt_length: ruby_vminsn_type = 201;
pub const YARVINSN_trace_opt_size: ruby_vminsn_type = 202;
pub const YARVINSN_trace_opt_empty_p: ruby_vminsn_type = 203;
pub const YARVINSN_trace_opt_succ: ruby_vminsn_type = 204;
pub const YARVINSN_trace_opt_not: ruby_vminsn_type = 205;
pub const YARVINSN_trace_opt_regexpmatch2: ruby_vminsn_type = 206;
pub const YARVINSN_trace_invokebuiltin: ruby_vminsn_type = 207;
pub const YARVINSN_trace_opt_invokebuiltin_delegate: ruby_vminsn_type = 208;
pub const YARVINSN_trace_opt_invokebuiltin_delegate_leave: ruby_vminsn_type = 209;
pub const YARVINSN_trace_getlocal_WC_0: ruby_vminsn_type = 210;
pub const YARVINSN_trace_getlocal_WC_1: ruby_vminsn_type = 211;
pub const YARVINSN_trace_setlocal_WC_0: ruby_vminsn_type = 212;
pub const YARVINSN_trace_setlocal_WC_1: ruby_vminsn_type = 213;
pub const YARVINSN_trace_putobject_INT2FIX_0_: ruby_vminsn_type = 214;
pub const YARVINSN_trace_putobject_INT2FIX_1_: ruby_vminsn_type = 215;
pub const VM_INSTRUCTION_SIZE: ruby_vminsn_type = 216;
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),