Skip to content

Commit 2f2f8aa

Browse files
committed
optimize
1 parent 2efece0 commit 2f2f8aa

File tree

7 files changed

+67
-69
lines changed

7 files changed

+67
-69
lines changed

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

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -799,6 +799,7 @@ pub fn exec_call(
799799
let is_vararg = chunk.is_vararg;
800800
let code_ptr = chunk.code.as_ptr();
801801
let constants_ptr = chunk.constants.as_ptr();
802+
let upvalues_ptr = func_ref.upvalues.as_ptr();
802803

803804
// Calculate argument count
804805
let arg_count = if b == 0 {
@@ -858,6 +859,7 @@ pub fn exec_call(
858859
func_id,
859860
code_ptr,
860861
constants_ptr,
862+
upvalues_ptr,
861863
new_base,
862864
arg_count,
863865
a,
@@ -880,6 +882,7 @@ pub fn exec_call(
880882
num_params,
881883
code_ptr,
882884
constants_ptr,
885+
upvalues_ptr,
883886
frame_ptr_ptr,
884887
);
885888
}
@@ -961,6 +964,7 @@ fn exec_call_lua_vararg(
961964
_num_params: usize,
962965
code_ptr: *const u32,
963966
constants_ptr: *const LuaValue,
967+
upvalues_ptr: *const crate::gc::UpvalueId,
964968
frame_ptr_ptr: &mut *mut LuaCallFrame,
965969
) -> LuaResult<()> {
966970
// Get argument count from top
@@ -1005,6 +1009,7 @@ fn exec_call_lua_vararg(
10051009
func_id,
10061010
code_ptr,
10071011
constants_ptr,
1012+
upvalues_ptr,
10081013
new_base,
10091014
arg_count,
10101015
a,
@@ -1035,12 +1040,13 @@ fn exec_call_lua_function(
10351040
// Extract chunk info from ObjectPool - use unchecked for hot path
10361041
let func_ref = unsafe { vm.object_pool.get_function_unchecked(func_id) };
10371042

1038-
let (max_stack_size, num_params, is_vararg, code_ptr, constants_ptr) = (
1043+
let (max_stack_size, num_params, is_vararg, code_ptr, constants_ptr, upvalues_ptr) = (
10391044
func_ref.chunk.max_stack_size,
10401045
func_ref.chunk.param_count,
10411046
func_ref.chunk.is_vararg,
10421047
func_ref.chunk.code.as_ptr(),
10431048
func_ref.chunk.constants.as_ptr(),
1049+
func_ref.upvalues.as_ptr(),
10441050
);
10451051

10461052
// Calculate argument count - use frame_ptr directly!
@@ -1118,6 +1124,7 @@ fn exec_call_lua_function(
11181124
func_id,
11191125
code_ptr,
11201126
constants_ptr,
1127+
upvalues_ptr,
11211128
new_base,
11221129
arg_count, // top = number of arguments
11231130
a, // result_reg
@@ -1186,6 +1193,7 @@ fn exec_call_lua_function(
11861193
func_id,
11871194
code_ptr,
11881195
constants_ptr,
1196+
upvalues_ptr,
11891197
new_base,
11901198
actual_arg_count, // top = number of arguments
11911199
a, // result_reg
@@ -1384,6 +1392,7 @@ pub fn exec_tailcall(
13841392
let max_stack_size = func_ref.chunk.max_stack_size;
13851393
let code_ptr = func_ref.chunk.code.as_ptr();
13861394
let constants_ptr = func_ref.chunk.constants.as_ptr();
1395+
let upvalues_ptr = func_ref.upvalues.as_ptr();
13871396

13881397
// CRITICAL: Before popping the frame, close all upvalues that point to it
13891398
// This ensures that any closures created in this frame can still access
@@ -1412,6 +1421,7 @@ pub fn exec_tailcall(
14121421
func_id,
14131422
code_ptr,
14141423
constants_ptr,
1424+
upvalues_ptr,
14151425
old_base,
14161426
arg_count, // top = number of arguments passed
14171427
result_reg, // result_reg from the CALLER (not 0!)

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

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -354,6 +354,7 @@ pub fn exec_tforcall(
354354
let max_stack_size = func_ref.chunk.max_stack_size;
355355
let code_ptr = func_ref.chunk.code.as_ptr();
356356
let constants_ptr = func_ref.chunk.constants.as_ptr();
357+
let upvalues_ptr = func_ref.upvalues.as_ptr();
357358

358359
// Set up arguments at base_ptr + a + 4 (first arg = state)
359360
// Arguments: state, control
@@ -376,6 +377,7 @@ pub fn exec_tforcall(
376377
func_id,
377378
code_ptr,
378379
constants_ptr,
380+
upvalues_ptr,
379381
call_base,
380382
2, // top = 2 (we have 2 arguments)
381383
a + 4, // result goes to R[A+4] relative to caller's base

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

Lines changed: 14 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ macro_rules! savepc {
3131
};
3232
}
3333

34-
/// Update pc, code_ptr and base_ptr from frame (like Lua C's updatestate)
34+
/// Update pc, code_ptr, base_ptr from frame (like Lua C's updatestate)
3535
/// Used after CALL/RETURN instructions when frame changes
3636
#[inline(always)]
3737
unsafe fn updatestate(
@@ -105,8 +105,7 @@ pub fn luavm_execute(vm: &mut LuaVM) -> LuaResult<LuaValue> {
105105
let a = Instruction::get_a(instr) as usize;
106106
let sbx = Instruction::get_sbx(instr);
107107
unsafe {
108-
*vm.register_stack.as_mut_ptr().add(base_ptr + a) =
109-
LuaValue::integer(sbx as i64);
108+
*vm.register_stack.as_mut_ptr().add(base_ptr + a) = LuaValue::integer(sbx as i64);
110109
}
111110
continue 'mainloop;
112111
}
@@ -116,8 +115,7 @@ pub fn luavm_execute(vm: &mut LuaVM) -> LuaResult<LuaValue> {
116115
let a = Instruction::get_a(instr) as usize;
117116
let sbx = Instruction::get_sbx(instr);
118117
unsafe {
119-
*vm.register_stack.as_mut_ptr().add(base_ptr + a) =
120-
LuaValue::number(sbx as f64);
118+
*vm.register_stack.as_mut_ptr().add(base_ptr + a) = LuaValue::number(sbx as f64);
121119
}
122120
continue 'mainloop;
123121
}
@@ -156,9 +154,9 @@ pub fn luavm_execute(vm: &mut LuaVM) -> LuaResult<LuaValue> {
156154
let b = Instruction::get_b(instr) as usize;
157155
unsafe {
158156
let nil_val = LuaValue::nil();
159-
let reg_ptr = vm.register_stack.as_mut_ptr().add(base_ptr);
157+
let reg_base = vm.register_stack.as_mut_ptr().add(base_ptr);
160158
for i in 0..=b {
161-
*reg_ptr.add(a + i) = nil_val;
159+
*reg_base.add(a + i) = nil_val;
162160
}
163161
}
164162
continue 'mainloop;
@@ -388,7 +386,7 @@ pub fn luavm_execute(vm: &mut LuaVM) -> LuaResult<LuaValue> {
388386
let a = Instruction::get_a(instr) as usize;
389387
let k = Instruction::get_k(instr);
390388
unsafe {
391-
let val = *vm.register_stack.as_ptr().add(base_ptr + a);
389+
let val = *vm.register_stack.as_mut_ptr().add(base_ptr + a);
392390
let is_truthy = val.is_truthy();
393391
if !is_truthy == k {
394392
pc += 1;
@@ -453,21 +451,16 @@ pub fn luavm_execute(vm: &mut LuaVM) -> LuaResult<LuaValue> {
453451
let b = Instruction::get_b(instr) as usize;
454452

455453
unsafe {
456-
// Get function's upvalue list pointer
457-
let func_id = (*frame_ptr).get_function_id_unchecked();
458-
let func_ref = vm.object_pool.get_function_unchecked(func_id);
459-
let upvalue_id = *func_ref.upvalues.get_unchecked(b);
454+
let upvalue_id = *(*frame_ptr).upvalues_ptr.add(b);
460455

461456
// Read upvalue value directly
462457
let uv = vm.object_pool.get_upvalue_unchecked(upvalue_id);
463458
let value = match &uv.state {
464-
UpvalueState::Open { stack_index } => {
465-
*vm.register_stack.get_unchecked(*stack_index)
466-
}
459+
UpvalueState::Open { stack_index } => *vm.register_stack.as_ptr().add(*stack_index),
467460
UpvalueState::Closed(val) => *val,
468461
};
469462

470-
*vm.register_stack.get_unchecked_mut(base_ptr + a) = value;
463+
*vm.register_stack.as_mut_ptr().add(base_ptr + a) = value;
471464
}
472465
continue 'mainloop;
473466
}
@@ -478,22 +471,20 @@ pub fn luavm_execute(vm: &mut LuaVM) -> LuaResult<LuaValue> {
478471

479472
unsafe {
480473
// Get the value to write
481-
let value = *vm.register_stack.get_unchecked(base_ptr + a);
474+
let value = *vm.register_stack.as_ptr().add(base_ptr + a);
482475

483-
// Get function's upvalue list pointer
484-
let func_id = (*frame_ptr).get_function_id_unchecked();
485-
let func_ref = vm.object_pool.get_function_unchecked(func_id);
486-
let upvalue_id = *func_ref.upvalues.get_unchecked(b);
476+
// Get upvalue
477+
let upvalue_id = *(*frame_ptr).upvalues_ptr.add(b);
487478

488479
// Write upvalue value directly
489480
let uv = vm.object_pool.get_upvalue_mut_unchecked(upvalue_id);
490481
match &mut uv.state {
491482
UpvalueState::Open { stack_index } => {
492-
*vm.register_stack.get_unchecked_mut(*stack_index) = value;
483+
*vm.register_stack.as_mut_ptr().add(*stack_index) = value;
493484
}
494485
UpvalueState::Closed(val) => *val = value,
495486
};
496-
487+
497488
// GC write barrier for upvalue
498489
vm.gc_barrier_upvalue(upvalue_id, &value);
499490
}

crates/luars/src/lua_vm/execute/table_instructions.rs

Lines changed: 5 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -444,10 +444,8 @@ pub fn exec_gettabup(
444444
// FAST PATH: Direct constant access via cached pointer
445445
let key_value = unsafe { *(*frame_ptr).constants_ptr.add(c) };
446446

447-
// OPTIMIZED: Use unchecked access for hot path
448-
let func_id = unsafe { (*frame_ptr).get_function_id().unwrap_unchecked() };
449-
let func_ref = unsafe { vm.object_pool.get_function_unchecked(func_id) };
450-
let upvalue_id = unsafe { *func_ref.upvalues.get_unchecked(b) };
447+
// OPTIMIZED: Use cached upvalues_ptr for direct access (avoids function lookup)
448+
let upvalue_id = unsafe { *(*frame_ptr).upvalues_ptr.add(b) };
451449

452450
// OPTIMIZED: Use unchecked upvalue read
453451
let table_value = unsafe { vm.read_upvalue_unchecked(upvalue_id) };
@@ -484,7 +482,7 @@ pub fn exec_gettabup(
484482

485483
/// SETTABUP A B C k
486484
/// UpValue[A][K[B]:string] := RK(C)
487-
/// OPTIMIZED: Uses cached constants_ptr for direct constant access
485+
/// OPTIMIZED: Uses cached constants_ptr and upvalues_ptr for direct access
488486
#[inline(always)]
489487
pub fn exec_settabup(
490488
vm: &mut LuaVM,
@@ -497,8 +495,6 @@ pub fn exec_settabup(
497495
let c = Instruction::get_c(instr) as usize;
498496
let k = Instruction::get_k(instr);
499497

500-
let func_id = unsafe { (*frame_ptr).get_function_id() };
501-
502498
// FAST PATH: Direct constant access via cached pointer
503499
let key_value = unsafe { *(*frame_ptr).constants_ptr.add(b) };
504500

@@ -509,17 +505,8 @@ pub fn exec_settabup(
509505
vm.register_stack[*base_ptr + c]
510506
};
511507

512-
// Get function for upvalues access (still needed)
513-
let Some(func_id) = func_id else {
514-
return Err(vm.error("Not a Lua function".to_string()));
515-
};
516-
let Some(func_ref) = vm.object_pool.get_function(func_id) else {
517-
return Err(vm.error("Invalid function ID".to_string()));
518-
};
519-
520-
let Some(&upvalue_id) = func_ref.upvalues.get(a) else {
521-
return Err(vm.error(format!("Invalid upvalue index: {}", a)));
522-
};
508+
// OPTIMIZED: Use cached upvalues_ptr for direct access
509+
let upvalue_id = unsafe { *(*frame_ptr).upvalues_ptr.add(a) };
523510

524511
// Get upvalue value
525512
let table_value = vm.read_upvalue(upvalue_id);

crates/luars/src/lua_vm/execute/upvalue_instructions.rs

Lines changed: 7 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -9,23 +9,18 @@ use crate::{
99
/// GETUPVAL A B
1010
/// R[A] := UpValue[B]
1111
/// Get upvalue from the closure's upvalue list
12+
/// OPTIMIZED: Uses cached upvalues_ptr in frame for direct access
1213
#[allow(dead_code)]
1314
#[inline(always)]
1415
pub fn exec_getupval(vm: &mut LuaVM, instr: u32, frame_ptr: *mut LuaCallFrame, base_ptr: usize) {
1516
let a = Instruction::get_a(instr) as usize;
1617
let b = Instruction::get_b(instr) as usize;
1718

18-
// Get the function's upvalue ID from its upvalue list
19-
let func_id = unsafe { (*frame_ptr).get_function_id_unchecked() };
20-
let upvalue_id = unsafe {
21-
vm.object_pool
22-
.get_function_unchecked(func_id)
23-
.upvalues
24-
.get_unchecked(b)
25-
};
19+
// FAST PATH: Use cached upvalues_ptr for direct access
20+
let upvalue_id = unsafe { *(*frame_ptr).upvalues_ptr.add(b) };
2621

2722
// Read the upvalue value
28-
let value = unsafe { vm.read_upvalue_unchecked(*upvalue_id) };
23+
let value = unsafe { vm.read_upvalue_unchecked(upvalue_id) };
2924
unsafe {
3025
*vm.register_stack.get_unchecked_mut(base_ptr + a) = value;
3126
}
@@ -34,20 +29,15 @@ pub fn exec_getupval(vm: &mut LuaVM, instr: u32, frame_ptr: *mut LuaCallFrame, b
3429
/// SETUPVAL A B
3530
/// UpValue[B] := R[A]
3631
/// Set upvalue in the closure's upvalue list
32+
/// OPTIMIZED: Uses cached upvalues_ptr in frame for direct access
3733
#[allow(dead_code)]
3834
#[inline(always)]
3935
pub fn exec_setupval(vm: &mut LuaVM, instr: u32, frame_ptr: *mut LuaCallFrame, base_ptr: usize) {
4036
let a = Instruction::get_a(instr) as usize;
4137
let b = Instruction::get_b(instr) as usize;
4238

43-
// Get the function's upvalue ID from its upvalue list
44-
let func_id = unsafe { (*frame_ptr).get_function_id_unchecked() };
45-
let upvalue_id = unsafe {
46-
*vm.object_pool
47-
.get_function_unchecked(func_id)
48-
.upvalues
49-
.get_unchecked(b)
50-
};
39+
// FAST PATH: Use cached upvalues_ptr for direct access
40+
let upvalue_id = unsafe { *(*frame_ptr).upvalues_ptr.add(b) };
5141

5242
let value = unsafe { *vm.register_stack.get_unchecked(base_ptr + a) };
5343

crates/luars/src/lua_vm/lua_call_frame.rs

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -44,8 +44,9 @@ use crate::{FunctionId, LuaValue};
4444
pub struct LuaCallFrame {
4545
/// NonBox field: high bits store call status, low 48 bits store function ID or C function pointer
4646
pub func_id_ptr: u64, // 8 bytes
47-
pub code_ptr: *const u32, // 8 bytes - direct pointer to instruction array
47+
pub code_ptr: *const u32, // 8 bytes - direct pointer to instruction array
4848
pub constants_ptr: *const LuaValue, // 8 bytes - direct pointer to constant array
49+
pub upvalues_ptr: *const crate::gc::UpvalueId, // 8 bytes - direct pointer to upvalues array
4950
pub base_ptr: u32, // 4 bytes - register stack base address
5051
pub top: u32, // 4 bytes - stack top
5152
pub pc: u32, // 4 bytes - program counter
@@ -83,6 +84,7 @@ impl Default for LuaCallFrame {
8384
func_id_ptr: 0, // C function, no flags
8485
code_ptr: std::ptr::null(),
8586
constants_ptr: std::ptr::null(),
87+
upvalues_ptr: std::ptr::null(),
8688
base_ptr: 0,
8789
top: 0,
8890
pc: 0,
@@ -135,6 +137,7 @@ impl LuaCallFrame {
135137
func_id: FunctionId,
136138
code_ptr: *const u32,
137139
constants_ptr: *const LuaValue,
140+
upvalues_ptr: *const crate::gc::UpvalueId,
138141
base_ptr: usize,
139142
top: usize,
140143
result_reg: usize,
@@ -144,6 +147,7 @@ impl LuaCallFrame {
144147
func_id_ptr: Self::pack_lua_function(func_id),
145148
code_ptr,
146149
constants_ptr,
150+
upvalues_ptr,
147151
base_ptr: base_ptr as u32,
148152
top: top as u32,
149153
pc: 0,
@@ -161,6 +165,7 @@ impl LuaCallFrame {
161165
func_id_ptr: 0, // C function, no FLAG_LUA
162166
code_ptr: std::ptr::null(),
163167
constants_ptr: std::ptr::null(),
168+
upvalues_ptr: std::ptr::null(),
164169
base_ptr: base_ptr as u32,
165170
top: top as u32,
166171
pc: 0,
@@ -331,14 +336,14 @@ mod tests {
331336
#[test]
332337
fn test_lua_call_frame_size() {
333338
// Verify frame size is compact
334-
assert_eq!(std::mem::size_of::<LuaCallFrame>(), 48);
339+
assert_eq!(std::mem::size_of::<LuaCallFrame>(), 56);
335340
}
336341

337342
#[test]
338343
fn test_nonbox_lua_function() {
339344
let func_id = FunctionId(12345);
340345
let frame =
341-
LuaCallFrame::new_lua_function(func_id, std::ptr::null(), std::ptr::null(), 0, 0, 0, 0);
346+
LuaCallFrame::new_lua_function(func_id, std::ptr::null(), std::ptr::null(), std::ptr::null(), 0, 0, 0, 0);
342347

343348
assert!(frame.is_lua());
344349
assert!(!frame.is_fresh());
@@ -361,7 +366,7 @@ mod tests {
361366
fn test_nonbox_flags() {
362367
let func_id = FunctionId(999);
363368
let mut frame =
364-
LuaCallFrame::new_lua_function(func_id, std::ptr::null(), std::ptr::null(), 0, 0, 0, 0);
369+
LuaCallFrame::new_lua_function(func_id, std::ptr::null(), std::ptr::null(), std::ptr::null(), 0, 0, 0, 0);
365370

366371
// Test fresh flag
367372
assert!(!frame.is_fresh());
@@ -391,7 +396,7 @@ mod tests {
391396
// Test large FunctionId value
392397
let func_id = FunctionId(0xFFFF_FFFF);
393398
let mut frame =
394-
LuaCallFrame::new_lua_function(func_id, std::ptr::null(), std::ptr::null(), 0, 0, 0, 0);
399+
LuaCallFrame::new_lua_function(func_id, std::ptr::null(), std::ptr::null(), std::ptr::null(), 0, 0, 0, 0);
395400

396401
// Set all flags
397402
frame.set_fresh();

0 commit comments

Comments
 (0)