summaryrefslogtreecommitdiff
path: root/zjit/src/profile.rs
diff options
context:
space:
mode:
Diffstat (limited to 'zjit/src/profile.rs')
-rw-r--r--zjit/src/profile.rs15
1 files changed, 12 insertions, 3 deletions
diff --git a/zjit/src/profile.rs b/zjit/src/profile.rs
index d8bcd50d96..08803c4570 100644
--- a/zjit/src/profile.rs
+++ b/zjit/src/profile.rs
@@ -95,9 +95,9 @@ fn profile_insn(bare_opcode: ruby_vminsn_type, ec: EcPtr) {
YARVINSN_invokesuper => profile_invokesuper(profiler, profile),
YARVINSN_opt_send_without_block | YARVINSN_send => {
let cd: *const rb_call_data = profiler.insn_opnd(0).as_ptr();
- let argc = unsafe { vm_ci_argc((*cd).ci) };
+ let argc = num_arguments_on_stack(cd);
// Profile all the arguments and self (+1).
- profile_operands(profiler, profile, (argc + 1) as usize);
+ profile_operands(profiler, profile, argc + 1);
}
YARVINSN_splatkw => profile_operands(profiler, profile, 2),
_ => {}
@@ -111,6 +111,15 @@ fn profile_insn(bare_opcode: ruby_vminsn_type, ec: EcPtr) {
}
}
+/// Return the argc as stated in the calldata plus:
+/// * 1 if there is an explicit blockarg, since that will be passed on the stack
+pub fn num_arguments_on_stack(cd: *const rb_call_data) -> usize {
+ let ci = unsafe { rb_get_call_data_ci(cd) };
+ let flags = unsafe { rb_vm_ci_flag(ci) };
+ let has_blockarg = (flags & VM_CALL_ARGS_BLOCKARG) != 0;
+ (unsafe { vm_ci_argc(ci) }) as usize + has_blockarg as usize
+}
+
const DISTRIBUTION_SIZE: usize = 4;
pub type TypeDistribution = Distribution<ProfiledType, DISTRIBUTION_SIZE>;
@@ -184,7 +193,7 @@ fn profile_invokesuper(profiler: &mut Profiler, profile: &mut IseqProfile) {
unsafe { rb_gc_writebarrier(profiler.iseq.into(), cme_value) };
let cd: *const rb_call_data = profiler.insn_opnd(0).as_ptr();
- let argc = unsafe { vm_ci_argc((*cd).ci) };
+ let argc = num_arguments_on_stack(cd);
// Profile all the arguments and self (+1).
profile_operands(profiler, profile, (argc + 1) as usize);