Commit c4b44d5d authored by Jakob Kummerow's avatar Jakob Kummerow Committed by Commit Bot

[bigint] Begin src/bigint refactoring

This patch moves a first function, Compare, from src/objects/bigint.cc
to src/bigint/, to blaze the trail. More to follow!

Bug: v8:11515
Change-Id: Id7fa0b40ea852dbed1360f7ab439cb32d0c15762
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/2737295Reviewed-by: 's avatarThibaud Michaud <thibaudm@chromium.org>
Reviewed-by: 's avatarHannes Payer <hpayer@chromium.org>
Commit-Queue: Jakob Kummerow <jkummerow@chromium.org>
Cr-Commit-Position: refs/heads/master@{#73511}
parent 0ee6f90a
...@@ -4261,6 +4261,7 @@ v8_source_set("v8_base_without_compiler") { ...@@ -4261,6 +4261,7 @@ v8_source_set("v8_base_without_compiler") {
deps = [ deps = [
":torque_generated_definitions", ":torque_generated_definitions",
":v8_bigint",
":v8_cppgc_shared", ":v8_cppgc_shared",
":v8_headers", ":v8_headers",
":v8_libbase", ":v8_libbase",
...@@ -4777,6 +4778,15 @@ v8_source_set("fuzzer_support") { ...@@ -4777,6 +4778,15 @@ v8_source_set("fuzzer_support") {
] ]
} }
v8_source_set("v8_bigint") {
sources = [
"src/bigint/bigint.h",
"src/bigint/vector-arithmetic.cc",
]
configs = [ ":internal_config" ]
}
v8_source_set("v8_cppgc_shared") { v8_source_set("v8_cppgc_shared") {
sources = [ sources = [
"src/heap/base/stack.cc", "src/heap/base/stack.cc",
......
...@@ -6,6 +6,8 @@ include_rules = [ ...@@ -6,6 +6,8 @@ include_rules = [
"-src/baseline", "-src/baseline",
"+src/baseline/baseline.h", "+src/baseline/baseline.h",
"+src/baseline/bytecode-offset-iterator.h", "+src/baseline/bytecode-offset-iterator.h",
"-src/bigint",
"+src/bigint/bigint.h",
"-src/compiler", "-src/compiler",
"+src/compiler/pipeline.h", "+src/compiler/pipeline.h",
"+src/compiler/code-assembler.h", "+src/compiler/code-assembler.h",
......
include_rules = [
# Don't depend on the rest of V8.
"-include",
"-src",
"+src/bigint",
]
specific_include_rules = {
# The public interface should not depend on internals.
"bigint.h": [
"-src/bigint",
],
}
jkummerow@chromium.org
thibaudm@chromium.org
// Copyright 2021 the V8 project authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef V8_BIGINT_BIGINT_H_
#define V8_BIGINT_BIGINT_H_
#include <stdint.h>
#include <algorithm>
#include <iostream>
namespace v8 {
namespace bigint {
// To play nice with embedders' macros, we define our own DCHECK here.
// It's only used in this file, and undef'ed at the end.
#ifdef DEBUG
#define BIGINT_H_DCHECK(cond) \
if (!(cond)) { \
std::cerr << __FILE__ << ":" << __LINE__ << ": "; \
std::cerr << "Assertion failed: " #cond "\n"; \
abort(); \
}
#else
#define BIGINT_H_DCHECK(cond) (void(0))
#endif
// The type of a digit: a register-width unsigned integer.
using digit_t = uintptr_t;
using signed_digit_t = intptr_t;
#if UINTPTR_MAX == 0xFFFFFFFF
// 32-bit platform.
using twodigit_t = uint64_t;
#define HAVE_TWODIGIT_T 1
static constexpr int kLog2DigitBits = 5;
#elif UINTPTR_MAX == 0xFFFFFFFFFFFFFFFF
// 64-bit platform.
static constexpr int kLog2DigitBits = 6;
#if defined(__SIZEOF_INT128__)
using twodigit_t = __uint128_t;
#define HAVE_TWODIGIT_T 1
#endif // defined(__SIZEOF_INT128__)
#else
#error Unsupported platform.
#endif
static constexpr int kDigitBits = 1 << kLog2DigitBits;
static_assert(kDigitBits == 8 * sizeof(digit_t), "inconsistent type sizes");
// Describes an array of digits, also known as a BigInt. Unsigned.
// Does not own the memory it points at, and only gives read-only access to it.
// Digits are stored in little-endian order.
class Digits {
public:
// This is the constructor intended for public consumption.
Digits(digit_t* mem, int len) : digits_(mem), len_(len) {}
// Provides a "slice" view into another Digits object.
Digits(Digits src, int offset, int len)
: digits_(src.digits_ + offset),
len_(std::max(0, std::min(src.len_ - offset, len))) {
BIGINT_H_DCHECK(offset >= 0);
}
// Alternative way to get a "slice" view into another Digits object.
Digits operator+(int i) {
BIGINT_H_DCHECK(i >= 0 && i <= len_);
return Digits(digits_ + i, len_ - i);
}
// Provides access to individual digits.
digit_t operator[](int i) {
BIGINT_H_DCHECK(i >= 0 && i < len_);
return digits_[i];
}
// Convenience accessor for the most significant digit.
digit_t msd() {
BIGINT_H_DCHECK(len_ > 0);
return digits_[len_ - 1];
}
// Checks "pointer equality" (does not compare digits contents).
bool operator==(const Digits& other) const {
return digits_ == other.digits_ && len_ == other.len_;
}
// Decrements {len_} until there are no leading zero digits left.
void Normalize() {
while (len_ > 0 && digits_[len_ - 1] == 0) len_--;
}
// Unconditionally drops exactly one leading zero digit.
void TrimOne() {
BIGINT_H_DCHECK(len_ > 0 && digits_[len_ - 1] == 0);
len_--;
}
int len() { return len_; }
const digit_t* digits() const { return digits_; }
protected:
friend class TemporaryLeftShift;
digit_t* digits_;
int len_;
};
// Returns r such that r < 0 if A < B; r > 0 if A > B; r == 0 if A == B.
int Compare(Digits A, Digits B);
} // namespace bigint
} // namespace v8
#undef BIGINT_H_DCHECK
#endif // V8_BIGINT_BIGINT_H_
// Copyright 2021 the V8 project authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "src/bigint/bigint.h"
namespace v8 {
namespace bigint {
int Compare(Digits A, Digits B) {
A.Normalize();
B.Normalize();
int diff = A.len() - B.len();
if (diff != 0) return diff;
int i = A.len() - 1;
while (i >= 0 && A[i] == B[i]) i--;
if (i < 0) return 0;
return A[i] > B[i] ? 1 : -1;
}
} // namespace bigint
} // namespace v8
...@@ -19,6 +19,7 @@ ...@@ -19,6 +19,7 @@
#include "src/objects/bigint.h" #include "src/objects/bigint.h"
#include "src/bigint/bigint.h"
#include "src/execution/isolate-inl.h" #include "src/execution/isolate-inl.h"
#include "src/heap/factory.h" #include "src/heap/factory.h"
#include "src/heap/heap-write-barrier-inl.h" #include "src/heap/heap-write-barrier-inl.h"
...@@ -135,10 +136,6 @@ class MutableBigInt : public FreshlyAllocatedBigInt { ...@@ -135,10 +136,6 @@ class MutableBigInt : public FreshlyAllocatedBigInt {
Isolate* isolate, Handle<BigIntBase> x, Handle<BigIntBase> y, Isolate* isolate, Handle<BigIntBase> x, Handle<BigIntBase> y,
MutableBigInt result_storage = MutableBigInt()); MutableBigInt result_storage = MutableBigInt());
static int AbsoluteCompare(Handle<BigIntBase> x, Handle<BigIntBase> y);
static int AbsoluteCompare(BigIntBase x, BigIntBase y);
static void MultiplyAccumulate(Handle<BigIntBase> multiplicand, static void MultiplyAccumulate(Handle<BigIntBase> multiplicand,
digit_t multiplier, digit_t multiplier,
Handle<MutableBigInt> accumulator, Handle<MutableBigInt> accumulator,
...@@ -232,6 +229,9 @@ class MutableBigInt : public FreshlyAllocatedBigInt { ...@@ -232,6 +229,9 @@ class MutableBigInt : public FreshlyAllocatedBigInt {
bool IsMutableBigInt() const { return IsBigInt(); } bool IsMutableBigInt() const { return IsBigInt(); }
static_assert(std::is_same<bigint::digit_t, BigIntBase::digit_t>::value,
"We must be able to call BigInt library functions");
NEVER_READ_ONLY_SPACE NEVER_READ_ONLY_SPACE
OBJECT_CONSTRUCTORS(MutableBigInt, FreshlyAllocatedBigInt); OBJECT_CONSTRUCTORS(MutableBigInt, FreshlyAllocatedBigInt);
...@@ -243,6 +243,15 @@ NEVER_READ_ONLY_SPACE_IMPL(MutableBigInt) ...@@ -243,6 +243,15 @@ NEVER_READ_ONLY_SPACE_IMPL(MutableBigInt)
#include "src/base/platform/wrappers.h" #include "src/base/platform/wrappers.h"
#include "src/objects/object-macros-undef.h" #include "src/objects/object-macros-undef.h"
struct GetDigits : bigint::Digits {
explicit GetDigits(Handle<BigIntBase> bigint) : GetDigits(*bigint) {}
explicit GetDigits(BigIntBase bigint)
: bigint::Digits(
reinterpret_cast<bigint::digit_t*>(
bigint.ptr() + BigIntBase::kDigitsOffset - kHeapObjectTag),
bigint.length()) {}
};
template <typename T, typename Isolate> template <typename T, typename Isolate>
MaybeHandle<T> ThrowBigIntTooBig(Isolate* isolate) { MaybeHandle<T> ThrowBigIntTooBig(Isolate* isolate) {
// If the result of a BigInt computation is truncated to 64 bit, Turbofan // If the result of a BigInt computation is truncated to 64 bit, Turbofan
...@@ -560,7 +569,7 @@ MaybeHandle<BigInt> BigInt::Divide(Isolate* isolate, Handle<BigInt> x, ...@@ -560,7 +569,7 @@ MaybeHandle<BigInt> BigInt::Divide(Isolate* isolate, Handle<BigInt> x,
// 2. Let quotient be the mathematical value of x divided by y. // 2. Let quotient be the mathematical value of x divided by y.
// 3. Return a BigInt representing quotient rounded towards 0 to the next // 3. Return a BigInt representing quotient rounded towards 0 to the next
// integral value. // integral value.
if (MutableBigInt::AbsoluteCompare(x, y) < 0) { if (bigint::Compare(GetDigits(x), GetDigits(y)) < 0) {
return Zero(isolate); return Zero(isolate);
} }
Handle<MutableBigInt> quotient; Handle<MutableBigInt> quotient;
...@@ -590,7 +599,7 @@ MaybeHandle<BigInt> BigInt::Remainder(Isolate* isolate, Handle<BigInt> x, ...@@ -590,7 +599,7 @@ MaybeHandle<BigInt> BigInt::Remainder(Isolate* isolate, Handle<BigInt> x,
} }
// 2. Return the BigInt representing x modulo y. // 2. Return the BigInt representing x modulo y.
// See https://github.com/tc39/proposal-bigint/issues/84 though. // See https://github.com/tc39/proposal-bigint/issues/84 though.
if (MutableBigInt::AbsoluteCompare(x, y) < 0) return x; if (bigint::Compare(GetDigits(x), GetDigits(y)) < 0) return x;
Handle<MutableBigInt> remainder; Handle<MutableBigInt> remainder;
if (y->length() == 1) { if (y->length() == 1) {
digit_t divisor = y->digit(0); digit_t divisor = y->digit(0);
...@@ -622,7 +631,7 @@ MaybeHandle<BigInt> BigInt::Add(Isolate* isolate, Handle<BigInt> x, ...@@ -622,7 +631,7 @@ MaybeHandle<BigInt> BigInt::Add(Isolate* isolate, Handle<BigInt> x,
} }
// x + -y == x - y == -(y - x) // x + -y == x - y == -(y - x)
// -x + y == y - x == -(x - y) // -x + y == y - x == -(x - y)
if (MutableBigInt::AbsoluteCompare(x, y) >= 0) { if (bigint::Compare(GetDigits(x), GetDigits(y)) >= 0) {
return MutableBigInt::AbsoluteSub(isolate, x, y, xsign); return MutableBigInt::AbsoluteSub(isolate, x, y, xsign);
} }
return MutableBigInt::AbsoluteSub(isolate, y, x, !xsign); return MutableBigInt::AbsoluteSub(isolate, y, x, !xsign);
...@@ -638,7 +647,7 @@ MaybeHandle<BigInt> BigInt::Subtract(Isolate* isolate, Handle<BigInt> x, ...@@ -638,7 +647,7 @@ MaybeHandle<BigInt> BigInt::Subtract(Isolate* isolate, Handle<BigInt> x,
} }
// x - y == -(y - x) // x - y == -(y - x)
// (-x) - (-y) == y - x == -(x - y) // (-x) - (-y) == y - x == -(x - y)
if (MutableBigInt::AbsoluteCompare(x, y) >= 0) { if (bigint::Compare(GetDigits(x), GetDigits(y)) >= 0) {
return MutableBigInt::AbsoluteSub(isolate, x, y, xsign); return MutableBigInt::AbsoluteSub(isolate, x, y, xsign);
} }
return MutableBigInt::AbsoluteSub(isolate, y, x, !xsign); return MutableBigInt::AbsoluteSub(isolate, y, x, !xsign);
...@@ -691,7 +700,7 @@ ComparisonResult BigInt::CompareToBigInt(Handle<BigInt> x, Handle<BigInt> y) { ...@@ -691,7 +700,7 @@ ComparisonResult BigInt::CompareToBigInt(Handle<BigInt> x, Handle<BigInt> y) {
bool x_sign = x->sign(); bool x_sign = x->sign();
if (x_sign != y->sign()) return UnequalSign(x_sign); if (x_sign != y->sign()) return UnequalSign(x_sign);
int result = MutableBigInt::AbsoluteCompare(x, y); int result = bigint::Compare(GetDigits(x), GetDigits(y));
if (result > 0) return AbsoluteGreater(x_sign); if (result > 0) return AbsoluteGreater(x_sign);
if (result < 0) return AbsoluteLess(x_sign); if (result < 0) return AbsoluteLess(x_sign);
return ComparisonResult::kEqual; return ComparisonResult::kEqual;
...@@ -1230,7 +1239,7 @@ MaybeHandle<BigInt> MutableBigInt::AbsoluteAdd(Isolate* isolate, ...@@ -1230,7 +1239,7 @@ MaybeHandle<BigInt> MutableBigInt::AbsoluteAdd(Isolate* isolate,
Handle<BigInt> MutableBigInt::AbsoluteSub(Isolate* isolate, Handle<BigInt> x, Handle<BigInt> MutableBigInt::AbsoluteSub(Isolate* isolate, Handle<BigInt> x,
Handle<BigInt> y, bool result_sign) { Handle<BigInt> y, bool result_sign) {
DCHECK(x->length() >= y->length()); DCHECK(x->length() >= y->length());
SLOW_DCHECK(AbsoluteCompare(x, y) >= 0); SLOW_DCHECK(bigint::Compare(GetDigits(x), GetDigits(y)) >= 0);
if (x->is_zero()) { if (x->is_zero()) {
DCHECK(y->is_zero()); DCHECK(y->is_zero());
return x; return x;
...@@ -1440,22 +1449,6 @@ Handle<MutableBigInt> MutableBigInt::AbsoluteXor(Isolate* isolate, ...@@ -1440,22 +1449,6 @@ Handle<MutableBigInt> MutableBigInt::AbsoluteXor(Isolate* isolate,
[](digit_t a, digit_t b) { return a ^ b; }); [](digit_t a, digit_t b) { return a ^ b; });
} }
// Returns a positive value if abs(x) > abs(y), a negative value if
// abs(x) < abs(y), or zero if abs(x) == abs(y).
int MutableBigInt::AbsoluteCompare(Handle<BigIntBase> x, Handle<BigIntBase> y) {
return MutableBigInt::AbsoluteCompare(*x, *y);
}
int MutableBigInt::AbsoluteCompare(BigIntBase x, BigIntBase y) {
DisallowGarbageCollection no_gc;
int diff = x.length() - y.length();
if (diff != 0) return diff;
int i = x.length() - 1;
while (i >= 0 && x.digit(i) == y.digit(i)) i--;
if (i < 0) return 0;
return x.digit(i) > y.digit(i) ? 1 : -1;
}
// Multiplies {multiplicand} with {multiplier} and adds the result to // Multiplies {multiplicand} with {multiplier} and adds the result to
// {accumulator}, starting at {accumulator_index} for the least-significant // {accumulator}, starting at {accumulator_index} for the least-significant
// digit. // digit.
...@@ -2766,7 +2759,7 @@ int32_t MutableBigInt_AbsoluteCompare(Address x_addr, Address y_addr) { ...@@ -2766,7 +2759,7 @@ int32_t MutableBigInt_AbsoluteCompare(Address x_addr, Address y_addr) {
BigInt x = BigInt::cast(Object(x_addr)); BigInt x = BigInt::cast(Object(x_addr));
BigInt y = BigInt::cast(Object(y_addr)); BigInt y = BigInt::cast(Object(y_addr));
return MutableBigInt::AbsoluteCompare(x, y); return bigint::Compare(GetDigits(x), GetDigits(y));
} }
void MutableBigInt_AbsoluteSubAndCanonicalize(Address result_addr, void MutableBigInt_AbsoluteSubAndCanonicalize(Address result_addr,
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment