YJIT: Refactor getlocal and setlocal insns (#7320)
This commit is contained in:
parent
b4c38f3c59
commit
8f22dc39f3
Notes:
git
2023-02-16 16:30:06 +00:00
Merged-By: maximecb <maximecb@ruby-lang.org>
@ -1468,32 +1468,8 @@ fn gen_expandarray(
|
|||||||
KeepCompiling
|
KeepCompiling
|
||||||
}
|
}
|
||||||
|
|
||||||
fn gen_getlocal_wc0(
|
|
||||||
jit: &mut JITState,
|
|
||||||
ctx: &mut Context,
|
|
||||||
asm: &mut Assembler,
|
|
||||||
_ocb: &mut OutlinedCb,
|
|
||||||
) -> CodegenStatus {
|
|
||||||
// Compute the offset from BP to the local
|
|
||||||
let slot_idx = jit_get_arg(jit, 0).as_i32();
|
|
||||||
let offs: i32 = -SIZEOF_VALUE_I32 * slot_idx;
|
|
||||||
let local_idx = slot_to_local_idx(jit.get_iseq(), slot_idx);
|
|
||||||
|
|
||||||
// Load environment pointer EP (level 0) from CFP
|
|
||||||
let ep_opnd = gen_get_ep(asm, 0);
|
|
||||||
|
|
||||||
// Load the local from the EP
|
|
||||||
let local_opnd = Opnd::mem(64, ep_opnd, offs);
|
|
||||||
|
|
||||||
// Write the local at SP
|
|
||||||
let stack_top = ctx.stack_push_local(local_idx.as_usize());
|
|
||||||
asm.mov(stack_top, local_opnd);
|
|
||||||
|
|
||||||
KeepCompiling
|
|
||||||
}
|
|
||||||
|
|
||||||
// Compute the index of a local variable from its slot index
|
// Compute the index of a local variable from its slot index
|
||||||
fn slot_to_local_idx(iseq: IseqPtr, slot_idx: i32) -> u32 {
|
fn ep_offset_to_local_idx(iseq: IseqPtr, ep_offset: u32) -> u32 {
|
||||||
// Layout illustration
|
// Layout illustration
|
||||||
// This is an array of VALUE
|
// This is an array of VALUE
|
||||||
// | VM_ENV_DATA_SIZE |
|
// | VM_ENV_DATA_SIZE |
|
||||||
@ -1504,7 +1480,7 @@ fn slot_to_local_idx(iseq: IseqPtr, slot_idx: i32) -> u32 {
|
|||||||
// ^ ^ ^ ^
|
// ^ ^ ^ ^
|
||||||
// +-------+---local_table_size----+ cfp->ep--+
|
// +-------+---local_table_size----+ cfp->ep--+
|
||||||
// | |
|
// | |
|
||||||
// +------------------slot_idx----------------+
|
// +------------------ep_offset---------------+
|
||||||
//
|
//
|
||||||
// See usages of local_var_name() from iseq.c for similar calculation.
|
// See usages of local_var_name() from iseq.c for similar calculation.
|
||||||
|
|
||||||
@ -1512,7 +1488,7 @@ fn slot_to_local_idx(iseq: IseqPtr, slot_idx: i32) -> u32 {
|
|||||||
let local_table_size: i32 = unsafe { get_iseq_body_local_table_size(iseq) }
|
let local_table_size: i32 = unsafe { get_iseq_body_local_table_size(iseq) }
|
||||||
.try_into()
|
.try_into()
|
||||||
.unwrap();
|
.unwrap();
|
||||||
let op = slot_idx - (VM_ENV_DATA_SIZE as i32);
|
let op = (ep_offset - VM_ENV_DATA_SIZE) as i32;
|
||||||
let local_idx = local_table_size - op - 1;
|
let local_idx = local_table_size - op - 1;
|
||||||
assert!(local_idx >= 0 && local_idx < local_table_size);
|
assert!(local_idx >= 0 && local_idx < local_table_size);
|
||||||
local_idx.try_into().unwrap()
|
local_idx.try_into().unwrap()
|
||||||
@ -1553,9 +1529,10 @@ fn gen_get_lep(jit: &mut JITState, asm: &mut Assembler) -> Opnd {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn gen_getlocal_generic(
|
fn gen_getlocal_generic(
|
||||||
|
jit: &mut JITState,
|
||||||
ctx: &mut Context,
|
ctx: &mut Context,
|
||||||
asm: &mut Assembler,
|
asm: &mut Assembler,
|
||||||
local_idx: u32,
|
ep_offset: u32,
|
||||||
level: u32,
|
level: u32,
|
||||||
) -> CodegenStatus {
|
) -> CodegenStatus {
|
||||||
// Load environment pointer EP (level 0) from CFP
|
// Load environment pointer EP (level 0) from CFP
|
||||||
@ -1563,11 +1540,16 @@ fn gen_getlocal_generic(
|
|||||||
|
|
||||||
// Load the local from the block
|
// Load the local from the block
|
||||||
// val = *(vm_get_ep(GET_EP(), level) - idx);
|
// val = *(vm_get_ep(GET_EP(), level) - idx);
|
||||||
let offs = -(SIZEOF_VALUE_I32 * local_idx as i32);
|
let offs = -(SIZEOF_VALUE_I32 * ep_offset as i32);
|
||||||
let local_opnd = Opnd::mem(64, ep_opnd, offs);
|
let local_opnd = Opnd::mem(64, ep_opnd, offs);
|
||||||
|
|
||||||
// Write the local at SP
|
// Write the local at SP
|
||||||
let stack_top = ctx.stack_push(Type::Unknown);
|
let stack_top = if level == 0 {
|
||||||
|
let local_idx = ep_offset_to_local_idx(jit.get_iseq(), ep_offset);
|
||||||
|
ctx.stack_push_local(local_idx.as_usize())
|
||||||
|
} else {
|
||||||
|
ctx.stack_push(Type::Unknown)
|
||||||
|
};
|
||||||
|
|
||||||
asm.mov(stack_top, local_opnd);
|
asm.mov(stack_top, local_opnd);
|
||||||
|
|
||||||
@ -1580,9 +1562,19 @@ fn gen_getlocal(
|
|||||||
asm: &mut Assembler,
|
asm: &mut Assembler,
|
||||||
_ocb: &mut OutlinedCb,
|
_ocb: &mut OutlinedCb,
|
||||||
) -> CodegenStatus {
|
) -> CodegenStatus {
|
||||||
let idx = jit_get_arg(jit, 0);
|
let idx = jit_get_arg(jit, 0).as_u32();
|
||||||
let level = jit_get_arg(jit, 1);
|
let level = jit_get_arg(jit, 1).as_u32();
|
||||||
gen_getlocal_generic(ctx, asm, idx.as_u32(), level.as_u32())
|
gen_getlocal_generic(jit, ctx, asm, idx, level)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn gen_getlocal_wc0(
|
||||||
|
jit: &mut JITState,
|
||||||
|
ctx: &mut Context,
|
||||||
|
asm: &mut Assembler,
|
||||||
|
_ocb: &mut OutlinedCb,
|
||||||
|
) -> CodegenStatus {
|
||||||
|
let idx = jit_get_arg(jit, 0).as_u32();
|
||||||
|
gen_getlocal_generic(jit, ctx, asm, idx, 0)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn gen_getlocal_wc1(
|
fn gen_getlocal_wc1(
|
||||||
@ -1591,66 +1583,8 @@ fn gen_getlocal_wc1(
|
|||||||
asm: &mut Assembler,
|
asm: &mut Assembler,
|
||||||
_ocb: &mut OutlinedCb,
|
_ocb: &mut OutlinedCb,
|
||||||
) -> CodegenStatus {
|
) -> CodegenStatus {
|
||||||
let idx = jit_get_arg(jit, 0);
|
let idx = jit_get_arg(jit, 0).as_u32();
|
||||||
gen_getlocal_generic(ctx, asm, idx.as_u32(), 1)
|
gen_getlocal_generic(jit, ctx, asm, idx, 1)
|
||||||
}
|
|
||||||
|
|
||||||
fn gen_setlocal_wc0(
|
|
||||||
jit: &mut JITState,
|
|
||||||
ctx: &mut Context,
|
|
||||||
asm: &mut Assembler,
|
|
||||||
ocb: &mut OutlinedCb,
|
|
||||||
) -> CodegenStatus {
|
|
||||||
/*
|
|
||||||
vm_env_write(const VALUE *ep, int index, VALUE v)
|
|
||||||
{
|
|
||||||
VALUE flags = ep[VM_ENV_DATA_INDEX_FLAGS];
|
|
||||||
if (LIKELY((flags & VM_ENV_FLAG_WB_REQUIRED) == 0)) {
|
|
||||||
VM_STACK_ENV_WRITE(ep, index, v);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
vm_env_write_slowpath(ep, index, v);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
|
|
||||||
let slot_idx = jit_get_arg(jit, 0).as_i32();
|
|
||||||
let local_idx = slot_to_local_idx(jit.get_iseq(), slot_idx).as_usize();
|
|
||||||
let value_type = ctx.get_opnd_type(StackOpnd(0));
|
|
||||||
|
|
||||||
// Load environment pointer EP (level 0) from CFP
|
|
||||||
let ep_opnd = gen_get_ep(asm, 0);
|
|
||||||
|
|
||||||
// Write barriers may be required when VM_ENV_FLAG_WB_REQUIRED is set, however write barriers
|
|
||||||
// only affect heap objects being written. If we know an immediate value is being written we
|
|
||||||
// can skip this check.
|
|
||||||
if !value_type.is_imm() {
|
|
||||||
// flags & VM_ENV_FLAG_WB_REQUIRED
|
|
||||||
let flags_opnd = Opnd::mem(
|
|
||||||
64,
|
|
||||||
ep_opnd,
|
|
||||||
SIZEOF_VALUE_I32 * VM_ENV_DATA_INDEX_FLAGS as i32,
|
|
||||||
);
|
|
||||||
asm.test(flags_opnd, VM_ENV_FLAG_WB_REQUIRED.into());
|
|
||||||
|
|
||||||
// Create a side-exit to fall back to the interpreter
|
|
||||||
let side_exit = get_side_exit(jit, ocb, ctx);
|
|
||||||
|
|
||||||
// if (flags & VM_ENV_FLAG_WB_REQUIRED) != 0
|
|
||||||
asm.jnz(side_exit);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Set the type of the local variable in the context
|
|
||||||
ctx.set_local_type(local_idx, value_type);
|
|
||||||
|
|
||||||
// Pop the value to write from the stack
|
|
||||||
let stack_top = ctx.stack_pop(1);
|
|
||||||
|
|
||||||
// Write the value at the environment pointer
|
|
||||||
let offs: i32 = -8 * slot_idx;
|
|
||||||
asm.mov(Opnd::mem(64, ep_opnd, offs), stack_top);
|
|
||||||
|
|
||||||
KeepCompiling
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn gen_setlocal_generic(
|
fn gen_setlocal_generic(
|
||||||
@ -1658,7 +1592,7 @@ fn gen_setlocal_generic(
|
|||||||
ctx: &mut Context,
|
ctx: &mut Context,
|
||||||
asm: &mut Assembler,
|
asm: &mut Assembler,
|
||||||
ocb: &mut OutlinedCb,
|
ocb: &mut OutlinedCb,
|
||||||
local_idx: i32,
|
ep_offset: u32,
|
||||||
level: u32,
|
level: u32,
|
||||||
) -> CodegenStatus {
|
) -> CodegenStatus {
|
||||||
let value_type = ctx.get_opnd_type(StackOpnd(0));
|
let value_type = ctx.get_opnd_type(StackOpnd(0));
|
||||||
@ -1685,11 +1619,16 @@ fn gen_setlocal_generic(
|
|||||||
asm.jnz(side_exit);
|
asm.jnz(side_exit);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if level == 0 {
|
||||||
|
let local_idx = ep_offset_to_local_idx(jit.get_iseq(), ep_offset).as_usize();
|
||||||
|
ctx.set_local_type(local_idx, value_type);
|
||||||
|
}
|
||||||
|
|
||||||
// Pop the value to write from the stack
|
// Pop the value to write from the stack
|
||||||
let stack_top = ctx.stack_pop(1);
|
let stack_top = ctx.stack_pop(1);
|
||||||
|
|
||||||
// Write the value at the environment pointer
|
// Write the value at the environment pointer
|
||||||
let offs = -(SIZEOF_VALUE_I32 * local_idx);
|
let offs = -(SIZEOF_VALUE_I32 * ep_offset as i32);
|
||||||
asm.mov(Opnd::mem(64, ep_opnd, offs), stack_top);
|
asm.mov(Opnd::mem(64, ep_opnd, offs), stack_top);
|
||||||
|
|
||||||
KeepCompiling
|
KeepCompiling
|
||||||
@ -1701,18 +1640,28 @@ fn gen_setlocal(
|
|||||||
asm: &mut Assembler,
|
asm: &mut Assembler,
|
||||||
ocb: &mut OutlinedCb,
|
ocb: &mut OutlinedCb,
|
||||||
) -> CodegenStatus {
|
) -> CodegenStatus {
|
||||||
let idx = jit_get_arg(jit, 0).as_i32();
|
let idx = jit_get_arg(jit, 0).as_u32();
|
||||||
let level = jit_get_arg(jit, 1).as_u32();
|
let level = jit_get_arg(jit, 1).as_u32();
|
||||||
gen_setlocal_generic(jit, ctx, asm, ocb, idx, level)
|
gen_setlocal_generic(jit, ctx, asm, ocb, idx, level)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn gen_setlocal_wc0(
|
||||||
|
jit: &mut JITState,
|
||||||
|
ctx: &mut Context,
|
||||||
|
asm: &mut Assembler,
|
||||||
|
ocb: &mut OutlinedCb,
|
||||||
|
) -> CodegenStatus {
|
||||||
|
let idx = jit_get_arg(jit, 0).as_u32();
|
||||||
|
gen_setlocal_generic(jit, ctx, asm, ocb, idx, 0)
|
||||||
|
}
|
||||||
|
|
||||||
fn gen_setlocal_wc1(
|
fn gen_setlocal_wc1(
|
||||||
jit: &mut JITState,
|
jit: &mut JITState,
|
||||||
ctx: &mut Context,
|
ctx: &mut Context,
|
||||||
asm: &mut Assembler,
|
asm: &mut Assembler,
|
||||||
ocb: &mut OutlinedCb,
|
ocb: &mut OutlinedCb,
|
||||||
) -> CodegenStatus {
|
) -> CodegenStatus {
|
||||||
let idx = jit_get_arg(jit, 0).as_i32();
|
let idx = jit_get_arg(jit, 0).as_u32();
|
||||||
gen_setlocal_generic(jit, ctx, asm, ocb, idx, 1)
|
gen_setlocal_generic(jit, ctx, asm, ocb, idx, 1)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user