LibJS/JIT: Add a builtin for Math.abs

This commit is contained in:
Simon Wanner 2023-11-17 11:56:40 +01:00 committed by Andreas Kling
parent 86b85aa68b
commit 6c8ab1ca0d
Notes: sideshowbarker 2024-07-16 22:34:39 +09:00
4 changed files with 58 additions and 3 deletions

View file

@ -582,6 +582,15 @@ struct X86_64Assembler {
emit_modrm_slash(0, dst);
}
void mov_if(Condition condition, Operand dst, Operand src)
{
VERIFY(dst.type == Operand::Type::Reg && src.type == Operand::Type::Reg);
emit_rex_for_rm(dst, src, REX_W::Yes);
emit8(0x0f);
emit8(0x40 | to_underlying(condition));
emit_modrm_rm(dst, src);
}
void sign_extend_32_to_64_bits(Reg reg)
{
mov32(Operand::Register(reg), Operand::Register(reg), Extension::SignExtend);
@ -989,6 +998,14 @@ struct X86_64Assembler {
}
}
void neg32(Operand reg)
{
VERIFY(reg.type == Operand::Type::Reg);
emit_rex_for_slash(reg, REX_W::No);
emit8(0xf7);
emit_modrm_slash(3, reg);
}
void convert_i32_to_double(Operand dst, Operand src)
{
VERIFY(dst.type == Operand::Type::FReg);

View file

@ -12,7 +12,8 @@
namespace JS::Bytecode {
// TitleCaseName, snake_case_name, base, property, argument_count
#define JS_ENUMERATE_BUILTINS(O)
#define JS_ENUMERATE_BUILTINS(O) \
O(MathAbs, math_abs, Math, abs, 1)
enum class Builtin {
#define DEFINE_BUILTIN_ENUM(name, ...) name,

View file

@ -2587,7 +2587,7 @@ void Compiler::compile_call(Bytecode::Op::Call const& op)
end.link(m_assembler);
}
void Compiler::compile_builtin(Bytecode::Builtin builtin, [[maybe_unused]] Assembler::Label& slow_case, [[maybe_unused]] Assembler::Label& end)
void Compiler::compile_builtin(Bytecode::Builtin builtin, Assembler::Label& slow_case, Assembler::Label& end)
{
switch (builtin) {
# define DEFINE_BUILTIN_CASE(name, snake_case_name, ...) \
@ -2601,6 +2601,43 @@ void Compiler::compile_builtin(Bytecode::Builtin builtin, [[maybe_unused]] Assem
}
}
void Compiler::compile_builtin_math_abs(Assembler::Label& slow_case, Assembler::Label& end)
{
branch_if_int32(ARG2, [&] {
// ARG2 &= 0xffffffff
m_assembler.mov32(Assembler::Operand::Register(ARG2), Assembler::Operand::Register(ARG2), Assembler::Extension::SignExtend);
// if (ARG2 == INT32_MIN) goto slow_case;
m_assembler.jump_if(
Assembler::Operand::Register(ARG2),
Assembler::Condition::EqualTo,
Assembler::Operand::Imm(NumericLimits<i32>::min()),
slow_case);
// accumulator = ARG2 < 0 ? -ARG2 : ARG2;
m_assembler.mov(Assembler::Operand::Register(CACHED_ACCUMULATOR), Assembler::Operand::Register(ARG2));
m_assembler.neg32(Assembler::Operand::Register(CACHED_ACCUMULATOR));
m_assembler.mov_if(Assembler::Condition::SignedLessThan, Assembler::Operand::Register(CACHED_ACCUMULATOR), Assembler::Operand::Register(ARG2));
// accumulator |= SHIFTED_INT32_TAG;
m_assembler.mov(Assembler::Operand::Register(GPR0), Assembler::Operand::Imm(SHIFTED_INT32_TAG));
m_assembler.bitwise_or(Assembler::Operand::Register(CACHED_ACCUMULATOR), Assembler::Operand::Register(GPR0));
m_assembler.jump(end);
});
// if (ARG2.is_double()) goto slow_case;
m_assembler.mov(Assembler::Operand::Register(GPR0), Assembler::Operand::Imm(CANON_NAN_BITS));
jump_if_not_double(ARG2, GPR0, GPR1, slow_case);
// accumulator = ARG2 & 0x7fffffffffffffff
m_assembler.mov(Assembler::Operand::Register(GPR0), Assembler::Operand::Imm(0x7fffffffffffffff));
m_assembler.bitwise_and(Assembler::Operand::Register(ARG2), Assembler::Operand::Register(GPR0));
store_accumulator(ARG2);
m_assembler.jump(end);
}
static Value cxx_call_with_argument_array(VM& vm, Value arguments, Value callee, Value this_value, Bytecode::Op::CallType call_type, Optional<Bytecode::StringTableIndex> const& expression_string)
{
TRY_OR_SET_EXCEPTION(throw_if_needed_for_call(vm.bytecode_interpreter(), callee, call_type, expression_string));

View file

@ -27,7 +27,7 @@ void MathObject::initialize(Realm& realm)
auto& vm = this->vm();
Base::initialize(realm);
u8 attr = Attribute::Writable | Attribute::Configurable;
define_native_function(realm, vm.names.abs, abs, 1, attr);
define_native_function(realm, vm.names.abs, abs, 1, attr, Bytecode::Builtin::MathAbs);
define_native_function(realm, vm.names.random, random, 0, attr);
define_native_function(realm, vm.names.sqrt, sqrt, 1, attr);
define_native_function(realm, vm.names.floor, floor, 1, attr);