Inline Class#new.

This commit inlines instructions for Class#new.  To make this work, we
added a new YARV instructions, `opt_new`.  `opt_new` checks whether or
not the `new` method is the default allocator method.  If it is, it
allocates the object, and pushes the instance on the stack.  If not, the
instruction jumps to the "slow path" method call instructions.

Old instructions:

```
> ruby --dump=insns -e'Object.new'
== disasm: #<ISeq:<main>@-e:1 (1,0)-(1,10)>
0000 opt_getconstant_path                   <ic:0 Object>             (   1)[Li]
0002 opt_send_without_block                 <calldata!mid:new, argc:0, ARGS_SIMPLE>
0004 leave
```

New instructions:

```
> ./miniruby --dump=insns -e'Object.new'
== disasm: #<ISeq:<main>@-e:1 (1,0)-(1,10)>
0000 opt_getconstant_path                   <ic:0 Object>             (   1)[Li]
0002 putnil
0003 swap
0004 opt_new                                <calldata!mid:new, argc:0, ARGS_SIMPLE>, 11
0007 opt_send_without_block                 <calldata!mid:initialize, argc:0, FCALL|ARGS_SIMPLE>
0009 jump                                   14
0011 opt_send_without_block                 <calldata!mid:new, argc:0, ARGS_SIMPLE>
0013 swap
0014 pop
0015 leave
```

This commit speeds up basic object allocation (`Foo.new`) by 60%, but
classes that take keyword parameters see an even bigger benefit because
no hash is allocated when instantiating the object (3x to 6x faster).

Here is an example that uses `Hash.new(capacity: 0)`:

```
> hyperfine "ruby --disable-gems -e'i = 0; while i < 10_000_000; Hash.new(capacity: 0); i += 1; end'" "./ruby --disable-gems -e'i = 0; while i < 10_000_000; Hash.new(capacity: 0); i += 1; end'"
Benchmark 1: ruby --disable-gems -e'i = 0; while i < 10_000_000; Hash.new(capacity: 0); i += 1; end'
  Time (mean ± σ):      1.082 s ±  0.004 s    [User: 1.074 s, System: 0.008 s]
  Range (min … max):    1.076 s …  1.088 s    10 runs

Benchmark 2: ./ruby --disable-gems -e'i = 0; while i < 10_000_000; Hash.new(capacity: 0); i += 1; end'
  Time (mean ± σ):     627.9 ms ±   3.5 ms    [User: 622.7 ms, System: 4.8 ms]
  Range (min … max):   622.7 ms … 633.2 ms    10 runs

Summary
  ./ruby --disable-gems -e'i = 0; while i < 10_000_000; Hash.new(capacity: 0); i += 1; end' ran
    1.72 ± 0.01 times faster than ruby --disable-gems -e'i = 0; while i < 10_000_000; Hash.new(capacity: 0); i += 1; end'
```

This commit changes the backtrace for `initialize`:

```
aaron@tc ~/g/ruby (inline-new)> cat test.rb
class Foo
  def initialize
    puts caller
  end
end

def hello
  Foo.new
end

hello
aaron@tc ~/g/ruby (inline-new)> ruby -v test.rb
ruby 3.4.2 (2025-02-15 revision d2930f8e7a) +PRISM [arm64-darwin24]
test.rb:8:in 'Class#new'
test.rb:8:in 'Object#hello'
test.rb:11:in '<main>'
aaron@tc ~/g/ruby (inline-new)> ./miniruby -v test.rb
ruby 3.5.0dev (2025-03-28T23:59:40Z inline-new c4157884e4) +PRISM [arm64-darwin24]
test.rb:8:in 'Object#hello'
test.rb:11:in '<main>'
```

It also increases memory usage for calls to `new` by 122 bytes:

```
aaron@tc ~/g/ruby (inline-new)> cat test.rb
require "objspace"

class Foo
  def initialize
    puts caller
  end
end

def hello
  Foo.new
end

puts ObjectSpace.memsize_of(RubyVM::InstructionSequence.of(method(:hello)))
aaron@tc ~/g/ruby (inline-new)> make runruby
RUBY_ON_BUG='gdb -x ./.gdbinit -p' ./miniruby -I./lib -I. -I.ext/common  ./tool/runruby.rb --extout=.ext  -- --disable-gems  ./test.rb
656
aaron@tc ~/g/ruby (inline-new)> ruby -v test.rb
ruby 3.4.2 (2025-02-15 revision d2930f8e7a) +PRISM [arm64-darwin24]
544
```

Thanks to @ko1 for coming up with this idea!

Co-Authored-By: John Hawthorn <john@hawthorn.email>
This commit is contained in:
Aaron Patterson 2025-03-17 16:59:19 -07:00 committed by Aaron Patterson
parent e0545a0250
commit 8ac8225c50
10 changed files with 355 additions and 192 deletions

View File

@ -316,6 +316,9 @@ RB_DEBUG_COUNTER(obj_imemo_callinfo)
RB_DEBUG_COUNTER(obj_imemo_callcache)
RB_DEBUG_COUNTER(obj_imemo_constcache)
RB_DEBUG_COUNTER(opt_new_hit)
RB_DEBUG_COUNTER(opt_new_miss)
/* ar_table */
RB_DEBUG_COUNTER(artable_hint_hit)
RB_DEBUG_COUNTER(artable_hint_miss)

View File

@ -905,6 +905,30 @@ opt_send_without_block
}
}
/* Jump if "new" method has been defined by user */
DEFINE_INSN
opt_new
(CALL_DATA cd, OFFSET dst)
()
()
// attr bool leaf = false;
{
VALUE argc = vm_ci_argc(cd->ci);
VALUE val = TOPN(argc);
if (vm_method_cfunc_is(GET_ISEQ(), cd, val, rb_class_new_instance_pass_kw)) {
RB_DEBUG_COUNTER_INC(opt_new_hit);
val = rb_obj_alloc(val);
TOPN(argc) = val;
RUBY_ASSERT(TOPN(argc + 1) == Qnil);
TOPN(argc + 1) = val;
}
else {
RB_DEBUG_COUNTER_INC(opt_new_miss);
JUMP(dst);
}
}
/* Convert object to string using to_s or equivalent. */
DEFINE_INSN
objtostring

