From a99707cd9c6a1d53cf8ebc883dc210219bd67a28 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89tienne=20Barri=C3=A9?= Date: Mon, 29 Jul 2024 12:15:02 +0200 Subject: [PATCH] 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 --- array.c | 4 + compile.c | 53 ++++- insns.def | 15 ++ internal/array.h | 1 + lib/ruby_vm/rjit/insn_compiler.rb | 19 ++ test/ruby/test_optimization.rb | 46 +++++ vm.c | 2 +- vm_insnhelper.c | 11 ++ yjit/src/codegen.rs | 18 ++ yjit/src/cruby_bindings.inc.rs | 314 +++++++++++++++--------------- 10 files changed, 324 insertions(+), 159 deletions(-) diff --git a/array.c b/array.c index 318449abb4..91f75d915f 100644 --- a/array.c +++ b/array.c @@ -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" diff --git a/compile.c b/compile.c index cf75dce619..32bcbf69af 100644 --- a/compile.c +++ b/compile.c @@ -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 , nil + * => + * opt_ary_freeze [...], + */ + 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 , nil + * => + * opt_ary_freeze [], + */ + 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) { diff --git a/insns.def b/insns.def index c8dcd61bec..8a763d6187 100644 --- a/insns.def +++ b/insns.def @@ -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) diff --git a/internal/array.h b/internal/array.h index 39f6fcbea6..398676df4a 100644 --- a/internal/array.h +++ b/internal/array.h @@ -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); diff --git a/lib/ruby_vm/rjit/insn_compiler.rb b/lib/ruby_vm/rjit/insn_compiler.rb index 7a9a0f3aa5..c6b886e192 100644 --- a/lib/ruby_vm/rjit/insn_compiler.rb +++ b/lib/ruby_vm/rjit/insn_compiler.rb @@ -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] diff --git a/test/ruby/test_optimization.rb b/test/ruby/test_optimization.rb index a7a0582dbb..671f7d7ed5 100644 --- a/test/ruby/test_optimization.rb +++ b/test/ruby/test_optimization.rb @@ -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 diff --git a/vm.c b/vm.c index b1e0780d9e..0f0c3c91b1 100644 --- a/vm.c +++ b/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)); diff --git a/vm_insnhelper.c b/vm_insnhelper.c index 227bfa2004..bc133f4013 100644 --- a/vm_insnhelper.c +++ b/vm_insnhelper.c @@ -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) { diff --git a/yjit/src/codegen.rs b/yjit/src/codegen.rs index 493e61c28b..08aaa60731 100644 --- a/yjit/src/codegen.rs +++ b/yjit/src/codegen.rs @@ -4187,6 +4187,23 @@ fn gen_opt_str_freeze( Some(KeepCompiling) } +fn gen_opt_ary_freeze( + jit: &mut JITState, + asm: &mut Assembler, +) -> Option { + 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 { 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), diff --git a/yjit/src/cruby_bindings.inc.rs b/yjit/src/cruby_bindings.inc.rs index 4720b4f4ea..7492a28f22 100644 --- a/yjit/src/cruby_bindings.inc.rs +++ b/yjit/src/cruby_bindings.inc.rs @@ -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),