Skip to content

Commit eb931a0

Browse files
authored
ZJIT: Fix "memory operand with non-register base" (#14153)
1 parent 8eb26eb commit eb931a0

File tree

3 files changed

+20
-2
lines changed

3 files changed

+20
-2
lines changed

test/ruby/test_zjit.rb

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -148,6 +148,18 @@ def test
148148
}, call_threshold: 2
149149
end
150150

151+
def test_send_on_heap_object_in_spilled_arg
152+
# This leads to a register spill, so not using `assert_compiles`
153+
assert_runs 'Hash', %q{
154+
def entry(a1, a2, a3, a4, a5, a6, a7, a8, a9)
155+
a9.itself.class
156+
end
157+
158+
entry(1, 2, 3, 4, 5, 6, 7, 8, {}) # profile
159+
entry(1, 2, 3, 4, 5, 6, 7, 8, {})
160+
}, call_threshold: 2
161+
end
162+
151163
def test_invokebuiltin
152164
omit 'Test fails at the moment due to not handling optional parameters'
153165
assert_compiles '["."]', %q{

zjit/src/backend/lir.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -111,7 +111,7 @@ impl Opnd
111111
})
112112
},
113113

114-
_ => unreachable!("memory operand with non-register base")
114+
_ => unreachable!("memory operand with non-register base: {base:?}")
115115
}
116116
}
117117

zjit/src/codegen.rs

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1088,9 +1088,15 @@ fn gen_guard_type(jit: &mut JITState, asm: &mut Assembler, val: lir::Opnd, guard
10881088
} else if let Some(expected_class) = guard_type.runtime_exact_ruby_class() {
10891089
asm_comment!(asm, "guard exact class for non-immediate types");
10901090

1091-
let side_exit = side_exit(jit, state, GuardType(guard_type))?;
1091+
// If val isn't in a register, load it to use it as the base of Opnd::mem later.
1092+
// TODO: Max thinks codegen should not care about the shapes of the operands except to create them. (Shopify/ruby#685)
1093+
let val = match val {
1094+
Opnd::Reg(_) | Opnd::VReg { .. } => val,
1095+
_ => asm.load(val),
1096+
};
10921097

10931098
// Check if it's a special constant
1099+
let side_exit = side_exit(jit, state, GuardType(guard_type))?;
10941100
asm.test(val, (RUBY_IMMEDIATE_MASK as u64).into());
10951101
asm.jnz(side_exit.clone());
10961102

0 commit comments

Comments
 (0)