diff options
| -rw-r--r-- | zjit/src/codegen.rs | 2 | ||||
| -rw-r--r-- | zjit/src/cruby_methods.rs | 12 | ||||
| -rw-r--r-- | zjit/src/hir.rs | 26 |
3 files changed, 27 insertions, 13 deletions
diff --git a/zjit/src/codegen.rs b/zjit/src/codegen.rs index b1a2cb6726..4b9331e05b 100644 --- a/zjit/src/codegen.rs +++ b/zjit/src/codegen.rs @@ -409,7 +409,7 @@ fn gen_insn(cb: &mut CodeBlock, jit: &mut JITState, asm: &mut Assembler, functio Insn::CCallWithFrame { cd, state, args, .. } if args.len() > C_ARG_OPNDS.len() => gen_send_without_block(jit, asm, *cd, &function.frame_state(*state), SendFallbackReason::CCallWithFrameTooManyArgs), Insn::CCallWithFrame { cfunc, args, cme, state, .. } => gen_ccall_with_frame(jit, asm, *cfunc, opnds!(args), *cme, &function.frame_state(*state)), - Insn::CCallVariadic { cfunc, recv, args, name: _, cme, state } => { + Insn::CCallVariadic { cfunc, recv, args, name: _, cme, state, return_type: _, elidable: _ } => { gen_ccall_variadic(jit, asm, *cfunc, opnd!(recv), opnds!(args), *cme, &function.frame_state(*state)) } Insn::GetIvar { self_val, id, state: _ } => gen_getivar(asm, opnd!(self_val), *id), diff --git a/zjit/src/cruby_methods.rs b/zjit/src/cruby_methods.rs index 334d4e2337..7721ca8440 100644 --- a/zjit/src/cruby_methods.rs +++ b/zjit/src/cruby_methods.rs @@ -31,6 +31,18 @@ pub struct FnProperties { pub elidable: bool, } +/// A safe default for un-annotated Ruby methods: we can't optimize them or their returned values. +impl Default for FnProperties { + fn default() -> Self { + Self { + no_gc: false, + leaf: false, + return_type: types::BasicObject, + elidable: false, + } + } +} + impl Annotations { /// Query about properties of a C method pub fn get_cfunc_properties(&self, method: *const rb_callable_method_entry_t) -> Option<FnProperties> { diff --git a/zjit/src/hir.rs b/zjit/src/hir.rs index ec6746ec39..cee546b026 100644 --- a/zjit/src/hir.rs +++ b/zjit/src/hir.rs @@ -670,6 +670,8 @@ pub enum Insn { cme: *const rb_callable_method_entry_t, name: ID, state: InsnId, + return_type: Type, + elidable: bool, }, /// Un-optimized fallback implementation (dynamic dispatch) for send-ish instructions @@ -1568,8 +1570,8 @@ impl Function { &ObjectAllocClass { class, state } => ObjectAllocClass { class, state: find!(state) }, &CCall { cfunc, ref args, name, return_type, elidable } => CCall { cfunc, args: find_vec!(args), name, return_type, elidable }, &CCallWithFrame { cd, cfunc, ref args, cme, name, state, return_type, elidable } => CCallWithFrame { cd, cfunc, args: find_vec!(args), cme, name, state: find!(state), return_type, elidable }, - &CCallVariadic { cfunc, recv, ref args, cme, name, state } => CCallVariadic { - cfunc, recv: find!(recv), args: find_vec!(args), cme, name, state + &CCallVariadic { cfunc, recv, ref args, cme, name, state, return_type, elidable } => CCallVariadic { + cfunc, recv: find!(recv), args: find_vec!(args), cme, name, state, return_type, elidable }, &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 }, @@ -1670,7 +1672,7 @@ impl Function { Insn::ObjectAllocClass { class, .. } => Type::from_class(*class), &Insn::CCallWithFrame { return_type, .. } => return_type, Insn::CCall { return_type, .. } => *return_type, - Insn::CCallVariadic { .. } => types::BasicObject, + &Insn::CCallVariadic { return_type, .. } => return_type, Insn::GuardType { val, guard_type, .. } => self.type_of(*val).intersection(*guard_type), Insn::GuardTypeNot { .. } => types::BasicObject, Insn::GuardBitEquals { val, expected, .. } => self.type_of(*val).intersection(Type::from_value(*expected)), @@ -2325,10 +2327,12 @@ impl Function { let ci_flags = unsafe { vm_ci_flag(call_info) }; + // Filter for simple call sites (i.e. no splats etc.) if ci_flags & VM_CALL_ARGS_SIMPLE == 0 { return Err(()); } + // Commit to the replacement. Put PatchPoint. gen_patch_points_for_optimized_ccall(fun, block, recv_class, method_id, method, state); if recv_class.instance_can_have_singleton_class() { fun.push_insn(block, Insn::PatchPoint { invariant: Invariant::NoSingletonClass { klass: recv_class }, state }); @@ -2341,17 +2345,10 @@ impl Function { let mut cfunc_args = vec![recv]; cfunc_args.append(&mut args); - // Filter for a leaf and GC free function - use crate::cruby_methods::FnProperties; - // Filter for simple call sites (i.e. no splats etc.) - // Commit to the replacement. Put PatchPoint. - let props = ZJITState::get_method_annotations().get_cfunc_properties(method) - .unwrap_or(FnProperties { leaf: false, - no_gc: false, - return_type: types::BasicObject, - elidable: false }); + let props = ZJITState::get_method_annotations().get_cfunc_properties(method).unwrap_or_default(); let return_type = props.return_type; let elidable = props.elidable; + // Filter for a leaf and GC free function if props.leaf && props.no_gc { let ccall = fun.push_insn(block, Insn::CCall { cfunc, args: cfunc_args, name: method_id, return_type, elidable }); fun.make_equal_to(send_insn_id, ccall); @@ -2385,6 +2382,9 @@ impl Function { } let cfunc = unsafe { get_mct_func(cfunc) }.cast(); + let props = ZJITState::get_method_annotations().get_cfunc_properties(method).unwrap_or_default(); + let return_type = props.return_type; + let elidable = props.elidable; let ccall = fun.push_insn(block, Insn::CCallVariadic { cfunc, recv, @@ -2392,6 +2392,8 @@ impl Function { cme: method, name: method_id, state, + return_type, + elidable, }); fun.make_equal_to(send_insn_id, ccall); |