View File

@ -472,7 +472,17 @@ class ERB::Compiler # :nodoc:
return enc, frozen
end
# :stopdoc:
WARNING_UPLEVEL = Class.new {
attr_reader :c
def initialize from
@c = caller.length - from.length
end
}.new(caller(0)).c
private_constant :WARNING_UPLEVEL
# :startdoc:
def warn_invalid_trim_mode(mode, uplevel:)
warn "Invalid ERB trim mode: #{mode.inspect} (trim_mode: nil, 0, 1, 2, or String composed of '%' and/or '-', '>', '<>')", uplevel: uplevel + 1
warn "Invalid ERB trim mode: #{mode.inspect} (trim_mode: nil, 0, 1, 2, or String composed of '%' and/or '-', '>', '<>')", uplevel: uplevel + WARNING_UPLEVEL
end
end

View File

@ -3620,6 +3620,9 @@ pm_compile_call(rb_iseq_t *iseq, const pm_call_node_t *call_node, LINK_ANCHOR *c
if (message_loc->start == NULL) message_loc = &call_node->base.location;
const pm_node_location_t location = PM_LOCATION_START_LOCATION(scope_node->parser, message_loc, call_node->base.node_id);
LINK_ELEMENT *opt_new_prelude = LAST_ELEMENT(ret);
LABEL *else_label = NEW_LABEL(location.line);
LABEL *end_label = NEW_LABEL(location.line);
LABEL *retry_end_l = NEW_LABEL(location.line);
@ -3714,7 +3717,49 @@ pm_compile_call(rb_iseq_t *iseq, const pm_call_node_t *call_node, LINK_ANCHOR *c
PUSH_INSN(ret, location, splatkw);
}
PUSH_SEND_R(ret, location, method_id, INT2FIX(orig_argc), block_iseq, INT2FIX(flags), kw_arg);
LABEL *not_basic_new = NEW_LABEL(location.line);
LABEL *not_basic_new_finish = NEW_LABEL(location.line);
bool inline_new = ISEQ_COMPILE_DATA(iseq)->option->specialized_instruction &&
method_id == rb_intern("new") &&
call_node->block == NULL;
if (inline_new) {
if (LAST_ELEMENT(ret) == opt_new_prelude) {
PUSH_INSN(ret, location, putnil);
PUSH_INSN(ret, location, swap);
}
else {
ELEM_INSERT_NEXT(opt_new_prelude, &new_insn_body(iseq, location.line, location.node_id, BIN(swap), 0)->link);
ELEM_INSERT_NEXT(opt_new_prelude, &new_insn_body(iseq, location.line, location.node_id, BIN(putnil), 0)->link);
}
// Jump unless the receiver uses the "basic" implementation of "new"
VALUE ci;
if (flags & VM_CALL_FORWARDING) {
ci = (VALUE)new_callinfo(iseq, method_id, orig_argc + 1, flags, kw_arg, 0);
}
else {
ci = (VALUE)new_callinfo(iseq, method_id, orig_argc, flags, kw_arg, 0);
}
PUSH_INSN2(ret, location, opt_new, ci, not_basic_new);
LABEL_REF(not_basic_new);
// optimized path
PUSH_SEND_R(ret, location, rb_intern("initialize"), INT2FIX(orig_argc), block_iseq, INT2FIX(flags | VM_CALL_FCALL), kw_arg);
PUSH_INSNL(ret, location, jump, not_basic_new_finish);
PUSH_LABEL(ret, not_basic_new);
// Fall back to normal send
PUSH_SEND_R(ret, location, method_id, INT2FIX(orig_argc), block_iseq, INT2FIX(flags), kw_arg);
PUSH_INSN(ret, location, swap);
PUSH_LABEL(ret, not_basic_new_finish);
PUSH_INSN(ret, location, pop);
}
else {
PUSH_SEND_R(ret, location, method_id, INT2FIX(orig_argc), block_iseq, INT2FIX(flags), kw_arg);
}
if (block_iseq && ISEQ_BODY(block_iseq)->catch_table) {
pm_compile_retry_end_label(iseq, ret, retry_end_l);

View File

@ -251,6 +251,12 @@ EOS
assert_equal("line\r\n" * 3, erb.result)
end
def test_safe_level_warning
assert_warning(/#{__FILE__}:#{__LINE__ + 1}/) do
@erb.new("", 1)
end
end
def test_invalid_trim_mode
pend if RUBY_ENGINE == 'truffleruby'

View File

@ -203,8 +203,8 @@ class TestObjSpace < Test::Unit::TestCase
assert_equal(line1, ObjectSpace.allocation_sourceline(o1))
assert_equal(__FILE__, ObjectSpace.allocation_sourcefile(o1))
assert_equal(c1, ObjectSpace.allocation_generation(o1))
assert_equal(Class.name, ObjectSpace.allocation_class_path(o1))
assert_equal(:new, ObjectSpace.allocation_method_id(o1))
assert_equal(self.class.name, ObjectSpace.allocation_class_path(o1))
assert_equal(__method__, ObjectSpace.allocation_method_id(o1))
assert_equal(__FILE__, ObjectSpace.allocation_sourcefile(o2))
assert_equal(line2, ObjectSpace.allocation_sourceline(o2))

View File

@ -1999,7 +1999,7 @@ CODE
TracePoint.new(:c_call, &capture_events).enable{
c.new
}
assert_equal [:c_call, :itself, :initialize], events[1]
assert_equal [:c_call, :itself, :initialize], events[0]
events.clear
o = Class.new{

View File

@ -389,6 +389,8 @@ fn main() {
// From internal/object.h
.allowlist_function("rb_class_allocate_instance")
.allowlist_function("rb_obj_equal")
.allowlist_function("rb_class_new_instance_pass_kw")
.allowlist_function("rb_obj_alloc")
// From gc.h and internal/gc.h
.allowlist_function("rb_obj_info")

View File

@ -4873,6 +4873,70 @@ fn gen_throw(
Some(EndBlock)
}
fn gen_opt_new(
jit: &mut JITState,
asm: &mut Assembler,
) -> Option<CodegenStatus> {
let cd = jit.get_arg(0).as_ptr();
let jump_offset = jit.get_arg(1).as_i32();
if !jit.at_compile_target() {
return jit.defer_compilation(asm);
}
let ci = unsafe { get_call_data_ci(cd) }; // info about the call site
let mid = unsafe { vm_ci_mid(ci) };
let argc: i32 = unsafe { vm_ci_argc(ci) }.try_into().unwrap();
let recv_idx = argc;
let comptime_recv = jit.peek_at_stack(&asm.ctx, recv_idx as isize);
// This is a singleton class
let comptime_recv_klass = comptime_recv.class_of();
let recv = asm.stack_opnd(recv_idx);
perf_call!("opt_new: ", jit_guard_known_klass(
jit,
asm,
comptime_recv_klass,
recv,
recv.into(),
comptime_recv,
SEND_MAX_DEPTH,
Counter::guard_send_klass_megamorphic,
));
// We now know that it's always comptime_recv_klass
if jit.assume_expected_cfunc(asm, comptime_recv_klass, mid, rb_class_new_instance_pass_kw as _) {
// Fast path
// call rb_class_alloc to actually allocate
jit_prepare_non_leaf_call(jit, asm);
let obj = asm.ccall(rb_obj_alloc as _, vec![comptime_recv.into()]);
// Get a reference to the stack location where we need to save the
// return instance.
let result = asm.stack_opnd(recv_idx + 1);
let recv = asm.stack_opnd(recv_idx);
// Replace the receiver for the upcoming initialize call
asm.ctx.set_opnd_mapping(recv.into(), TempMapping::MapToStack(Type::UnknownHeap));
asm.mov(recv, obj);
// Save the allocated object for return
asm.ctx.set_opnd_mapping(result.into(), TempMapping::MapToStack(Type::UnknownHeap));
asm.mov(result, obj);
jump_to_next_insn(jit, asm)
} else {
// general case
// Get the branch target instruction offsets
let jump_idx = jit.next_insn_idx() as i32 + jump_offset;
return end_block_with_jump(jit, asm, jump_idx as u16);
}
}
fn gen_jump(
jit: &mut JITState,
asm: &mut Assembler,
@ -10699,6 +10763,7 @@ fn get_gen_fn(opcode: VALUE) -> Option<InsnGenFn> {
YARVINSN_branchnil => Some(gen_branchnil),
YARVINSN_throw => Some(gen_throw),
YARVINSN_jump => Some(gen_jump),
YARVINSN_opt_new => Some(gen_opt_new),
YARVINSN_getblockparamproxy => Some(gen_getblockparamproxy),
YARVINSN_getblockparam => Some(gen_getblockparam),

View File

@ -785,193 +785,195 @@ pub const YARVINSN_definesmethod: ruby_vminsn_type = 54;
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_ary_freeze: ruby_vminsn_type = 59;
pub const YARVINSN_opt_hash_freeze: ruby_vminsn_type = 60;
pub const YARVINSN_opt_str_freeze: ruby_vminsn_type = 61;
pub const YARVINSN_opt_nil_p: ruby_vminsn_type = 62;
pub const YARVINSN_opt_str_uminus: ruby_vminsn_type = 63;
pub const YARVINSN_opt_duparray_send: ruby_vminsn_type = 64;
pub const YARVINSN_opt_newarray_send: ruby_vminsn_type = 65;
pub const YARVINSN_invokesuper: ruby_vminsn_type = 66;
pub const YARVINSN_invokesuperforward: ruby_vminsn_type = 67;
pub const YARVINSN_invokeblock: ruby_vminsn_type = 68;
pub const YARVINSN_leave: ruby_vminsn_type = 69;
pub const YARVINSN_throw: ruby_vminsn_type = 70;
pub const YARVINSN_jump: ruby_vminsn_type = 71;
pub const YARVINSN_branchif: ruby_vminsn_type = 72;
pub const YARVINSN_branchunless: ruby_vminsn_type = 73;
pub const YARVINSN_branchnil: ruby_vminsn_type = 74;
pub const YARVINSN_once: ruby_vminsn_type = 75;
pub const YARVINSN_opt_case_dispatch: ruby_vminsn_type = 76;
pub const YARVINSN_opt_plus: ruby_vminsn_type = 77;
pub const YARVINSN_opt_minus: ruby_vminsn_type = 78;
pub const YARVINSN_opt_mult: ruby_vminsn_type = 79;
pub const YARVINSN_opt_div: ruby_vminsn_type = 80;
pub const YARVINSN_opt_mod: ruby_vminsn_type = 81;
pub const YARVINSN_opt_eq: ruby_vminsn_type = 82;
pub const YARVINSN_opt_neq: ruby_vminsn_type = 83;
pub const YARVINSN_opt_lt: ruby_vminsn_type = 84;
pub const YARVINSN_opt_le: ruby_vminsn_type = 85;
pub const YARVINSN_opt_gt: ruby_vminsn_type = 86;
pub const YARVINSN_opt_ge: ruby_vminsn_type = 87;
pub const YARVINSN_opt_ltlt: ruby_vminsn_type = 88;
pub const YARVINSN_opt_and: ruby_vminsn_type = 89;
pub const YARVINSN_opt_or: ruby_vminsn_type = 90;
pub const YARVINSN_opt_aref: ruby_vminsn_type = 91;
pub const YARVINSN_opt_aset: ruby_vminsn_type = 92;
pub const YARVINSN_opt_aset_with: ruby_vminsn_type = 93;
pub const YARVINSN_opt_aref_with: ruby_vminsn_type = 94;
pub const YARVINSN_opt_length: ruby_vminsn_type = 95;
pub const YARVINSN_opt_size: ruby_vminsn_type = 96;
pub const YARVINSN_opt_empty_p: ruby_vminsn_type = 97;
pub const YARVINSN_opt_succ: ruby_vminsn_type = 98;
pub const YARVINSN_opt_not: ruby_vminsn_type = 99;
pub const YARVINSN_opt_regexpmatch2: ruby_vminsn_type = 100;
pub const YARVINSN_invokebuiltin: ruby_vminsn_type = 101;
pub const YARVINSN_opt_invokebuiltin_delegate: ruby_vminsn_type = 102;
pub const YARVINSN_opt_invokebuiltin_delegate_leave: ruby_vminsn_type = 103;
pub const YARVINSN_getlocal_WC_0: ruby_vminsn_type = 104;
pub const YARVINSN_getlocal_WC_1: ruby_vminsn_type = 105;
pub const YARVINSN_setlocal_WC_0: ruby_vminsn_type = 106;
pub const YARVINSN_setlocal_WC_1: ruby_vminsn_type = 107;
pub const YARVINSN_putobject_INT2FIX_0_: ruby_vminsn_type = 108;
pub const YARVINSN_putobject_INT2FIX_1_: ruby_vminsn_type = 109;
pub const YARVINSN_zjit_opt_send_without_block: ruby_vminsn_type = 110;
pub const YARVINSN_zjit_opt_plus: ruby_vminsn_type = 111;
pub const YARVINSN_zjit_opt_minus: ruby_vminsn_type = 112;
pub const YARVINSN_zjit_opt_mult: ruby_vminsn_type = 113;
pub const YARVINSN_zjit_opt_div: ruby_vminsn_type = 114;
pub const YARVINSN_zjit_opt_mod: ruby_vminsn_type = 115;
pub const YARVINSN_zjit_opt_eq: ruby_vminsn_type = 116;
pub const YARVINSN_zjit_opt_neq: ruby_vminsn_type = 117;
pub const YARVINSN_zjit_opt_lt: ruby_vminsn_type = 118;
pub const YARVINSN_zjit_opt_le: ruby_vminsn_type = 119;
pub const YARVINSN_zjit_opt_gt: ruby_vminsn_type = 120;
pub const YARVINSN_zjit_opt_ge: ruby_vminsn_type = 121;
pub const YARVINSN_trace_nop: ruby_vminsn_type = 122;
pub const YARVINSN_trace_getlocal: ruby_vminsn_type = 123;
pub const YARVINSN_trace_setlocal: ruby_vminsn_type = 124;
pub const YARVINSN_trace_getblockparam: ruby_vminsn_type = 125;
pub const YARVINSN_trace_setblockparam: ruby_vminsn_type = 126;
pub const YARVINSN_trace_getblockparamproxy: ruby_vminsn_type = 127;
pub const YARVINSN_trace_getspecial: ruby_vminsn_type = 128;
pub const YARVINSN_trace_setspecial: ruby_vminsn_type = 129;
pub const YARVINSN_trace_getinstancevariable: ruby_vminsn_type = 130;
pub const YARVINSN_trace_setinstancevariable: ruby_vminsn_type = 131;
pub const YARVINSN_trace_getclassvariable: ruby_vminsn_type = 132;
pub const YARVINSN_trace_setclassvariable: ruby_vminsn_type = 133;
pub const YARVINSN_trace_opt_getconstant_path: ruby_vminsn_type = 134;
pub const YARVINSN_trace_getconstant: ruby_vminsn_type = 135;
pub const YARVINSN_trace_setconstant: ruby_vminsn_type = 136;
pub const YARVINSN_trace_getglobal: ruby_vminsn_type = 137;
pub const YARVINSN_trace_setglobal: ruby_vminsn_type = 138;
pub const YARVINSN_trace_putnil: ruby_vminsn_type = 139;
pub const YARVINSN_trace_putself: ruby_vminsn_type = 140;
pub const YARVINSN_trace_putobject: ruby_vminsn_type = 141;
pub const YARVINSN_trace_putspecialobject: ruby_vminsn_type = 142;
pub const YARVINSN_trace_putstring: ruby_vminsn_type = 143;
pub const YARVINSN_trace_putchilledstring: ruby_vminsn_type = 144;
pub const YARVINSN_trace_concatstrings: ruby_vminsn_type = 145;
pub const YARVINSN_trace_anytostring: ruby_vminsn_type = 146;
pub const YARVINSN_trace_toregexp: ruby_vminsn_type = 147;
pub const YARVINSN_trace_intern: ruby_vminsn_type = 148;
pub const YARVINSN_trace_newarray: ruby_vminsn_type = 149;
pub const YARVINSN_trace_pushtoarraykwsplat: ruby_vminsn_type = 150;
pub const YARVINSN_trace_duparray: ruby_vminsn_type = 151;
pub const YARVINSN_trace_duphash: ruby_vminsn_type = 152;
pub const YARVINSN_trace_expandarray: ruby_vminsn_type = 153;
pub const YARVINSN_trace_concatarray: ruby_vminsn_type = 154;
pub const YARVINSN_trace_concattoarray: ruby_vminsn_type = 155;
pub const YARVINSN_trace_pushtoarray: ruby_vminsn_type = 156;
pub const YARVINSN_trace_splatarray: ruby_vminsn_type = 157;
pub const YARVINSN_trace_splatkw: ruby_vminsn_type = 158;
pub const YARVINSN_trace_newhash: ruby_vminsn_type = 159;
pub const YARVINSN_trace_newrange: ruby_vminsn_type = 160;
pub const YARVINSN_trace_pop: ruby_vminsn_type = 161;
pub const YARVINSN_trace_dup: ruby_vminsn_type = 162;
pub const YARVINSN_trace_dupn: ruby_vminsn_type = 163;
pub const YARVINSN_trace_swap: ruby_vminsn_type = 164;
pub const YARVINSN_trace_opt_reverse: ruby_vminsn_type = 165;
pub const YARVINSN_trace_topn: ruby_vminsn_type = 166;
pub const YARVINSN_trace_setn: ruby_vminsn_type = 167;
pub const YARVINSN_trace_adjuststack: ruby_vminsn_type = 168;
pub const YARVINSN_trace_defined: ruby_vminsn_type = 169;
pub const YARVINSN_trace_definedivar: ruby_vminsn_type = 170;
pub const YARVINSN_trace_checkmatch: ruby_vminsn_type = 171;
pub const YARVINSN_trace_checkkeyword: ruby_vminsn_type = 172;
pub const YARVINSN_trace_checktype: ruby_vminsn_type = 173;
pub const YARVINSN_trace_defineclass: ruby_vminsn_type = 174;
pub const YARVINSN_trace_definemethod: ruby_vminsn_type = 175;
pub const YARVINSN_trace_definesmethod: ruby_vminsn_type = 176;
pub const YARVINSN_trace_send: ruby_vminsn_type = 177;
pub const YARVINSN_trace_sendforward: ruby_vminsn_type = 178;
pub const YARVINSN_trace_opt_send_without_block: ruby_vminsn_type = 179;
pub const YARVINSN_trace_objtostring: ruby_vminsn_type = 180;
pub const YARVINSN_trace_opt_ary_freeze: ruby_vminsn_type = 181;
pub const YARVINSN_trace_opt_hash_freeze: ruby_vminsn_type = 182;
pub const YARVINSN_trace_opt_str_freeze: ruby_vminsn_type = 183;
pub const YARVINSN_trace_opt_nil_p: ruby_vminsn_type = 184;
pub const YARVINSN_trace_opt_str_uminus: ruby_vminsn_type = 185;
pub const YARVINSN_trace_opt_duparray_send: ruby_vminsn_type = 186;
pub const YARVINSN_trace_opt_newarray_send: ruby_vminsn_type = 187;
pub const YARVINSN_trace_invokesuper: ruby_vminsn_type = 188;
pub const YARVINSN_trace_invokesuperforward: ruby_vminsn_type = 189;
pub const YARVINSN_trace_invokeblock: ruby_vminsn_type = 190;
pub const YARVINSN_trace_leave: ruby_vminsn_type = 191;
pub const YARVINSN_trace_throw: ruby_vminsn_type = 192;
pub const YARVINSN_trace_jump: ruby_vminsn_type = 193;
pub const YARVINSN_trace_branchif: ruby_vminsn_type = 194;
pub const YARVINSN_trace_branchunless: ruby_vminsn_type = 195;
pub const YARVINSN_trace_branchnil: ruby_vminsn_type = 196;
pub const YARVINSN_trace_once: ruby_vminsn_type = 197;
pub const YARVINSN_trace_opt_case_dispatch: ruby_vminsn_type = 198;
pub const YARVINSN_trace_opt_plus: ruby_vminsn_type = 199;
pub const YARVINSN_trace_opt_minus: ruby_vminsn_type = 200;
pub const YARVINSN_trace_opt_mult: ruby_vminsn_type = 201;
pub const YARVINSN_trace_opt_div: ruby_vminsn_type = 202;
pub const YARVINSN_trace_opt_mod: ruby_vminsn_type = 203;
pub const YARVINSN_trace_opt_eq: ruby_vminsn_type = 204;
pub const YARVINSN_trace_opt_neq: ruby_vminsn_type = 205;
pub const YARVINSN_trace_opt_lt: ruby_vminsn_type = 206;
pub const YARVINSN_trace_opt_le: ruby_vminsn_type = 207;
pub const YARVINSN_trace_opt_gt: ruby_vminsn_type = 208;
pub const YARVINSN_trace_opt_ge: ruby_vminsn_type = 209;
pub const YARVINSN_trace_opt_ltlt: ruby_vminsn_type = 210;
pub const YARVINSN_trace_opt_and: ruby_vminsn_type = 211;
pub const YARVINSN_trace_opt_or: ruby_vminsn_type = 212;
pub const YARVINSN_trace_opt_aref: ruby_vminsn_type = 213;
pub const YARVINSN_trace_opt_aset: ruby_vminsn_type = 214;
pub const YARVINSN_trace_opt_aset_with: ruby_vminsn_type = 215;
pub const YARVINSN_trace_opt_aref_with: ruby_vminsn_type = 216;
pub const YARVINSN_trace_opt_length: ruby_vminsn_type = 217;
pub const YARVINSN_trace_opt_size: ruby_vminsn_type = 218;
pub const YARVINSN_trace_opt_empty_p: ruby_vminsn_type = 219;
pub const YARVINSN_trace_opt_succ: ruby_vminsn_type = 220;
pub const YARVINSN_trace_opt_not: ruby_vminsn_type = 221;
pub const YARVINSN_trace_opt_regexpmatch2: ruby_vminsn_type = 222;
pub const YARVINSN_trace_invokebuiltin: ruby_vminsn_type = 223;
pub const YARVINSN_trace_opt_invokebuiltin_delegate: ruby_vminsn_type = 224;
pub const YARVINSN_trace_opt_invokebuiltin_delegate_leave: ruby_vminsn_type = 225;
pub const YARVINSN_trace_getlocal_WC_0: ruby_vminsn_type = 226;
pub const YARVINSN_trace_getlocal_WC_1: ruby_vminsn_type = 227;
pub const YARVINSN_trace_setlocal_WC_0: ruby_vminsn_type = 228;
pub const YARVINSN_trace_setlocal_WC_1: ruby_vminsn_type = 229;
pub const YARVINSN_trace_putobject_INT2FIX_0_: ruby_vminsn_type = 230;
pub const YARVINSN_trace_putobject_INT2FIX_1_: ruby_vminsn_type = 231;
pub const YARVINSN_trace_zjit_opt_send_without_block: ruby_vminsn_type = 232;
pub const YARVINSN_trace_zjit_opt_plus: ruby_vminsn_type = 233;
pub const YARVINSN_trace_zjit_opt_minus: ruby_vminsn_type = 234;
pub const YARVINSN_trace_zjit_opt_mult: ruby_vminsn_type = 235;
pub const YARVINSN_trace_zjit_opt_div: ruby_vminsn_type = 236;
pub const YARVINSN_trace_zjit_opt_mod: ruby_vminsn_type = 237;
pub const YARVINSN_trace_zjit_opt_eq: ruby_vminsn_type = 238;
pub const YARVINSN_trace_zjit_opt_neq: ruby_vminsn_type = 239;
pub const YARVINSN_trace_zjit_opt_lt: ruby_vminsn_type = 240;
pub const YARVINSN_trace_zjit_opt_le: ruby_vminsn_type = 241;
pub const YARVINSN_trace_zjit_opt_gt: ruby_vminsn_type = 242;
pub const YARVINSN_trace_zjit_opt_ge: ruby_vminsn_type = 243;
pub const VM_INSTRUCTION_SIZE: ruby_vminsn_type = 244;
pub const YARVINSN_opt_new: ruby_vminsn_type = 58;
pub const YARVINSN_objtostring: ruby_vminsn_type = 59;
pub const YARVINSN_opt_ary_freeze: ruby_vminsn_type = 60;
pub const YARVINSN_opt_hash_freeze: ruby_vminsn_type = 61;
pub const YARVINSN_opt_str_freeze: ruby_vminsn_type = 62;
pub const YARVINSN_opt_nil_p: ruby_vminsn_type = 63;
pub const YARVINSN_opt_str_uminus: ruby_vminsn_type = 64;
pub const YARVINSN_opt_duparray_send: ruby_vminsn_type = 65;
pub const YARVINSN_opt_newarray_send: ruby_vminsn_type = 66;
pub const YARVINSN_invokesuper: ruby_vminsn_type = 67;
pub const YARVINSN_invokesuperforward: ruby_vminsn_type = 68;
pub const YARVINSN_invokeblock: ruby_vminsn_type = 69;
pub const YARVINSN_leave: ruby_vminsn_type = 70;
pub const YARVINSN_throw: ruby_vminsn_type = 71;
pub const YARVINSN_jump: ruby_vminsn_type = 72;
pub const YARVINSN_branchif: ruby_vminsn_type = 73;
pub const YARVINSN_branchunless: ruby_vminsn_type = 74;
pub const YARVINSN_branchnil: ruby_vminsn_type = 75;
pub const YARVINSN_once: ruby_vminsn_type = 76;
pub const YARVINSN_opt_case_dispatch: ruby_vminsn_type = 77;
pub const YARVINSN_opt_plus: ruby_vminsn_type = 78;
pub const YARVINSN_opt_minus: ruby_vminsn_type = 79;
pub const YARVINSN_opt_mult: ruby_vminsn_type = 80;
pub const YARVINSN_opt_div: ruby_vminsn_type = 81;
pub const YARVINSN_opt_mod: ruby_vminsn_type = 82;
pub const YARVINSN_opt_eq: ruby_vminsn_type = 83;
pub const YARVINSN_opt_neq: ruby_vminsn_type = 84;
pub const YARVINSN_opt_lt: ruby_vminsn_type = 85;
pub const YARVINSN_opt_le: ruby_vminsn_type = 86;
pub const YARVINSN_opt_gt: ruby_vminsn_type = 87;
pub const YARVINSN_opt_ge: ruby_vminsn_type = 88;
pub const YARVINSN_opt_ltlt: ruby_vminsn_type = 89;
pub const YARVINSN_opt_and: ruby_vminsn_type = 90;
pub const YARVINSN_opt_or: ruby_vminsn_type = 91;
pub const YARVINSN_opt_aref: ruby_vminsn_type = 92;
pub const YARVINSN_opt_aset: ruby_vminsn_type = 93;
pub const YARVINSN_opt_aset_with: ruby_vminsn_type = 94;
pub const YARVINSN_opt_aref_with: ruby_vminsn_type = 95;
pub const YARVINSN_opt_length: ruby_vminsn_type = 96;
pub const YARVINSN_opt_size: ruby_vminsn_type = 97;
pub const YARVINSN_opt_empty_p: ruby_vminsn_type = 98;
pub const YARVINSN_opt_succ: ruby_vminsn_type = 99;
pub const YARVINSN_opt_not: ruby_vminsn_type = 100;
pub const YARVINSN_opt_regexpmatch2: ruby_vminsn_type = 101;
pub const YARVINSN_invokebuiltin: ruby_vminsn_type = 102;
pub const YARVINSN_opt_invokebuiltin_delegate: ruby_vminsn_type = 103;
pub const YARVINSN_opt_invokebuiltin_delegate_leave: ruby_vminsn_type = 104;
pub const YARVINSN_getlocal_WC_0: ruby_vminsn_type = 105;
pub const YARVINSN_getlocal_WC_1: ruby_vminsn_type = 106;
pub const YARVINSN_setlocal_WC_0: ruby_vminsn_type = 107;
pub const YARVINSN_setlocal_WC_1: ruby_vminsn_type = 108;
pub const YARVINSN_putobject_INT2FIX_0_: ruby_vminsn_type = 109;
pub const YARVINSN_putobject_INT2FIX_1_: ruby_vminsn_type = 110;
pub const YARVINSN_zjit_opt_send_without_block: ruby_vminsn_type = 111;
pub const YARVINSN_zjit_opt_plus: ruby_vminsn_type = 112;
pub const YARVINSN_zjit_opt_minus: ruby_vminsn_type = 113;
pub const YARVINSN_zjit_opt_mult: ruby_vminsn_type = 114;
pub const YARVINSN_zjit_opt_div: ruby_vminsn_type = 115;
pub const YARVINSN_zjit_opt_mod: ruby_vminsn_type = 116;
pub const YARVINSN_zjit_opt_eq: ruby_vminsn_type = 117;
pub const YARVINSN_zjit_opt_neq: ruby_vminsn_type = 118;
pub const YARVINSN_zjit_opt_lt: ruby_vminsn_type = 119;
pub const YARVINSN_zjit_opt_le: ruby_vminsn_type = 120;
pub const YARVINSN_zjit_opt_gt: ruby_vminsn_type = 121;
pub const YARVINSN_zjit_opt_ge: ruby_vminsn_type = 122;
pub const YARVINSN_trace_nop: ruby_vminsn_type = 123;
pub const YARVINSN_trace_getlocal: ruby_vminsn_type = 124;
pub const YARVINSN_trace_setlocal: ruby_vminsn_type = 125;
pub const YARVINSN_trace_getblockparam: ruby_vminsn_type = 126;
pub const YARVINSN_trace_setblockparam: ruby_vminsn_type = 127;
pub const YARVINSN_trace_getblockparamproxy: ruby_vminsn_type = 128;
pub const YARVINSN_trace_getspecial: ruby_vminsn_type = 129;
pub const YARVINSN_trace_setspecial: ruby_vminsn_type = 130;
pub const YARVINSN_trace_getinstancevariable: ruby_vminsn_type = 131;
pub const YARVINSN_trace_setinstancevariable: ruby_vminsn_type = 132;
pub const YARVINSN_trace_getclassvariable: ruby_vminsn_type = 133;
pub const YARVINSN_trace_setclassvariable: ruby_vminsn_type = 134;
pub const YARVINSN_trace_opt_getconstant_path: ruby_vminsn_type = 135;
pub const YARVINSN_trace_getconstant: ruby_vminsn_type = 136;
pub const YARVINSN_trace_setconstant: ruby_vminsn_type = 137;
pub const YARVINSN_trace_getglobal: ruby_vminsn_type = 138;
pub const YARVINSN_trace_setglobal: ruby_vminsn_type = 139;
pub const YARVINSN_trace_putnil: ruby_vminsn_type = 140;
pub const YARVINSN_trace_putself: ruby_vminsn_type = 141;
pub const YARVINSN_trace_putobject: ruby_vminsn_type = 142;
pub const YARVINSN_trace_putspecialobject: ruby_vminsn_type = 143;
pub const YARVINSN_trace_putstring: ruby_vminsn_type = 144;
pub const YARVINSN_trace_putchilledstring: ruby_vminsn_type = 145;
pub const YARVINSN_trace_concatstrings: ruby_vminsn_type = 146;
pub const YARVINSN_trace_anytostring: ruby_vminsn_type = 147;
pub const YARVINSN_trace_toregexp: ruby_vminsn_type = 148;
pub const YARVINSN_trace_intern: ruby_vminsn_type = 149;
pub const YARVINSN_trace_newarray: ruby_vminsn_type = 150;
pub const YARVINSN_trace_pushtoarraykwsplat: ruby_vminsn_type = 151;
pub const YARVINSN_trace_duparray: ruby_vminsn_type = 152;
pub const YARVINSN_trace_duphash: ruby_vminsn_type = 153;
pub const YARVINSN_trace_expandarray: ruby_vminsn_type = 154;
pub const YARVINSN_trace_concatarray: ruby_vminsn_type = 155;
pub const YARVINSN_trace_concattoarray: ruby_vminsn_type = 156;
pub const YARVINSN_trace_pushtoarray: ruby_vminsn_type = 157;
pub const YARVINSN_trace_splatarray: ruby_vminsn_type = 158;
pub const YARVINSN_trace_splatkw: ruby_vminsn_type = 159;
pub const YARVINSN_trace_newhash: ruby_vminsn_type = 160;
pub const YARVINSN_trace_newrange: ruby_vminsn_type = 161;
pub const YARVINSN_trace_pop: ruby_vminsn_type = 162;
pub const YARVINSN_trace_dup: ruby_vminsn_type = 163;
pub const YARVINSN_trace_dupn: ruby_vminsn_type = 164;
pub const YARVINSN_trace_swap: ruby_vminsn_type = 165;
pub const YARVINSN_trace_opt_reverse: ruby_vminsn_type = 166;
pub const YARVINSN_trace_topn: ruby_vminsn_type = 167;
pub const YARVINSN_trace_setn: ruby_vminsn_type = 168;
pub const YARVINSN_trace_adjuststack: ruby_vminsn_type = 169;
pub const YARVINSN_trace_defined: ruby_vminsn_type = 170;
pub const YARVINSN_trace_definedivar: ruby_vminsn_type = 171;
pub const YARVINSN_trace_checkmatch: ruby_vminsn_type = 172;
pub const YARVINSN_trace_checkkeyword: ruby_vminsn_type = 173;
pub const YARVINSN_trace_checktype: ruby_vminsn_type = 174;
pub const YARVINSN_trace_defineclass: ruby_vminsn_type = 175;
pub const YARVINSN_trace_definemethod: ruby_vminsn_type = 176;
pub const YARVINSN_trace_definesmethod: ruby_vminsn_type = 177;
pub const YARVINSN_trace_send: ruby_vminsn_type = 178;
pub const YARVINSN_trace_sendforward: ruby_vminsn_type = 179;
pub const YARVINSN_trace_opt_send_without_block: ruby_vminsn_type = 180;
pub const YARVINSN_trace_opt_new: ruby_vminsn_type = 181;
pub const YARVINSN_trace_objtostring: ruby_vminsn_type = 182;
pub const YARVINSN_trace_opt_ary_freeze: ruby_vminsn_type = 183;
pub const YARVINSN_trace_opt_hash_freeze: ruby_vminsn_type = 184;
pub const YARVINSN_trace_opt_str_freeze: ruby_vminsn_type = 185;
pub const YARVINSN_trace_opt_nil_p: ruby_vminsn_type = 186;
pub const YARVINSN_trace_opt_str_uminus: ruby_vminsn_type = 187;
pub const YARVINSN_trace_opt_duparray_send: ruby_vminsn_type = 188;
pub const YARVINSN_trace_opt_newarray_send: ruby_vminsn_type = 189;
pub const YARVINSN_trace_invokesuper: ruby_vminsn_type = 190;
pub const YARVINSN_trace_invokesuperforward: ruby_vminsn_type = 191;
pub const YARVINSN_trace_invokeblock: ruby_vminsn_type = 192;
pub const YARVINSN_trace_leave: ruby_vminsn_type = 193;
pub const YARVINSN_trace_throw: ruby_vminsn_type = 194;
pub const YARVINSN_trace_jump: ruby_vminsn_type = 195;
pub const YARVINSN_trace_branchif: ruby_vminsn_type = 196;
pub const YARVINSN_trace_branchunless: ruby_vminsn_type = 197;
pub const YARVINSN_trace_branchnil: ruby_vminsn_type = 198;
pub const YARVINSN_trace_once: ruby_vminsn_type = 199;
pub const YARVINSN_trace_opt_case_dispatch: ruby_vminsn_type = 200;
pub const YARVINSN_trace_opt_plus: ruby_vminsn_type = 201;
pub const YARVINSN_trace_opt_minus: ruby_vminsn_type = 202;
pub const YARVINSN_trace_opt_mult: ruby_vminsn_type = 203;
pub const YARVINSN_trace_opt_div: ruby_vminsn_type = 204;
pub const YARVINSN_trace_opt_mod: ruby_vminsn_type = 205;
pub const YARVINSN_trace_opt_eq: ruby_vminsn_type = 206;
pub const YARVINSN_trace_opt_neq: ruby_vminsn_type = 207;
pub const YARVINSN_trace_opt_lt: ruby_vminsn_type = 208;
pub const YARVINSN_trace_opt_le: ruby_vminsn_type = 209;
pub const YARVINSN_trace_opt_gt: ruby_vminsn_type = 210;
pub const YARVINSN_trace_opt_ge: ruby_vminsn_type = 211;
pub const YARVINSN_trace_opt_ltlt: ruby_vminsn_type = 212;
pub const YARVINSN_trace_opt_and: ruby_vminsn_type = 213;
pub const YARVINSN_trace_opt_or: ruby_vminsn_type = 214;
pub const YARVINSN_trace_opt_aref: ruby_vminsn_type = 215;
pub const YARVINSN_trace_opt_aset: ruby_vminsn_type = 216;
pub const YARVINSN_trace_opt_aset_with: ruby_vminsn_type = 217;
pub const YARVINSN_trace_opt_aref_with: ruby_vminsn_type = 218;
pub const YARVINSN_trace_opt_length: ruby_vminsn_type = 219;
pub const YARVINSN_trace_opt_size: ruby_vminsn_type = 220;
pub const YARVINSN_trace_opt_empty_p: ruby_vminsn_type = 221;
pub const YARVINSN_trace_opt_succ: ruby_vminsn_type = 222;
pub const YARVINSN_trace_opt_not: ruby_vminsn_type = 223;
pub const YARVINSN_trace_opt_regexpmatch2: ruby_vminsn_type = 224;
pub const YARVINSN_trace_invokebuiltin: ruby_vminsn_type = 225;
pub const YARVINSN_trace_opt_invokebuiltin_delegate: ruby_vminsn_type = 226;
pub const YARVINSN_trace_opt_invokebuiltin_delegate_leave: ruby_vminsn_type = 227;
pub const YARVINSN_trace_getlocal_WC_0: ruby_vminsn_type = 228;
pub const YARVINSN_trace_getlocal_WC_1: ruby_vminsn_type = 229;
pub const YARVINSN_trace_setlocal_WC_0: ruby_vminsn_type = 230;
pub const YARVINSN_trace_setlocal_WC_1: ruby_vminsn_type = 231;
pub const YARVINSN_trace_putobject_INT2FIX_0_: ruby_vminsn_type = 232;
pub const YARVINSN_trace_putobject_INT2FIX_1_: ruby_vminsn_type = 233;
pub const YARVINSN_trace_zjit_opt_send_without_block: ruby_vminsn_type = 234;
pub const YARVINSN_trace_zjit_opt_plus: ruby_vminsn_type = 235;
pub const YARVINSN_trace_zjit_opt_minus: ruby_vminsn_type = 236;
pub const YARVINSN_trace_zjit_opt_mult: ruby_vminsn_type = 237;
pub const YARVINSN_trace_zjit_opt_div: ruby_vminsn_type = 238;
pub const YARVINSN_trace_zjit_opt_mod: ruby_vminsn_type = 239;
pub const YARVINSN_trace_zjit_opt_eq: ruby_vminsn_type = 240;
pub const YARVINSN_trace_zjit_opt_neq: ruby_vminsn_type = 241;
pub const YARVINSN_trace_zjit_opt_lt: ruby_vminsn_type = 242;
pub const YARVINSN_trace_zjit_opt_le: ruby_vminsn_type = 243;
pub const YARVINSN_trace_zjit_opt_gt: ruby_vminsn_type = 244;
pub const YARVINSN_trace_zjit_opt_ge: ruby_vminsn_type = 245;
pub const VM_INSTRUCTION_SIZE: ruby_vminsn_type = 246;
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),
@ -1049,7 +1051,13 @@ extern "C" {
pub fn rb_intern2(name: *const ::std::os::raw::c_char, len: ::std::os::raw::c_long) -> ID;
pub fn rb_id2name(id: ID) -> *const ::std::os::raw::c_char;
pub fn rb_class2name(klass: VALUE) -> *const ::std::os::raw::c_char;
pub fn rb_class_new_instance_pass_kw(
argc: ::std::os::raw::c_int,
argv: *const VALUE,
klass: VALUE,
) -> VALUE;
pub fn rb_obj_is_kind_of(obj: VALUE, klass: VALUE) -> VALUE;
pub fn rb_obj_alloc(klass: VALUE) -> VALUE;
pub fn rb_obj_frozen_p(obj: VALUE) -> VALUE;
pub fn rb_backref_get() -> VALUE;
pub fn rb_range_new(beg: VALUE, end: VALUE, excl: ::std::os::raw::c_int) -> VALUE;