Skip to content

Commit 90a03b4

Browse files
committed
fix(aot): unbox tagged array indexes
1 parent 9b384de commit 90a03b4

2 files changed

Lines changed: 64 additions & 2 deletions

File tree

src/vm/aot/ssa.rs

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2438,13 +2438,19 @@ fn emit_tagged_binary_with_int_rhs<E: InstEmitter>(
24382438
) -> Result<bool, AotSsaBuildError> {
24392439
let rhs = frame.pop(ip, instruction)?;
24402440
let lhs = frame.pop(ip, instruction)?;
2441-
if lhs.value.repr != AotSsaValueRepr::Tagged || rhs.value.repr != AotSsaValueRepr::I64 {
2441+
if lhs.value.repr != AotSsaValueRepr::Tagged
2442+
|| !matches!(
2443+
rhs.value.repr,
2444+
AotSsaValueRepr::I64 | AotSsaValueRepr::Tagged
2445+
)
2446+
{
24422447
frame.stack.push(lhs);
24432448
frame.stack.push(rhs);
24442449
return Ok(false);
24452450
}
2451+
let rhs = coerce_numeric_to_int(emitter, ip, rhs.value);
24462452
frame.stack.push(FrameValue {
2447-
value: emitter.emit(ip, build(lhs.value.id, rhs.value.id), output_repr),
2453+
value: emitter.emit(ip, build(lhs.value.id, rhs.id), output_repr),
24482454
});
24492455
Ok(true)
24502456
}

tests/jit/jit_tests.rs

Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -501,6 +501,62 @@ fn aot_inlines_array_len_and_get_without_builtin_boundary() {
501501
);
502502
}
503503

504+
#[test]
505+
fn aot_inlines_array_get_result_used_as_next_array_index() {
506+
if !native_jit_supported() {
507+
return;
508+
}
509+
510+
let get_call = builtin_call_index("get").expect("get builtin should exist");
511+
let mut bc = BytecodeBuilder::new();
512+
bc.ldc(0);
513+
bc.stloc(0);
514+
bc.ldc(1);
515+
bc.stloc(1);
516+
517+
bc.ldloc(0);
518+
bc.ldloc(1);
519+
bc.ldc(2);
520+
let index_get_ip = bc.position();
521+
bc.call(get_call, 2);
522+
let value_get_ip = bc.position();
523+
bc.call(get_call, 2);
524+
bc.ret();
525+
526+
let program = Program::new(
527+
vec![
528+
Value::array(vec![Value::Int(100), Value::Int(200), Value::Int(300)]),
529+
Value::array(vec![Value::Int(2)]),
530+
Value::Int(0),
531+
],
532+
bc.finish(),
533+
)
534+
.with_local_count(2);
535+
let program = force_local_types(program, &[(0, ValueType::Array), (1, ValueType::Array)]);
536+
let program = force_operand_types(
537+
program,
538+
&[
539+
(index_get_ip as usize, (ValueType::Array, ValueType::Int)),
540+
(value_get_ip as usize, (ValueType::Array, ValueType::Int)),
541+
],
542+
);
543+
let mut vm = Vm::new(program);
544+
vm.set_jit_native_bridge_stats_enabled(true);
545+
install_aot(&mut vm);
546+
547+
assert_eq!(vm.run().expect("aot vm should run"), VmStatus::Halted);
548+
assert_eq!(vm.stack(), &[Value::Int(300)]);
549+
assert!(vm.aot_exec_count() > 0, "aot should execute natively");
550+
let bridge_hits = vm.jit_native_bridge_stats_snapshot();
551+
assert_eq!(
552+
bridge_hits
553+
.iter()
554+
.find_map(|(name, count)| (*name == "get").then_some(*count)),
555+
None,
556+
"Array get should not cross the builtin bridge: {bridge_hits:?}"
557+
);
558+
}
559+
504560
#[test]
505561
fn aot_inlines_same_local_map_set_in_loop() {
506562
if !native_jit_supported() {

0 commit comments

Comments
 (0)