Skip to content

Commit 6e99162

Browse files
committed
optimize callframe access performance
1 parent f48752b commit 6e99162

File tree

7 files changed

+156
-111
lines changed

7 files changed

+156
-111
lines changed

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

Lines changed: 97 additions & 65 deletions
Original file line numberDiff line numberDiff line change
@@ -382,6 +382,7 @@ pub fn exec_addi(vm: &mut LuaVM, instr: u32, frame_ptr: *mut LuaCallFrame) {
382382
}
383383

384384
/// ADDK: R[A] = R[B] + K[C]
385+
/// OPTIMIZED: Uses cached constants_ptr for direct constant access
385386
#[inline(always)]
386387
pub fn exec_addk(vm: &mut LuaVM, instr: u32, frame_ptr: *mut LuaCallFrame) {
387388
let a = Instruction::get_a(instr) as usize;
@@ -392,23 +393,32 @@ pub fn exec_addk(vm: &mut LuaVM, instr: u32, frame_ptr: *mut LuaCallFrame) {
392393
let base_ptr = (*frame_ptr).base_ptr;
393394
let left = *vm.register_stack.as_ptr().add(base_ptr + b);
394395

395-
// Get constant
396-
let constant = if let Some(func_id) = (*frame_ptr).function_value.as_function_id() {
397-
if let Some(func_ref) = vm.object_pool.get_function(func_id) {
398-
if let Some(&k) = func_ref.chunk.constants.get(c) { k } else { return; }
399-
} else { return; }
400-
} else { return; };
396+
// FAST PATH: Direct constant access via cached pointer
397+
let constant = *(*frame_ptr).constants_ptr.add(c);
401398

402-
// Try integer operation
399+
// Integer + Integer fast path
403400
if left.primary == TAG_INTEGER && constant.primary == TAG_INTEGER {
404-
let l = left.secondary as i64;
405-
let r = constant.secondary as i64;
406-
*vm.register_stack.as_mut_ptr().add(base_ptr + a) = LuaValue::integer(l.wrapping_add(r));
401+
let result = (left.secondary as i64).wrapping_add(constant.secondary as i64);
402+
*vm.register_stack.as_mut_ptr().add(base_ptr + a) = LuaValue {
403+
primary: TAG_INTEGER,
404+
secondary: result as u64,
405+
};
406+
(*frame_ptr).pc += 1;
407+
return;
408+
}
409+
410+
// Float + Float fast path
411+
if left.primary == TAG_FLOAT && constant.primary == TAG_FLOAT {
412+
let result = f64::from_bits(left.secondary) + f64::from_bits(constant.secondary);
413+
*vm.register_stack.as_mut_ptr().add(base_ptr + a) = LuaValue {
414+
primary: TAG_FLOAT,
415+
secondary: result.to_bits(),
416+
};
407417
(*frame_ptr).pc += 1;
408418
return;
409419
}
410420

411-
// Try float operation
421+
// Mixed types
412422
if let (Some(l), Some(r)) = (left.as_number(), constant.as_number()) {
413423
*vm.register_stack.as_mut_ptr().add(base_ptr + a) = LuaValue::number(l + r);
414424
(*frame_ptr).pc += 1;
@@ -417,6 +427,7 @@ pub fn exec_addk(vm: &mut LuaVM, instr: u32, frame_ptr: *mut LuaCallFrame) {
417427
}
418428

419429
/// SUBK: R[A] = R[B] - K[C]
430+
/// OPTIMIZED: Uses cached constants_ptr for direct constant access
420431
#[inline(always)]
421432
pub fn exec_subk(vm: &mut LuaVM, instr: u32, frame_ptr: *mut LuaCallFrame) {
422433
let a = Instruction::get_a(instr) as usize;
@@ -427,20 +438,32 @@ pub fn exec_subk(vm: &mut LuaVM, instr: u32, frame_ptr: *mut LuaCallFrame) {
427438
let base_ptr = (*frame_ptr).base_ptr;
428439
let left = *vm.register_stack.as_ptr().add(base_ptr + b);
429440

430-
let constant = if let Some(func_id) = (*frame_ptr).function_value.as_function_id() {
431-
if let Some(func_ref) = vm.object_pool.get_function(func_id) {
432-
if let Some(&k) = func_ref.chunk.constants.get(c) { k } else { return; }
433-
} else { return; }
434-
} else { return; };
441+
// FAST PATH: Direct constant access via cached pointer
442+
let constant = *(*frame_ptr).constants_ptr.add(c);
435443

444+
// Integer - Integer fast path
436445
if left.primary == TAG_INTEGER && constant.primary == TAG_INTEGER {
437-
let l = left.secondary as i64;
438-
let r = constant.secondary as i64;
439-
*vm.register_stack.as_mut_ptr().add(base_ptr + a) = LuaValue::integer(l.wrapping_sub(r));
446+
let result = (left.secondary as i64).wrapping_sub(constant.secondary as i64);
447+
*vm.register_stack.as_mut_ptr().add(base_ptr + a) = LuaValue {
448+
primary: TAG_INTEGER,
449+
secondary: result as u64,
450+
};
451+
(*frame_ptr).pc += 1;
452+
return;
453+
}
454+
455+
// Float - Float fast path
456+
if left.primary == TAG_FLOAT && constant.primary == TAG_FLOAT {
457+
let result = f64::from_bits(left.secondary) - f64::from_bits(constant.secondary);
458+
*vm.register_stack.as_mut_ptr().add(base_ptr + a) = LuaValue {
459+
primary: TAG_FLOAT,
460+
secondary: result.to_bits(),
461+
};
440462
(*frame_ptr).pc += 1;
441463
return;
442464
}
443465

466+
// Mixed types
444467
if let (Some(l), Some(r)) = (left.as_number(), constant.as_number()) {
445468
*vm.register_stack.as_mut_ptr().add(base_ptr + a) = LuaValue::number(l - r);
446469
(*frame_ptr).pc += 1;
@@ -449,6 +472,7 @@ pub fn exec_subk(vm: &mut LuaVM, instr: u32, frame_ptr: *mut LuaCallFrame) {
449472
}
450473

451474
/// MULK: R[A] = R[B] * K[C]
475+
/// OPTIMIZED: Uses cached constants_ptr for direct constant access
452476
#[inline(always)]
453477
pub fn exec_mulk(vm: &mut LuaVM, instr: u32, frame_ptr: *mut LuaCallFrame) {
454478
let a = Instruction::get_a(instr) as usize;
@@ -458,21 +482,33 @@ pub fn exec_mulk(vm: &mut LuaVM, instr: u32, frame_ptr: *mut LuaCallFrame) {
458482
unsafe {
459483
let base_ptr = (*frame_ptr).base_ptr;
460484
let left = *vm.register_stack.as_ptr().add(base_ptr + b);
485+
486+
// FAST PATH: Direct constant access via cached pointer
487+
let constant = *(*frame_ptr).constants_ptr.add(c);
488+
489+
// Float * Float fast path (most common in benchmarks)
490+
if left.primary == TAG_FLOAT && constant.primary == TAG_FLOAT {
491+
let result = f64::from_bits(left.secondary) * f64::from_bits(constant.secondary);
492+
*vm.register_stack.as_mut_ptr().add(base_ptr + a) = LuaValue {
493+
primary: TAG_FLOAT,
494+
secondary: result.to_bits(),
495+
};
496+
(*frame_ptr).pc += 1;
497+
return;
498+
}
461499

462-
let constant = if let Some(func_id) = (*frame_ptr).function_value.as_function_id() {
463-
if let Some(func_ref) = vm.object_pool.get_function(func_id) {
464-
if let Some(&k) = func_ref.chunk.constants.get(c) { k } else { return; }
465-
} else { return; }
466-
} else { return; };
467-
500+
// Integer * Integer
468501
if left.primary == TAG_INTEGER && constant.primary == TAG_INTEGER {
469-
let l = left.secondary as i64;
470-
let r = constant.secondary as i64;
471-
*vm.register_stack.as_mut_ptr().add(base_ptr + a) = LuaValue::integer(l.wrapping_mul(r));
502+
let result = (left.secondary as i64).wrapping_mul(constant.secondary as i64);
503+
*vm.register_stack.as_mut_ptr().add(base_ptr + a) = LuaValue {
504+
primary: TAG_INTEGER,
505+
secondary: result as u64,
506+
};
472507
(*frame_ptr).pc += 1;
473508
return;
474509
}
475510

511+
// Mixed types
476512
if left.primary == TAG_FLOAT || constant.primary == TAG_FLOAT {
477513
let l = if left.primary == TAG_FLOAT {
478514
f64::from_bits(left.secondary)
@@ -493,6 +529,7 @@ pub fn exec_mulk(vm: &mut LuaVM, instr: u32, frame_ptr: *mut LuaCallFrame) {
493529
}
494530

495531
/// MODK: R[A] = R[B] % K[C]
532+
/// OPTIMIZED: Uses cached constants_ptr for direct constant access
496533
#[inline(always)]
497534
pub fn exec_modk(vm: &mut LuaVM, instr: u32, frame_ptr: *mut LuaCallFrame) {
498535
let a = Instruction::get_a(instr) as usize;
@@ -503,21 +540,23 @@ pub fn exec_modk(vm: &mut LuaVM, instr: u32, frame_ptr: *mut LuaCallFrame) {
503540
let base_ptr = (*frame_ptr).base_ptr;
504541
let left = *vm.register_stack.as_ptr().add(base_ptr + b);
505542

506-
let constant = if let Some(func_id) = (*frame_ptr).function_value.as_function_id() {
507-
if let Some(func_ref) = vm.object_pool.get_function(func_id) {
508-
if let Some(&k) = func_ref.chunk.constants.get(c) { k } else { return; }
509-
} else { return; }
510-
} else { return; };
543+
// FAST PATH: Direct constant access via cached pointer
544+
let constant = *(*frame_ptr).constants_ptr.add(c);
511545

546+
// Integer % Integer fast path
512547
if left.primary == TAG_INTEGER && constant.primary == TAG_INTEGER {
513548
let r = constant.secondary as i64;
514549
if r == 0 { return; }
515550
let l = left.secondary as i64;
516-
*vm.register_stack.as_mut_ptr().add(base_ptr + a) = LuaValue::integer(l.rem_euclid(r));
551+
*vm.register_stack.as_mut_ptr().add(base_ptr + a) = LuaValue {
552+
primary: TAG_INTEGER,
553+
secondary: l.rem_euclid(r) as u64,
554+
};
517555
(*frame_ptr).pc += 1;
518556
return;
519557
}
520558

559+
// Float % Float
521560
if let (Some(l), Some(r)) = (left.as_number(), constant.as_number()) {
522561
let result = l - (l / r).floor() * r;
523562
*vm.register_stack.as_mut_ptr().add(base_ptr + a) = LuaValue::number(result);
@@ -527,6 +566,7 @@ pub fn exec_modk(vm: &mut LuaVM, instr: u32, frame_ptr: *mut LuaCallFrame) {
527566
}
528567

529568
/// POWK: R[A] = R[B] ^ K[C]
569+
/// OPTIMIZED: Uses cached constants_ptr for direct constant access
530570
#[inline(always)]
531571
pub fn exec_powk(vm: &mut LuaVM, instr: u32, frame_ptr: *mut LuaCallFrame) {
532572
let a = Instruction::get_a(instr) as usize;
@@ -537,11 +577,8 @@ pub fn exec_powk(vm: &mut LuaVM, instr: u32, frame_ptr: *mut LuaCallFrame) {
537577
let base_ptr = (*frame_ptr).base_ptr;
538578
let left = *vm.register_stack.as_ptr().add(base_ptr + b);
539579

540-
let constant = if let Some(func_id) = (*frame_ptr).function_value.as_function_id() {
541-
if let Some(func_ref) = vm.object_pool.get_function(func_id) {
542-
if let Some(&k) = func_ref.chunk.constants.get(c) { k } else { return; }
543-
} else { return; }
544-
} else { return; };
580+
// FAST PATH: Direct constant access via cached pointer
581+
let constant = *(*frame_ptr).constants_ptr.add(c);
545582

546583
let l_float = match left.as_number() { Some(n) => n, None => return };
547584
let r_float = match constant.as_number() { Some(n) => n, None => return };
@@ -552,6 +589,7 @@ pub fn exec_powk(vm: &mut LuaVM, instr: u32, frame_ptr: *mut LuaCallFrame) {
552589
}
553590

554591
/// DIVK: R[A] = R[B] / K[C]
592+
/// OPTIMIZED: Uses cached constants_ptr for direct constant access
555593
#[inline(always)]
556594
pub fn exec_divk(vm: &mut LuaVM, instr: u32, frame_ptr: *mut LuaCallFrame) {
557595
let a = Instruction::get_a(instr) as usize;
@@ -562,11 +600,8 @@ pub fn exec_divk(vm: &mut LuaVM, instr: u32, frame_ptr: *mut LuaCallFrame) {
562600
let base_ptr = (*frame_ptr).base_ptr;
563601
let left = *vm.register_stack.as_ptr().add(base_ptr + b);
564602

565-
let constant = if let Some(func_id) = (*frame_ptr).function_value.as_function_id() {
566-
if let Some(func_ref) = vm.object_pool.get_function(func_id) {
567-
if let Some(&k) = func_ref.chunk.constants.get(c) { k } else { return; }
568-
} else { return; }
569-
} else { return; };
603+
// FAST PATH: Direct constant access via cached pointer
604+
let constant = *(*frame_ptr).constants_ptr.add(c);
570605

571606
let l_float = match left.as_number() { Some(n) => n, None => return };
572607
let r_float = match constant.as_number() { Some(n) => n, None => return };
@@ -577,6 +612,7 @@ pub fn exec_divk(vm: &mut LuaVM, instr: u32, frame_ptr: *mut LuaCallFrame) {
577612
}
578613

579614
/// IDIVK: R[A] = R[B] // K[C]
615+
/// OPTIMIZED: Uses cached constants_ptr for direct constant access
580616
#[inline(always)]
581617
pub fn exec_idivk(vm: &mut LuaVM, instr: u32, frame_ptr: *mut LuaCallFrame) {
582618
let a = Instruction::get_a(instr) as usize;
@@ -587,21 +623,23 @@ pub fn exec_idivk(vm: &mut LuaVM, instr: u32, frame_ptr: *mut LuaCallFrame) {
587623
let base_ptr = (*frame_ptr).base_ptr;
588624
let left = *vm.register_stack.as_ptr().add(base_ptr + b);
589625

590-
let constant = if let Some(func_id) = (*frame_ptr).function_value.as_function_id() {
591-
if let Some(func_ref) = vm.object_pool.get_function(func_id) {
592-
if let Some(&k) = func_ref.chunk.constants.get(c) { k } else { return; }
593-
} else { return; }
594-
} else { return; };
626+
// FAST PATH: Direct constant access via cached pointer
627+
let constant = *(*frame_ptr).constants_ptr.add(c);
595628

629+
// Integer // Integer fast path
596630
if left.primary == TAG_INTEGER && constant.primary == TAG_INTEGER {
597631
let r = constant.secondary as i64;
598632
if r == 0 { return; }
599633
let l = left.secondary as i64;
600-
*vm.register_stack.as_mut_ptr().add(base_ptr + a) = LuaValue::integer(l.div_euclid(r));
634+
*vm.register_stack.as_mut_ptr().add(base_ptr + a) = LuaValue {
635+
primary: TAG_INTEGER,
636+
secondary: l.div_euclid(r) as u64,
637+
};
601638
(*frame_ptr).pc += 1;
602639
return;
603640
}
604641

642+
// Float // Float
605643
if let (Some(l), Some(r)) = (left.as_number(), constant.as_number()) {
606644
*vm.register_stack.as_mut_ptr().add(base_ptr + a) = LuaValue::number((l / r).floor());
607645
(*frame_ptr).pc += 1;
@@ -717,6 +755,7 @@ pub fn exec_shr(vm: &mut LuaVM, instr: u32, frame_ptr: *mut LuaCallFrame) {
717755
}
718756

719757
/// BANDK: R[A] = R[B] & K[C]
758+
/// OPTIMIZED: Uses cached constants_ptr for direct constant access
720759
#[inline(always)]
721760
pub fn exec_bandk(vm: &mut LuaVM, instr: u32, frame_ptr: *mut LuaCallFrame) {
722761
let a = Instruction::get_a(instr) as usize;
@@ -727,11 +766,8 @@ pub fn exec_bandk(vm: &mut LuaVM, instr: u32, frame_ptr: *mut LuaCallFrame) {
727766
let base_ptr = (*frame_ptr).base_ptr;
728767
let left = *vm.register_stack.as_ptr().add(base_ptr + b);
729768

730-
let constant = if let Some(func_id) = (*frame_ptr).function_value.as_function_id() {
731-
if let Some(func_ref) = vm.object_pool.get_function(func_id) {
732-
if let Some(&k) = func_ref.chunk.constants.get(c) { k } else { return; }
733-
} else { return; }
734-
} else { return; };
769+
// FAST PATH: Direct constant access via cached pointer
770+
let constant = *(*frame_ptr).constants_ptr.add(c);
735771

736772
let l_int = left.as_integer().or_else(|| {
737773
left.as_number().and_then(|f| {
@@ -752,6 +788,7 @@ pub fn exec_bandk(vm: &mut LuaVM, instr: u32, frame_ptr: *mut LuaCallFrame) {
752788
}
753789

754790
/// BORK: R[A] = R[B] | K[C]
791+
/// OPTIMIZED: Uses cached constants_ptr for direct constant access
755792
#[inline(always)]
756793
pub fn exec_bork(vm: &mut LuaVM, instr: u32, frame_ptr: *mut LuaCallFrame) {
757794
let a = Instruction::get_a(instr) as usize;
@@ -762,11 +799,8 @@ pub fn exec_bork(vm: &mut LuaVM, instr: u32, frame_ptr: *mut LuaCallFrame) {
762799
let base_ptr = (*frame_ptr).base_ptr;
763800
let left = *vm.register_stack.as_ptr().add(base_ptr + b);
764801

765-
let constant = if let Some(func_id) = (*frame_ptr).function_value.as_function_id() {
766-
if let Some(func_ref) = vm.object_pool.get_function(func_id) {
767-
if let Some(&k) = func_ref.chunk.constants.get(c) { k } else { return; }
768-
} else { return; }
769-
} else { return; };
802+
// FAST PATH: Direct constant access via cached pointer
803+
let constant = *(*frame_ptr).constants_ptr.add(c);
770804

771805
let l_int = left.as_integer().or_else(|| {
772806
left.as_number().and_then(|f| {
@@ -787,6 +821,7 @@ pub fn exec_bork(vm: &mut LuaVM, instr: u32, frame_ptr: *mut LuaCallFrame) {
787821
}
788822

789823
/// BXORK: R[A] = R[B] ~ K[C]
824+
/// OPTIMIZED: Uses cached constants_ptr for direct constant access
790825
#[inline(always)]
791826
pub fn exec_bxork(vm: &mut LuaVM, instr: u32, frame_ptr: *mut LuaCallFrame) {
792827
let a = Instruction::get_a(instr) as usize;
@@ -797,11 +832,8 @@ pub fn exec_bxork(vm: &mut LuaVM, instr: u32, frame_ptr: *mut LuaCallFrame) {
797832
let base_ptr = (*frame_ptr).base_ptr;
798833
let left = *vm.register_stack.as_ptr().add(base_ptr + b);
799834

800-
let constant = if let Some(func_id) = (*frame_ptr).function_value.as_function_id() {
801-
if let Some(func_ref) = vm.object_pool.get_function(func_id) {
802-
if let Some(&k) = func_ref.chunk.constants.get(c) { k } else { return; }
803-
} else { return; }
804-
} else { return; };
835+
// FAST PATH: Direct constant access via cached pointer
836+
let constant = *(*frame_ptr).constants_ptr.add(c);
805837

806838
let l_int = left.as_integer().or_else(|| {
807839
left.as_number().and_then(|f| {

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

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -785,10 +785,11 @@ fn exec_call_lua_function(
785785
return Err(vm.error("Invalid function ID".to_string()));
786786
};
787787

788-
let (max_stack_size, is_vararg, code_ptr) = (
788+
let (max_stack_size, is_vararg, code_ptr, constants_ptr) = (
789789
func_ref.chunk.max_stack_size,
790790
func_ref.chunk.is_vararg,
791791
func_ref.chunk.code.as_ptr(),
792+
func_ref.chunk.constants.as_ptr(),
792793
);
793794

794795
// Calculate argument count - use frame_ptr directly!
@@ -842,6 +843,7 @@ fn exec_call_lua_function(
842843
let new_frame = LuaCallFrame::new_lua_function(
843844
func,
844845
code_ptr,
846+
constants_ptr,
845847
new_base,
846848
arg_count, // top = number of arguments
847849
a, // result_reg
@@ -906,6 +908,7 @@ fn exec_call_lua_function(
906908
let new_frame = LuaCallFrame::new_lua_function(
907909
func,
908910
code_ptr,
911+
constants_ptr,
909912
new_base,
910913
actual_arg_count, // top = number of arguments
911914
a, // result_reg
@@ -1092,6 +1095,7 @@ pub fn exec_tailcall(vm: &mut LuaVM, instr: u32, frame_ptr_ptr: &mut *mut LuaCal
10921095
};
10931096
let max_stack_size = func_ref.chunk.max_stack_size;
10941097
let code_ptr = func_ref.chunk.code.as_ptr();
1098+
let constants_ptr = func_ref.chunk.constants.as_ptr();
10951099

10961100
// CRITICAL: Before popping the frame, close all upvalues that point to it
10971101
// This ensures that any closures created in this frame can still access
@@ -1115,6 +1119,7 @@ pub fn exec_tailcall(vm: &mut LuaVM, instr: u32, frame_ptr_ptr: &mut *mut LuaCal
11151119
let new_frame = LuaCallFrame::new_lua_function(
11161120
func,
11171121
code_ptr,
1122+
constants_ptr,
11181123
old_base,
11191124
arg_count, // top = number of arguments passed
11201125
result_reg, // result_reg from the CALLER (not 0!)

0 commit comments

Comments
 (0)