Backed out changeset 64b039293b0a (bug 1501104) for causing SM bustages on non262/BigInt/large-bit-length.js.

This commit is contained in:
Cosmin Sabou 2018-11-07 21:39:03 +02:00
parent ed43e261f7
commit 2726d7f95e
5 changed files with 1 additions and 241 deletions

View File

@ -181,66 +181,10 @@ BigIntObject::toLocaleString(JSContext* cx, unsigned argc, Value* vp)
return CallNonGenericMethod<IsBigInt, toLocaleString_impl>(cx, args);
}
// BigInt proposal section 5.2.1. BigInt.asUintN ( bits, bigint )
bool
BigIntObject::asUintN(JSContext* cx, unsigned argc, Value* vp)
{
CallArgs args = CallArgsFromVp(argc, vp);
// Step 1.
uint64_t bits;
if (!ToIndex(cx, args[0], &bits)) {
return false;
}
// Step 2.
RootedBigInt bi(cx, ToBigInt(cx, args[1]));
if (!bi) {
return false;
}
// Step 3.
BigInt* res = BigInt::asUintN(cx, bi, bits);
if (!res) {
return false;
}
args.rval().setBigInt(res);
return true;
}
// BigInt proposal section 5.2.2. BigInt.asIntN ( bits, bigint )
bool
BigIntObject::asIntN(JSContext* cx, unsigned argc, Value* vp)
{
CallArgs args = CallArgsFromVp(argc, vp);
// Step 1.
uint64_t bits;
if (!ToIndex(cx, args[0], &bits)) {
return false;
}
// Step 2.
RootedBigInt bi(cx, ToBigInt(cx, args[1]));
if (!bi) {
return false;
}
// Step 3.
BigInt* res = BigInt::asIntN(cx, bi, bits);
if (!res) {
return false;
}
args.rval().setBigInt(res);
return true;
}
const ClassSpec BigIntObject::classSpec_ = {
GenericCreateConstructor<BigIntConstructor, 1, gc::AllocKind::FUNCTION>,
GenericCreatePrototype<BigIntObject>,
BigIntObject::staticMethods,
nullptr,
nullptr,
BigIntObject::methods,
BigIntObject::properties
@ -274,9 +218,3 @@ const JSFunctionSpec BigIntObject::methods[] = {
JS_FN("toLocaleString", toLocaleString, 0, 0),
JS_FS_END
};
const JSFunctionSpec BigIntObject::staticMethods[] = {
JS_FN("asUintN", asUintN, 2, 0),
JS_FN("asIntN", asIntN, 2, 0),
JS_FS_END
};

View File

@ -35,15 +35,12 @@ class BigIntObject : public NativeObject
static bool toString(JSContext* cx, unsigned argc, JS::Value* vp);
static bool toLocaleString_impl(JSContext* cx, const CallArgs& args);
static bool toLocaleString(JSContext* cx, unsigned argc, JS::Value* vp);
static bool asUintN(JSContext* cx, unsigned argc, JS::Value* vp);
static bool asIntN(JSContext* cx, unsigned argc, JS::Value* vp);
JS::BigInt* unbox() const;
private:
static const JSPropertySpec properties[];
static const JSFunctionSpec methods[];
static const JSFunctionSpec staticMethods[];
};
extern JSObject*

View File

@ -1,33 +0,0 @@
// Any copyright is dedicated to the Public Domain.
// https://creativecommons.org/licenses/publicdomain/
function test(thunk, result) {
let val, err;
try {
val = thunk();
} catch (e) {
err = e;
}
if (err) {
assertEq(err instanceof RangeError, true);
} else {
assertEq(val, result);
}
}
const UINT32_MAX = 2**32-1;
// Check that BigInt.asIntN and BigInt.asUintN either return correct results or
// throw RangeErrors for large |bits| arguments. GMP uses a type equivalent to
// 'unsigned long' for bit counts, which may be too small to represent all JS
// integer indexes.
for (let bits of [UINT32_MAX-1, UINT32_MAX, UINT32_MAX+1, Number.MAX_SAFE_INTEGER]) {
test(() => BigInt.asIntN(bits, 1n), 1n);
test(() => BigInt.asIntN(bits, 0n), 0n);
test(() => BigInt.asIntN(bits, -1n), -1n);
test(() => BigInt.asUintN(bits, 1n), 1n);
test(() => BigInt.asUintN(bits, 0n), 0n);
// Skip testing asUintN with negative BigInts since it could OOM.
}
reportCompare(true, true);

View File

