mirror of
https://github.com/ruby/ruby.git
synced 2025-08-15 13:39:04 +02:00
ZJIT: Implement defined?
codegen for non-yield calls (#14101)
This commit is contained in:
parent
c41c323f1a
commit
2edc944702
3 changed files with 43 additions and 12 deletions
|
@ -369,7 +369,7 @@ fn gen_insn(cb: &mut CodeBlock, jit: &mut JITState, asm: &mut Assembler, functio
|
|||
Insn::SideExit { state, reason } => return gen_side_exit(jit, asm, reason, &function.frame_state(*state)),
|
||||
Insn::PutSpecialObject { value_type } => gen_putspecialobject(asm, *value_type),
|
||||
Insn::AnyToString { val, str, state } => gen_anytostring(asm, opnd!(val), opnd!(str), &function.frame_state(*state))?,
|
||||
Insn::Defined { op_type, obj, pushval, v } => gen_defined(jit, asm, *op_type, *obj, *pushval, opnd!(v))?,
|
||||
Insn::Defined { op_type, obj, pushval, v, state } => gen_defined(jit, asm, *op_type, *obj, *pushval, opnd!(v), &function.frame_state(*state))?,
|
||||
&Insn::IncrCounter(counter) => return Some(gen_incr_counter(asm, counter)),
|
||||
Insn::ArrayExtend { .. }
|
||||
| Insn::ArrayMax { .. }
|
||||
|
@ -438,7 +438,7 @@ fn gen_get_ep(asm: &mut Assembler, level: u32) -> Opnd {
|
|||
ep_opnd
|
||||
}
|
||||
|
||||
fn gen_defined(jit: &JITState, asm: &mut Assembler, op_type: usize, _obj: VALUE, pushval: VALUE, _tested_value: Opnd) -> Option<Opnd> {
|
||||
fn gen_defined(jit: &JITState, asm: &mut Assembler, op_type: usize, obj: VALUE, pushval: VALUE, tested_value: Opnd, state: &FrameState) -> Option<Opnd> {
|
||||
match op_type as defined_type {
|
||||
DEFINED_YIELD => {
|
||||
// `yield` goes to the block handler stowed in the "local" iseq which is
|
||||
|
@ -455,7 +455,17 @@ fn gen_defined(jit: &JITState, asm: &mut Assembler, op_type: usize, _obj: VALUE,
|
|||
Some(Qnil.into())
|
||||
}
|
||||
}
|
||||
_ => None
|
||||
_ => {
|
||||
// Save the PC and SP because the callee may allocate or call #respond_to?
|
||||
gen_prepare_non_leaf_call(jit, asm, state)?;
|
||||
|
||||
// TODO: Inline the cases for each op_type
|
||||
// Call vm_defined(ec, reg_cfp, op_type, obj, v)
|
||||
let def_result = asm_ccall!(asm, rb_vm_defined, EC, CFP, op_type.into(), obj.into(), tested_value);
|
||||
|
||||
asm.cmp(def_result.with_num_bits(8).unwrap(), 0.into());
|
||||
Some(asm.csel_ne(pushval.into(), Qnil.into()))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -472,7 +472,7 @@ pub enum Insn {
|
|||
Test { val: InsnId },
|
||||
/// Return C `true` if `val` is `Qnil`, else `false`.
|
||||
IsNil { val: InsnId },
|
||||
Defined { op_type: usize, obj: VALUE, pushval: VALUE, v: InsnId },
|
||||
Defined { op_type: usize, obj: VALUE, pushval: VALUE, v: InsnId, state: InsnId },
|
||||
GetConstantPath { ic: *const iseq_inline_constant_cache, state: InsnId },
|
||||
|
||||
/// Get a global variable named `id`
|
||||
|
@ -1173,7 +1173,7 @@ impl Function {
|
|||
&ArrayDup { val, state } => ArrayDup { val: find!(val), state },
|
||||
&HashDup { val, state } => HashDup { val: find!(val), state },
|
||||
&CCall { cfun, ref args, name, return_type, elidable } => CCall { cfun, args: find_vec!(args), name, return_type, elidable },
|
||||
&Defined { op_type, obj, pushval, v } => Defined { op_type, obj, pushval, v: find!(v) },
|
||||
&Defined { op_type, obj, pushval, v, state } => Defined { op_type, obj, pushval, v: find!(v), state: find!(state) },
|
||||
&DefinedIvar { self_val, pushval, id, state } => DefinedIvar { self_val: find!(self_val), pushval, id, state },
|
||||
&NewArray { ref elements, state } => NewArray { elements: find_vec!(elements), state: find!(state) },
|
||||
&NewHash { ref elements, state } => {
|
||||
|
@ -2788,7 +2788,8 @@ pub fn iseq_to_hir(iseq: *const rb_iseq_t) -> Result<Function, ParseError> {
|
|||
let obj = get_arg(pc, 1);
|
||||
let pushval = get_arg(pc, 2);
|
||||
let v = state.stack_pop()?;
|
||||
state.stack_push(fun.push_insn(block, Insn::Defined { op_type, obj, pushval, v }));
|
||||
let exit_id = fun.push_insn(block, Insn::Snapshot { state: exit_state });
|
||||
state.stack_push(fun.push_insn(block, Insn::Defined { op_type, obj, pushval, v, state: exit_id }));
|
||||
}
|
||||
YARVINSN_definedivar => {
|
||||
// (ID id, IVC ic, VALUE pushval)
|
||||
|
@ -4061,12 +4062,12 @@ mod tests {
|
|||
fn test@<compiled>:2:
|
||||
bb0(v0:BasicObject):
|
||||
v2:NilClass = Const Value(nil)
|
||||
v3:BasicObject = Defined constant, v2
|
||||
v4:BasicObject = Defined func, v0
|
||||
v5:NilClass = Const Value(nil)
|
||||
v6:BasicObject = Defined global-variable, v5
|
||||
v8:ArrayExact = NewArray v3, v4, v6
|
||||
Return v8
|
||||
v4:BasicObject = Defined constant, v2
|
||||
v6:BasicObject = Defined func, v0
|
||||
v7:NilClass = Const Value(nil)
|
||||
v9:BasicObject = Defined global-variable, v7
|
||||
v11:ArrayExact = NewArray v4, v6, v9
|
||||
Return v11
|
||||
"#]]);
|
||||
}
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue