YJIT: Drop Copy trait from Context (#8138)
This commit is contained in:
parent
087a2deccf
commit
bde4080b39
Notes:
git
2023-07-30 01:14:23 +00:00
Merged-By: maximecb <maximecb@ruby-lang.org>
@ -933,8 +933,36 @@ pub struct SideExitContext {
|
|||||||
/// PC of the instruction being compiled
|
/// PC of the instruction being compiled
|
||||||
pub pc: *mut VALUE,
|
pub pc: *mut VALUE,
|
||||||
|
|
||||||
/// Context when it started to compile the instruction
|
/// Context fields used by get_generic_ctx()
|
||||||
pub ctx: Context,
|
pub stack_size: u8,
|
||||||
|
pub sp_offset: i8,
|
||||||
|
pub reg_temps: RegTemps,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl SideExitContext {
|
||||||
|
/// Convert PC and Context into SideExitContext
|
||||||
|
pub fn new(pc: *mut VALUE, ctx: Context) -> Self {
|
||||||
|
let exit_ctx = SideExitContext {
|
||||||
|
pc,
|
||||||
|
stack_size: ctx.get_stack_size(),
|
||||||
|
sp_offset: ctx.get_sp_offset(),
|
||||||
|
reg_temps: ctx.get_reg_temps(),
|
||||||
|
};
|
||||||
|
if cfg!(debug_assertions) {
|
||||||
|
// Assert that we're not losing any mandatory metadata
|
||||||
|
assert_eq!(exit_ctx.get_ctx(), ctx.get_generic_ctx());
|
||||||
|
}
|
||||||
|
exit_ctx
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Convert SideExitContext to Context
|
||||||
|
fn get_ctx(&self) -> Context {
|
||||||
|
let mut ctx = Context::default();
|
||||||
|
ctx.set_stack_size(self.stack_size);
|
||||||
|
ctx.set_sp_offset(self.sp_offset);
|
||||||
|
ctx.set_reg_temps(self.reg_temps);
|
||||||
|
ctx
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Object into which we assemble instructions to be
|
/// Object into which we assemble instructions to be
|
||||||
@ -1039,10 +1067,10 @@ impl Assembler
|
|||||||
if let Some(Target::SideExit { context, .. }) = insn.target_mut() {
|
if let Some(Target::SideExit { context, .. }) = insn.target_mut() {
|
||||||
// We should skip this when this instruction is being copied from another Assembler.
|
// We should skip this when this instruction is being copied from another Assembler.
|
||||||
if context.is_none() {
|
if context.is_none() {
|
||||||
*context = Some(SideExitContext {
|
*context = Some(SideExitContext::new(
|
||||||
pc: self.side_exit_pc.unwrap(),
|
self.side_exit_pc.unwrap(),
|
||||||
ctx: self.ctx.with_stack_size(self.side_exit_stack_size.unwrap()),
|
self.ctx.with_stack_size(self.side_exit_stack_size.unwrap()),
|
||||||
});
|
));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1052,14 +1080,10 @@ impl Assembler
|
|||||||
|
|
||||||
/// Get a cached side exit, wrapping a counter if specified
|
/// Get a cached side exit, wrapping a counter if specified
|
||||||
pub fn get_side_exit(&mut self, side_exit_context: &SideExitContext, counter: Option<Counter>, ocb: &mut OutlinedCb) -> CodePtr {
|
pub fn get_side_exit(&mut self, side_exit_context: &SideExitContext, counter: Option<Counter>, ocb: &mut OutlinedCb) -> CodePtr {
|
||||||
// Drop type information from a cache key
|
|
||||||
let mut side_exit_context = side_exit_context.clone();
|
|
||||||
side_exit_context.ctx = side_exit_context.ctx.get_generic_ctx();
|
|
||||||
|
|
||||||
// Get a cached side exit
|
// Get a cached side exit
|
||||||
let side_exit = match self.side_exits.get(&side_exit_context) {
|
let side_exit = match self.side_exits.get(&side_exit_context) {
|
||||||
None => {
|
None => {
|
||||||
let exit_code = gen_outlined_exit(side_exit_context.pc, &side_exit_context.ctx, ocb);
|
let exit_code = gen_outlined_exit(side_exit_context.pc, &side_exit_context.get_ctx(), ocb);
|
||||||
self.side_exits.insert(side_exit_context.clone(), exit_code);
|
self.side_exits.insert(side_exit_context.clone(), exit_code);
|
||||||
exit_code
|
exit_code
|
||||||
}
|
}
|
||||||
|
@ -546,7 +546,7 @@ pub fn jit_ensure_block_entry_exit(jit: &mut JITState, asm: &mut Assembler, ocb:
|
|||||||
// If we're compiling the first instruction in the block.
|
// If we're compiling the first instruction in the block.
|
||||||
if jit.insn_idx == jit.starting_insn_idx {
|
if jit.insn_idx == jit.starting_insn_idx {
|
||||||
// Generate the exit with the cache in Assembler.
|
// Generate the exit with the cache in Assembler.
|
||||||
let side_exit_context = SideExitContext { pc: jit.pc, ctx: block_starting_context.clone() };
|
let side_exit_context = SideExitContext::new(jit.pc, block_starting_context.clone());
|
||||||
let entry_exit = asm.get_side_exit(&side_exit_context, None, ocb);
|
let entry_exit = asm.get_side_exit(&side_exit_context, None, ocb);
|
||||||
jit.block_entry_exit = Some(entry_exit);
|
jit.block_entry_exit = Some(entry_exit);
|
||||||
} else {
|
} else {
|
||||||
@ -800,7 +800,7 @@ pub fn gen_single_block(
|
|||||||
let blockid_idx = blockid.idx;
|
let blockid_idx = blockid.idx;
|
||||||
let chain_depth = if asm.ctx.get_chain_depth() > 0 { format!("(chain_depth: {})", asm.ctx.get_chain_depth()) } else { "".to_string() };
|
let chain_depth = if asm.ctx.get_chain_depth() > 0 { format!("(chain_depth: {})", asm.ctx.get_chain_depth()) } else { "".to_string() };
|
||||||
asm.comment(&format!("Block: {} {}", iseq_get_location(blockid.iseq, blockid_idx), chain_depth));
|
asm.comment(&format!("Block: {} {}", iseq_get_location(blockid.iseq, blockid_idx), chain_depth));
|
||||||
asm.comment(&format!("reg_temps: {:08b}", ctx.get_reg_temps().as_u8()));
|
asm.comment(&format!("reg_temps: {:08b}", asm.ctx.get_reg_temps().as_u8()));
|
||||||
}
|
}
|
||||||
|
|
||||||
// For each instruction to compile
|
// For each instruction to compile
|
||||||
@ -8555,7 +8555,7 @@ mod tests {
|
|||||||
#[test]
|
#[test]
|
||||||
fn test_get_side_exit() {
|
fn test_get_side_exit() {
|
||||||
let (_jit, ctx, mut asm, _, mut ocb) = setup_codegen();
|
let (_jit, ctx, mut asm, _, mut ocb) = setup_codegen();
|
||||||
let side_exit_context = SideExitContext { pc: 0 as _, ctx };
|
let side_exit_context = SideExitContext::new(0 as _, ctx);
|
||||||
asm.get_side_exit(&side_exit_context, None, &mut ocb);
|
asm.get_side_exit(&side_exit_context, None, &mut ocb);
|
||||||
assert!(ocb.unwrap().get_write_pos() > 0);
|
assert!(ocb.unwrap().get_write_pos() > 0);
|
||||||
}
|
}
|
||||||
|
@ -417,7 +417,7 @@ impl RegTemps {
|
|||||||
/// Code generation context
|
/// Code generation context
|
||||||
/// Contains information we can use to specialize/optimize code
|
/// Contains information we can use to specialize/optimize code
|
||||||
/// There are a lot of context objects so we try to keep the size small.
|
/// There are a lot of context objects so we try to keep the size small.
|
||||||
#[derive(Clone, Copy, Default, Eq, Hash, PartialEq, Debug)]
|
#[derive(Clone, Default, Eq, Hash, PartialEq, Debug)]
|
||||||
pub struct Context {
|
pub struct Context {
|
||||||
// Number of values currently on the temporary stack
|
// Number of values currently on the temporary stack
|
||||||
stack_size: u8,
|
stack_size: u8,
|
||||||
@ -1567,6 +1567,10 @@ impl Context {
|
|||||||
self.stack_size
|
self.stack_size
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn set_stack_size(&mut self, stack_size: u8) {
|
||||||
|
self.stack_size = stack_size;
|
||||||
|
}
|
||||||
|
|
||||||
/// Create a new Context that is compatible with self but doesn't have type information.
|
/// Create a new Context that is compatible with self but doesn't have type information.
|
||||||
pub fn get_generic_ctx(&self) -> Context {
|
pub fn get_generic_ctx(&self) -> Context {
|
||||||
let mut generic_ctx = Context::default();
|
let mut generic_ctx = Context::default();
|
||||||
|
Loading…
x
Reference in New Issue
Block a user