1
Fork 0
mirror of https://github.com/RGBCube/serenity synced 2025-05-31 12:48:10 +00:00

LibJS/JIT: Add a fast path for floating point comparisons

This commit is contained in:
Stephan Vedder 2023-11-14 16:46:10 +01:00 committed by Andreas Kling
parent 4164af2ca4
commit 32352aa729
3 changed files with 107 additions and 48 deletions

View file

@ -391,7 +391,7 @@ void Compiler::convert_to_double(Assembler::Reg dst, Assembler::Reg src, Assembl
}
template<typename CodegenI32, typename CodegenDouble, typename CodegenValue>
void Compiler::branch_if_both_numbers(Assembler::Reg lhs, Assembler::Reg rhs, CodegenI32 codegen_i32, CodegenDouble codegen_double, CodegenValue codegen_value)
void Compiler::compile_binary_op_fastpaths(Assembler::Reg lhs, Assembler::Reg rhs, CodegenI32 codegen_i32, CodegenDouble codegen_double, CodegenValue codegen_value)
{
Assembler::Label end {};
Assembler::Label slow_case {};
@ -446,6 +446,37 @@ void Compiler::branch_if_both_numbers(Assembler::Reg lhs, Assembler::Reg rhs, Co
end.link(m_assembler);
}
template<typename CodegenI32, typename CodegenDouble, typename CodegenValue>
void Compiler::compiler_comparison_fastpaths(Assembler::Reg lhs, Assembler::Reg rhs, CodegenI32 codegen_i32, CodegenDouble codegen_double, CodegenValue codegen_value)
{
Assembler::Label end {};
Assembler::Label slow_case {};
// The only case where we can take the int32 fastpath
branch_if_both_int32(lhs, rhs, [&] {
store_accumulator(codegen_i32(lhs, rhs));
// accumulator |= SHIFTED_BOOLEAN_TAG;
m_assembler.jump(end);
});
// accumulator = op_double(lhs.to_double(), rhs.to_double())
auto temp_register = GPR0;
auto nan_register = GPR1;
m_assembler.mov(Assembler::Operand::Register(nan_register), Assembler::Operand::Imm(CANON_NAN_BITS));
convert_to_double(FPR0, ARG1, nan_register, temp_register, slow_case);
convert_to_double(FPR1, ARG2, nan_register, temp_register, slow_case);
store_accumulator(codegen_double(FPR0, FPR1));
m_assembler.jump(end);
slow_case.link(m_assembler);
// accumulator = TRY(op_value(lhs, rhs))
store_accumulator(codegen_value(lhs, rhs));
check_exception();
end.link(m_assembler);
}
void Compiler::compile_increment(Bytecode::Op::Increment const&)
{
load_accumulator(ARG1);
@ -989,7 +1020,7 @@ void Compiler::compile_add(Bytecode::Op::Add const& op)
load_vm_register(ARG1, op.lhs());
load_accumulator(ARG2);
branch_if_both_numbers(
compile_binary_op_fastpaths(
ARG1, ARG2,
[&](auto lhs, auto rhs, auto& slow_case) {
m_assembler.add32(
@ -1024,7 +1055,7 @@ void Compiler::compile_sub(Bytecode::Op::Sub const& op)
load_vm_register(ARG1, op.lhs());
load_accumulator(ARG2);
branch_if_both_numbers(
compile_binary_op_fastpaths(
ARG1, ARG2,
[&](auto lhs, auto rhs, auto& slow_case) {
m_assembler.sub32(
@ -1059,7 +1090,7 @@ void Compiler::compile_mul(Bytecode::Op::Mul const& op)
load_vm_register(ARG1, op.lhs());
load_accumulator(ARG2);
branch_if_both_numbers(
compile_binary_op_fastpaths(
ARG1, ARG2,
[&](auto lhs, auto rhs, auto& slow_case) {
m_assembler.mul32(
@ -1084,42 +1115,63 @@ void Compiler::compile_mul(Bytecode::Op::Mul const& op)
});
}
# define DO_COMPILE_COMPARISON_OP(TitleCaseName, snake_case_name, AssemblerCondition) \
static Value cxx_##snake_case_name(VM& vm, Value lhs, Value rhs) \
{ \
return TRY_OR_SET_EXCEPTION(snake_case_name(vm, lhs, rhs)); \
} \
\
void Compiler::compile_##snake_case_name(Bytecode::Op::TitleCaseName const& op) \
{ \
load_vm_register(ARG1, op.lhs()); \
load_accumulator(ARG2); \
\
Assembler::Label end {}; \
\
branch_if_both_int32(ARG1, ARG2, [&] { \
m_assembler.sign_extend_32_to_64_bits(ARG1); \
m_assembler.sign_extend_32_to_64_bits(ARG2); \
\
/* accumulator = SHIFTED_BOOLEAN_TAG | (arg1 condition arg2) */ \
m_assembler.mov( \
Assembler::Operand::Register(GPR0), \
Assembler::Operand::Imm(SHIFTED_BOOLEAN_TAG)); \
m_assembler.cmp( \
Assembler::Operand::Register(ARG1), \
Assembler::Operand::Register(ARG2)); \
m_assembler.set_if( \
Assembler::Condition::AssemblerCondition, \
Assembler::Operand::Register(GPR0)); /* sets only first byte */ \
store_accumulator(GPR0); \
\
m_assembler.jump(end); \
}); \
\
native_call((void*)cxx_##snake_case_name); \
store_accumulator(RET); \
check_exception(); \
end.link(m_assembler); \
# define DO_COMPILE_COMPARISON_OP(TitleCaseName, snake_case_name, IntegerCondition, FloatCondition) \
static Value cxx_##snake_case_name(VM& vm, Value lhs, Value rhs) \
{ \
return TRY_OR_SET_EXCEPTION(snake_case_name(vm, lhs, rhs)); \
} \
\
void Compiler::compile_##snake_case_name(Bytecode::Op::TitleCaseName const& op) \
{ \
load_vm_register(ARG1, op.lhs()); \
load_accumulator(ARG2); \
\
compiler_comparison_fastpaths( \
ARG1, ARG2, \
[&](auto lhs, auto rhs) { \
m_assembler.sign_extend_32_to_64_bits(lhs); \
m_assembler.sign_extend_32_to_64_bits(rhs); \
\
/* accumulator = SHIFTED_BOOLEAN_TAG | (arg1 condition arg2) */ \
m_assembler.mov( \
Assembler::Operand::Register(GPR0), \
Assembler::Operand::Imm(SHIFTED_BOOLEAN_TAG)); \
m_assembler.cmp( \
Assembler::Operand::Register(lhs), \
Assembler::Operand::Register(rhs)); \
m_assembler.set_if( \
Assembler::Condition::IntegerCondition, \
Assembler::Operand::Register(GPR0)); /* sets only first byte */ \
return GPR0; \
}, \
[&](auto lhs, auto rhs) { \
Assembler::Label is_nan; \
/* accumulator = SHIFTED_BOOLEAN_TAG | (arg1 condition arg2) */ \
m_assembler.mov( \
Assembler::Operand::Register(GPR0), \
Assembler::Operand::Imm(SHIFTED_BOOLEAN_TAG)); \
m_assembler.cmp( \
Assembler::Operand::FloatRegister(lhs), \
Assembler::Operand::FloatRegister(rhs)); \
m_assembler.jump_if( \
Assembler::Condition::Unordered, \
is_nan); \
m_assembler.set_if( \
Assembler::Condition::FloatCondition, \
Assembler::Operand::Register(GPR0)); /* sets only first byte */ \
is_nan.link(m_assembler); \
return GPR0; \
}, \
[&](auto lhs, auto rhs) { \
m_assembler.mov( \
Assembler::Operand::Register(ARG1), \
Assembler::Operand::Register(lhs)); \
m_assembler.mov( \
Assembler::Operand::Register(ARG2), \
Assembler::Operand::Register(rhs)); \
native_call((void*)cxx_##snake_case_name); \
return RET; \
}); \
}
JS_ENUMERATE_COMPARISON_OPS(DO_COMPILE_COMPARISON_OP)