bug 1466893 - Part 2: Convert BigInt arguments to the Number constructor. r=jandem
authorRobin Templeton <robin@igalia.com>
Tue, 12 Jun 2018 13:58:20 -0400
changeset 422399 7cdfba2700eb020b568fe2c34282d4154ba13577
parent 422398 631e90e9e0747845da585184217fa6f30525c14e
child 422400 ffb7f17d5496feada5770f25f61d20701060289d
push id34132
push usercsabou@mozilla.com
push dateWed, 13 Jun 2018 09:22:38 +0000
treeherdermozilla-central@0344af552239 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersjandem
bugs1466893
milestone62.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
bug 1466893 - Part 2: Convert BigInt arguments to the Number constructor. r=jandem
js/src/jsnum.cpp
js/src/vm/BigIntType.cpp
js/src/vm/BigIntType.h
--- a/js/src/jsnum.cpp
+++ b/js/src/jsnum.cpp
@@ -24,16 +24,19 @@
 
 #include "jstypes.h"
 
 #include "builtin/String.h"
 #include "double-conversion/double-conversion.h"
 #include "js/Conversions.h"
 #include "util/DoubleToString.h"
 #include "util/StringBuffer.h"
+#ifdef ENABLE_BIGINT
+#include "vm/BigIntType.h"
+#endif
 #include "vm/GlobalObject.h"
 #include "vm/JSAtom.h"
 #include "vm/JSContext.h"
 #include "vm/JSObject.h"
 
 #include "vm/NativeObject-inl.h"
 #include "vm/NumberObject-inl.h"
 #include "vm/StringType-inl.h"
@@ -482,18 +485,24 @@ const Class NumberObject::class_ = {
 };
 
 static bool
 Number(JSContext* cx, unsigned argc, Value* vp)
 {
     CallArgs args = CallArgsFromVp(argc, vp);
 
     if (args.length() > 0) {
-        if (!ToNumber(cx, args[0]))
+        // BigInt proposal section 6.2, steps 2a-c.
+        if (!ToNumeric(cx, args[0]))
             return false;
+#ifdef ENABLE_BIGINT
+        if (args[0].isBigInt())
+            args[0].setNumber(BigInt::numberValue(args[0].toBigInt()));
+#endif
+        MOZ_ASSERT(args[0].isNumber());
     }
 
     if (!args.isConstructing()) {
         if (args.length() > 0)
             args.rval().set(args[0]);
         else
             args.rval().setInt32(0);
         return true;
--- a/js/src/vm/BigIntType.cpp
+++ b/js/src/vm/BigIntType.cpp
@@ -170,16 +170,28 @@ js::ToBigInt(JSContext* cx, HandleValue 
         RootedString str(cx, v.toString());
         return StringToBigInt(cx, str, 0);
     }
 
     JS_ReportErrorNumberASCII(cx, GetErrorMessage, nullptr, JSMSG_NOT_BIGINT);
     return nullptr;
 }
 
+// ES 2019 draft 6.1.6
+double
+BigInt::numberValue(BigInt* x)
+{
+    // mpz_get_d may cause a hardware overflow trap, so use
+    // mpz_get_d_2exp to get the fractional part and exponent
+    // separately.
+    signed long int exp;
+    double d = mpz_get_d_2exp(&exp, x->num_);
+    return ldexp(d, exp);
+}
+
 JSLinearString*
 BigInt::toString(JSContext* cx, BigInt* x, uint8_t radix)
 {
     MOZ_ASSERT(2 <= radix && radix <= 36);
     // We need two extra chars for '\0' and potentially '-'.
     size_t strSize = mpz_sizeinbase(x->num_, 10) + 2;
     UniqueChars str(static_cast<char*>(js_malloc(strSize)));
     if (!str) {
--- a/js/src/vm/BigIntType.h
+++ b/js/src/vm/BigIntType.h
@@ -64,16 +64,17 @@ class BigInt final : public js::gc::Tenu
     size_t sizeOfExcludingThis(mozilla::MallocSizeOf mallocSizeOf) const;
 
     bool toBoolean();
 
     static void init();
 
     static BigInt* copy(JSContext* cx, Handle<BigInt*> x);
 
+    static double numberValue(BigInt* x);
     static JSLinearString* toString(JSContext* cx, BigInt* x, uint8_t radix);
 };
 
 static_assert(sizeof(BigInt) >= js::gc::MinCellSize,
               "sizeof(BigInt) must be greater than the minimum allocation size");
 
 } // namespace JS