mirror of
https://github.com/ruby/ruby.git
synced 2025-08-15 13:39:04 +02:00
ZJIT: Avoid optimizing locals on eval (#13840)
* ZJIT: Avoid optimizing locals on eval * Maintain the local state for eval
This commit is contained in:
parent
9d41541b0c
commit
9ab80a7455
5 changed files with 53 additions and 25 deletions
|
@ -1,6 +1,5 @@
|
|||
use std::cell::Cell;
|
||||
use std::rc::Rc;
|
||||
use std::num::NonZeroU32;
|
||||
|
||||
use crate::backend::current::{Reg, ALLOC_REGS};
|
||||
use crate::invariants::track_bop_assumption;
|
||||
|
@ -302,8 +301,8 @@ fn gen_insn(cb: &mut CodeBlock, jit: &mut JITState, asm: &mut Assembler, functio
|
|||
Insn::GetIvar { self_val, id, state: _ } => gen_getivar(asm, opnd!(self_val), *id),
|
||||
Insn::SetGlobal { id, val, state: _ } => return Some(gen_setglobal(asm, *id, opnd!(val))),
|
||||
Insn::GetGlobal { id, state: _ } => gen_getglobal(asm, *id),
|
||||
&Insn::GetLocal { ep_offset, level } => gen_nested_getlocal(asm, ep_offset, level)?,
|
||||
Insn::SetLocal { val, ep_offset, level } => return gen_nested_setlocal(asm, opnd!(val), *ep_offset, *level),
|
||||
&Insn::GetLocal { ep_offset, level } => gen_getlocal_with_ep(asm, ep_offset, level)?,
|
||||
Insn::SetLocal { val, ep_offset, level } => return gen_setlocal_with_ep(asm, opnd!(val), *ep_offset, *level),
|
||||
Insn::GetConstantPath { ic, state } => gen_get_constant_path(asm, *ic, &function.frame_state(*state)),
|
||||
Insn::SetIvar { self_val, id, val, state: _ } => return gen_setivar(asm, opnd!(self_val), *id, opnd!(val)),
|
||||
Insn::SideExit { state, reason: _ } => return gen_side_exit(jit, asm, &function.frame_state(*state)),
|
||||
|
@ -383,16 +382,20 @@ fn gen_defined(jit: &JITState, asm: &mut Assembler, op_type: usize, _obj: VALUE,
|
|||
}
|
||||
}
|
||||
|
||||
/// Get a local variable from a higher scope. `local_ep_offset` is in number of VALUEs.
|
||||
fn gen_nested_getlocal(asm: &mut Assembler, local_ep_offset: u32, level: NonZeroU32) -> Option<lir::Opnd> {
|
||||
let ep = gen_get_ep(asm, level.get());
|
||||
/// Get a local variable from a higher scope or the heap. `local_ep_offset` is in number of VALUEs.
|
||||
/// We generate this instruction with level=0 only when the local variable is on the heap, so we
|
||||
/// can't optimize the level=0 case using the SP register.
|
||||
fn gen_getlocal_with_ep(asm: &mut Assembler, local_ep_offset: u32, level: u32) -> Option<lir::Opnd> {
|
||||
let ep = gen_get_ep(asm, level);
|
||||
let offset = -(SIZEOF_VALUE_I32 * i32::try_from(local_ep_offset).ok()?);
|
||||
Some(asm.load(Opnd::mem(64, ep, offset)))
|
||||
}
|
||||
|
||||
/// Set a local variable from a higher scope. `local_ep_offset` is in number of VALUEs.
|
||||
fn gen_nested_setlocal(asm: &mut Assembler, val: Opnd, local_ep_offset: u32, level: NonZeroU32) -> Option<()> {
|
||||
let ep = gen_get_ep(asm, level.get());
|
||||
/// Set a local variable from a higher scope or the heap. `local_ep_offset` is in number of VALUEs.
|
||||
/// We generate this instruction with level=0 only when the local variable is on the heap, so we
|
||||
/// can't optimize the level=0 case using the SP register.
|
||||
fn gen_setlocal_with_ep(asm: &mut Assembler, val: Opnd, local_ep_offset: u32, level: u32) -> Option<()> {
|
||||
let ep = gen_get_ep(asm, level);
|
||||
let offset = -(SIZEOF_VALUE_I32 * i32::try_from(local_ep_offset).ok()?);
|
||||
asm.mov(Opnd::mem(64, ep, offset), val);
|
||||
Some(())
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue