From 1d8a601f968bb3b4e388b255676d861c335be288 Mon Sep 17 00:00:00 2001 From: Andreas Kling Date: Fri, 24 Nov 2023 09:31:23 +0100 Subject: [PATCH] LibJS/JIT: Add builtin for Math.log() Note that we still call out to a C++ helper, but by having a builtin, we still avoid the cost of a full JS function call. --- Userland/Libraries/LibJS/Bytecode/Builtins.h | 5 +++-- Userland/Libraries/LibJS/JIT/Compiler.cpp | 14 ++++++++++++++ Userland/Libraries/LibJS/Runtime/MathObject.cpp | 12 +++++++++--- Userland/Libraries/LibJS/Runtime/MathObject.h | 2 ++ 4 files changed, 28 insertions(+), 5 deletions(-) diff --git a/Userland/Libraries/LibJS/Bytecode/Builtins.h b/Userland/Libraries/LibJS/Bytecode/Builtins.h index b67de4b855..e69762819c 100644 --- a/Userland/Libraries/LibJS/Bytecode/Builtins.h +++ b/Userland/Libraries/LibJS/Bytecode/Builtins.h @@ -12,8 +12,9 @@ namespace JS::Bytecode { // TitleCaseName, snake_case_name, base, property, argument_count -#define JS_ENUMERATE_BUILTINS(O) \ - O(MathAbs, math_abs, Math, abs, 1) +#define JS_ENUMERATE_BUILTINS(O) \ + O(MathAbs, math_abs, Math, abs, 1) \ + O(MathLog, math_log, Math, log, 1) enum class Builtin { #define DEFINE_BUILTIN_ENUM(name, ...) name, diff --git a/Userland/Libraries/LibJS/JIT/Compiler.cpp b/Userland/Libraries/LibJS/JIT/Compiler.cpp index b26efd471e..6d13442599 100644 --- a/Userland/Libraries/LibJS/JIT/Compiler.cpp +++ b/Userland/Libraries/LibJS/JIT/Compiler.cpp @@ -18,6 +18,7 @@ #include #include #include +#include #include #include #include @@ -2623,6 +2624,19 @@ void Compiler::compile_builtin(Bytecode::Builtin builtin, Assembler::Label& slow } } +static Value cxx_math_log(VM& vm, Value, Value value) +{ + return TRY_OR_SET_EXCEPTION(MathObject::log_impl(vm, value)); +} + +void Compiler::compile_builtin_math_log(Assembler::Label&, Assembler::Label& end) +{ + native_call((void*)cxx_math_log); + store_accumulator(RET); + check_exception(); + m_assembler.jump(end); +} + void Compiler::compile_builtin_math_abs(Assembler::Label& slow_case, Assembler::Label& end) { branch_if_int32(ARG2, [&] { diff --git a/Userland/Libraries/LibJS/Runtime/MathObject.cpp b/Userland/Libraries/LibJS/Runtime/MathObject.cpp index 8225b5bc6e..19608dede4 100644 --- a/Userland/Libraries/LibJS/Runtime/MathObject.cpp +++ b/Userland/Libraries/LibJS/Runtime/MathObject.cpp @@ -58,7 +58,7 @@ void MathObject::initialize(Realm& realm) define_native_function(realm, vm.names.fround, fround, 1, attr); define_native_function(realm, vm.names.hypot, hypot, 2, attr); define_native_function(realm, vm.names.imul, imul, 2, attr); - define_native_function(realm, vm.names.log, log, 1, attr); + define_native_function(realm, vm.names.log, log, 1, attr, Bytecode::Builtin::MathLog); define_native_function(realm, vm.names.log2, log2, 1, attr); define_native_function(realm, vm.names.log10, log10, 1, attr); define_native_function(realm, vm.names.sinh, sinh, 1, attr); @@ -555,10 +555,10 @@ JS_DEFINE_NATIVE_FUNCTION(MathObject::imul) } // 21.3.2.20 Math.log ( x ), https://tc39.es/ecma262/#sec-math.log -JS_DEFINE_NATIVE_FUNCTION(MathObject::log) +ThrowCompletionOr MathObject::log_impl(VM& vm, Value x) { // 1. Let n be ? ToNumber(x). - auto number = TRY(vm.argument(0).to_number(vm)); + auto number = TRY(x.to_number(vm)); // 2. If n is NaN or n is +∞𝔽, return n. if (number.is_nan() || number.is_positive_infinity()) @@ -580,6 +580,12 @@ JS_DEFINE_NATIVE_FUNCTION(MathObject::log) return Value(::log(number.as_double())); } +// 21.3.2.20 Math.log ( x ), https://tc39.es/ecma262/#sec-math.log +JS_DEFINE_NATIVE_FUNCTION(MathObject::log) +{ + return log_impl(vm, vm.argument(0)); +} + // 21.3.2.21 Math.log1p ( x ), https://tc39.es/ecma262/#sec-math.log1p JS_DEFINE_NATIVE_FUNCTION(MathObject::log1p) { diff --git a/Userland/Libraries/LibJS/Runtime/MathObject.h b/Userland/Libraries/LibJS/Runtime/MathObject.h index 81ba320efc..7fdb665f39 100644 --- a/Userland/Libraries/LibJS/Runtime/MathObject.h +++ b/Userland/Libraries/LibJS/Runtime/MathObject.h @@ -18,6 +18,8 @@ public: virtual void initialize(Realm&) override; virtual ~MathObject() override = default; + static ThrowCompletionOr log_impl(VM&, Value); + private: explicit MathObject(Realm&);