Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit ea37fdb

Browse files
committed
Emit CCall if we know the type statically, not just from profiles
1 parent b1e943c commit ea37fdb

File tree

1 file changed

+34
-14
lines changed

1 file changed

+34
-14
lines changed

zjit/src/hir.rs

+34-14
Original file line numberDiff line numberDiff line change
@@ -1028,10 +1028,11 @@ impl Function {
10281028
fun: &mut Function,
10291029
block: BlockId,
10301030
payload: &profile::IseqPayload,
1031+
self_type: Type,
10311032
send: Insn,
10321033
send_insn_id: InsnId,
10331034
) -> Result<(), ()> {
1034-
let Insn::SendWithoutBlock { self_val, cd, mut args, state, .. } = send else {
1035+
let Insn::SendWithoutBlock { mut self_val, cd, mut args, state, .. } = send else {
10351036
return Err(());
10361037
};
10371038

@@ -1045,13 +1046,14 @@ impl Function {
10451046
// TODO(alan): there was a seemingly a miscomp here if you swap with
10461047
// `inexact_ruby_class`. Theoretically it can call a method too general
10471048
// for the receiver. Confirm and add a test.
1048-
//
1049-
// TODO(max): Use runtime_exact_ruby_class so we can also specialize on known (not just
1050-
// profiled) types.
1051-
let (recv_class, recv_type) = payload.get_operand_types(iseq_insn_idx)
1049+
let (recv_class, guard_type) = if let Some(klass) = self_type.runtime_exact_ruby_class() {
1050+
(klass, None)
1051+
} else {
1052+
payload.get_operand_types(iseq_insn_idx)
10521053
.and_then(|types| types.get(argc as usize))
1053-
.and_then(|recv_type| recv_type.exact_ruby_class().and_then(|class| Some((class, recv_type))))
1054-
.ok_or(())?;
1054+
.and_then(|recv_type| recv_type.exact_ruby_class().and_then(|class| Some((class, Some(recv_type.unspecialized())))))
1055+
.ok_or(())?
1056+
};
10551057

10561058
// Do method lookup
10571059
let method = unsafe { rb_callable_method_entry(recv_class, method_id) };
@@ -1090,8 +1092,10 @@ impl Function {
10901092
if ci_flags & VM_CALL_ARGS_SIMPLE != 0 {
10911093
// Commit to the replacement. Put PatchPoint.
10921094
fun.push_insn(block, Insn::PatchPoint(Invariant::MethodRedefined { klass: recv_class, method: method_id }));
1093-
// Guard receiver class
1094-
let self_val = fun.push_insn(block, Insn::GuardType { val: self_val, guard_type: recv_type.unspecialized(), state });
1095+
if let Some(guard_type) = guard_type {
1096+
// Guard receiver class
1097+
self_val = fun.push_insn(block, Insn::GuardType { val: self_val, guard_type, state });
1098+
}
10951099
let cfun = unsafe { get_mct_func(cfunc) }.cast();
10961100
let mut cfunc_args = vec![self_val];
10971101
cfunc_args.append(&mut args);
@@ -1119,8 +1123,9 @@ impl Function {
11191123
let old_insns = std::mem::take(&mut self.blocks[block.0].insns);
11201124
assert!(self.blocks[block.0].insns.is_empty());
11211125
for insn_id in old_insns {
1122-
if let send @ Insn::SendWithoutBlock { .. } = self.find(insn_id) {
1123-
if reduce_to_ccall(self, block, payload, send, insn_id).is_ok() {
1126+
if let send @ Insn::SendWithoutBlock { self_val, .. } = self.find(insn_id) {
1127+
let self_type = self.type_of(self_val);
1128+
if reduce_to_ccall(self, block, payload, self_type, send, insn_id).is_ok() {
11241129
continue;
11251130
}
11261131
}
@@ -3330,7 +3335,7 @@ mod opt_tests {
33303335
}
33313336

33323337
#[test]
3333-
fn kernel_itself_simple() {
3338+
fn kernel_itself_const() {
33343339
eval("
33353340
def test(x) = x.itself
33363341
test(0) # profile
@@ -3346,6 +3351,21 @@ mod opt_tests {
33463351
"#]]);
33473352
}
33483353

3354+
#[test]
3355+
fn kernel_itself_known_type() {
3356+
eval("
3357+
def test(x) = [].itself
3358+
");
3359+
assert_optimized_method_hir("test", expect![[r#"
3360+
fn test:
3361+
bb0(v0:BasicObject):
3362+
v3:ArrayExact = NewArray
3363+
PatchPoint MethodRedefined(Array@0x1000, itself@0x1008)
3364+
v8:BasicObject = CCall itself@0x1010, v3
3365+
Return v8
3366+
"#]]);
3367+
}
3368+
33493369
#[test]
33503370
fn kernel_itself_argc_mismatch() {
33513371
eval("
@@ -3412,8 +3432,8 @@ mod opt_tests {
34123432
v1:StringExact[VALUE(0x1000)] = Const Value(VALUE(0x1000))
34133433
v2:StringExact = StringCopy v1
34143434
PatchPoint MethodRedefined(String@0x1008, bytesize@0x1010)
3415-
v8:Fixnum = CCall bytesize@0x1018, v2
3416-
Return v8
3435+
v7:Fixnum = CCall bytesize@0x1018, v2
3436+
Return v7
34173437
"#]]);
34183438
}
34193439
}

0 commit comments

Comments
 (0)