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:
parent
4164af2ca4
commit
32352aa729
3 changed files with 107 additions and 48 deletions
|
@ -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)
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue