Refactor gen_opt_mod in YJIT
This commit is contained in:
Dave Schwantes 2022-06-30 09:26:46 -05:00 коммит произвёл GitHub
Родитель 2366e14976
Коммит b6f6fc6e87
Не найден ключ, соответствующий данной подписи
Идентификатор ключа GPG: 4AEE18F83AFDEB23
4 изменённых файлов: 48 добавлений и 25 удалений

Просмотреть файл

@ -5253,12 +5253,6 @@ vm_opt_mod(VALUE recv, VALUE obj)
}
}
VALUE
rb_vm_opt_mod(VALUE recv, VALUE obj)
{
return vm_opt_mod(recv, obj);
}
static VALUE
vm_opt_neq(const rb_iseq_t *iseq, CALL_DATA cd, CALL_DATA cd_eq, VALUE recv, VALUE obj)
{

7
yjit.c
Просмотреть файл

@ -13,6 +13,7 @@
#include "internal/variable.h"
#include "internal/compile.h"
#include "internal/class.h"
#include "internal/fixnum.h"
#include "gc.h"
#include "vm_core.h"
#include "vm_callinfo.h"
@ -714,6 +715,12 @@ rb_yarv_ary_entry_internal(VALUE ary, long offset)
return rb_ary_entry_internal(ary, offset);
}
VALUE
rb_yarv_fix_mod_fix(VALUE recv, VALUE obj)
{
return rb_fix_mod_fix(recv, obj);
}
// Print the Ruby source location of some ISEQ for debugging purposes
void
rb_yjit_dump_iseq_loc(const rb_iseq_t *iseq, uint32_t insn_idx)

Просмотреть файл

@ -2951,30 +2951,50 @@ fn gen_opt_mod(
cb: &mut CodeBlock,
ocb: &mut OutlinedCb,
) -> CodegenStatus {
// Save the PC and SP because the callee may allocate bignums
// Note that this modifies REG_SP, which is why we do it first
jit_prepare_routine_call(jit, ctx, cb, REG0);
// Defer compilation so we can specialize on a runtime `self`
if !jit_at_current_insn(jit) {
defer_compilation(jit, ctx, cb, ocb);
return EndBlock;
}
let side_exit = get_side_exit(jit, ocb, ctx);
let comptime_a = jit_peek_at_stack(jit, ctx, 1);
let comptime_b = jit_peek_at_stack(jit, ctx, 0);
// Get the operands from the stack
let arg1 = ctx.stack_pop(1);
let arg0 = ctx.stack_pop(1);
if comptime_a.fixnum_p() && comptime_b.fixnum_p() {
// Create a side-exit to fall back to the interpreter
// Note: we generate the side-exit before popping operands from the stack
let side_exit = get_side_exit(jit, ocb, ctx);
// Call rb_vm_opt_mod(VALUE recv, VALUE obj)
mov(cb, C_ARG_REGS[0], arg0);
mov(cb, C_ARG_REGS[1], arg1);
call_ptr(cb, REG0, rb_vm_opt_mod as *const u8);
if !assume_bop_not_redefined(jit, ocb, INTEGER_REDEFINED_OP_FLAG, BOP_MOD) {
return CantCompile;
}
// If val == Qundef, bail to do a method call
cmp(cb, RAX, imm_opnd(Qundef.as_i64()));
je_ptr(cb, side_exit);
// Check that both operands are fixnums
guard_two_fixnums(ctx, cb, side_exit);
// Push the return value onto the stack
let stack_ret = ctx.stack_push(Type::Unknown);
mov(cb, stack_ret, RAX);
// Get the operands and destination from the stack
let arg1 = ctx.stack_pop(1);
let arg0 = ctx.stack_pop(1);
KeepCompiling
mov(cb, C_ARG_REGS[0], arg0);
mov(cb, C_ARG_REGS[1], arg1);
// Check for arg0 % 0
cmp(cb, C_ARG_REGS[1], imm_opnd(VALUE::fixnum_from_usize(0).as_i64()));
je_ptr(cb, side_exit);
// Call rb_fix_mod_fix(VALUE recv, VALUE obj)
call_ptr(cb, REG0, rb_fix_mod_fix as *const u8);
// Push the return value onto the stack
let stack_ret = ctx.stack_push(Type::Unknown);
mov(cb, stack_ret, RAX);
KeepCompiling
} else {
// Delegate to send, call the method on the recv
gen_opt_send_without_block(jit, ctx, cb, ocb)
}
}
fn gen_opt_ltlt(

Просмотреть файл

@ -235,6 +235,9 @@ extern "C" {
#[link_name = "rb_yarv_ary_entry_internal"]
pub fn rb_ary_entry_internal(ary: VALUE, offset: c_long) -> VALUE;
#[link_name = "rb_yarv_fix_mod_fix"]
pub fn rb_fix_mod_fix(recv: VALUE, obj: VALUE) -> VALUE;
#[link_name = "rb_FL_TEST"]
pub fn FL_TEST(obj: VALUE, flags: VALUE) -> VALUE;
@ -255,7 +258,6 @@ extern "C" {
// Ruby only defines these in vm_insnhelper.c, not in any header.
// Parsing it would result in a lot of duplicate definitions.
pub fn rb_vm_opt_mod(recv: VALUE, obj: VALUE) -> VALUE;
pub fn rb_vm_splat_array(flag: VALUE, ary: VALUE) -> VALUE;
pub fn rb_vm_defined(
ec: EcPtr,