diff --git a/NEWS.md b/NEWS.md index 8b6d4e8817..a4380a83a1 100644 --- a/NEWS.md +++ b/NEWS.md @@ -7,6 +7,12 @@ Note that each entry is kept to a minimum, see links for details. ## Language changes +* String literals in files without a `frozen_string_literal` comment now behave + as if they were frozen. If they are mutated a deprecation warning is emited. + These warnings can be enabled with `-W:deprecated` or by setting `Warning[:deprecated] = true`. + To disable this change you can run Ruby with the `--disable-frozen-string-literal` command line + argument. [Feature #20205] + * `it` is added to reference a block parameter. [[Feature #18980]] * Keyword splatting `nil` when calling methods is now supported. diff --git a/bootstraptest/test_ractor.rb b/bootstraptest/test_ractor.rb index 3298ff1443..4868810308 100644 --- a/bootstraptest/test_ractor.rb +++ b/bootstraptest/test_ractor.rb @@ -1792,3 +1792,14 @@ assert_equal 'ok', %q{ } end # if !ENV['GITHUB_WORKFLOW'] + +# Chilled strings are not shareable +assert_equal 'false', %q{ + Ractor.shareable?("chilled") +} + +# Chilled strings can be made shareable +assert_equal 'true', %q{ + shareable = Ractor.make_shareable("chilled") + shareable == "chilled" && Ractor.shareable?(shareable) +} diff --git a/bootstraptest/test_yjit.rb b/bootstraptest/test_yjit.rb index ddd1e321a0..3eef86e0a9 100644 --- a/bootstraptest/test_yjit.rb +++ b/bootstraptest/test_yjit.rb @@ -4679,6 +4679,37 @@ assert_equal '[0, {1=>1}]', %q{ test(KwInit, [Hash.ruby2_keywords_hash({1 => 1})]) } +# Chilled string setivar trigger warning +assert_equal 'literal string will be frozen in the future', %q{ + Warning[:deprecated] = true + $VERBOSE = true + $warning = "no-warning" + module ::Warning + def self.warn(message) + $warning = message.split("warning: ").last.strip + end + end + + class String + def setivar! + @ivar = 42 + end + end + + def setivar!(str) + str.setivar! + end + + 10.times { setivar!("mutable".dup) } + 10.times do + setivar!("frozen".freeze) + rescue FrozenError + end + + setivar!("chilled") # Emit warning + $warning +} + # arity=-2 cfuncs assert_equal '["", "1/2", [0, [:ok, 1]]]', %q{ def test_cases(file, chain) diff --git a/class.c b/class.c index 98e7dfcc08..cee2065ae4 100644 --- a/class.c +++ b/class.c @@ -2244,7 +2244,10 @@ singleton_class_of(VALUE obj) return klass; case T_STRING: - if (FL_TEST_RAW(obj, RSTRING_FSTR)) { + if (CHILLED_STRING_P(obj)) { + CHILLED_STRING_MUTATED(obj); + } + else if (FL_TEST_RAW(obj, RSTRING_FSTR)) { rb_raise(rb_eTypeError, "can't define singleton"); } } diff --git a/compile.c b/compile.c index 099341bcf6..5516f64f54 100644 --- a/compile.c +++ b/compile.c @@ -4723,7 +4723,7 @@ frozen_string_literal_p(const rb_iseq_t *iseq) return ISEQ_COMPILE_DATA(iseq)->option->frozen_string_literal > 0; } -static inline int +static inline bool static_literal_node_p(const NODE *node, const rb_iseq_t *iseq, bool hash_key) { switch (nd_type(node)) { @@ -10365,12 +10365,18 @@ iseq_compile_each0(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *const no debugp_param("nd_lit", get_string_value(node)); if (!popped) { VALUE lit = get_string_value(node); - if (!frozen_string_literal_p(iseq)) { + switch (ISEQ_COMPILE_DATA(iseq)->option->frozen_string_literal) { + case ISEQ_FROZEN_STRING_LITERAL_UNSET: + lit = rb_fstring(lit); + ADD_INSN1(ret, node, putchilledstring, lit); + RB_OBJ_WRITTEN(iseq, Qundef, lit); + break; + case ISEQ_FROZEN_STRING_LITERAL_DISABLED: lit = rb_fstring(lit); ADD_INSN1(ret, node, putstring, lit); RB_OBJ_WRITTEN(iseq, Qundef, lit); - } - else { + break; + case ISEQ_FROZEN_STRING_LITERAL_ENABLED: if (ISEQ_COMPILE_DATA(iseq)->option->debug_frozen_string_literal || RTEST(ruby_debug)) { VALUE debug_info = rb_ary_new_from_args(2, rb_iseq_path(iseq), INT2FIX(line)); lit = rb_str_dup(lit); @@ -10382,6 +10388,9 @@ iseq_compile_each0(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *const no } ADD_INSN1(ret, node, putobject, lit); RB_OBJ_WRITTEN(iseq, Qundef, lit); + break; + default: + rb_bug("invalid frozen_string_literal"); } } break; diff --git a/error.c b/error.c index b9a99dc0bc..dc032df651 100644 --- a/error.c +++ b/error.c @@ -3860,6 +3860,12 @@ void rb_error_frozen_object(VALUE frozen_obj) { rb_yjit_lazy_push_frame(GET_EC()->cfp->pc); + + if (CHILLED_STRING_P(frozen_obj)) { + CHILLED_STRING_MUTATED(frozen_obj); + return; + } + VALUE debug_info; const ID created_info = id_debug_created_info; VALUE mesg = rb_sprintf("can't modify frozen %"PRIsVALUE": ", diff --git a/ext/objspace/objspace_dump.c b/ext/objspace/objspace_dump.c index d05fe66037..bb479b91c5 100644 --- a/ext/objspace/objspace_dump.c +++ b/ext/objspace/objspace_dump.c @@ -476,6 +476,8 @@ dump_object(VALUE obj, struct dump_config *dc) dump_append(dc, ", \"embedded\":true"); if (FL_TEST(obj, RSTRING_FSTR)) dump_append(dc, ", \"fstring\":true"); + if (CHILLED_STRING_P(obj)) + dump_append(dc, ", \"chilled\":true"); if (STR_SHARED_P(obj)) dump_append(dc, ", \"shared\":true"); else diff --git a/gems/bundled_gems b/gems/bundled_gems index 5b56c88a49..f64651592d 100644 --- a/gems/bundled_gems +++ b/gems/bundled_gems @@ -5,8 +5,12 @@ # - repository-url: URL from where clone for test # - revision: revision in repository-url to test # if `revision` is not given, "v"+`version` or `version` will be used. -minitest 5.22.3 https://github.com/minitest/minitest -power_assert 2.0.3 https://github.com/ruby/power_assert + +# Waiting for https://github.com/minitest/minitest/pull/991 +minitest 5.22.3 https://github.com/Shopify/minitest b5f5202575894796e00109a8f8a5041b778991ee + +# Waiting for https://github.com/ruby/power_assert/pull/48 +power_assert 2.0.3 https://github.com/ruby/power_assert 78dd2ab3ccd93796d83c0b35b978c39bfabb938c rake 13.1.0 https://github.com/ruby/rake test-unit 3.6.2 https://github.com/test-unit/test-unit rexml 3.2.6 https://github.com/ruby/rexml @@ -17,8 +21,8 @@ net-pop 0.1.2 https://github.com/ruby/net-pop net-smtp 0.4.0.1 https://github.com/ruby/net-smtp matrix 0.4.2 https://github.com/ruby/matrix prime 0.1.2 https://github.com/ruby/prime -rbs 3.4.4 https://github.com/ruby/rbs 61b412bc7ba00519e7d6d08450bd384990d94ea2 -typeprof 0.21.11 https://github.com/ruby/typeprof +rbs 3.4.4 https://github.com/ruby/rbs ba7872795d5de04adb8ff500c0e6afdc81a041dd +typeprof 0.21.11 https://github.com/ruby/typeprof b19a6416da3a05d57fadd6ffdadb382b6d236ca5 debug 1.9.1 https://github.com/ruby/debug 2d602636d99114d55a32fedd652c9c704446a749 racc 1.7.3 https://github.com/ruby/racc mutex_m 0.2.0 https://github.com/ruby/mutex_m diff --git a/include/ruby/internal/fl_type.h b/include/ruby/internal/fl_type.h index 16e0dfe139..eb212db7dc 100644 --- a/include/ruby/internal/fl_type.h +++ b/include/ruby/internal/fl_type.h @@ -916,6 +916,9 @@ static inline void RB_OBJ_FREEZE_RAW(VALUE obj) { RB_FL_SET_RAW(obj, RUBY_FL_FREEZE); + if (TYPE(obj) == T_STRING) { + RB_FL_UNSET_RAW(obj, FL_USER3); // STR_CHILLED + } } RUBY_SYMBOL_EXPORT_BEGIN diff --git a/include/ruby/internal/intern/error.h b/include/ruby/internal/intern/error.h index bf8daadd3e..11e147a121 100644 --- a/include/ruby/internal/intern/error.h +++ b/include/ruby/internal/intern/error.h @@ -190,7 +190,6 @@ RBIMPL_ATTR_NONNULL(()) */ void rb_error_frozen(const char *what); -RBIMPL_ATTR_NORETURN() /** * Identical to rb_error_frozen(), except it takes arbitrary Ruby object * instead of C's string. diff --git a/insns.def b/insns.def index 966f51ecfb..9c649904b8 100644 --- a/insns.def +++ b/insns.def @@ -375,7 +375,17 @@ putstring () (VALUE val) { - val = rb_ec_str_resurrect(ec, str); + val = rb_ec_str_resurrect(ec, str, false); +} + +/* put chilled string val. string will be copied but frozen in the future. */ +DEFINE_INSN +putchilledstring +(VALUE str) +() +(VALUE val) +{ + val = rb_ec_str_resurrect(ec, str, true); } /* put concatenate strings */ diff --git a/internal/string.h b/internal/string.h index cde81a1a25..fb37f73114 100644 --- a/internal/string.h +++ b/internal/string.h @@ -17,6 +17,7 @@ #define STR_NOEMBED FL_USER1 #define STR_SHARED FL_USER2 /* = ELTS_SHARED */ +#define STR_CHILLED FL_USER3 #ifdef rb_fstring_cstr # undef rb_fstring_cstr @@ -77,7 +78,7 @@ VALUE rb_id_quote_unprintable(ID); VALUE rb_sym_proc_call(ID mid, int argc, const VALUE *argv, int kw_splat, VALUE passed_proc); struct rb_execution_context_struct; -VALUE rb_ec_str_resurrect(struct rb_execution_context_struct *ec, VALUE str); +VALUE rb_ec_str_resurrect(struct rb_execution_context_struct *ec, VALUE str, bool chilled); #define rb_fstring_lit(str) rb_fstring_new((str), rb_strlen_lit(str)) #define rb_fstring_literal(str) rb_fstring_lit(str) @@ -108,6 +109,26 @@ STR_SHARED_P(VALUE str) return FL_ALL_RAW(str, STR_NOEMBED | STR_SHARED); } +static inline bool +CHILLED_STRING_P(VALUE obj) +{ + return RB_TYPE_P(obj, T_STRING) && FL_TEST_RAW(obj, STR_CHILLED); +} + +static inline void +CHILLED_STRING_MUTATED(VALUE str) +{ + rb_category_warn(RB_WARN_CATEGORY_DEPRECATED, "literal string will be frozen in the future"); + FL_UNSET_RAW(str, STR_CHILLED | FL_FREEZE); +} + +static inline void +STR_CHILL_RAW(VALUE str) +{ + // Chilled strings are always also frozen + FL_SET_RAW(str, STR_CHILLED | RUBY_FL_FREEZE); +} + static inline bool is_ascii_string(VALUE str) { diff --git a/iseq.c b/iseq.c index 1d903f9591..057e047ef9 100644 --- a/iseq.c +++ b/iseq.c @@ -720,18 +720,20 @@ finish_iseq_build(rb_iseq_t *iseq) } static rb_compile_option_t COMPILE_OPTION_DEFAULT = { - OPT_INLINE_CONST_CACHE, /* int inline_const_cache; */ - OPT_PEEPHOLE_OPTIMIZATION, /* int peephole_optimization; */ - OPT_TAILCALL_OPTIMIZATION, /* int tailcall_optimization */ - OPT_SPECIALISED_INSTRUCTION, /* int specialized_instruction; */ - OPT_OPERANDS_UNIFICATION, /* int operands_unification; */ - OPT_INSTRUCTIONS_UNIFICATION, /* int instructions_unification; */ - OPT_FROZEN_STRING_LITERAL, - OPT_DEBUG_FROZEN_STRING_LITERAL, - TRUE, /* coverage_enabled */ + .inline_const_cache = OPT_INLINE_CONST_CACHE, + .peephole_optimization = OPT_PEEPHOLE_OPTIMIZATION, + .tailcall_optimization = OPT_TAILCALL_OPTIMIZATION, + .specialized_instruction = OPT_SPECIALISED_INSTRUCTION, + .operands_unification = OPT_OPERANDS_UNIFICATION, + .instructions_unification = OPT_INSTRUCTIONS_UNIFICATION, + .frozen_string_literal = OPT_FROZEN_STRING_LITERAL, + .debug_frozen_string_literal = OPT_DEBUG_FROZEN_STRING_LITERAL, + .coverage_enabled = TRUE, }; -static const rb_compile_option_t COMPILE_OPTION_FALSE = {0}; +static const rb_compile_option_t COMPILE_OPTION_FALSE = { + .frozen_string_literal = -1, // unspecified +}; int rb_iseq_opt_frozen_string_literal(void) @@ -770,9 +772,11 @@ set_compile_option_from_ast(rb_compile_option_t *option, const rb_ast_body_t *as { #define SET_COMPILE_OPTION(o, a, mem) \ ((a)->mem < 0 ? 0 : ((o)->mem = (a)->mem > 0)) - SET_COMPILE_OPTION(option, ast, frozen_string_literal); SET_COMPILE_OPTION(option, ast, coverage_enabled); #undef SET_COMPILE_OPTION + if (ast->frozen_string_literal >= 0) { + option->frozen_string_literal = ast->frozen_string_literal; + } return option; } @@ -814,13 +818,14 @@ make_compile_option_value(rb_compile_option_t *option) SET_COMPILE_OPTION(option, opt, specialized_instruction); SET_COMPILE_OPTION(option, opt, operands_unification); SET_COMPILE_OPTION(option, opt, instructions_unification); - SET_COMPILE_OPTION(option, opt, frozen_string_literal); SET_COMPILE_OPTION(option, opt, debug_frozen_string_literal); SET_COMPILE_OPTION(option, opt, coverage_enabled); SET_COMPILE_OPTION_NUM(option, opt, debug_level); } #undef SET_COMPILE_OPTION #undef SET_COMPILE_OPTION_NUM + VALUE frozen_string_literal = option->frozen_string_literal == -1 ? Qnil : RBOOL(option->frozen_string_literal); + rb_hash_aset(opt, ID2SYM(rb_intern("frozen_string_literal")), frozen_string_literal); return opt; } @@ -1248,7 +1253,7 @@ pm_iseq_compile_with_option(VALUE src, VALUE file, VALUE realpath, VALUE line, V pm_parse_result_t result = { 0 }; pm_options_line_set(&result.options, NUM2INT(line)); - pm_options_frozen_string_literal_set(&result.options, option.frozen_string_literal); + pm_options_frozen_string_literal_init(&result, option.frozen_string_literal); VALUE error; if (RB_TYPE_P(src, T_FILE)) { diff --git a/iseq.h b/iseq.h index 78e0d900db..a0b59c441f 100644 --- a/iseq.h +++ b/iseq.h @@ -47,6 +47,10 @@ extern const ID rb_iseq_shared_exc_local_tbl[]; #define ISEQ_FLIP_CNT(iseq) ISEQ_BODY(iseq)->variable.flip_count +#define ISEQ_FROZEN_STRING_LITERAL_ENABLED 1 +#define ISEQ_FROZEN_STRING_LITERAL_DISABLED 0 +#define ISEQ_FROZEN_STRING_LITERAL_UNSET -1 + static inline rb_snum_t ISEQ_FLIP_CNT_INCREMENT(const rb_iseq_t *iseq) { @@ -227,7 +231,7 @@ struct rb_compile_option_struct { unsigned int specialized_instruction: 1; unsigned int operands_unification: 1; unsigned int instructions_unification: 1; - unsigned int frozen_string_literal: 1; + signed int frozen_string_literal: 2; /* -1: not specified, 0: false, 1: true */ unsigned int debug_frozen_string_literal: 1; unsigned int coverage_enabled: 1; int debug_level; diff --git a/lib/ruby_vm/rjit/insn_compiler.rb b/lib/ruby_vm/rjit/insn_compiler.rb index 1bcee7cb70..2346c92bd1 100644 --- a/lib/ruby_vm/rjit/insn_compiler.rb +++ b/lib/ruby_vm/rjit/insn_compiler.rb @@ -57,6 +57,7 @@ module RubyVM::RJIT when :putobject then putobject(jit, ctx, asm) when :putspecialobject then putspecialobject(jit, ctx, asm) when :putstring then putstring(jit, ctx, asm) + when :putchilledstring then putchilledstring(jit, ctx, asm) when :concatstrings then concatstrings(jit, ctx, asm) when :anytostring then anytostring(jit, ctx, asm) when :toregexp then toregexp(jit, ctx, asm) @@ -776,6 +777,27 @@ module RubyVM::RJIT asm.mov(C_ARGS[0], EC) asm.mov(C_ARGS[1], to_value(put_val)) + asm.mov(C_ARGS[2], 0) + asm.call(C.rb_ec_str_resurrect) + + stack_top = ctx.stack_push(Type::TString) + asm.mov(stack_top, C_RET) + + KeepCompiling + end + + # @param jit [RubyVM::RJIT::JITState] + # @param ctx [RubyVM::RJIT::Context] + # @param asm [RubyVM::RJIT::Assembler] + def putchilledstring(jit, ctx, asm) + put_val = jit.operand(0, ruby: true) + + # Save the PC and SP because the callee will allocate + jit_prepare_routine_call(jit, ctx, asm) + + asm.mov(C_ARGS[0], EC) + asm.mov(C_ARGS[1], to_value(put_val)) + asm.mov(C_ARGS[2], 1) asm.call(C.rb_ec_str_resurrect) stack_top = ctx.stack_push(Type::TString) diff --git a/mini_builtin.c b/mini_builtin.c index a93a5ebddb..dce822a86c 100644 --- a/mini_builtin.c +++ b/mini_builtin.c @@ -28,16 +28,16 @@ builtin_iseq_load(const char *feature_name, const struct rb_builtin_function *ta } vm->builtin_function_table = table; static const rb_compile_option_t optimization = { - TRUE, /* unsigned int inline_const_cache; */ - TRUE, /* unsigned int peephole_optimization; */ - FALSE,/* unsigned int tailcall_optimization; */ - TRUE, /* unsigned int specialized_instruction; */ - TRUE, /* unsigned int operands_unification; */ - TRUE, /* unsigned int instructions_unification; */ - TRUE, /* unsigned int frozen_string_literal; */ - FALSE, /* unsigned int debug_frozen_string_literal; */ - FALSE, /* unsigned int coverage_enabled; */ - 0, /* int debug_level; */ + .inline_const_cache = TRUE, + .peephole_optimization = TRUE, + .tailcall_optimization = FALSE, + .specialized_instruction = TRUE, + .operands_unification = TRUE, + .instructions_unification = TRUE, + .frozen_string_literal = TRUE, + .debug_frozen_string_literal = FALSE, + .coverage_enabled = FALSE, + .debug_level = 0, }; const rb_iseq_t *iseq = rb_iseq_new_with_opt(&ast->body, name_str, name_str, Qnil, 0, NULL, 0, ISEQ_TYPE_TOP, &optimization); GET_VM()->builtin_function_table = NULL; diff --git a/object.c b/object.c index 26c03075a0..572f577312 100644 --- a/object.c +++ b/object.c @@ -502,7 +502,10 @@ rb_obj_clone_setup(VALUE obj, VALUE clone, VALUE kwfreeze) case Qnil: rb_funcall(clone, id_init_clone, 1, obj); RBASIC(clone)->flags |= RBASIC(obj)->flags & FL_FREEZE; - if (RB_OBJ_FROZEN(obj)) { + if (CHILLED_STRING_P(obj)) { + STR_CHILL_RAW(clone); + } + else if (RB_OBJ_FROZEN(obj)) { rb_shape_t * next_shape = rb_shape_transition_shape_frozen(clone); if (!rb_shape_obj_too_complex(clone) && next_shape->type == SHAPE_OBJ_TOO_COMPLEX) { rb_evict_ivars_to_hash(clone); diff --git a/prism_compile.c b/prism_compile.c index 0508ced5ff..e919a44c08 100644 --- a/prism_compile.c +++ b/prism_compile.c @@ -787,6 +787,44 @@ pm_interpolated_node_compile(pm_node_list_t *parts, rb_iseq_t *iseq, NODE dummy_ if (parts_size > 0) { VALUE current_string = Qnil; + bool literal = true; + for (size_t index = 0; index < parts_size; index++) { + const pm_node_t *part = parts->nodes[index]; + + if (!PM_NODE_TYPE_P(part, PM_STRING_NODE)) { + literal = false; + break; + } + } + + if (literal) { + for (size_t index = 0; index < parts_size; index++) { + const pm_node_t *part = parts->nodes[index]; + const pm_string_node_t *string_node = (const pm_string_node_t *)part; + VALUE string_value = parse_string_encoded(scope_node, (pm_node_t *)string_node, &string_node->unescaped); + + if (RTEST(current_string)) { + current_string = rb_str_concat(current_string, string_value); + } + else { + current_string = string_value; + } + } + + const pm_node_t *part = parts->nodes[0]; + current_string = rb_fstring(current_string); + if (PM_NODE_FLAG_P(part, PM_STRING_FLAGS_FROZEN)) { + ADD_INSN1(ret, &dummy_line_node, putobject, current_string); + } + else if (PM_NODE_FLAG_P(part, PM_STRING_FLAGS_MUTABLE)) { + ADD_INSN1(ret, &dummy_line_node, putstring, current_string); + } + else { + ADD_INSN1(ret, &dummy_line_node, putchilledstring, current_string); + } + return 1; + } + for (size_t index = 0; index < parts_size; index++) { const pm_node_t *part = parts->nodes[index]; @@ -820,12 +858,7 @@ pm_interpolated_node_compile(pm_node_list_t *parts, rb_iseq_t *iseq, NODE dummy_ current_string = rb_enc_str_new(NULL, 0, scope_node->encoding); } - if (frozen_string_literal_p(iseq)) { - ADD_INSN1(ret, &dummy_line_node, putobject, rb_str_freeze(current_string)); - } - else { - ADD_INSN1(ret, &dummy_line_node, putstring, rb_str_freeze(current_string)); - } + ADD_INSN1(ret, &dummy_line_node, putobject, rb_fstring(current_string)); current_string = Qnil; number_of_items_pushed++; @@ -841,14 +874,7 @@ pm_interpolated_node_compile(pm_node_list_t *parts, rb_iseq_t *iseq, NODE dummy_ if (RTEST(current_string)) { current_string = rb_fstring(current_string); - - if (frozen_string_literal_p(iseq)) { - ADD_INSN1(ret, &dummy_line_node, putobject, current_string); - } - else { - ADD_INSN1(ret, &dummy_line_node, putstring, current_string); - } - + ADD_INSN1(ret, &dummy_line_node, putobject, current_string); current_string = Qnil; number_of_items_pushed++; } @@ -7925,9 +7951,12 @@ pm_compile_node(rb_iseq_t *iseq, const pm_node_t *node, LINK_ANCHOR *const ret, if (PM_NODE_FLAG_P(cast, PM_STRING_FLAGS_FROZEN)) { PUSH_INSN1(ret, location, putobject, string); } - else { + else if (PM_NODE_FLAG_P(cast, PM_STRING_FLAGS_MUTABLE)) { PUSH_INSN1(ret, location, putstring, string); } + else { + PUSH_INSN1(ret, location, putchilledstring, string); + } } return; } @@ -7979,9 +8008,12 @@ pm_compile_node(rb_iseq_t *iseq, const pm_node_t *node, LINK_ANCHOR *const ret, if (PM_NODE_FLAG_P(node, PM_STRING_FLAGS_FROZEN)) { PUSH_INSN1(ret, location, putobject, value); } - else { + else if (PM_NODE_FLAG_P(node, PM_STRING_FLAGS_MUTABLE)) { PUSH_INSN1(ret, location, putstring, value); } + else { + PUSH_INSN1(ret, location, putchilledstring, value); + } } return; } @@ -8354,6 +8386,24 @@ pm_parse_file_script_lines(const pm_scope_node_t *scope_node, const pm_parser_t return lines; } +void +pm_options_frozen_string_literal_init(pm_parse_result_t *result, int frozen_string_literal) +{ + switch (frozen_string_literal) { + case ISEQ_FROZEN_STRING_LITERAL_UNSET: + break; + case ISEQ_FROZEN_STRING_LITERAL_DISABLED: + pm_options_frozen_string_literal_set(&result->options, false); + break; + case ISEQ_FROZEN_STRING_LITERAL_ENABLED: + pm_options_frozen_string_literal_set(&result->options, true); + break; + default: + rb_bug("pm_options_frozen_string_literal_init: invalid frozen_string_literal=%d", frozen_string_literal); + break; + } +} + /** * Attempt to load the file into memory. Return a Ruby error if the file cannot * be read. diff --git a/prism_compile.h b/prism_compile.h index 427fa54b51..0c1510d67f 100644 --- a/prism_compile.h +++ b/prism_compile.h @@ -47,6 +47,7 @@ typedef struct { bool parsed; } pm_parse_result_t; +void pm_options_frozen_string_literal_init(pm_parse_result_t *result, int frozen_string_literal); VALUE pm_load_file(pm_parse_result_t *result, VALUE filepath); VALUE pm_parse_file(pm_parse_result_t *result, VALUE filepath); VALUE pm_load_parse_file(pm_parse_result_t *result, VALUE filepath); diff --git a/ractor.c b/ractor.c index 4eee3cc731..7b9c088ceb 100644 --- a/ractor.c +++ b/ractor.c @@ -2985,7 +2985,10 @@ rb_obj_traverse(VALUE obj, static int frozen_shareable_p(VALUE obj, bool *made_shareable) { - if (!RB_TYPE_P(obj, T_DATA)) { + if (CHILLED_STRING_P(obj)) { + return false; + } + else if (!RB_TYPE_P(obj, T_DATA)) { return true; } else if (RTYPEDDATA_P(obj)) { @@ -3014,6 +3017,17 @@ make_shareable_check_shareable(VALUE obj) if (rb_ractor_shareable_p(obj)) { return traverse_skip; } + else if (CHILLED_STRING_P(obj)) { + rb_funcall(obj, idFreeze, 0); + + if (UNLIKELY(!RB_OBJ_FROZEN_RAW(obj))) { + rb_raise(rb_eRactorError, "#freeze does not freeze object correctly"); + } + + if (RB_OBJ_SHAREABLE_P(obj)) { + return traverse_skip; + } + } else if (!frozen_shareable_p(obj, &made_shareable)) { if (made_shareable) { return traverse_skip; diff --git a/ruby.c b/ruby.c index 3b9cce01f1..5c1d44ec6d 100644 --- a/ruby.c +++ b/ruby.c @@ -2116,7 +2116,7 @@ prism_script(ruby_cmdline_options_t *opt, pm_parse_result_t *result) pm_options_t *options = &result->options; pm_options_line_set(options, 1); - pm_options_frozen_string_literal_set(&result->options, rb_iseq_opt_frozen_string_literal()); + pm_options_frozen_string_literal_init(result, rb_iseq_opt_frozen_string_literal()); if (opt->ext.enc.name != 0) { pm_options_encoding_set(options, StringValueCStr(opt->ext.enc.name)); diff --git a/spec/ruby/command_line/fixtures/string_literal_frozen_comment.rb b/spec/ruby/command_line/fixtures/string_literal_frozen_comment.rb new file mode 100644 index 0000000000..fb84b546c0 --- /dev/null +++ b/spec/ruby/command_line/fixtures/string_literal_frozen_comment.rb @@ -0,0 +1,4 @@ +# frozen_string_literal: true +frozen = "test".frozen? +interned = "test".equal?("test") +puts "frozen:#{frozen} interned:#{interned}" diff --git a/spec/ruby/command_line/fixtures/string_literal_mutable_comment.rb b/spec/ruby/command_line/fixtures/string_literal_mutable_comment.rb new file mode 100644 index 0000000000..381a742001 --- /dev/null +++ b/spec/ruby/command_line/fixtures/string_literal_mutable_comment.rb @@ -0,0 +1,4 @@ +# frozen_string_literal: false +frozen = "test".frozen? +interned = "test".equal?("test") +puts "frozen:#{frozen} interned:#{interned}" diff --git a/spec/ruby/command_line/fixtures/string_literal_raw.rb b/spec/ruby/command_line/fixtures/string_literal_raw.rb new file mode 100644 index 0000000000..56b1841296 --- /dev/null +++ b/spec/ruby/command_line/fixtures/string_literal_raw.rb @@ -0,0 +1,3 @@ +frozen = "test".frozen? +interned = "test".equal?("test") +puts "frozen:#{frozen} interned:#{interned}" diff --git a/spec/ruby/command_line/frozen_strings_spec.rb b/spec/ruby/command_line/frozen_strings_spec.rb index 647b69daed..24b979b68b 100644 --- a/spec/ruby/command_line/frozen_strings_spec.rb +++ b/spec/ruby/command_line/frozen_strings_spec.rb @@ -19,6 +19,41 @@ describe "The --enable-frozen-string-literal flag causes string literals to" do end end +describe "The --disable-frozen-string-literal flag causes string literals to" do + + it "produce a different object each time" do + ruby_exe(fixture(__FILE__, "freeze_flag_one_literal.rb"), options: "--disable-frozen-string-literal").chomp.should == "false" + end + +end + +describe "With neither --enable-frozen-string-literal nor --disable-frozen-string-literal flag set" do + + it "produce a different object each time" do + ruby_exe(fixture(__FILE__, "freeze_flag_one_literal.rb")).chomp.should == "false" + end + + ruby_version_is "3.4" do + it "if file has no frozen_string_literal comment produce different frozen strings each time" do + ruby_exe(fixture(__FILE__, "string_literal_raw.rb")).chomp.should == "frozen:true interned:false" + end + end + + ruby_version_is ""..."3.4" do + it "if file has no frozen_string_literal comment produce different mutable strings each time" do + ruby_exe(fixture(__FILE__, "string_literal_raw.rb")).chomp.should == "frozen:false interned:false" + end + end + + it "if file has frozen_string_literal:true comment produce same frozen strings each time" do + ruby_exe(fixture(__FILE__, "string_literal_frozen_comment.rb")).chomp.should == "frozen:true interned:true" + end + + it "if file has frozen_string_literal:false comment produce different mutable strings each time" do + ruby_exe(fixture(__FILE__, "string_literal_mutable_comment.rb")).chomp.should == "frozen:false interned:false" + end +end + describe "The --debug flag produces" do it "debugging info on attempted frozen string modification" do error_str = ruby_exe(fixture(__FILE__, 'debug_info.rb'), options: '--debug', args: "2>&1") diff --git a/spec/ruby/core/kernel/eval_spec.rb b/spec/ruby/core/kernel/eval_spec.rb index 15c9d511fc..5d82f57e44 100644 --- a/spec/ruby/core/kernel/eval_spec.rb +++ b/spec/ruby/core/kernel/eval_spec.rb @@ -350,9 +350,11 @@ CODE end it "allows a magic encoding comment and a subsequent frozen_string_literal magic comment" do + frozen_string_default = "test".frozen? + code = < { eval(code) }.should complain(/warning: [`']frozen_string_literal' is ignored after any tokens/, verbose: true) - EvalSpecs::Vπstring_not_frozen.frozen?.should == default_frozen_string_literal + EvalSpecs::Vπstring_not_frozen.frozen?.should == frozen_string_default EvalSpecs.send :remove_const, :Vπstring_not_frozen -> { eval(code) }.should_not complain(verbose: false) - EvalSpecs::Vπstring_not_frozen.frozen?.should == default_frozen_string_literal + EvalSpecs::Vπstring_not_frozen.frozen?.should == frozen_string_default EvalSpecs.send :remove_const, :Vπstring_not_frozen end end diff --git a/spec/ruby/core/string/chilled_string_spec.rb b/spec/ruby/core/string/chilled_string_spec.rb new file mode 100644 index 0000000000..8de4fc421b --- /dev/null +++ b/spec/ruby/core/string/chilled_string_spec.rb @@ -0,0 +1,69 @@ +require_relative '../../spec_helper' + +describe "chilled String" do + guard -> { ruby_version_is "3.4" and !"test".equal?("test") } do + describe "#frozen?" do + it "returns true" do + "chilled".frozen?.should == true + end + end + + describe "#-@" do + it "returns a different instance" do + input = "chilled" + interned = (-input) + interned.frozen?.should == true + interned.object_id.should_not == input.object_id + end + end + + describe "#+@" do + it "returns a different instance" do + input = "chilled" + duped = (+input) + duped.frozen?.should == false + duped.object_id.should_not == input.object_id + end + end + + describe "#clone" do + it "preserves chilled status" do + input = "chilled".clone + -> { + input << "-mutated" + }.should complain(/literal string will be frozen in the future/) + input.should == "chilled-mutated" + end + end + + describe "mutation" do + it "emits a warning" do + input = "chilled" + -> { + input << "-mutated" + }.should complain(/literal string will be frozen in the future/) + input.should == "chilled-mutated" + end + + it "emits a warning on singleton_class creaation" do + -> { + "chilled".singleton_class + }.should complain(/literal string will be frozen in the future/) + end + + it "emits a warning on instance variable assignment" do + -> { + "chilled".instance_variable_set(:@ivar, 42) + }.should complain(/literal string will be frozen in the future/) + end + + it "raises FrozenError after the string was explictly frozen" do + input = "chilled" + input.freeze + -> { + input << "mutated" + }.should raise_error(FrozenError) + end + end + end +end diff --git a/spec/ruby/language/string_spec.rb b/spec/ruby/language/string_spec.rb index f2764eada0..1a1cd35850 100644 --- a/spec/ruby/language/string_spec.rb +++ b/spec/ruby/language/string_spec.rb @@ -232,8 +232,8 @@ describe "Ruby String literals" do end it "produce different objects for literals with the same content in different files if the other file doesn't have the comment" do - frozen_literals_by_default = eval("'test'").frozen? - ruby_exe(fixture(__FILE__, "freeze_magic_comment_across_files_no_comment.rb")).chomp.should == (!frozen_literals_by_default).to_s + frozen_string_literal = "test".frozen? && "test".equal?("test") + ruby_exe(fixture(__FILE__, "freeze_magic_comment_across_files_no_comment.rb")).chomp.should == (!frozen_string_literal).to_s end it "produce different objects for literals with the same content in different files if they have different encodings" do diff --git a/spec/ruby/shared/kernel/object_id.rb b/spec/ruby/shared/kernel/object_id.rb index 3e032102f1..099df8ff94 100644 --- a/spec/ruby/shared/kernel/object_id.rb +++ b/spec/ruby/shared/kernel/object_id.rb @@ -52,7 +52,7 @@ describe :object_id, shared: true do o1.send(@method).should_not == o2.send(@method) end - guard -> { "test".frozen? } do # --enable-frozen-string-literal in $RUBYOPT + guard -> { "test".frozen? && "test".equal?("test") } do # --enable-frozen-string-literal in $RUBYOPT it "returns the same value for two identical String literals" do o1 = "hello" o2 = "hello" @@ -60,7 +60,17 @@ describe :object_id, shared: true do end end - guard_not -> { "test".frozen? } do + guard -> { "test".frozen? && !"test".equal?("test") } do # chilled string literals + it "returns a different frozen value for two String literals" do + o1 = "hello" + o2 = "hello" + o1.send(@method).should_not == o2.send(@method) + o1.frozen?.should == true + o2.frozen?.should == true + end + end + + guard -> { !"test".frozen? } do it "returns a different value for two String literals" do o1 = "hello" o2 = "hello" diff --git a/string.c b/string.c index a756523c4b..cbd8f90585 100644 --- a/string.c +++ b/string.c @@ -380,8 +380,9 @@ fstr_update_callback(st_data_t *key, st_data_t *value, st_data_t data, int exist OBJ_FREEZE_RAW(str); } else { - if (!OBJ_FROZEN(str)) + if (!OBJ_FROZEN(str) || CHILLED_STRING_P(str)) { str = str_new_frozen(rb_cString, str); + } if (STR_SHARED_P(str)) { /* str should not be shared */ /* shared substring */ str_make_independent(str); @@ -422,7 +423,7 @@ rb_fstring(VALUE str) } } - if (!FL_TEST_RAW(str, FL_FREEZE | STR_NOFREE)) + if (!FL_TEST_RAW(str, FL_FREEZE | STR_NOFREE | STR_CHILLED)) rb_str_resize(str, RSTRING_LEN(str)); fstr = register_fstring(str, FALSE); @@ -1822,10 +1823,14 @@ rb_str_resurrect(VALUE str) } VALUE -rb_ec_str_resurrect(struct rb_execution_context_struct *ec, VALUE str) +rb_ec_str_resurrect(struct rb_execution_context_struct *ec, VALUE str, bool chilled) { RUBY_DTRACE_CREATE_HOOK(STRING, RSTRING_LEN(str)); - return ec_str_duplicate(ec, rb_cString, str); + VALUE new_str = ec_str_duplicate(ec, rb_cString, str); + if (chilled) { + STR_CHILL_RAW(new_str); + } + return new_str; } /* @@ -3019,12 +3024,15 @@ str_substr(VALUE str, long beg, long len, int empty) VALUE rb_str_freeze(VALUE str) { + if (CHILLED_STRING_P(str)) { + FL_UNSET_RAW(str, STR_CHILLED); + } + if (OBJ_FROZEN(str)) return str; rb_str_resize(str, RSTRING_LEN(str)); return rb_obj_freeze(str); } - /* * call-seq: * +string -> new_string or self diff --git a/test/ruby/test_compile_prism.rb b/test/ruby/test_compile_prism.rb index 8af9f1ade0..eef909eb07 100644 --- a/test/ruby/test_compile_prism.rb +++ b/test/ruby/test_compile_prism.rb @@ -592,22 +592,16 @@ module Prism assert_prism_eval('$pit = 1; "1 #$pit 1"') assert_prism_eval('"1 #{1 + 2} 1"') assert_prism_eval('"Prism" "::" "TestCompilePrism"') - assert_prism_eval('("a""b").frozen?') - assert_prism_eval(<<-CODE) + assert_prism_eval(<<-'RUBY') # frozen_string_literal: true - ("a""b").frozen? - CODE - assert_prism_eval(<<-CODE) + !("a""b""#{1}").frozen? + RUBY + assert_prism_eval(<<-'RUBY') # frozen_string_literal: true - ("a""b""#{1}").frozen? - CODE - assert_prism_eval(<<-CODE) - # frozen_string_literal: true - - ("a""#{1}""b").frozen? - CODE + !("a""#{1}""b").frozen? + RUBY # Test encoding of interpolated strings assert_prism_eval(<<~'RUBY') @@ -620,6 +614,15 @@ module Prism RUBY end + def test_concatenated_StringNode + assert_prism_eval('("a""b").frozen?') + assert_prism_eval(<<-CODE) + # frozen_string_literal: true + + ("a""b").frozen? + CODE + end + def test_InterpolatedSymbolNode assert_prism_eval('$pit = 1; :"1 #$pit 1"') assert_prism_eval(':"1 #{1 + 2} 1"') @@ -673,7 +676,9 @@ module Prism def test_StringNode assert_prism_eval('"pit"') assert_prism_eval('"a".frozen?') + end + def test_StringNode_frozen_string_literal_true [ # Test that string literal is frozen <<~RUBY, @@ -690,6 +695,31 @@ module Prism end end + def test_StringNode_frozen_string_literal_false + [ + # Test that string literal is frozen + <<~RUBY, + # frozen_string_literal: false + !"a".frozen? + RUBY + # Test that two string literals with the same contents are the same string + <<~RUBY, + # frozen_string_literal: false + !"hello".equal?("hello") + RUBY + ].each do |src| + assert_prism_eval(src, raw: true) + end + end + + def test_StringNode_frozen_string_literal_default + # Test that string literal is chilled + assert_prism_eval('"a".frozen?') + + # Test that two identical chilled string literals aren't the same object + assert_prism_eval('!"hello".equal?("hello")') + end + def test_SymbolNode assert_prism_eval(":pit") @@ -2620,27 +2650,28 @@ end private - def compare_eval(source, raw:) + def compare_eval(source, raw:, location:) source = raw ? source : "class Prism::TestCompilePrism\n#{source}\nend" ruby_eval = RubyVM::InstructionSequence.compile(source).eval prism_eval = RubyVM::InstructionSequence.compile_prism(source).eval if ruby_eval.is_a? Proc - assert_equal ruby_eval.class, prism_eval.class + assert_equal ruby_eval.class, prism_eval.class, "@#{location.path}:#{location.lineno}" else - assert_equal ruby_eval, prism_eval + assert_equal ruby_eval, prism_eval, "@#{location.path}:#{location.lineno}" end end def assert_prism_eval(source, raw: false) + location = caller_locations(1, 1).first $VERBOSE, verbose_bak = nil, $VERBOSE begin - compare_eval(source, raw:) + compare_eval(source, raw:, location:) # Test "popped" functionality - compare_eval("#{source}; 1", raw:) + compare_eval("#{source}; 1", raw:, location:) ensure $VERBOSE = verbose_bak end diff --git a/test/ruby/test_string.rb b/test/ruby/test_string.rb index 58e1af2b61..3f1b91a6a9 100644 --- a/test/ruby/test_string.rb +++ b/test/ruby/test_string.rb @@ -3610,6 +3610,39 @@ CODE assert_bytesplice_raise(ArgumentError, S("hello"), 0..-1, "bye", 0, 3) end + def test_chilled_string + chilled_string = eval('"chilled"') + + # Chilled strings pretend to be frozen + assert_predicate chilled_string, :frozen? + + assert_not_predicate chilled_string.dup, :frozen? + assert_predicate chilled_string.clone, :frozen? + + # @+ treat the original string as frozen + assert_not_predicate +chilled_string, :frozen? + assert_not_same chilled_string, +chilled_string + + # @- the the original string as mutable + assert_predicate -chilled_string, :frozen? + assert_not_same chilled_string, -chilled_string + end + + def test_chilled_string_setivar + String.class_eval <<~RUBY, __FILE__, __LINE__ + 1 + def setivar! + @ivar = 42 + @ivar + end + RUBY + chilled_string = eval('"chilled"') + begin + assert_equal 42, chilled_string.setivar! + ensure + String.undef_method(:setivar!) + end + end + private def assert_bytesplice_result(expected, s, *args) diff --git a/vm_eval.c b/vm_eval.c index c52244ed1e..c9a9751ab3 100644 --- a/vm_eval.c +++ b/vm_eval.c @@ -1663,7 +1663,7 @@ pm_eval_make_iseq(VALUE src, VALUE fname, int line, pm_parse_result_t result = { 0 }; pm_options_line_set(&result.options, line); - pm_options_frozen_string_literal_set(&result.options, rb_iseq_opt_frozen_string_literal()); + pm_options_frozen_string_literal_init(&result, rb_iseq_opt_frozen_string_literal()); // Cout scopes, one for each parent iseq, plus one for our local scope int scopes_count = 0; diff --git a/vm_opts.h b/vm_opts.h index 7b3caf4754..ce47745b11 100644 --- a/vm_opts.h +++ b/vm_opts.h @@ -19,7 +19,7 @@ #define OPT_PEEPHOLE_OPTIMIZATION 1 #define OPT_SPECIALISED_INSTRUCTION 1 #define OPT_INLINE_CONST_CACHE 1 -#define OPT_FROZEN_STRING_LITERAL 0 +#define OPT_FROZEN_STRING_LITERAL -1 #define OPT_DEBUG_FROZEN_STRING_LITERAL 0 /* Build Options. diff --git a/yjit/src/codegen.rs b/yjit/src/codegen.rs index 745433ab00..6963aca48e 100644 --- a/yjit/src/codegen.rs +++ b/yjit/src/codegen.rs @@ -2327,7 +2327,28 @@ fn gen_putstring( let str_opnd = asm.ccall( rb_ec_str_resurrect as *const u8, - vec![EC, put_val.into()] + vec![EC, put_val.into(), 0.into()] + ); + + let stack_top = asm.stack_push(Type::TString); + asm.mov(stack_top, str_opnd); + + Some(KeepCompiling) +} + +fn gen_putchilledstring( + jit: &mut JITState, + asm: &mut Assembler, + _ocb: &mut OutlinedCb, +) -> Option { + let put_val = jit.get_arg(0); + + // Save the PC and SP because the callee will allocate + jit_prepare_call_with_gc(jit, asm); + + let str_opnd = asm.ccall( + rb_ec_str_resurrect as *const u8, + vec![EC, put_val.into(), 1.into()] ); let stack_top = asm.stack_push(Type::TString); @@ -9778,6 +9799,7 @@ fn get_gen_fn(opcode: VALUE) -> Option { YARVINSN_pushtoarray => Some(gen_pushtoarray), YARVINSN_newrange => Some(gen_newrange), YARVINSN_putstring => Some(gen_putstring), + YARVINSN_putchilledstring => Some(gen_putchilledstring), YARVINSN_expandarray => Some(gen_expandarray), YARVINSN_defined => Some(gen_defined), YARVINSN_definedivar => Some(gen_definedivar), diff --git a/yjit/src/cruby_bindings.inc.rs b/yjit/src/cruby_bindings.inc.rs index 36a0865246..359227d60d 100644 --- a/yjit/src/cruby_bindings.inc.rs +++ b/yjit/src/cruby_bindings.inc.rs @@ -726,195 +726,197 @@ pub const YARVINSN_putself: ruby_vminsn_type = 18; pub const YARVINSN_putobject: ruby_vminsn_type = 19; pub const YARVINSN_putspecialobject: ruby_vminsn_type = 20; pub const YARVINSN_putstring: ruby_vminsn_type = 21; -pub const YARVINSN_concatstrings: ruby_vminsn_type = 22; -pub const YARVINSN_anytostring: ruby_vminsn_type = 23; -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_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 const YARVINSN_putchilledstring: ruby_vminsn_type = 22; +pub const YARVINSN_concatstrings: ruby_vminsn_type = 23; +pub const YARVINSN_anytostring: ruby_vminsn_type = 24; +pub const YARVINSN_toregexp: ruby_vminsn_type = 25; +pub const YARVINSN_intern: ruby_vminsn_type = 26; +pub const YARVINSN_newarray: ruby_vminsn_type = 27; +pub const YARVINSN_newarraykwsplat: ruby_vminsn_type = 28; +pub const YARVINSN_pushtoarraykwsplat: ruby_vminsn_type = 29; +pub const YARVINSN_duparray: ruby_vminsn_type = 30; +pub const YARVINSN_duphash: ruby_vminsn_type = 31; +pub const YARVINSN_expandarray: ruby_vminsn_type = 32; +pub const YARVINSN_concatarray: ruby_vminsn_type = 33; +pub const YARVINSN_concattoarray: ruby_vminsn_type = 34; +pub const YARVINSN_pushtoarray: ruby_vminsn_type = 35; +pub const YARVINSN_splatarray: ruby_vminsn_type = 36; +pub const YARVINSN_splatkw: ruby_vminsn_type = 37; +pub const YARVINSN_newhash: ruby_vminsn_type = 38; +pub const YARVINSN_newrange: ruby_vminsn_type = 39; +pub const YARVINSN_pop: ruby_vminsn_type = 40; +pub const YARVINSN_dup: ruby_vminsn_type = 41; +pub const YARVINSN_dupn: ruby_vminsn_type = 42; +pub const YARVINSN_swap: ruby_vminsn_type = 43; +pub const YARVINSN_opt_reverse: ruby_vminsn_type = 44; +pub const YARVINSN_topn: ruby_vminsn_type = 45; +pub const YARVINSN_setn: ruby_vminsn_type = 46; +pub const YARVINSN_adjuststack: ruby_vminsn_type = 47; +pub const YARVINSN_defined: ruby_vminsn_type = 48; +pub const YARVINSN_definedivar: ruby_vminsn_type = 49; +pub const YARVINSN_checkmatch: ruby_vminsn_type = 50; +pub const YARVINSN_checkkeyword: ruby_vminsn_type = 51; +pub const YARVINSN_checktype: ruby_vminsn_type = 52; +pub const YARVINSN_defineclass: ruby_vminsn_type = 53; +pub const YARVINSN_definemethod: ruby_vminsn_type = 54; +pub const YARVINSN_definesmethod: ruby_vminsn_type = 55; +pub const YARVINSN_send: 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_invokeblock: ruby_vminsn_type = 64; +pub const YARVINSN_leave: ruby_vminsn_type = 65; +pub const YARVINSN_throw: ruby_vminsn_type = 66; +pub const YARVINSN_jump: ruby_vminsn_type = 67; +pub const YARVINSN_branchif: ruby_vminsn_type = 68; +pub const YARVINSN_branchunless: ruby_vminsn_type = 69; +pub const YARVINSN_branchnil: ruby_vminsn_type = 70; +pub const YARVINSN_once: ruby_vminsn_type = 71; +pub const YARVINSN_opt_case_dispatch: ruby_vminsn_type = 72; +pub const YARVINSN_opt_plus: ruby_vminsn_type = 73; +pub const YARVINSN_opt_minus: ruby_vminsn_type = 74; +pub const YARVINSN_opt_mult: ruby_vminsn_type = 75; +pub const YARVINSN_opt_div: ruby_vminsn_type = 76; +pub const YARVINSN_opt_mod: ruby_vminsn_type = 77; +pub const YARVINSN_opt_eq: ruby_vminsn_type = 78; +pub const YARVINSN_opt_neq: ruby_vminsn_type = 79; +pub const YARVINSN_opt_lt: ruby_vminsn_type = 80; +pub const YARVINSN_opt_le: ruby_vminsn_type = 81; +pub const YARVINSN_opt_gt: ruby_vminsn_type = 82; +pub const YARVINSN_opt_ge: ruby_vminsn_type = 83; +pub const YARVINSN_opt_ltlt: ruby_vminsn_type = 84; +pub const YARVINSN_opt_and: ruby_vminsn_type = 85; +pub const YARVINSN_opt_or: ruby_vminsn_type = 86; +pub const YARVINSN_opt_aref: ruby_vminsn_type = 87; +pub const YARVINSN_opt_aset: ruby_vminsn_type = 88; +pub const YARVINSN_opt_aset_with: ruby_vminsn_type = 89; +pub const YARVINSN_opt_aref_with: ruby_vminsn_type = 90; +pub const YARVINSN_opt_length: ruby_vminsn_type = 91; +pub const YARVINSN_opt_size: ruby_vminsn_type = 92; +pub const YARVINSN_opt_empty_p: ruby_vminsn_type = 93; +pub const YARVINSN_opt_succ: ruby_vminsn_type = 94; +pub const YARVINSN_opt_not: ruby_vminsn_type = 95; +pub const YARVINSN_opt_regexpmatch2: ruby_vminsn_type = 96; +pub const YARVINSN_invokebuiltin: ruby_vminsn_type = 97; +pub const YARVINSN_opt_invokebuiltin_delegate: ruby_vminsn_type = 98; +pub const YARVINSN_opt_invokebuiltin_delegate_leave: ruby_vminsn_type = 99; +pub const YARVINSN_getlocal_WC_0: ruby_vminsn_type = 100; +pub const YARVINSN_getlocal_WC_1: ruby_vminsn_type = 101; +pub const YARVINSN_setlocal_WC_0: ruby_vminsn_type = 102; +pub const YARVINSN_setlocal_WC_1: ruby_vminsn_type = 103; +pub const YARVINSN_putobject_INT2FIX_0_: ruby_vminsn_type = 104; +pub const YARVINSN_putobject_INT2FIX_1_: ruby_vminsn_type = 105; +pub const YARVINSN_trace_nop: ruby_vminsn_type = 106; +pub const YARVINSN_trace_getlocal: ruby_vminsn_type = 107; +pub const YARVINSN_trace_setlocal: ruby_vminsn_type = 108; +pub const YARVINSN_trace_getblockparam: ruby_vminsn_type = 109; +pub const YARVINSN_trace_setblockparam: ruby_vminsn_type = 110; +pub const YARVINSN_trace_getblockparamproxy: ruby_vminsn_type = 111; +pub const YARVINSN_trace_getspecial: ruby_vminsn_type = 112; +pub const YARVINSN_trace_setspecial: ruby_vminsn_type = 113; +pub const YARVINSN_trace_getinstancevariable: ruby_vminsn_type = 114; +pub const YARVINSN_trace_setinstancevariable: ruby_vminsn_type = 115; +pub const YARVINSN_trace_getclassvariable: ruby_vminsn_type = 116; +pub const YARVINSN_trace_setclassvariable: ruby_vminsn_type = 117; +pub const YARVINSN_trace_opt_getconstant_path: ruby_vminsn_type = 118; +pub const YARVINSN_trace_getconstant: ruby_vminsn_type = 119; +pub const YARVINSN_trace_setconstant: ruby_vminsn_type = 120; +pub const YARVINSN_trace_getglobal: ruby_vminsn_type = 121; +pub const YARVINSN_trace_setglobal: ruby_vminsn_type = 122; +pub const YARVINSN_trace_putnil: ruby_vminsn_type = 123; +pub const YARVINSN_trace_putself: ruby_vminsn_type = 124; +pub const YARVINSN_trace_putobject: ruby_vminsn_type = 125; +pub const YARVINSN_trace_putspecialobject: ruby_vminsn_type = 126; +pub const YARVINSN_trace_putstring: ruby_vminsn_type = 127; +pub const YARVINSN_trace_putchilledstring: ruby_vminsn_type = 128; +pub const YARVINSN_trace_concatstrings: ruby_vminsn_type = 129; +pub const YARVINSN_trace_anytostring: ruby_vminsn_type = 130; +pub const YARVINSN_trace_toregexp: ruby_vminsn_type = 131; +pub const YARVINSN_trace_intern: ruby_vminsn_type = 132; +pub const YARVINSN_trace_newarray: ruby_vminsn_type = 133; +pub const YARVINSN_trace_newarraykwsplat: 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_opt_send_without_block: ruby_vminsn_type = 163; +pub const YARVINSN_trace_objtostring: ruby_vminsn_type = 164; +pub const YARVINSN_trace_opt_str_freeze: ruby_vminsn_type = 165; +pub const YARVINSN_trace_opt_nil_p: ruby_vminsn_type = 166; +pub const YARVINSN_trace_opt_str_uminus: ruby_vminsn_type = 167; +pub const YARVINSN_trace_opt_newarray_send: ruby_vminsn_type = 168; +pub const YARVINSN_trace_invokesuper: ruby_vminsn_type = 169; +pub const YARVINSN_trace_invokeblock: ruby_vminsn_type = 170; +pub const YARVINSN_trace_leave: ruby_vminsn_type = 171; +pub const YARVINSN_trace_throw: ruby_vminsn_type = 172; +pub const YARVINSN_trace_jump: ruby_vminsn_type = 173; +pub const YARVINSN_trace_branchif: ruby_vminsn_type = 174; +pub const YARVINSN_trace_branchunless: ruby_vminsn_type = 175; +pub const YARVINSN_trace_branchnil: ruby_vminsn_type = 176; +pub const YARVINSN_trace_once: ruby_vminsn_type = 177; +pub const YARVINSN_trace_opt_case_dispatch: ruby_vminsn_type = 178; +pub const YARVINSN_trace_opt_plus: ruby_vminsn_type = 179; +pub const YARVINSN_trace_opt_minus: ruby_vminsn_type = 180; +pub const YARVINSN_trace_opt_mult: ruby_vminsn_type = 181; +pub const YARVINSN_trace_opt_div: ruby_vminsn_type = 182; +pub const YARVINSN_trace_opt_mod: ruby_vminsn_type = 183; +pub const YARVINSN_trace_opt_eq: ruby_vminsn_type = 184; +pub const YARVINSN_trace_opt_neq: ruby_vminsn_type = 185; +pub const YARVINSN_trace_opt_lt: ruby_vminsn_type = 186; +pub const YARVINSN_trace_opt_le: ruby_vminsn_type = 187; +pub const YARVINSN_trace_opt_gt: ruby_vminsn_type = 188; +pub const YARVINSN_trace_opt_ge: ruby_vminsn_type = 189; +pub const YARVINSN_trace_opt_ltlt: ruby_vminsn_type = 190; +pub const YARVINSN_trace_opt_and: ruby_vminsn_type = 191; +pub const YARVINSN_trace_opt_or: ruby_vminsn_type = 192; +pub const YARVINSN_trace_opt_aref: ruby_vminsn_type = 193; +pub const YARVINSN_trace_opt_aset: ruby_vminsn_type = 194; +pub const YARVINSN_trace_opt_aset_with: ruby_vminsn_type = 195; +pub const YARVINSN_trace_opt_aref_with: ruby_vminsn_type = 196; +pub const YARVINSN_trace_opt_length: ruby_vminsn_type = 197; +pub const YARVINSN_trace_opt_size: ruby_vminsn_type = 198; +pub const YARVINSN_trace_opt_empty_p: ruby_vminsn_type = 199; +pub const YARVINSN_trace_opt_succ: ruby_vminsn_type = 200; +pub const YARVINSN_trace_opt_not: ruby_vminsn_type = 201; +pub const YARVINSN_trace_opt_regexpmatch2: ruby_vminsn_type = 202; +pub const YARVINSN_trace_invokebuiltin: ruby_vminsn_type = 203; +pub const YARVINSN_trace_opt_invokebuiltin_delegate: ruby_vminsn_type = 204; +pub const YARVINSN_trace_opt_invokebuiltin_delegate_leave: ruby_vminsn_type = 205; +pub const YARVINSN_trace_getlocal_WC_0: ruby_vminsn_type = 206; +pub const YARVINSN_trace_getlocal_WC_1: ruby_vminsn_type = 207; +pub const YARVINSN_trace_setlocal_WC_0: ruby_vminsn_type = 208; +pub const YARVINSN_trace_setlocal_WC_1: ruby_vminsn_type = 209; +pub const YARVINSN_trace_putobject_INT2FIX_0_: ruby_vminsn_type = 210; +pub const YARVINSN_trace_putobject_INT2FIX_1_: ruby_vminsn_type = 211; +pub const VM_INSTRUCTION_SIZE: ruby_vminsn_type = 212; 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), @@ -1055,7 +1057,11 @@ extern "C" { pub fn rb_str_byte_substr(str_: VALUE, beg: VALUE, len: VALUE) -> VALUE; pub fn rb_obj_as_string_result(str_: VALUE, obj: VALUE) -> VALUE; pub fn rb_str_concat_literals(num: usize, strary: *const VALUE) -> VALUE; - pub fn rb_ec_str_resurrect(ec: *mut rb_execution_context_struct, str_: VALUE) -> VALUE; + pub fn rb_ec_str_resurrect( + ec: *mut rb_execution_context_struct, + str_: VALUE, + chilled: bool, + ) -> VALUE; pub fn rb_to_hash_type(obj: VALUE) -> VALUE; pub fn rb_hash_stlike_foreach( hash: VALUE,