Skip to content

Commit 43c035e

Browse files
committed
optimize performance
1 parent b2b7dc7 commit 43c035e

File tree

8 files changed

+127
-101
lines changed

8 files changed

+127
-101
lines changed

crates/luars/src/lua_value/lua_thread.rs

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -73,10 +73,17 @@ impl LuaThread {
7373
.register_stack
7474
.resize(max_stack_size, LuaValue::nil());
7575

76+
// Get code pointer from function
77+
let func_ptr = function.as_function_ptr()
78+
.expect("Thread function must be a Lua function");
79+
let func_obj = unsafe { &*func_ptr };
80+
let code_ptr = func_obj.borrow().chunk.code.as_ptr();
81+
7682
// Create initial call frame for the function
7783
let frame = LuaCallFrame::new_lua_function(
7884
0, // frame_id
7985
function, // function to execute
86+
code_ptr, // code pointer
8087
0, // base_ptr
8188
max_stack_size,
8289
0, // result_reg

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

Lines changed: 27 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,7 @@ pub fn exec_add(vm: &mut LuaVM, instr: u32) -> LuaResult<DispatchAction> {
5050
unsafe {
5151
*vm.register_stack.as_mut_ptr().add(base_ptr + a) = result;
5252
}
53-
Ok(DispatchAction::Skip(1))
53+
Ok(DispatchAction::Skip1)
5454
}
5555

5656
#[cold]
@@ -99,7 +99,7 @@ pub fn exec_sub(vm: &mut LuaVM, instr: u32) -> LuaResult<DispatchAction> {
9999
unsafe {
100100
*vm.register_stack.as_mut_ptr().add(base_ptr + a) = result;
101101
}
102-
Ok(DispatchAction::Skip(1))
102+
Ok(DispatchAction::Skip1)
103103
}
104104

105105
#[cold]
@@ -146,7 +146,7 @@ pub fn exec_mul(vm: &mut LuaVM, instr: u32) -> LuaResult<DispatchAction> {
146146
};
147147

148148
vm.register_stack[base_ptr + a] = result;
149-
Ok(DispatchAction::Skip(1))
149+
Ok(DispatchAction::Skip1)
150150
}
151151

152152
#[cold]
@@ -181,7 +181,7 @@ pub fn exec_div(vm: &mut LuaVM, instr: u32) -> LuaResult<DispatchAction> {
181181
let result = LuaValue::number(l_float / r_float);
182182
vm.register_stack[base_ptr + a] = result;
183183
// Skip the following MMBIN instruction since the operation succeeded
184-
Ok(DispatchAction::Skip(1))
184+
Ok(DispatchAction::Skip1)
185185
}
186186

187187
/// IDIV: R[A] = R[B] // R[C] (floor division)
@@ -219,7 +219,7 @@ pub fn exec_idiv(vm: &mut LuaVM, instr: u32) -> LuaResult<DispatchAction> {
219219

220220
vm.register_stack[base_ptr + a] = result;
221221
// Skip the following MMBIN instruction since the operation succeeded
222-
Ok(DispatchAction::Skip(1))
222+
Ok(DispatchAction::Skip1)
223223
}
224224

225225
/// MOD: R[A] = R[B] % R[C]
@@ -257,7 +257,7 @@ pub fn exec_mod(vm: &mut LuaVM, instr: u32) -> LuaResult<DispatchAction> {
257257

258258
vm.register_stack[base_ptr + a] = result;
259259
// Skip the following MMBIN instruction since the operation succeeded
260-
Ok(DispatchAction::Skip(1))
260+
Ok(DispatchAction::Skip1)
261261
}
262262

263263
/// POW: R[A] = R[B] ^ R[C]
@@ -285,7 +285,7 @@ pub fn exec_pow(vm: &mut LuaVM, instr: u32) -> LuaResult<DispatchAction> {
285285
let result = LuaValue::number(l_float.powf(r_float));
286286
vm.register_stack[base_ptr + a] = result;
287287
// Skip the following MMBIN instruction since the operation succeeded
288-
Ok(DispatchAction::Skip(1))
288+
Ok(DispatchAction::Skip1)
289289
}
290290

291291
/// UNM: R[A] = -R[B] (unary minus)
@@ -394,14 +394,14 @@ pub fn exec_addk(vm: &mut LuaVM, instr: u32) -> LuaResult<DispatchAction> {
394394
if let (Some(l), Some(r)) = (left.as_integer(), constant.as_integer()) {
395395
// Integer operation with wraparound, skip fallback
396396
vm.register_stack[base_ptr + a] = LuaValue::integer(l.wrapping_add(r));
397-
return Ok(DispatchAction::Skip(1)); // Skip MMBIN fallback
397+
return Ok(DispatchAction::Skip1); // Skip MMBIN fallback
398398
}
399399

400400
// Try float operation
401401
if let (Some(l), Some(r)) = (left.as_number(), constant.as_number()) {
402402
// Float operation succeeded, skip fallback
403403
vm.register_stack[base_ptr + a] = LuaValue::number(l + r);
404-
return Ok(DispatchAction::Skip(1)); // Skip MMBIN fallback
404+
return Ok(DispatchAction::Skip1); // Skip MMBIN fallback
405405
}
406406

407407
// Not numbers, fallthrough to MMBIN
@@ -434,13 +434,13 @@ pub fn exec_subk(vm: &mut LuaVM, instr: u32) -> LuaResult<DispatchAction> {
434434
// Try integer operation
435435
if let (Some(l), Some(r)) = (left.as_integer(), constant.as_integer()) {
436436
vm.register_stack[base_ptr + a] = LuaValue::integer(l.wrapping_sub(r));
437-
return Ok(DispatchAction::Skip(1)); // Skip MMBIN fallback
437+
return Ok(DispatchAction::Skip1); // Skip MMBIN fallback
438438
}
439439

440440
// Try float operation
441441
if let (Some(l), Some(r)) = (left.as_number(), constant.as_number()) {
442442
vm.register_stack[base_ptr + a] = LuaValue::number(l - r);
443-
return Ok(DispatchAction::Skip(1)); // Skip MMBIN fallback
443+
return Ok(DispatchAction::Skip1); // Skip MMBIN fallback
444444
}
445445
Ok(DispatchAction::Continue)
446446
}
@@ -476,7 +476,7 @@ pub fn exec_mulk(vm: &mut LuaVM, instr: u32) -> LuaResult<DispatchAction> {
476476
let l = left.secondary as i64;
477477
let r = constant.secondary as i64;
478478
vm.register_stack[base_ptr + a] = LuaValue::integer(l.wrapping_mul(r));
479-
return Ok(DispatchAction::Skip(1));
479+
return Ok(DispatchAction::Skip1);
480480
}
481481

482482
// Check if at least one is float (covers float*float, float*int, int*float)
@@ -499,7 +499,7 @@ pub fn exec_mulk(vm: &mut LuaVM, instr: u32) -> LuaResult<DispatchAction> {
499499
};
500500

501501
vm.register_stack[base_ptr + a] = LuaValue::float(l * r);
502-
return Ok(DispatchAction::Skip(1));
502+
return Ok(DispatchAction::Skip1);
503503
}
504504

505505
Ok(DispatchAction::Continue)
@@ -536,14 +536,14 @@ pub fn exec_modk(vm: &mut LuaVM, instr: u32) -> LuaResult<DispatchAction> {
536536
));
537537
}
538538
vm.register_stack[base_ptr + a] = LuaValue::integer(l.rem_euclid(r));
539-
return Ok(DispatchAction::Skip(1)); // Skip MMBIN fallback
539+
return Ok(DispatchAction::Skip1); // Skip MMBIN fallback
540540
}
541541

542542
// Try float operation
543543
if let (Some(l), Some(r)) = (left.as_number(), constant.as_number()) {
544544
let result = l - (l / r).floor() * r;
545545
vm.register_stack[base_ptr + a] = LuaValue::number(result);
546-
return Ok(DispatchAction::Skip(1)); // Skip MMBIN fallback
546+
return Ok(DispatchAction::Skip1); // Skip MMBIN fallback
547547
}
548548
Ok(DispatchAction::Continue)
549549
}
@@ -583,7 +583,7 @@ pub fn exec_powk(vm: &mut LuaVM, instr: u32) -> LuaResult<DispatchAction> {
583583

584584
let result = LuaValue::number(l_float.powf(r_float));
585585
vm.register_stack[base_ptr + a] = result;
586-
Ok(DispatchAction::Skip(1)) // Skip MMBIN fallback
586+
Ok(DispatchAction::Skip1) // Skip MMBIN fallback
587587
}
588588

589589
/// DIVK: R[A] = R[B] / K[C]
@@ -622,7 +622,7 @@ pub fn exec_divk(vm: &mut LuaVM, instr: u32) -> LuaResult<DispatchAction> {
622622
let result = LuaValue::number(l_float / r_float);
623623
vm.register_stack[base_ptr + a] = result;
624624
// Skip next instruction (MMBINK fallback) if operation succeeded
625-
Ok(DispatchAction::Skip(1))
625+
Ok(DispatchAction::Skip1)
626626
}
627627

628628
/// IDIVK: R[A] = R[B] // K[C]
@@ -656,13 +656,13 @@ pub fn exec_idivk(vm: &mut LuaVM, instr: u32) -> LuaResult<DispatchAction> {
656656
));
657657
}
658658
vm.register_stack[base_ptr + a] = LuaValue::integer(l.div_euclid(r));
659-
return Ok(DispatchAction::Skip(1)); // Skip MMBIN fallback
659+
return Ok(DispatchAction::Skip1); // Skip MMBIN fallback
660660
}
661661

662662
// Try float operation
663663
if let (Some(l), Some(r)) = (left.as_number(), constant.as_number()) {
664664
vm.register_stack[base_ptr + a] = LuaValue::number((l / r).floor());
665-
return Ok(DispatchAction::Skip(1)); // Skip MMBIN fallback
665+
return Ok(DispatchAction::Skip1); // Skip MMBIN fallback
666666
}
667667
Ok(DispatchAction::Continue)
668668
}
@@ -693,7 +693,7 @@ pub fn exec_band(vm: &mut LuaVM, instr: u32) -> LuaResult<DispatchAction> {
693693
let result = LuaValue::integer(l_int & r_int);
694694
vm.register_stack[base_ptr + a] = result;
695695
// Skip the following MMBIN instruction since the operation succeeded
696-
Ok(DispatchAction::Skip(1))
696+
Ok(DispatchAction::Skip1)
697697
}
698698

699699
/// BOR: R[A] = R[B] | R[C]
@@ -720,7 +720,7 @@ pub fn exec_bor(vm: &mut LuaVM, instr: u32) -> LuaResult<DispatchAction> {
720720
let result = LuaValue::integer(l_int | r_int);
721721
vm.register_stack[base_ptr + a] = result;
722722
// Skip the following MMBIN instruction since the operation succeeded
723-
Ok(DispatchAction::Skip(1))
723+
Ok(DispatchAction::Skip1)
724724
}
725725

726726
/// BXOR: R[A] = R[B] ~ R[C]
@@ -747,7 +747,7 @@ pub fn exec_bxor(vm: &mut LuaVM, instr: u32) -> LuaResult<DispatchAction> {
747747
let result = LuaValue::integer(l_int ^ r_int);
748748
vm.register_stack[base_ptr + a] = result;
749749
// Skip the following MMBIN instruction since the operation succeeded
750-
Ok(DispatchAction::Skip(1))
750+
Ok(DispatchAction::Skip1)
751751
}
752752

753753
/// SHL: R[A] = R[B] << R[C]
@@ -783,7 +783,7 @@ pub fn exec_shl(vm: &mut LuaVM, instr: u32) -> LuaResult<DispatchAction> {
783783

784784
vm.register_stack[base_ptr + a] = result;
785785
// Skip the following MMBIN instruction since the operation succeeded
786-
Ok(DispatchAction::Skip(1))
786+
Ok(DispatchAction::Skip1)
787787
}
788788

789789
/// SHR: R[A] = R[B] >> R[C]
@@ -815,7 +815,7 @@ pub fn exec_shr(vm: &mut LuaVM, instr: u32) -> LuaResult<DispatchAction> {
815815

816816
vm.register_stack[base_ptr + a] = result;
817817
// Skip the following MMBIN instruction since the operation succeeded
818-
Ok(DispatchAction::Skip(1))
818+
Ok(DispatchAction::Skip1)
819819
}
820820

821821
/// BANDK: R[A] = R[B] & K[C]
@@ -868,7 +868,7 @@ pub fn exec_bandk(vm: &mut LuaVM, instr: u32) -> LuaResult<DispatchAction> {
868868
};
869869

870870
vm.register_stack[base_ptr + a] = LuaValue::integer(l_int & r_int);
871-
Ok(DispatchAction::Skip(1)) // Skip MMBIN fallback
871+
Ok(DispatchAction::Skip1) // Skip MMBIN fallback
872872
}
873873

