Skip to main content

luaur_code_gen/functions/
call_barrier_table_fast.rs

1use crate::enums::condition_x_64::ConditionX64;
2use crate::enums::size_x_64::SizeX64;
3use crate::records::assembly_builder_x_64::AssemblyBuilderX64;
4use crate::records::ir_call_wrapper_x_64::IrCallWrapperX64;
5use crate::records::ir_op::IrOp;
6use crate::records::ir_reg_alloc_x_64::IrRegAllocX64;
7use crate::records::label::Label;
8use crate::records::native_context::NativeContext;
9use crate::records::operand_x_64::OperandX64;
10use crate::records::register_x_64::RegisterX64;
11use crate::records::scoped_spills::ScopedSpills;
12use luaur_vm::macros::bitmask::bitmask;
13use luaur_vm::macros::blackbit::BLACKBIT;
14use luaur_vm::records::g_cheader::GCheader;
15use luaur_vm::records::lua_table::LuaTable;
16
17const fn r_state() -> RegisterX64 {
18    RegisterX64 {
19        bits: (15u8 << RegisterX64::INDEX_SHIFT) | SizeX64::qword as u8,
20    }
21}
22
23const fn r_native_context() -> RegisterX64 {
24    RegisterX64 {
25        bits: (13u8 << RegisterX64::INDEX_SHIFT) | SizeX64::qword as u8,
26    }
27}
28
29pub fn call_barrier_table_fast(
30    regs: &mut IrRegAllocX64,
31    build: &mut AssemblyBuilderX64,
32    table: RegisterX64,
33    table_op: IrOp,
34) {
35    let mut skip = Label { id: 0, location: 0 };
36
37    // isblack(obj2gco(t))
38    build.test(
39        OperandX64::mem(
40            SizeX64::byte,
41            RegisterX64::noreg,
42            1,
43            table,
44            core::mem::offset_of!(GCheader, marked) as i32,
45        ),
46        OperandX64::imm(bitmask(BLACKBIT as i32)),
47    );
48    build.jcc(ConditionX64::Zero, &mut skip);
49
50    {
51        let _spill_guard = {
52            let mut guard = ScopedSpills {
53                owner: regs as *mut _,
54                start_spill_id: 0,
55            };
56            guard.scoped_spills_scoped_spills_ir_reg_alloc_x_64(regs);
57            guard
58        };
59
60        let mut call_wrap = IrCallWrapperX64::ir_call_wrapper_x_64_ir_call_wrapper_x_64(
61            regs,
62            build,
63            regs.curr_inst_idx,
64        );
65
66        call_wrap.add_argument_size_x_64_operand_x_64_ir_op(
67            SizeX64::qword,
68            OperandX64::reg(r_state()),
69            IrOp::ir_op(),
70        );
71        call_wrap.add_argument_size_x_64_operand_x_64_ir_op(
72            SizeX64::qword,
73            OperandX64::reg(table),
74            table_op,
75        );
76        call_wrap.add_argument_size_x_64_operand_x_64_ir_op(
77            SizeX64::qword,
78            OperandX64::mem(
79                SizeX64::none,
80                RegisterX64::noreg,
81                1,
82                table,
83                core::mem::offset_of!(LuaTable, gclist) as i32,
84            ),
85            IrOp::ir_op(),
86        );
87
88        call_wrap.call(&OperandX64::mem(
89            SizeX64::qword,
90            RegisterX64::noreg,
91            1,
92            r_native_context(),
93            core::mem::offset_of!(NativeContext, luaC_barrierback) as i32,
94        ));
95    }
96
97    build.set_label_label(&mut skip);
98}