Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

YJIT: Enhance the String#<< method substitution to handle integer codepoint values. #11032

Merged
merged 4 commits into from
Aug 2, 2024
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
YJIT: Move runtime type check into YJIT.
Performing the check in YJIT means we can make assumptions about the type. It also improves correctness of stack traces in cases where the codepoint argument is not a String or a Fixnum.
  • Loading branch information
nirvdrum committed Aug 2, 2024
commit 44af5eedc4eb363de787214346ede86601178453
2 changes: 1 addition & 1 deletion string.c
Original file line number Diff line number Diff line change
Expand Up @@ -12300,7 12300,7 @@ rb_enc_interned_str_cstr(const char *ptr, rb_encoding *enc)
void
rb_yjit_str_concat_codepoint(VALUE str, VALUE codepoint)
{
if (RB_LIKELY(FIXNUM_P(codepoint)) && RB_LIKELY(ENCODING_GET_INLINED(str) == rb_ascii8bit_encindex())) {
if (RB_LIKELY(ENCODING_GET_INLINED(str) == rb_ascii8bit_encindex())) {
ssize_t code = RB_NUM2SSIZE(codepoint);

if (RB_LIKELY(code >= 0 && code < 0xff)) {
Expand Down
42 changes: 42 additions & 0 deletions yjit/src/codegen.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1999,6 1999,46 @@ fn guard_object_is_hash(
}
}

fn guard_object_is_fixnum(
jit: &mut JITState,
asm: &mut Assembler,
object: Opnd,
object_opnd: YARVOpnd
) {
let object_type = asm.ctx.get_opnd_type(object_opnd);
if object_type.is_heap() {
asm_comment!(asm, "arg is heap object");
asm.jmp(Target::side_exit(Counter::guard_send_not_fixnum));
return;
}

if object_type != Type::Fixnum && object_type.is_specific() {
asm_comment!(asm, "arg is not fixnum");
asm.jmp(Target::side_exit(Counter::guard_send_not_fixnum));
return;
}

assert!(!object_type.is_heap());
assert!(object_type == Type::Fixnum || object_type.is_unknown());

// If not fixnums at run-time, fall back
if object_type != Type::Fixnum {
asm_comment!(asm, "guard object fixnum");
asm.test(object, Opnd::UImm(RUBY_FIXNUM_FLAG as u64));

jit_chain_guard(
JCC_JZ,
jit,
asm,
SEND_MAX_DEPTH,
Counter::guard_send_not_fixnum,
);
}

// Set the stack type in the context.
asm.ctx.upgrade_opnd_type(object.into(), Type::Fixnum);
}

fn guard_object_is_string(
asm: &mut Assembler,
object: Opnd,
Expand Down Expand Up @@ -5791,6 5831,8 @@ fn jit_rb_str_concat_codepoint(
let codepoint = asm.stack_opnd(0);
let recv = asm.stack_opnd(1);

guard_object_is_fixnum(jit, asm, codepoint, StackOpnd(0));

asm.ccall(rb_yjit_str_concat_codepoint as *const u8, vec![recv, codepoint]);

// The receiver is the return value, so we only need to pop the codepoint argument off the stack.
Expand Down
1 change: 1 addition & 0 deletions yjit/src/stats.rs
Original file line number Diff line number Diff line change
Expand Up @@ -453,6 453,7 @@ make_counters! {
guard_send_instance_of_class_mismatch,
guard_send_interrupted,
guard_send_not_fixnums,
guard_send_not_fixnum,
guard_send_not_fixnum_or_flonum,
guard_send_not_string,
guard_send_respond_to_mid_mismatch,
Expand Down