Skip to content

Commit 49dc05a

Browse files
committed
update
1 parent 04c6e14 commit 49dc05a

File tree

4 files changed

+105
-95
lines changed

4 files changed

+105
-95
lines changed

crates/luars/src/lua_vm/dispatcher/arithmetic_instructions.rs

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -353,6 +353,7 @@ pub fn exec_unm(vm: &mut LuaVM, instr: u32) -> LuaResult<()> {
353353
// ============ Arithmetic Immediate Instructions ============
354354

355355
/// ADDI: R[A] = R[B] + sC
356+
/// OPTIMIZATION: After successful integer add, check if next instruction is JMP and execute inline
356357
#[inline(always)]
357358
pub fn exec_addi(vm: &mut LuaVM, instr: u32, frame_ptr: *mut LuaCallFrame) -> LuaResult<()> {
358359
let a = Instruction::get_a(instr) as usize;
@@ -367,7 +368,16 @@ pub fn exec_addi(vm: &mut LuaVM, instr: u32, frame_ptr: *mut LuaCallFrame) -> Lu
367368
let l = left.secondary as i64;
368369
*vm.register_stack.as_mut_ptr().add(base_ptr + a) =
369370
LuaValue::integer(l.wrapping_add(sc as i64));
370-
(*frame_ptr).pc += 1;
371+
(*frame_ptr).pc += 1; // Skip MMBINI
372+
373+
// OPTIMIZATION: Check if next instruction is backward JMP (loop)
374+
let next_instr = (*frame_ptr).code_ptr.add((*frame_ptr).pc).read();
375+
if (next_instr & 0x7F) == 56 { // JMP opcode
376+
let sj = ((next_instr >> 7) & 0x1FFFFFF) as i32 - 16777215;
377+
if sj < 0 { // Backward jump = loop
378+
(*frame_ptr).pc = ((*frame_ptr).pc as i32 + 1 + sj) as usize;
379+
}
380+
}
371381
return Ok(());
372382
}
373383

crates/luars/src/lua_vm/dispatcher/control_instructions.rs

Lines changed: 83 additions & 79 deletions
Original file line numberDiff line numberDiff line change
@@ -145,12 +145,13 @@ pub fn exec_return(vm: &mut LuaVM, instr: u32) -> LuaResult<()> {
145145
/// JMP sJ
146146
/// pc += sJ
147147
#[inline(always)]
148-
pub fn exec_jmp(vm: &mut LuaVM, instr: u32) -> LuaResult<()> {
148+
pub fn exec_jmp(_vm: &mut LuaVM, instr: u32, frame_ptr: *mut LuaCallFrame) -> LuaResult<()> {
149149
let sj = Instruction::get_sj(instr);
150150

151-
let frame = vm.current_frame_mut();
152-
// PC already incremented by dispatcher, so we add offset directly
153-
frame.pc = (frame.pc as i32 + sj) as usize;
151+
unsafe {
152+
// PC already incremented by dispatcher, so we add offset directly
153+
(*frame_ptr).pc = ((*frame_ptr).pc as i32 + sj) as usize;
154+
}
154155

155156
Ok(())
156157
}
@@ -574,32 +575,32 @@ pub fn exec_eqi(vm: &mut LuaVM, instr: u32) -> LuaResult<()> {
574575
/// LTI A sB k
575576
/// if ((R[A] < sB) ~= k) then pc++
576577
#[inline(always)]
577-
pub fn exec_lti(vm: &mut LuaVM, instr: u32) -> LuaResult<()> {
578+
pub fn exec_lti(vm: &mut LuaVM, instr: u32, frame_ptr: *mut LuaCallFrame) -> LuaResult<()> {
578579
let a = Instruction::get_a(instr) as usize;
579580
let sb = Instruction::get_sb(instr);
580581
let k = Instruction::get_k(instr);
581582

582-
let base_ptr = vm.current_frame().base_ptr;
583-
584-
// OPTIMIZATION: Use unsafe for unchecked register access
585-
let left = unsafe { *vm.register_stack.as_ptr().add(base_ptr + a) };
586-
587-
// OPTIMIZATION: Direct type tag comparison
588-
use crate::lua_value::{TAG_INTEGER, TYPE_MASK};
589-
let is_less = if (left.primary & TYPE_MASK) == TAG_INTEGER {
590-
// Fast integer path
591-
(left.secondary as i64) < (sb as i64)
592-
} else if let Some(l) = left.as_number() {
593-
l < sb as f64
594-
} else {
595-
return Err(vm.error(format!(
596-
"attempt to compare {} with number",
597-
left.type_name()
598-
)));
599-
};
583+
unsafe {
584+
let base_ptr = (*frame_ptr).base_ptr;
585+
let left = *vm.register_stack.as_ptr().add(base_ptr + a);
586+
587+
// OPTIMIZATION: Direct type tag comparison
588+
use crate::lua_value::{TAG_INTEGER, TYPE_MASK};
589+
let is_less = if (left.primary & TYPE_MASK) == TAG_INTEGER {
590+
// Fast integer path
591+
(left.secondary as i64) < (sb as i64)
592+
} else if let Some(l) = left.as_number() {
593+
l < sb as f64
594+
} else {
595+
return Err(vm.error(format!(
596+
"attempt to compare {} with number",
597+
left.type_name()
598+
)));
599+
};
600600

601-
if is_less != k {
602-
vm.current_frame_mut().pc += 1;
601+
if is_less != k {
602+
(*frame_ptr).pc += 1;
603+
}
603604
}
604605

605606
Ok(())
@@ -608,29 +609,30 @@ pub fn exec_lti(vm: &mut LuaVM, instr: u32) -> LuaResult<()> {
608609
/// LEI A sB k
609610
/// if ((R[A] <= sB) ~= k) then pc++
610611
#[inline(always)]
611-
pub fn exec_lei(vm: &mut LuaVM, instr: u32) -> LuaResult<()> {
612+
pub fn exec_lei(vm: &mut LuaVM, instr: u32, frame_ptr: *mut LuaCallFrame) -> LuaResult<()> {
612613
let a = Instruction::get_a(instr) as usize;
613614
let sb = Instruction::get_sb(instr);
614615
let k = Instruction::get_k(instr);
615616

616-
let base_ptr = vm.current_frame().base_ptr;
617-
618-
let left = unsafe { *vm.register_stack.as_ptr().add(base_ptr + a) };
619-
620-
use crate::lua_value::{TAG_INTEGER, TYPE_MASK};
621-
let is_less_equal = if (left.primary & TYPE_MASK) == TAG_INTEGER {
622-
(left.secondary as i64) <= (sb as i64)
623-
} else if let Some(l) = left.as_number() {
624-
l <= sb as f64
625-
} else {
626-
return Err(vm.error(format!(
627-
"attempt to compare {} with number",
628-
left.type_name()
629-
)));
630-
};
617+
unsafe {
618+
let base_ptr = (*frame_ptr).base_ptr;
619+
let left = *vm.register_stack.as_ptr().add(base_ptr + a);
620+
621+
use crate::lua_value::{TAG_INTEGER, TYPE_MASK};
622+
let is_less_equal = if (left.primary & TYPE_MASK) == TAG_INTEGER {
623+
(left.secondary as i64) <= (sb as i64)
624+
} else if let Some(l) = left.as_number() {
625+
l <= sb as f64
626+
} else {
627+
return Err(vm.error(format!(
628+
"attempt to compare {} with number",
629+
left.type_name()
630+
)));
631+
};
631632

632-
if is_less_equal != k {
633-
vm.current_frame_mut().pc += 1;
633+
if is_less_equal != k {
634+
(*frame_ptr).pc += 1;
635+
}
634636
}
635637

636638
Ok(())
@@ -639,29 +641,30 @@ pub fn exec_lei(vm: &mut LuaVM, instr: u32) -> LuaResult<()> {
639641
/// GTI A sB k
640642
/// if ((R[A] > sB) ~= k) then pc++
641643
#[inline(always)]
642-
pub fn exec_gti(vm: &mut LuaVM, instr: u32) -> LuaResult<()> {
644+
pub fn exec_gti(vm: &mut LuaVM, instr: u32, frame_ptr: *mut LuaCallFrame) -> LuaResult<()> {
643645
let a = Instruction::get_a(instr) as usize;
644646
let sb = Instruction::get_sb(instr);
645647
let k = Instruction::get_k(instr);
646648

647-
let base_ptr = vm.current_frame().base_ptr;
648-
649-
let left = unsafe { *vm.register_stack.as_ptr().add(base_ptr + a) };
650-
651-
use crate::lua_value::{TAG_INTEGER, TYPE_MASK};
652-
let is_greater = if (left.primary & TYPE_MASK) == TAG_INTEGER {
653-
(left.secondary as i64) > (sb as i64)
654-
} else if let Some(l) = left.as_number() {
655-
l > sb as f64
656-
} else {
657-
return Err(vm.error(format!(
658-
"attempt to compare {} with number",
659-
left.type_name()
660-
)));
661-
};
649+
unsafe {
650+
let base_ptr = (*frame_ptr).base_ptr;
651+
let left = *vm.register_stack.as_ptr().add(base_ptr + a);
652+
653+
use crate::lua_value::{TAG_INTEGER, TYPE_MASK};
654+
let is_greater = if (left.primary & TYPE_MASK) == TAG_INTEGER {
655+
(left.secondary as i64) > (sb as i64)
656+
} else if let Some(l) = left.as_number() {
657+
l > sb as f64
658+
} else {
659+
return Err(vm.error(format!(
660+
"attempt to compare {} with number",
661+
left.type_name()
662+
)));
663+
};
662664

663-
if is_greater != k {
664-
vm.current_frame_mut().pc += 1;
665+
if is_greater != k {
666+
(*frame_ptr).pc += 1;
667+
}
665668
}
666669

667670
Ok(())
@@ -670,29 +673,30 @@ pub fn exec_gti(vm: &mut LuaVM, instr: u32) -> LuaResult<()> {
670673
/// GEI A sB k
671674
/// if ((R[A] >= sB) ~= k) then pc++
672675
#[inline(always)]
673-
pub fn exec_gei(vm: &mut LuaVM, instr: u32) -> LuaResult<()> {
676+
pub fn exec_gei(vm: &mut LuaVM, instr: u32, frame_ptr: *mut LuaCallFrame) -> LuaResult<()> {
674677
let a = Instruction::get_a(instr) as usize;
675678
let sb = Instruction::get_sb(instr);
676679
let k = Instruction::get_k(instr);
677680

678-
let base_ptr = vm.current_frame().base_ptr;
679-
680-
let left = unsafe { *vm.register_stack.as_ptr().add(base_ptr + a) };
681-
682-
use crate::lua_value::{TAG_INTEGER, TYPE_MASK};
683-
let is_greater_equal = if (left.primary & TYPE_MASK) == TAG_INTEGER {
684-
(left.secondary as i64) >= (sb as i64)
685-
} else if let Some(l) = left.as_number() {
686-
l >= sb as f64
687-
} else {
688-
return Err(vm.error(format!(
689-
"attempt to compare {} with number",
690-
left.type_name()
691-
)));
692-
};
681+
unsafe {
682+
let base_ptr = (*frame_ptr).base_ptr;
683+
let left = *vm.register_stack.as_ptr().add(base_ptr + a);
684+
685+
use crate::lua_value::{TAG_INTEGER, TYPE_MASK};
686+
let is_greater_equal = if (left.primary & TYPE_MASK) == TAG_INTEGER {
687+
(left.secondary as i64) >= (sb as i64)
688+
} else if let Some(l) = left.as_number() {
689+
l >= sb as f64
690+
} else {
691+
return Err(vm.error(format!(
692+
"attempt to compare {} with number",
693+
left.type_name()
694+
)));
695+
};
693696

694-
if is_greater_equal != k {
695-
vm.current_frame_mut().pc += 1;
697+
if is_greater_equal != k {
698+
(*frame_ptr).pc += 1;
699+
}
696700
}
697701

698702
Ok(())

crates/luars/src/lua_vm/dispatcher/mod.rs

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -94,13 +94,13 @@ pub fn dispatch_instruction(vm: &mut LuaVM, instr: u32, frame_ptr: *mut LuaCallF
9494
OpCode::Le => exec_le(vm, instr),
9595
OpCode::EqK => exec_eqk(vm, instr),
9696
OpCode::EqI => exec_eqi(vm, instr),
97-
OpCode::LtI => exec_lti(vm, instr),
98-
OpCode::LeI => exec_lei(vm, instr),
99-
OpCode::GtI => exec_gti(vm, instr),
100-
OpCode::GeI => exec_gei(vm, instr),
97+
OpCode::LtI => exec_lti(vm, instr, frame_ptr),
98+
OpCode::LeI => exec_lei(vm, instr, frame_ptr),
99+
OpCode::GtI => exec_gti(vm, instr, frame_ptr),
100+
OpCode::GeI => exec_gei(vm, instr, frame_ptr),
101101

102102
// Jump and test instructions
103-
OpCode::Jmp => exec_jmp(vm, instr),
103+
OpCode::Jmp => exec_jmp(vm, instr, frame_ptr),
104104
OpCode::Test => exec_test(vm, instr),
105105
OpCode::TestSet => exec_testset(vm, instr),
106106

crates/luars/src/lua_vm/mod.rs

Lines changed: 6 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -261,7 +261,6 @@ impl LuaVM {
261261

262262
/// Main execution loop - interprets bytecode instructions
263263
/// Main VM execution loop - MAXIMUM PERFORMANCE
264-
/// 零返回值,零分支,直接调度
265264
fn run(&mut self) -> LuaResult<LuaValue> {
266265
// CRITICAL OPTIMIZATION: Check frames.is_empty() OUTSIDE the loop
267266
// RETURN instruction will pop frames and check if empty
@@ -273,15 +272,12 @@ impl LuaVM {
273272
let instr = unsafe { (*frame_ptr).code_ptr.add((*frame_ptr).pc).read() };
274273
unsafe { (*frame_ptr).pc += 1; }
275274

276-
if let Err(e) = dispatch_instruction(self, instr, frame_ptr) {
277-
match e {
278-
LuaError::Yield => return Ok(LuaValue::nil()),
279-
LuaError::Exit => {
280-
// Normal exit when all frames are popped
281-
return Ok(LuaValue::nil());
282-
}
283-
_ => return Err(e),
284-
}
275+
// Use match with explicit Ok branch for better branch prediction hints
276+
match dispatch_instruction(self, instr, frame_ptr) {
277+
Ok(()) => {}
278+
Err(LuaError::Exit) => return Ok(LuaValue::nil()),
279+
Err(LuaError::Yield) => return Ok(LuaValue::nil()),
280+
Err(e) => return Err(e),
285281
}
286282
}
287283
}

0 commit comments

Comments
 (0)