From c0d849e7881c23b9e107191e0091a48bec41ce09 Mon Sep 17 00:00:00 2001 From: Aakash Patel Date: Wed, 28 Aug 2019 15:03:31 -0700 Subject: [PATCH] Extract exponentiation operation from mathPow function. Summary: In anticipation of adding support for `**`, we move the exponentiation logic out of `mathPow` and place it in `expOp`, where it will be used to avoid duplicating logic in the interpreter loop. Reviewed By: dulinriley Differential Revision: D16628558 fbshipit-source-id: 83e3cfd3c41525498b2e13e31f2164f5d1947cfc --- include/hermes/VM/Operations.h | 17 +++++++++++++++++ lib/VM/JSLib/Math.cpp | 20 ++------------------ 2 files changed, 19 insertions(+), 18 deletions(-) diff --git a/include/hermes/VM/Operations.h b/include/hermes/VM/Operations.h index 1416b61e6af..e465a395019 100644 --- a/include/hermes/VM/Operations.h +++ b/include/hermes/VM/Operations.h @@ -213,6 +213,23 @@ bool isPrimitive(HermesValue val); CallResult addOp_RJS(Runtime *runtime, Handle<> xHandle, Handle<> yHandle); +/// ES9.0 12.6.4 +inline double expOp(double x, double y) { + constexpr double nan = std::numeric_limits::quiet_NaN(); + + // Handle special cases that std::pow handles differently. + if (std::isnan(y)) { + return nan; + } else if (y == 0) { + return 1; + } else if (std::abs(x) == 1 && std::isinf(y)) { + return nan; + } + + // std::pow handles the other edge cases as the ES9.0 spec requires. + return std::pow(x, y); +} + /// ES5.1 7.2 inline bool isWhiteSpaceChar(char16_t c) { return c == u'\u0009' || c == u'\u000B' || c == u'\u000C' || c == u'\u0020' || diff --git a/lib/VM/JSLib/Math.cpp b/lib/VM/JSLib/Math.cpp index 4a662733a88..79e29d25945 100644 --- a/lib/VM/JSLib/Math.cpp +++ b/lib/VM/JSLib/Math.cpp @@ -179,7 +179,7 @@ CallResult mathMin(void *, Runtime *runtime, NativeArgs args) { return HermesValue::encodeDoubleValue(result); } -// ES5.1 15.8.2.13 +// ES9.0 20.2.2.26 CallResult mathPow(void *, Runtime *runtime, NativeArgs args) { auto res = toNumber_RJS(runtime, args.getArgHandle(runtime, 0)); if (LLVM_UNLIKELY(res == ExecutionStatus::EXCEPTION)) { @@ -193,23 +193,7 @@ CallResult mathPow(void *, Runtime *runtime, NativeArgs args) { } const double y = res->getNumber(); - const double nan = std::numeric_limits::quiet_NaN(); - - double result; - - // Handle special cases that std::pow handles differently. - if (std::isnan(y)) { - result = nan; - } else if (y == 0) { - result = 1; - } else if (std::abs(x) == 1 && std::isinf(y)) { - result = nan; - } else { - // std::pow handles the other edge cases as ES5.1 specifies. - result = std::pow(x, y); - } - - return HermesValue::encodeNumberValue(result); + return HermesValue::encodeNumberValue(expOp(x, y)); } // ES5.1 15.8.2.14