mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-10-24 02:35:41 +00:00
Backed out changeset 64b039293b0a (bug 1501104) for causing SM bustages on non262/BigInt/large-bit-length.js.
This commit is contained in:
parent
ed43e261f7
commit
2726d7f95e
@ -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
|
||||
};
|
||||
|
@ -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*
|
||||
|
@ -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);
|
@ -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)
|
||||
{
|
||||
|
@ -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
|
||||
|
Loading…
Reference in New Issue
Block a user