summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNARUSE, Yui <naruse@airemix.jp>2023-03-07 19:48:32 +0900
committerNARUSE, Yui <naruse@airemix.jp>2023-03-07 19:48:32 +0900
commit4d75035e1762a23d38c5192b30bb47f40b752bee (patch)
tree192c44ecea4b99cf57f82e91e3a71881debc0ed2
parentf1cde05d99898f491c8e302ae74029468fdb6eb9 (diff)
downloadruby-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.rb44
-rw-r--r--version.h2
-rw-r--r--yjit/src/codegen.rs15
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
diff --git a/version.h b/version.h
index afcff7071b..9664aefc20 100644
--- a/version.h
+++ b/version.h
@@ -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);