874874
/// BORK: R[A] = R[B] | K[C]
@@ -921,7 +921,7 @@ pub fn exec_bork(vm: &mut LuaVM, instr: u32) -> LuaResult<DispatchAction> {
921921
};
922922

923923
vm.register_stack[base_ptr + a] = LuaValue::integer(l_int | r_int);
924-
Ok(DispatchAction::Skip(1)) // Skip MMBIN fallback
924+
Ok(DispatchAction::Skip1) // Skip MMBIN fallback
925925
}
926926

927927
/// BXORK: R[A] = R[B] ~ K[C]
@@ -974,7 +974,7 @@ pub fn exec_bxork(vm: &mut LuaVM, instr: u32) -> LuaResult<DispatchAction> {
974974
};
975975

976976
vm.register_stack[base_ptr + a] = LuaValue::integer(l_int ^ r_int);
977-
Ok(DispatchAction::Skip(1)) // Skip MMBIN fallback
977+
Ok(DispatchAction::Skip1) // Skip MMBIN fallback
978978
}
979979

980980
/// SHRI: R[A] = R[B] >> sC

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

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -902,12 +902,19 @@ pub fn exec_call(vm: &mut LuaVM, instr: u32) -> LuaResult<DispatchAction> {
902902
}
903903
}
904904

