Skip to content

Commit 7b4272a

Browse files
devsnekrvagg
authored andcommitted
deps: cherry-pick 477df06 from upstream v8
Original commit message: [API] Expand BigInt API Provide a more complete BigInt API. Bug: v8:7712 Cq-Include-Trybots: luci.chromium.try:linux_chromium_rel_ng Change-Id: Ic8562d616f3125deabdf8b52c7019b191bef0e07 Reviewed-on: chromium-review.googlesource.com/1101198 Commit-Queue: Yang Guo <[email protected]> Reviewed-by: Jakob Kummerow <[email protected]> Reviewed-by: Yang Guo <[email protected]> Cr-Commit-Position: refs/heads/master@{#54122} Backport-PR-URL: #21668 PR-URL: #21644 Reviewed-By: Tiancheng "Timothy" Gu <[email protected]> Reviewed-By: Anna Henningsen <[email protected]>
1 parent a0bf7aa commit 7b4272a

File tree

8 files changed

+271
-1
lines changed

8 files changed

+271
-1
lines changed

common.gypi

+1-1
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@
2929

3030
# Reset this number to 0 on major V8 upgrades.
3131
# Increment by one for each non-official patch applied to deps/v8.
32-
'v8_embedder_string': '-node.6',
32+
'v8_embedder_string': '-node.7',
3333

3434
# Enable disassembler for `--print-code` v8 options
3535
'v8_enable_disassembler': 1,

deps/v8/include/v8.h

+42
Original file line numberDiff line numberDiff line change
@@ -3165,6 +3165,48 @@ class V8_EXPORT Uint32 : public Integer {
31653165
class V8_EXPORT BigInt : public Primitive {
31663166
public:
31673167
static Local<BigInt> New(Isolate* isolate, int64_t value);
3168+
static Local<BigInt> NewFromUnsigned(Isolate* isolate, uint64_t value);
3169+
/**
3170+
* Creates a new BigInt object using a specified sign bit and a
3171+
* specified list of digits/words.
3172+
* The resulting number is calculated as:
3173+
*
3174+
* (-1)^sign_bit * (words[0] * (2^64)^0 + words[1] * (2^64)^1 + ...)
3175+
*/
3176+
static MaybeLocal<BigInt> NewFromWords(Local<Context> context, int sign_bit,
3177+
int word_count, const uint64_t* words);
3178+
3179+
/**
3180+
* Returns the value of this BigInt as an unsigned 64-bit integer.
3181+
* If `lossless` is provided, it will reflect whether the return value was
3182+
* truncated or wrapped around. In particular, it is set to `false` if this
3183+
* BigInt is negative.
3184+
*/
3185+
uint64_t Uint64Value(bool* lossless = nullptr) const;
3186+
3187+
/**
3188+
* Returns the value of this BigInt as a signed 64-bit integer.
3189+
* If `lossless` is provided, it will reflect whether this BigInt was
3190+
* truncated or not.
3191+
*/
3192+
int64_t Int64Value(bool* lossless = nullptr) const;
3193+
3194+
/**
3195+
* Returns the number of 64-bit words needed to store the result of
3196+
* ToWordsArray().
3197+
*/
3198+
int WordCount() const;
3199+
3200+
/**
3201+
* Writes the contents of this BigInt to a specified memory location.
3202+
* `sign_bit` must be provided and will be set to 1 if this BigInt is
3203+
* negative.
3204+
* `*word_count` has to be initialized to the length of the `words` array.
3205+
* Upon return, it will be set to the actual number of words that would
3206+
* be needed to store this BigInt (i.e. the return value of `WordCount()`).
3207+
*/
3208+
void ToWordsArray(int* sign_bit, int* word_count, uint64_t* words) const;
3209+
31683210
V8_INLINE static BigInt* Cast(v8::Value* obj);
31693211

31703212
private:

deps/v8/src/api.cc

+43
Original file line numberDiff line numberDiff line change
@@ -8000,6 +8000,49 @@ Local<BigInt> v8::BigInt::New(Isolate* isolate, int64_t value) {
80008000
return Utils::ToLocal(result);
80018001
}
80028002

8003+
Local<BigInt> v8::BigInt::NewFromUnsigned(Isolate* isolate, uint64_t value) {
8004+
CHECK(i::FLAG_harmony_bigint);
8005+
i::Isolate* internal_isolate = reinterpret_cast<i::Isolate*>(isolate);
8006+
ENTER_V8_NO_SCRIPT_NO_EXCEPTION(internal_isolate);
8007+
i::Handle<i::BigInt> result = i::BigInt::FromUint64(internal_isolate, value);
8008+
return Utils::ToLocal(result);
8009+
}
8010+
8011+
MaybeLocal<BigInt> v8::BigInt::NewFromWords(Local<Context> context,
8012+
int sign_bit, int word_count,
8013+
const uint64_t* words) {
8014+
CHECK(i::FLAG_harmony_bigint);
8015+
i::Isolate* isolate = reinterpret_cast<i::Isolate*>(context->GetIsolate());
8016+
ENTER_V8_NO_SCRIPT(isolate, context, BigInt, NewFromWords,
8017+
MaybeLocal<BigInt>(), InternalEscapableScope);
8018+
i::MaybeHandle<i::BigInt> result =
8019+
i::BigInt::FromWords64(isolate, sign_bit, word_count, words);
8020+
has_pending_exception = result.is_null();
8021+
RETURN_ON_FAILED_EXECUTION(BigInt);
8022+
RETURN_ESCAPED(Utils::ToLocal(result.ToHandleChecked()));
8023+
}
8024+
8025+
uint64_t v8::BigInt::Uint64Value(bool* lossless) const {
8026+
i::Handle<i::BigInt> handle = Utils::OpenHandle(this);
8027+
return handle->AsUint64(lossless);
8028+
}
8029+
8030+
int64_t v8::BigInt::Int64Value(bool* lossless) const {
8031+
i::Handle<i::BigInt> handle = Utils::OpenHandle(this);
8032+
return handle->AsInt64(lossless);
8033+
}
8034+
8035+
int BigInt::WordCount() const {
8036+
i::Handle<i::BigInt> handle = Utils::OpenHandle(this);
8037+
return handle->Words64Count();
8038+
}
8039+
8040+
void BigInt::ToWordsArray(int* sign_bit, int* word_count,
8041+
uint64_t* words) const {
8042+
i::Handle<i::BigInt> handle = Utils::OpenHandle(this);
8043+
return handle->ToWordsArray64(sign_bit, word_count, words);
8044+
}
8045+
80038046
void Isolate::ReportExternalAllocationLimitReached() {
80048047
i::Heap* heap = reinterpret_cast<i::Isolate*>(this)->heap();
80058048
if (heap->gc_state() != i::Heap::NOT_IN_GC) return;

deps/v8/src/api.h

+1
Original file line numberDiff line numberDiff line change
@@ -127,6 +127,7 @@ class RegisteredExtension {
127127
V(Promise, JSPromise) \
128128
V(Primitive, Object) \
129129
V(PrimitiveArray, FixedArray) \
130+
V(BigInt, BigInt) \
130131
V(ScriptOrModule, Script)
131132

132133
class Utils {

deps/v8/src/counters.h

+1
Original file line numberDiff line numberDiff line change
@@ -692,6 +692,7 @@ class RuntimeCallTimer final {
692692
V(ArrayBuffer_New) \
693693
V(Array_CloneElementAt) \
694694
V(Array_New) \
695+
V(BigInt_NewFromWords) \
695696
V(BigInt64Array_New) \
696697
V(BigUint64Array_New) \
697698
V(BigIntObject_New) \

deps/v8/src/objects/bigint.cc

+64
Original file line numberDiff line numberDiff line change
@@ -2259,6 +2259,70 @@ Handle<BigInt> BigInt::FromUint64(Isolate* isolate, uint64_t n) {
22592259
return MutableBigInt::MakeImmutable(result);
22602260
}
22612261

2262+
MaybeHandle<BigInt> BigInt::FromWords64(Isolate* isolate, int sign_bit,
2263+
int words64_count,
2264+
const uint64_t* words) {
2265+
if (words64_count < 0 || words64_count > kMaxLength / (64 / kDigitBits)) {
2266+
THROW_NEW_ERROR(isolate, NewRangeError(MessageTemplate::kBigIntTooBig),
2267+
BigInt);
2268+
}
2269+
if (words64_count == 0) return MutableBigInt::Zero(isolate);
2270+
STATIC_ASSERT(kDigitBits == 64 || kDigitBits == 32);
2271+
int length = (64 / kDigitBits) * words64_count;
2272+
DCHECK_GT(length, 0);
2273+
if (kDigitBits == 32 && words[words64_count - 1] <= (1ULL << 32)) length--;
2274+
2275+
Handle<MutableBigInt> result;
2276+
if (!MutableBigInt::New(isolate, length).ToHandle(&result)) {
2277+
return MaybeHandle<BigInt>();
2278+
}
2279+
2280+
result->set_sign(sign_bit);
2281+
if (kDigitBits == 64) {
2282+
for (int i = 0; i < length; ++i) {
2283+
result->set_digit(i, static_cast<digit_t>(words[i]));
2284+
}
2285+
} else {
2286+
for (int i = 0; i < length; i += 2) {
2287+
digit_t lo = static_cast<digit_t>(words[i / 2]);
2288+
digit_t hi = static_cast<digit_t>(words[i / 2] >> 32);
2289+
result->set_digit(i, lo);
2290+
if (i + 1 < length) result->set_digit(i + 1, hi);
2291+
}
2292+
}
2293+
2294+
return MutableBigInt::MakeImmutable(result);
2295+
}
2296+
2297+
int BigInt::Words64Count() {
2298+
STATIC_ASSERT(kDigitBits == 64 || kDigitBits == 32);
2299+
return length() / (64 / kDigitBits) +
2300+
(kDigitBits == 32 && length() % 2 == 1 ? 1 : 0);
2301+
}
2302+
2303+
void BigInt::ToWordsArray64(int* sign_bit, int* words64_count,
2304+
uint64_t* words) {
2305+
DCHECK_NE(sign_bit, nullptr);
2306+
DCHECK_NE(words64_count, nullptr);
2307+
*sign_bit = sign();
2308+
int available_words = *words64_count;
2309+
*words64_count = Words64Count();
2310+
if (available_words == 0) return;
2311+
DCHECK_NE(words, nullptr);
2312+
2313+
int len = length();
2314+
if (kDigitBits == 64) {
2315+
for (int i = 0; i < len && i < available_words; ++i) words[i] = digit(i);
2316+
} else {
2317+
for (int i = 0; i < len && available_words > 0; i += 2) {
2318+
uint64_t lo = digit(i);
2319+
uint64_t hi = (i + 1) < len ? digit(i + 1) : 0;
2320+
words[i / 2] = lo | (hi << 32);
2321+
available_words--;
2322+
}
2323+
}
2324+
}
2325+
22622326
uint64_t MutableBigInt::GetRawBits(BigIntBase* x, bool* lossless) {
22632327
if (lossless != nullptr) *lossless = true;
22642328
if (x->is_zero()) return 0;

deps/v8/src/objects/bigint.h

+5
Original file line numberDiff line numberDiff line change
@@ -144,8 +144,13 @@ class V8_EXPORT_PRIVATE BigInt : public BigIntBase {
144144

145145
static Handle<BigInt> FromInt64(Isolate* isolate, int64_t n);
146146
static Handle<BigInt> FromUint64(Isolate* isolate, uint64_t n);
147+
static MaybeHandle<BigInt> FromWords64(Isolate* isolate, int sign_bit,
148+
int words64_count,
149+
const uint64_t* words);
147150
int64_t AsInt64(bool* lossless = nullptr);
148151
uint64_t AsUint64(bool* lossless = nullptr);
152+
int Words64Count();
153+
void ToWordsArray64(int* sign_bit, int* words64_count, uint64_t* words);
149154

150155
DECL_CAST(BigInt)
151156
DECL_VERIFIER(BigInt)

deps/v8/test/cctest/test-api.cc

+114
Original file line numberDiff line numberDiff line change
@@ -27805,3 +27805,117 @@ TEST(WasmStreamingAbortNoReject) {
2780527805
streaming.Abort({});
2780627806
CHECK_EQ(streaming.GetPromise()->State(), v8::Promise::kPending);
2780727807
}
27808+
27809+
TEST(BigIntAPI) {
27810+
LocalContext env;
27811+
v8::Isolate* isolate = env->GetIsolate();
27812+
v8::HandleScope scope(isolate);
27813+
bool lossless;
27814+
uint64_t words1[10];
27815+
uint64_t words2[10];
27816+
27817+
{
27818+
Local<Value> bi = CompileRun("12n");
27819+
CHECK(bi->IsBigInt());
27820+
27821+
CHECK_EQ(bi.As<v8::BigInt>()->Uint64Value(), 12);
27822+
CHECK_EQ(bi.As<v8::BigInt>()->Uint64Value(&lossless), 12);
27823+
CHECK_EQ(lossless, true);
27824+
CHECK_EQ(bi.As<v8::BigInt>()->Int64Value(), 12);
27825+
CHECK_EQ(bi.As<v8::BigInt>()->Int64Value(&lossless), 12);
27826+
CHECK_EQ(lossless, true);
27827+
}
27828+
27829+
{
27830+
Local<Value> bi = CompileRun("-12n");
27831+
CHECK(bi->IsBigInt());
27832+
27833+
CHECK_EQ(bi.As<v8::BigInt>()->Uint64Value(), static_cast<uint64_t>(-12));
27834+
CHECK_EQ(bi.As<v8::BigInt>()->Uint64Value(&lossless),
27835+
static_cast<uint64_t>(-12));
27836+
CHECK_EQ(lossless, false);
27837+
CHECK_EQ(bi.As<v8::BigInt>()->Int64Value(), -12);
27838+
CHECK_EQ(bi.As<v8::BigInt>()->Int64Value(&lossless), -12);
27839+
CHECK_EQ(lossless, true);
27840+
}
27841+
27842+
{
27843+
Local<Value> bi = CompileRun("123456789012345678901234567890n");
27844+
CHECK(bi->IsBigInt());
27845+
27846+
CHECK_EQ(bi.As<v8::BigInt>()->Uint64Value(), 14083847773837265618ULL);
27847+
CHECK_EQ(bi.As<v8::BigInt>()->Uint64Value(&lossless),
27848+
14083847773837265618ULL);
27849+
CHECK_EQ(lossless, false);
27850+
CHECK_EQ(bi.As<v8::BigInt>()->Int64Value(), -4362896299872285998LL);
27851+
CHECK_EQ(bi.As<v8::BigInt>()->Int64Value(&lossless),
27852+
-4362896299872285998LL);
27853+
CHECK_EQ(lossless, false);
27854+
}
27855+
27856+
{
27857+
Local<Value> bi = CompileRun("-123456789012345678901234567890n");
27858+
CHECK(bi->IsBigInt());
27859+
27860+
CHECK_EQ(bi.As<v8::BigInt>()->Uint64Value(), 4362896299872285998LL);
27861+
CHECK_EQ(bi.As<v8::BigInt>()->Uint64Value(&lossless),
27862+
4362896299872285998LL);
27863+
CHECK_EQ(lossless, false);
27864+
CHECK_EQ(bi.As<v8::BigInt>()->Int64Value(), 4362896299872285998LL);
27865+
CHECK_EQ(bi.As<v8::BigInt>()->Int64Value(&lossless), 4362896299872285998LL);
27866+
CHECK_EQ(lossless, false);
27867+
}
27868+
27869+
{
27870+
Local<v8::BigInt> bi =
27871+
v8::BigInt::NewFromWords(env.local(), 0, 0, words1).ToLocalChecked();
27872+
CHECK_EQ(bi->Uint64Value(), 0);
27873+
CHECK_EQ(bi->WordCount(), 0);
27874+
}
27875+
27876+
{
27877+
TryCatch try_catch(isolate);
27878+
v8::MaybeLocal<v8::BigInt> bi = v8::BigInt::NewFromWords(
27879+
env.local(), 0, std::numeric_limits<int>::max(), words1);
27880+
CHECK(bi.IsEmpty());
27881+
CHECK(try_catch.HasCaught());
27882+
}
27883+
27884+
{
27885+
TryCatch try_catch(isolate);
27886+
v8::MaybeLocal<v8::BigInt> bi =
27887+
v8::BigInt::NewFromWords(env.local(), 0, -1, words1);
27888+
CHECK(bi.IsEmpty());
27889+
CHECK(try_catch.HasCaught());
27890+
}
27891+
27892+
{
27893+
TryCatch try_catch(isolate);
27894+
v8::MaybeLocal<v8::BigInt> bi =
27895+
v8::BigInt::NewFromWords(env.local(), 0, 1 << 30, words1);
27896+
CHECK(bi.IsEmpty());
27897+
CHECK(try_catch.HasCaught());
27898+
}
27899+
27900+
for (int sign_bit = 0; sign_bit <= 1; sign_bit++) {
27901+
words1[0] = 0xffffffff00000000ULL;
27902+
words1[1] = 0x00000000ffffffffULL;
27903+
v8::Local<v8::BigInt> bi =
27904+
v8::BigInt::NewFromWords(env.local(), sign_bit, 2, words1)
27905+
.ToLocalChecked();
27906+
CHECK_EQ(bi->Uint64Value(&lossless),
27907+
sign_bit ? static_cast<uint64_t>(-static_cast<int64_t>(words1[0]))
27908+
: words1[0]);
27909+
CHECK_EQ(lossless, false);
27910+
CHECK_EQ(bi->Int64Value(&lossless), sign_bit
27911+
? -static_cast<int64_t>(words1[0])
27912+
: static_cast<int64_t>(words1[0]));
27913+
CHECK_EQ(lossless, false);
27914+
CHECK_EQ(bi->WordCount(), 2);
27915+
int real_sign_bit;
27916+
int word_count = arraysize(words2);
27917+
bi->ToWordsArray(&real_sign_bit, &word_count, words2);
27918+
CHECK_EQ(real_sign_bit, sign_bit);
27919+
CHECK_EQ(word_count, 2);
27920+
}
27921+
}

0 commit comments

Comments
 (0)