diff options
author | NARUSE, Yui <naruse@airemix.jp> | 2023-03-07 19:48:32 +0900 |
---|---|---|
committer | NARUSE, Yui <naruse@airemix.jp> | 2023-03-07 19:48:32 +0900 |
commit | 4d75035e1762a23d38c5192b30bb47f40b752bee (patch) | |
tree | 192c44ecea4b99cf57f82e91e3a71881debc0ed2 | |
parent | f1cde05d99898f491c8e302ae74029468fdb6eb9 (diff) | |
download | ruby-4d75035e1762a23d38c5192b30bb47f40b752bee.tar.gz |
merge revision(s) c178926fbe879045fa711444a1fd9e906af23e3b,a4b7ec12298c78392797e5ba7704076550e4f100: [Backport #19444]
YJIT: jit_prepare_routine_call() for String#+@ missing
We saw SEGVs due to this when running with StackProf, which needs a
correct PC for RUBY_INTERNAL_EVENT_NEWOBJ, the same event used for
ObjectSpace allocation tracing.
[Bug #19444]
---
test/ruby/test_yjit.rb | 27 +++++++++++++++++++++++++++
yjit/src/codegen.rs | 5 ++++-
2 files changed, 31 insertions(+), 1 deletion(-)
YJIT: Fix false assumption that String#+@ => ::String
Could return a subclass.
[Bug #19444]
---
test/ruby/test_yjit.rb | 17 +++++++++++++++++
yjit/src/codegen.rs | 10 +++++++---
2 files changed, 24 insertions(+), 3 deletions(-)
-rw-r--r-- | test/ruby/test_yjit.rb | 44 | ||||
-rw-r--r-- | version.h | 2 | ||||
-rw-r--r-- | yjit/src/codegen.rs | 15 |
3 files changed, 56 insertions, 5 deletions
diff --git a/test/ruby/test_yjit.rb b/test/ruby/test_yjit.rb index 565e9843ab..2ea915bc0d 100644 --- a/test/ruby/test_yjit.rb +++ b/test/ruby/test_yjit.rb @@ -1077,6 +1077,50 @@ class TestYJIT < Test::Unit::TestCase RUBY end + def test_tracing_str_uplus + assert_compiles(<<~RUBY, frozen_string_literal: true, result: :ok) + def str_uplus + _ = 1 + _ = 2 + ret = [+"frfr", __LINE__] + _ = 3 + _ = 4 + + ret + end + + str_uplus + require 'objspace' + ObjectSpace.trace_object_allocations_start + + str, expected_line = str_uplus + alloc_line = ObjectSpace.allocation_sourceline(str) + + if expected_line == alloc_line + :ok + else + [expected_line, alloc_line] + end + RUBY + end + + def test_str_uplus_subclass + assert_compiles(<<~RUBY, frozen_string_literal: true, result: :subclass) + class S < String + def encoding + :subclass + end + end + + def test(str) + (+str).encoding + end + + test "" + test S.new + RUBY + end + private def code_gc_helpers @@ -11,7 +11,7 @@ # define RUBY_VERSION_MINOR RUBY_API_VERSION_MINOR #define RUBY_VERSION_TEENY 1 #define RUBY_RELEASE_DATE RUBY_RELEASE_YEAR_STR"-"RUBY_RELEASE_MONTH_STR"-"RUBY_RELEASE_DAY_STR -#define RUBY_PATCHLEVEL 35 +#define RUBY_PATCHLEVEL 36 #include "ruby/version.h" #include "ruby/internal/abi.h" diff --git a/yjit/src/codegen.rs b/yjit/src/codegen.rs index 2b2543b37a..8c5b413286 100644 --- a/yjit/src/codegen.rs +++ b/yjit/src/codegen.rs @@ -4047,17 +4047,24 @@ fn jit_rb_int_equal( /// If string is frozen, duplicate it to get a non-frozen string. Otherwise, return it. fn jit_rb_str_uplus( - _jit: &mut JITState, + jit: &mut JITState, ctx: &mut Context, asm: &mut Assembler, _ocb: &mut OutlinedCb, _ci: *const rb_callinfo, _cme: *const rb_callable_method_entry_t, _block: Option<IseqPtr>, - _argc: i32, + argc: i32, _known_recv_class: *const VALUE, ) -> bool { + if argc != 0 { + return false; + } + + // We allocate when we dup the string + jit_prepare_routine_call(jit, ctx, asm); + asm.comment("Unary plus on string"); let recv_opnd = asm.load(ctx.stack_pop(1)); let flags_opnd = asm.load(Opnd::mem(64, recv_opnd, RUBY_OFFSET_RBASIC_FLAGS)); @@ -4065,8 +4072,8 @@ fn jit_rb_str_uplus( let ret_label = asm.new_label("stack_ret"); - // We guard for the receiver being a ::String, so the return value is too - let stack_ret = ctx.stack_push(Type::CString); + // String#+@ can only exist on T_STRING + let stack_ret = ctx.stack_push(Type::TString); // If the string isn't frozen, we just return it. asm.mov(stack_ret, recv_opnd); |