Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix callx error discrepancy between interpreter and jit #629

Merged
merged 13 commits into from
Nov 22, 2024
27 changes: 15 additions & 12 deletions src/jit.rs
Original file line number Diff line number Diff line change
Expand Up @@ -979,20 +979,19 @@ impl<'a, C: ContextObject> JitCompiler<'a, C> {
}

#[inline]
fn emit_undo_profile_instruction_count(&mut self, target_pc: Option<usize>) {
fn emit_undo_profile_instruction_count(&mut self, target_pc: Value) {
if self.config.enable_instruction_meter {
match target_pc {
Some(target_pc) => {
self.emit_ins(X86Instruction::alu(OperandSize::S64, 0x81, 0, REGISTER_INSTRUCTION_METER, self.pc as i64 + 1 - target_pc as i64, None)); // instruction_meter += (self.pc + 1) - target_pc;
Value::Constant64(target_pc, _) => {
self.emit_ins(X86Instruction::alu(OperandSize::S64, 0x81, 0, REGISTER_INSTRUCTION_METER, self.pc as i64 + 1 - target_pc, None)); // instruction_meter += (self.pc + 1) - target_pc;
}
None => {
self.emit_ins(X86Instruction::alu(OperandSize::S64, 0x29, REGISTER_SCRATCH, REGISTER_INSTRUCTION_METER, 0, None)); // instruction_meter -= guest_target_pc
Value::Register(reg) => {
self.emit_ins(X86Instruction::alu(OperandSize::S64, 0x29, reg, REGISTER_INSTRUCTION_METER, 0, None)); // instruction_meter -= guest_target_pc
LucasSte marked this conversation as resolved.
Show resolved Hide resolved
self.emit_ins(X86Instruction::alu(OperandSize::S64, 0x81, 0, REGISTER_INSTRUCTION_METER, 1, None)); // instruction_meter += 1
// Retrieve the current program from the stack. `return_near` popped an element from the stack,
// so the offset is 16. Check `ANCHOR_INTERNAL_FUNCTION_CALL_REG` for more details.
self.emit_ins(X86Instruction::load(OperandSize::S64, RSP, REGISTER_SCRATCH, X86IndirectAccess::OffsetIndexShift(-16, RSP, 0)));
LucasSte marked this conversation as resolved.
Show resolved Hide resolved
self.emit_ins(X86Instruction::alu(OperandSize::S64, 0x01, REGISTER_SCRATCH, REGISTER_INSTRUCTION_METER, 0, None)); // instruction_meter += guest_current_pc
LucasSte marked this conversation as resolved.
Show resolved Hide resolved
}
_ => {},
LucasSte marked this conversation as resolved.
Show resolved Hide resolved
}
}
}
Expand Down Expand Up @@ -1137,7 +1136,7 @@ impl<'a, C: ContextObject> JitCompiler<'a, C> {
}
}

self.emit_undo_profile_instruction_count(Some(0));
self.emit_undo_profile_instruction_count(Value::Constant64(0, false));

// Restore the previous frame pointer
self.emit_ins(X86Instruction::pop(REGISTER_MAP[FRAME_PTR_REG]));
Expand All @@ -1151,7 +1150,7 @@ impl<'a, C: ContextObject> JitCompiler<'a, C> {
self.emit_validate_and_profile_instruction_count(false, Some(0));
self.emit_ins(X86Instruction::load_immediate(OperandSize::S64, REGISTER_SCRATCH, function as usize as i64));
self.emit_ins(X86Instruction::call_immediate(self.relative_to_anchor(ANCHOR_EXTERNAL_FUNCTION_CALL, 5)));
self.emit_undo_profile_instruction_count(Some(0));
self.emit_undo_profile_instruction_count(Value::Constant64(0, false));
}

#[inline]
Expand Down Expand Up @@ -1236,7 +1235,7 @@ impl<'a, C: ContextObject> JitCompiler<'a, C> {
self.emit_ins(X86Instruction::load_immediate(OperandSize::S64, REGISTER_SCRATCH, target_pc as i64));
let jump_offset = self.relative_to_target_pc(target_pc, 6);
self.emit_ins(X86Instruction::conditional_jump_immediate(op, jump_offset));
self.emit_undo_profile_instruction_count(Some(target_pc));
self.emit_undo_profile_instruction_count(Value::Constant64(target_pc as i64, false));
LucasSte marked this conversation as resolved.
Show resolved Hide resolved
}

#[inline]
Expand All @@ -1257,7 +1256,7 @@ impl<'a, C: ContextObject> JitCompiler<'a, C> {
self.emit_ins(X86Instruction::load_immediate(OperandSize::S64, REGISTER_SCRATCH, target_pc as i64));
let jump_offset = self.relative_to_target_pc(target_pc, 6);
self.emit_ins(X86Instruction::conditional_jump_immediate(op, jump_offset));
self.emit_undo_profile_instruction_count(Some(target_pc));
self.emit_undo_profile_instruction_count(Value::Constant64(target_pc as i64, false));
LucasSte marked this conversation as resolved.
Show resolved Hide resolved
}

fn emit_shift(&mut self, size: OperandSize, opcode_extension: u8, source: u8, destination: u8, immediate: Option<i64>) {
Expand Down Expand Up @@ -1602,7 +1601,11 @@ impl<'a, C: ContextObject> JitCompiler<'a, C> {
// If callx lands in an invalid address, we must undo the changes in the instruction meter
// so that we can correctly calculate the number of executed instructions for error handling.
self.set_anchor(ANCHOR_CALL_REG_UNSUPPORTED_INSTRUCTION);
self.emit_undo_profile_instruction_count(None);
self.emit_ins(X86Instruction::mov(OperandSize::S64, REGISTER_SCRATCH, REGISTER_MAP[0]));
// Retrieve the current program from the stack. `return_near` popped an element from the stack,
LucasSte marked this conversation as resolved.
Show resolved Hide resolved
// so the offset is 16. Check `ANCHOR_INTERNAL_FUNCTION_CALL_REG` for more details.
self.emit_ins(X86Instruction::load(OperandSize::S64, RSP, REGISTER_SCRATCH, X86IndirectAccess::OffsetIndexShift(-16, RSP, 0)));
self.emit_undo_profile_instruction_count(Value::Register(REGISTER_MAP[0]));
self.emit_ins(X86Instruction::jump_immediate(self.relative_to_anchor(ANCHOR_CALL_UNSUPPORTED_INSTRUCTION, 5)));

// Translates a vm memory address to a host memory address
Expand Down