905+
// Get code pointer from function
906+
let func_ptr = func.as_function_ptr()
907+
.ok_or_else(|| LuaError::RuntimeError("Not a Lua function".to_string()))?;
908+
let func_obj = unsafe { &*func_ptr };
909+
let code_ptr = func_obj.borrow().chunk.code.as_ptr();
910+
905911
// Create and push new frame
906912
// IMPORTANT: For vararg functions, top should reflect actual arg count, not max_stack_size
907913
// VARARGPREP will use this to determine the number of varargs
908914
let new_frame = LuaCallFrame::new_lua_function(
909915
frame_id,
910916
func,
917+
code_ptr,
911918
new_base,
912919
actual_arg_count, // top = number of arguments passed
913920
a, // result_reg: where to store return values
@@ -1000,9 +1007,16 @@ pub fn exec_tailcall(vm: &mut LuaVM, instr: u32) -> LuaResult<DispatchAction> {
10001007
vm.register_stack[old_base + i] = *arg;
10011008
}
10021009

1010+
// Get code pointer from function
1011+
let func_ptr = func.as_function_ptr()
1012+
.ok_or_else(|| LuaError::RuntimeError("Not a Lua function".to_string()))?;
1013+
let func_obj = unsafe { &*func_ptr };
1014+
let code_ptr = func_obj.borrow().chunk.code.as_ptr();
1015+
10031016
let new_frame = LuaCallFrame::new_lua_function(
10041017
frame_id,
10051018
func,
1019+
code_ptr,
10061020
old_base,
10071021
arg_count, // top = number of arguments passed
10081022
result_reg, // result_reg from the CALLER (not 0!)

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

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -300,10 +300,17 @@ pub fn exec_tforcall(vm: &mut LuaVM, instr: u32) -> LuaResult<DispatchAction> {
300300
// Copy arguments
301301
vm.register_stack[call_base] = state;
302302
vm.register_stack[call_base + 1] = control;
303+
304+
// Get code pointer from function
305+
let func_ptr = func.as_function_ptr()
306+
.ok_or_else(|| LuaError::RuntimeError("Not a Lua function".to_string()))?;
307+
let func_obj = unsafe { &*func_ptr };
308+
let code_ptr = func_obj.borrow().chunk.code.as_ptr();
303309

304310
let new_frame = LuaCallFrame::new_lua_function(
305311
frame_id,
306312
func,
313+
code_ptr,
307314
call_base,
308315
max_stack_size,
309316
a + 3, // result goes to R[A+3]

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

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -149,8 +149,9 @@ pub fn dispatch_instruction(vm: &mut LuaVM, instr: u32) -> LuaResult<DispatchAct
149149
pub enum DispatchAction {
150150
/// Continue executing next instruction
151151
Continue,
152-
/// Skip next N instructions (used by *K instructions that skip their MMBIN* fallback)
153-
Skip(usize),
152+
/// Skip 1 instruction (used by *K instructions that skip their MMBIN* fallback)
153+
/// OPTIMIZATION: Separate variant to avoid carrying data (all skips are Skip(1))
154+
Skip1,
154155
/// Return from current function (includes return values in VM)
155156
Return,
156157
/// Yield from coroutine (yield values stored in thread)

crates/luars/src/lua_vm/lua_call_frame.rs

Lines changed: 21 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -2,33 +2,31 @@ use crate::LuaFunction;
22
use crate::LuaValue;
33
use std::cell::RefCell;
44

5-
/// 极限优化的 LuaCallFrame: 80 bytes → 64 bytes (20% reduction!)
5+
/// ULTRA-OPTIMIZED LuaCallFrame - 仿照原生 Lua 的 CallInfo 设计
66
///
7-
/// 在保持代码兼容性的前提下,通过以下方式压缩:
8-
/// 1. result_reg: usize → u16 (寄存器索引 < 65536)
9-
/// 2. num_results: usize → u16 (返回值数量 < 65535, 0xFFFF = 多值)
10-
/// 3. vararg_count: usize → u16 (可变参数 < 65536)
11-
/// 4. flags: u8 合并布尔标志
7+
/// 关键优化:直接缓存 code 指针,避免每次循环都要解引用 function → chunk → code
128
///
13-
/// 内存布局(64 bytes,完美对齐):
14-
/// - 16 bytes: function_value
9+
/// 内存布局(72 bytes):
10+
/// - 16 bytes: function_value (LuaValue - 包含函数ID)
11+
/// - 8 bytes: code_ptr (直接指向指令数组 - HOT PATH!)
1512
/// - 40 bytes: base_ptr + top + pc + frame_id + vararg_start (5×usize)
1613
/// - 6 bytes: result_reg + num_results + vararg_count (3×u16)
1714
/// - 1 byte: flags
1815
/// - 1 byte: padding
1916
pub struct LuaCallFrame {
20-
pub function_value: LuaValue, // 16 bytes - 包含 ID + 指针!
21-
pub base_ptr: usize, // 8 bytes - 保持 usize 避免类型转换
22-
pub top: usize, // 8 bytes
23-
pub pc: usize, // 8 bytes
24-
pub frame_id: usize, // 8 bytes
25-
pub vararg_start: usize, // 8 bytes
26-
pub result_reg: u16, // 2 bytes (was 8) - 寄存器索引
27-
pub num_results: u16, // 2 bytes (was 8) - 期望返回数
28-
pub vararg_count: u16, // 2 bytes (was 8) - vararg 数量
29-
flags: u8, // 1 byte - 标志位
30-
_padding: u8, // 1 byte - 对齐
31-
// Total: 64 bytes (20% reduction from 80 bytes!)
17+
pub function_value: LuaValue, // 16 bytes - 包含 ID + 指针
18+
pub code_ptr: *const u32, // 8 bytes - HOT PATH: 直接指向指令数组!
19+
pub base_ptr: usize, // 8 bytes - 寄存器栈基址
20+
pub top: usize, // 8 bytes - 栈顶
21+
pub pc: usize, // 8 bytes - 程序计数器
22+
pub frame_id: usize, // 8 bytes - 帧ID
23+
pub vararg_start: usize, // 8 bytes - 可变参数起始位置
24+
pub result_reg: u16, // 2 bytes - 结果寄存器索引
25+
pub num_results: u16, // 2 bytes - 期望返回数
26+
pub vararg_count: u16, // 2 bytes - 可变参数数量
27+
flags: u8, // 1 byte - 标志位
28+
_padding: u8, // 1 byte - 对齐
29+
// Total: 72 bytes
3230
}
3331

3432
// Flag bits
@@ -43,13 +41,15 @@ impl LuaCallFrame {
4341
pub fn new_lua_function(
4442
frame_id: usize,
4543
function_value: LuaValue,
44+
code_ptr: *const u32, // 新增:直接传入 code 指针
4645
base_ptr: usize,
4746
max_stack_size: usize,
4847
result_reg: usize,
4948
num_results: usize,
5049
) -> Self {
5150
LuaCallFrame {
5251
function_value,
52+
code_ptr,
5353
base_ptr,
5454
top: max_stack_size,
5555
pc: 0,
@@ -77,6 +77,7 @@ impl LuaCallFrame {
7777
) -> Self {
7878
LuaCallFrame {
7979
function_value: parent_function_value,
80+
code_ptr: std::ptr::null(), // C 函数没有 code
8081
base_ptr,
8182
top: num_args,
8283
pc: parent_pc,

0 commit comments

Comments
 (0)