YJIT: Add codegen for Float arithmetics (#9774)
* YJIT: Add codegen for Float arithmetics * Add Flonum and Fixnum tests
This commit is contained in:
parent
cc9bbbdd80
commit
09427f51a2
@ -2484,6 +2484,16 @@ assert_equal '[true, false, true, false]', %q{
|
||||
[is_odd(123), is_odd(456), is_odd(bignum), is_odd(bignum+1)]
|
||||
}
|
||||
|
||||
# Flonum and Flonum
|
||||
assert_equal '[2.0, 0.0, 1.0, 4.0]', %q{
|
||||
[1.0 + 1.0, 1.0 - 1.0, 1.0 * 1.0, 8.0 / 2.0]
|
||||
}
|
||||
|
||||
# Flonum and Fixnum
|
||||
assert_equal '[2.0, 0.0, 1.0, 4.0]', %q{
|
||||
[1.0 + 1, 1.0 - 1, 1.0 * 1, 8.0 / 2]
|
||||
}
|
||||
|
||||
# Call to static and dynamic symbol
|
||||
assert_equal 'bar', %q{
|
||||
def to_string(obj)
|
||||
|
@ -217,6 +217,10 @@ fn main() {
|
||||
|
||||
// From internal/numeric.h
|
||||
.allowlist_function("rb_fix_aref")
|
||||
.allowlist_function("rb_float_plus")
|
||||
.allowlist_function("rb_float_minus")
|
||||
.allowlist_function("rb_float_mul")
|
||||
.allowlist_function("rb_float_div")
|
||||
|
||||
// From internal/string.h
|
||||
.allowlist_function("rb_ec_str_resurrect")
|
||||
|
@ -4992,6 +4992,182 @@ fn jit_rb_int_aref(
|
||||
true
|
||||
}
|
||||
|
||||
fn jit_rb_float_plus(
|
||||
jit: &mut JITState,
|
||||
asm: &mut Assembler,
|
||||
ocb: &mut OutlinedCb,
|
||||
_ci: *const rb_callinfo,
|
||||
_cme: *const rb_callable_method_entry_t,
|
||||
_block: Option<BlockHandler>,
|
||||
_argc: i32,
|
||||
_known_recv_class: *const VALUE,
|
||||
) -> bool {
|
||||
// Guard obj is Fixnum or Flonum to avoid rb_funcall on rb_num_coerce_bin
|
||||
let comptime_obj = jit.peek_at_stack(&asm.ctx, 0);
|
||||
if comptime_obj.fixnum_p() || comptime_obj.flonum_p() {
|
||||
let obj = asm.stack_opnd(0);
|
||||
jit_guard_known_klass(
|
||||
jit,
|
||||
asm,
|
||||
ocb,
|
||||
comptime_obj.class_of(),
|
||||
obj,
|
||||
obj.into(),
|
||||
comptime_obj,
|
||||
SEND_MAX_DEPTH,
|
||||
Counter::guard_send_not_fixnum_or_flonum,
|
||||
);
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Save the PC and SP because the callee may allocate Float on heap
|
||||
jit_prepare_routine_call(jit, asm);
|
||||
|
||||
asm_comment!(asm, "Float#+");
|
||||
let obj = asm.stack_opnd(0);
|
||||
let recv = asm.stack_opnd(1);
|
||||
|
||||
let ret = asm.ccall(rb_float_plus as *const u8, vec![recv, obj]);
|
||||
asm.stack_pop(2); // Keep recv during ccall for GC
|
||||
|
||||
let ret_opnd = asm.stack_push(Type::Unknown); // Flonum or heap Float
|
||||
asm.mov(ret_opnd, ret);
|
||||
true
|
||||
}
|
||||
|
||||
fn jit_rb_float_minus(
|
||||
jit: &mut JITState,
|
||||
asm: &mut Assembler,
|
||||
ocb: &mut OutlinedCb,
|
||||
_ci: *const rb_callinfo,
|
||||
_cme: *const rb_callable_method_entry_t,
|
||||
_block: Option<BlockHandler>,
|
||||
_argc: i32,
|
||||
_known_recv_class: *const VALUE,
|
||||
) -> bool {
|
||||
// Guard obj is Fixnum or Flonum to avoid rb_funcall on rb_num_coerce_bin
|
||||
let comptime_obj = jit.peek_at_stack(&asm.ctx, 0);
|
||||
if comptime_obj.fixnum_p() || comptime_obj.flonum_p() {
|
||||
let obj = asm.stack_opnd(0);
|
||||
jit_guard_known_klass(
|
||||
jit,
|
||||
asm,
|
||||
ocb,
|
||||
comptime_obj.class_of(),
|
||||
obj,
|
||||
obj.into(),
|
||||
comptime_obj,
|
||||
SEND_MAX_DEPTH,
|
||||
Counter::guard_send_not_fixnum_or_flonum,
|
||||
);
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Save the PC and SP because the callee may allocate Float on heap
|
||||
jit_prepare_routine_call(jit, asm);
|
||||
|
||||
asm_comment!(asm, "Float#-");
|
||||
let obj = asm.stack_opnd(0);
|
||||
let recv = asm.stack_opnd(1);
|
||||
|
||||
let ret = asm.ccall(rb_float_minus as *const u8, vec![recv, obj]);
|
||||
asm.stack_pop(2); // Keep recv during ccall for GC
|
||||
|
||||
let ret_opnd = asm.stack_push(Type::Unknown); // Flonum or heap Float
|
||||
asm.mov(ret_opnd, ret);
|
||||
true
|
||||
}
|
||||
|
||||
fn jit_rb_float_mul(
|
||||
jit: &mut JITState,
|
||||
asm: &mut Assembler,
|
||||
ocb: &mut OutlinedCb,
|
||||
_ci: *const rb_callinfo,
|
||||
_cme: *const rb_callable_method_entry_t,
|
||||
_block: Option<BlockHandler>,
|
||||
_argc: i32,
|
||||
_known_recv_class: *const VALUE,
|
||||
) -> bool {
|
||||
// Guard obj is Fixnum or Flonum to avoid rb_funcall on rb_num_coerce_bin
|
||||
let comptime_obj = jit.peek_at_stack(&asm.ctx, 0);
|
||||
if comptime_obj.fixnum_p() || comptime_obj.flonum_p() {
|
||||
let obj = asm.stack_opnd(0);
|
||||
jit_guard_known_klass(
|
||||
jit,
|
||||
asm,
|
||||
ocb,
|
||||
comptime_obj.class_of(),
|
||||
obj,
|
||||
obj.into(),
|
||||
comptime_obj,
|
||||
SEND_MAX_DEPTH,
|
||||
Counter::guard_send_not_fixnum_or_flonum,
|
||||
);
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Save the PC and SP because the callee may allocate Float on heap
|
||||
jit_prepare_routine_call(jit, asm);
|
||||
|
||||
asm_comment!(asm, "Float#*");
|
||||
let obj = asm.stack_opnd(0);
|
||||
let recv = asm.stack_opnd(1);
|
||||
|
||||
let ret = asm.ccall(rb_float_mul as *const u8, vec![recv, obj]);
|
||||
asm.stack_pop(2); // Keep recv during ccall for GC
|
||||
|
||||
let ret_opnd = asm.stack_push(Type::Unknown); // Flonum or heap Float
|
||||
asm.mov(ret_opnd, ret);
|
||||
true
|
||||
}
|
||||
|
||||
fn jit_rb_float_div(
|
||||
jit: &mut JITState,
|
||||
asm: &mut Assembler,
|
||||
ocb: &mut OutlinedCb,
|
||||
_ci: *const rb_callinfo,
|
||||
_cme: *const rb_callable_method_entry_t,
|
||||
_block: Option<BlockHandler>,
|
||||
_argc: i32,
|
||||
_known_recv_class: *const VALUE,
|
||||
) -> bool {
|
||||
// Guard obj is Fixnum or Flonum to avoid rb_funcall on rb_num_coerce_bin
|
||||
let comptime_obj = jit.peek_at_stack(&asm.ctx, 0);
|
||||
if comptime_obj.fixnum_p() || comptime_obj.flonum_p() {
|
||||
let obj = asm.stack_opnd(0);
|
||||
jit_guard_known_klass(
|
||||
jit,
|
||||
asm,
|
||||
ocb,
|
||||
comptime_obj.class_of(),
|
||||
obj,
|
||||
obj.into(),
|
||||
comptime_obj,
|
||||
SEND_MAX_DEPTH,
|
||||
Counter::guard_send_not_fixnum_or_flonum,
|
||||
);
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Save the PC and SP because the callee may allocate Float on heap
|
||||
jit_prepare_routine_call(jit, asm);
|
||||
|
||||
asm_comment!(asm, "Float#/");
|
||||
let obj = asm.stack_opnd(0);
|
||||
let recv = asm.stack_opnd(1);
|
||||
|
||||
let ret = asm.ccall(rb_float_div as *const u8, vec![recv, obj]);
|
||||
asm.stack_pop(2); // Keep recv during ccall for GC
|
||||
|
||||
let ret_opnd = asm.stack_push(Type::Unknown); // Flonum or heap Float
|
||||
asm.mov(ret_opnd, ret);
|
||||
true
|
||||
}
|
||||
|
||||
/// If string is frozen, duplicate it to get a non-frozen string. Otherwise, return it.
|
||||
fn jit_rb_str_uplus(
|
||||
jit: &mut JITState,
|
||||
@ -9179,6 +9355,11 @@ pub fn yjit_reg_method_codegen_fns() {
|
||||
yjit_reg_method(rb_cInteger, "^", jit_rb_int_xor);
|
||||
yjit_reg_method(rb_cInteger, "[]", jit_rb_int_aref);
|
||||
|
||||
yjit_reg_method(rb_cFloat, "+", jit_rb_float_plus);
|
||||
yjit_reg_method(rb_cFloat, "-", jit_rb_float_minus);
|
||||
yjit_reg_method(rb_cFloat, "*", jit_rb_float_mul);
|
||||
yjit_reg_method(rb_cFloat, "/", jit_rb_float_div);
|
||||
|
||||
yjit_reg_method(rb_cString, "empty?", jit_rb_str_empty_p);
|
||||
yjit_reg_method(rb_cString, "to_s", jit_rb_str_to_s);
|
||||
yjit_reg_method(rb_cString, "to_str", jit_rb_str_to_s);
|
||||
|
@ -1030,6 +1030,10 @@ extern "C" {
|
||||
) -> ::std::os::raw::c_int;
|
||||
pub fn rb_insn_len(insn: VALUE) -> ::std::os::raw::c_int;
|
||||
pub fn rb_vm_insn_decode(encoded: VALUE) -> ::std::os::raw::c_int;
|
||||
pub fn rb_float_plus(x: VALUE, y: VALUE) -> VALUE;
|
||||
pub fn rb_float_minus(x: VALUE, y: VALUE) -> VALUE;
|
||||
pub fn rb_float_mul(x: VALUE, y: VALUE) -> VALUE;
|
||||
pub fn rb_float_div(x: VALUE, y: VALUE) -> VALUE;
|
||||
pub fn rb_fix_aref(fix: VALUE, idx: VALUE) -> VALUE;
|
||||
pub fn rb_vm_insn_addr2opcode(addr: *const ::std::os::raw::c_void) -> ::std::os::raw::c_int;
|
||||
pub fn rb_iseq_line_no(iseq: *const rb_iseq_t, pos: usize) -> ::std::os::raw::c_uint;
|
||||
|
@ -437,6 +437,7 @@ make_counters! {
|
||||
guard_send_instance_of_class_mismatch,
|
||||
guard_send_interrupted,
|
||||
guard_send_not_fixnums,
|
||||
guard_send_not_fixnum_or_flonum,
|
||||
guard_send_not_string,
|
||||
guard_send_respond_to_mid_mismatch,
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user