@ -6,11 +6,8 @@
#include "vm/BigIntType.h"
#include "mozilla/Casting.h"
#include "mozilla/CheckedInt.h"
#include "mozilla/FloatingPoint.h"
#include "mozilla/HashFunctions.h"
#include "mozilla/MathAlgorithms.h"
#include "mozilla/Maybe.h"
#include "mozilla/Range.h"
#include "mozilla/RangedPtr.h"
@ -30,9 +27,6 @@
using namespace js;
using mozilla::Abs;
using mozilla::BitwiseCast;
using mozilla::CheckedInt;
using mozilla::Maybe;
using mozilla::Some;
using mozilla::Nothing;
@ -139,35 +133,6 @@ BigInt::createFromBytes(JSContext* cx, int sign, void* bytes, size_t nbytes)
return x;
}
BigInt*
BigInt::createFromInt64(JSContext* cx, int64_t n)
{
BigInt* res = createFromUint64(cx, Abs(n));
if (!res) {
return nullptr;
}
if (n < 0) {
mpz_neg(res->num_, res->num_);
}
return res;
}
BigInt*
BigInt::createFromUint64(JSContext* cx, uint64_t n)
{
BigInt* res = create(cx);
if (!res) {
return nullptr;
}
// cf. mpz_import parameters in createFromBytes, above.
mpz_import(res->num_, 1, 1, sizeof(uint64_t), 0, 0, &n);
return res;
}
// BigInt proposal section 5.1.1
static bool
IsInteger(double d)
@ -423,104 +388,6 @@ BigInt::bitNot(JSContext* cx, HandleBigInt x)
return z;
}
int64_t
BigInt::toInt64(BigInt* x)
{
return BitwiseCast<int64_t>(toUint64(x));
}
uint64_t
BigInt::toUint64(BigInt* x)
{
static_assert(GMP_LIMB_BITS == 32 || GMP_LIMB_BITS == 64,
"limbs must be either 32 or 64 bits");
uint64_t digit;
if (GMP_LIMB_BITS == 32) {
uint64_t lo = mpz_getlimbn(x->num_, 0);
uint64_t hi = mpz_getlimbn(x->num_, 1);
digit = hi << 32 | lo;
} else {
digit = mpz_getlimbn(x->num_, 0);
}
// Return the two's complement if x is negative.
if (mpz_sgn(x->num_) < 0) {
return ~(digit - 1);
}
return digit;
}
BigInt*
BigInt::asUintN(JSContext* cx, HandleBigInt x, uint64_t bits)
{
if (bits == 64) {
return createFromUint64(cx, toUint64(x));
}
if (bits == 0) {
return create(cx);
}
// Throw a RangeError if the bits argument is too large to represent using a
// GMP bit count.
CheckedInt<mp_bitcnt_t> bitCount = bits;
if (!bitCount.isValid()) {
JS_ReportErrorNumberASCII(cx, GetErrorMessage, nullptr,
JSMSG_BIGINT_TOO_LARGE);
return nullptr;
}
BigInt* res = create(cx);
if (!res) {
return nullptr;
}
mpz_fdiv_r_2exp(res->num_, x->num_, bitCount.value());
return res;
}
BigInt*
BigInt::asIntN(JSContext* cx, HandleBigInt x, uint64_t bits)
{
if (bits == 64) {
return createFromInt64(cx, toInt64(x));
}
if (bits == 0) {
return create(cx);
}
// Throw a RangeError if the bits argument is too large to represent using a
// GMP bit count.
CheckedInt<mp_bitcnt_t> bitCount = bits;
if (!bitCount.isValid()) {
JS_ReportErrorNumberASCII(cx, GetErrorMessage, nullptr,
JSMSG_BIGINT_TOO_LARGE);
return nullptr;
}
CheckedInt<mp_bitcnt_t> bitIndex = bitCount - 1;
MOZ_ASSERT(bitIndex.isValid());
BigInt* res = create(cx);
if (!res) {
return nullptr;
}
// Choose the rounding mode based on x's sign bit. mpz_tstbit will simulate
// sign extension if the requested index is larger than the bit length of x.
if (mpz_tstbit(x->num_, bitIndex.value())) {
mpz_cdiv_r_2exp(res->num_, x->num_, bitCount.value());
} else {
mpz_fdiv_r_2exp(res->num_, x->num_, bitCount.value());
}
return res;
}
static bool
ValidBigIntOperands(JSContext* cx, HandleValue lhs, HandleValue rhs)
{

View File

@ -61,9 +61,6 @@ class BigInt final : public js::gc::TenuredCell
// Read a BigInt value from a little-endian byte array.
static BigInt* createFromBytes(JSContext* cx, int sign, void* bytes, size_t nbytes);
static BigInt* createFromInt64(JSContext* cx, int64_t n);
static BigInt* createFromUint64(JSContext* cx, uint64_t n);
static const JS::TraceKind TraceKind = JS::TraceKind::BigInt;
void traceChildren(JSTracer* trc);
@ -94,12 +91,6 @@ class BigInt final : public js::gc::TenuredCell
static BigInt* bitOr(JSContext* cx, Handle<BigInt*> x, Handle<BigInt*> y);
static BigInt* bitNot(JSContext* cx, Handle<BigInt*> x);
static int64_t toInt64(BigInt* x);
static uint64_t toUint64(BigInt* x);
static BigInt* asIntN(JSContext* cx, HandleBigInt x, uint64_t bits);
static BigInt* asUintN(JSContext* cx, HandleBigInt x, uint64_t bits);
// Type-checking versions of arithmetic operations. These methods
// must be called with at least one BigInt operand. Binary
// operations with throw a TypeError if one of the operands is not a