Skip to content

Commit

Permalink
YJIT: Move runtime type check into YJIT.
Browse files Browse the repository at this point in the history
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
1 parent 003ca52 commit 44af5ee
Show file tree
Hide file tree
Showing 3 changed files with 44 additions and 1 deletion.
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

0 comments on commit 44af5ee

Please sign in to comment.