[ubsan] Port BigInt to the new design

Bug: v8:3770
Change-Id: I6ad84a663926fffc9e1acc590c13780c39461274
Reviewed-on: https://chromium-review.googlesource.com/c/1351248
Commit-Queue: Jakob Kummerow <jkummerow@chromium.org>
Reviewed-by: Hannes Payer <hpayer@chromium.org>
Reviewed-by: Adam Klein <adamk@chromium.org>
Cr-Commit-Position: refs/heads/master@{#57952}
This commit is contained in:
Jakob Kummerow 2018-11-29 15:39:32 -08:00 committed by Commit Bot
parent cb62c6ede9
commit 172ab5dcc9
7 changed files with 85 additions and 57 deletions

View File

@ -2313,7 +2313,7 @@ Handle<FreshlyAllocatedBigInt> Factory::NewBigInt(int length,
}
HeapObject* result = AllocateRawWithImmortalMap(BigInt::SizeFor(length),
pretenure, *bigint_map());
FreshlyAllocatedBigInt* bigint = FreshlyAllocatedBigInt::cast(result);
FreshlyAllocatedBigInt bigint = FreshlyAllocatedBigInt::cast(result);
bigint->clear_padding();
return handle(bigint, isolate());
}

View File

@ -34,7 +34,7 @@ class WasmInstanceObject;
#define TYPED_VISITOR_ID_LIST(V) \
V(AllocationSite, AllocationSite*) \
V(BigInt, BigInt*) \
V(BigInt, BigInt) \
V(ByteArray, ByteArray) \
V(BytecodeArray, BytecodeArray) \
V(Cell, Cell*) \

View File

@ -508,11 +508,15 @@ NormalizedMapCache::NormalizedMapCache(Address ptr) : WeakFixedArray(ptr) {
// OBJECT_CONSTRUCTORS_IMPL macro?
}
OBJECT_CONSTRUCTORS_IMPL(BigIntBase, HeapObjectPtr)
OBJECT_CONSTRUCTORS_IMPL(BigInt, BigIntBase)
OBJECT_CONSTRUCTORS_IMPL(FreshlyAllocatedBigInt, BigIntBase)
// ------------------------------------
// Cast operations
CAST_ACCESSOR(AccessorPair)
CAST_ACCESSOR(BigInt)
CAST_ACCESSOR2(BigInt)
CAST_ACCESSOR2(ObjectBoilerplateDescription)
CAST_ACCESSOR(Cell)
CAST_ACCESSOR(ArrayBoilerplateDescription)
@ -1602,7 +1606,7 @@ int HeapObject::SizeFromMap(Map map) const {
reinterpret_cast<const FeedbackVector*>(this)->length());
}
if (instance_type == BIGINT_TYPE) {
return BigInt::SizeFor(reinterpret_cast<const BigInt*>(this)->length());
return BigInt::SizeFor(BigInt::unchecked_cast(this)->length());
}
if (instance_type == PRE_PARSED_SCOPE_DATA_TYPE) {
return PreParsedScopeData::SizeFor(
@ -2063,9 +2067,9 @@ bool ScopeInfo::HasSimpleParameters() const {
FOR_EACH_SCOPE_INFO_NUMERIC_FIELD(FIELD_ACCESSORS)
#undef FIELD_ACCESSORS
FreshlyAllocatedBigInt* FreshlyAllocatedBigInt::cast(Object* object) {
FreshlyAllocatedBigInt FreshlyAllocatedBigInt::cast(Object* object) {
SLOW_DCHECK(object->IsBigInt());
return reinterpret_cast<FreshlyAllocatedBigInt*>(object);
return FreshlyAllocatedBigInt(object->ptr());
}
} // namespace internal

View File

@ -34,8 +34,7 @@ namespace internal {
// Many of the functions in this class use arguments of type {BigIntBase},
// indicating that they will be used in a read-only capacity, and both
// {BigInt} and {MutableBigInt} objects can be passed in.
class MutableBigInt : public FreshlyAllocatedBigInt,
public NeverReadOnlySpaceObject {
class MutableBigInt : public FreshlyAllocatedBigInt {
public:
// Bottleneck for converting MutableBigInts to BigInts.
static MaybeHandle<BigInt> MakeImmutable(MaybeHandle<MutableBigInt> maybe);
@ -58,6 +57,9 @@ class MutableBigInt : public FreshlyAllocatedBigInt,
SLOW_DCHECK(bigint->IsBigInt());
return Handle<MutableBigInt>::cast(bigint);
}
static MutableBigInt unchecked_cast(ObjectPtr o) {
return MutableBigInt(o.ptr());
}
// Internal helpers.
static MaybeHandle<MutableBigInt> BitwiseAnd(Isolate* isolate,
@ -82,7 +84,7 @@ class MutableBigInt : public FreshlyAllocatedBigInt,
Handle<BigInt> y, bool result_sign);
static MaybeHandle<MutableBigInt> AbsoluteAddOne(
Isolate* isolate, Handle<BigIntBase> x, bool sign,
MutableBigInt* result_storage = nullptr);
MutableBigInt result_storage = MutableBigInt());
static Handle<MutableBigInt> AbsoluteSubOne(Isolate* isolate,
Handle<BigIntBase> x);
static MaybeHandle<MutableBigInt> AbsoluteSubOne(Isolate* isolate,
@ -93,21 +95,21 @@ class MutableBigInt : public FreshlyAllocatedBigInt,
enum SymmetricOp { kSymmetric, kNotSymmetric };
static inline Handle<MutableBigInt> AbsoluteBitwiseOp(
Isolate* isolate, Handle<BigIntBase> x, Handle<BigIntBase> y,
MutableBigInt* result_storage, ExtraDigitsHandling extra_digits,
MutableBigInt result_storage, ExtraDigitsHandling extra_digits,
SymmetricOp symmetric,
const std::function<digit_t(digit_t, digit_t)>& op);
static Handle<MutableBigInt> AbsoluteAnd(
Isolate* isolate, Handle<BigIntBase> x, Handle<BigIntBase> y,
MutableBigInt* result_storage = nullptr);
MutableBigInt result_storage = MutableBigInt());
static Handle<MutableBigInt> AbsoluteAndNot(
Isolate* isolate, Handle<BigIntBase> x, Handle<BigIntBase> y,
MutableBigInt* result_storage = nullptr);
MutableBigInt result_storage = MutableBigInt());
static Handle<MutableBigInt> AbsoluteOr(
Isolate* isolate, Handle<BigIntBase> x, Handle<BigIntBase> y,
MutableBigInt* result_storage = nullptr);
MutableBigInt result_storage = MutableBigInt());
static Handle<MutableBigInt> AbsoluteXor(
Isolate* isolate, Handle<BigIntBase> x, Handle<BigIntBase> y,
MutableBigInt* result_storage = nullptr);
MutableBigInt result_storage = MutableBigInt());
static int AbsoluteCompare(Handle<BigIntBase> x, Handle<BigIntBase> y);
@ -115,9 +117,8 @@ class MutableBigInt : public FreshlyAllocatedBigInt,
digit_t multiplier,
Handle<MutableBigInt> accumulator,
int accumulator_index);
static void InternalMultiplyAdd(BigIntBase* source, digit_t factor,
digit_t summand, int n,
MutableBigInt* result);
static void InternalMultiplyAdd(BigIntBase source, digit_t factor,
digit_t summand, int n, MutableBigInt result);
void InplaceMultiplyAdd(uintptr_t factor, uintptr_t summand);
// Specialized helpers for Divide/Remainder.
@ -167,7 +168,7 @@ class MutableBigInt : public FreshlyAllocatedBigInt,
// Returns the least significant 64 bits, simulating two's complement
// representation.
static uint64_t GetRawBits(BigIntBase* x, bool* lossless);
static uint64_t GetRawBits(BigIntBase x, bool* lossless);
// Digit arithmetic helpers.
static inline digit_t digit_add(digit_t a, digit_t b, digit_t* carry);
@ -201,11 +202,21 @@ class MutableBigInt : public FreshlyAllocatedBigInt,
Address address = FIELD_ADDR(this, kDigitsOffset + n * kDigitSize);
(*reinterpret_cast<digit_t*>(address)) = value;
}
#include "src/objects/object-macros-undef.h"
void set_64_bits(uint64_t bits);
bool IsMutableBigInt() const { return IsBigInt(); }
NEVER_READ_ONLY_SPACE
OBJECT_CONSTRUCTORS(MutableBigInt, FreshlyAllocatedBigInt)
};
OBJECT_CONSTRUCTORS_IMPL(MutableBigInt, FreshlyAllocatedBigInt)
NEVER_READ_ONLY_SPACE_IMPL(MutableBigInt)
#include "src/objects/object-macros-undef.h"
MaybeHandle<MutableBigInt> MutableBigInt::New(Isolate* isolate, int length,
PretenureFlag pretenure) {
if (length > BigInt::kMaxLength) {
@ -318,9 +329,8 @@ Handle<MutableBigInt> MutableBigInt::Copy(Isolate* isolate,
}
void MutableBigInt::InitializeDigits(int length, byte value) {
memset(reinterpret_cast<void*>(reinterpret_cast<Address>(this) +
kDigitsOffset - kHeapObjectTag),
value, length * kDigitSize);
memset(reinterpret_cast<void*>(ptr() + kDigitsOffset - kHeapObjectTag), value,
length * kDigitSize);
}
MaybeHandle<BigInt> MutableBigInt::MakeImmutable(
@ -623,7 +633,7 @@ ComparisonResult BigInt::CompareToBigInt(Handle<BigInt> x, Handle<BigInt> y) {
return ComparisonResult::kEqual;
}
bool BigInt::EqualToBigInt(BigInt* x, BigInt* y) {
bool BigInt::EqualToBigInt(BigInt x, BigInt y) {
if (x->sign() != y->sign()) return false;
if (x->length() != y->length()) return false;
for (int i = 0; i < x->length(); i++) {
@ -1173,7 +1183,7 @@ Handle<BigInt> MutableBigInt::AbsoluteSub(Isolate* isolate, Handle<BigInt> x,
// modification.
MaybeHandle<MutableBigInt> MutableBigInt::AbsoluteAddOne(
Isolate* isolate, Handle<BigIntBase> x, bool sign,
MutableBigInt* result_storage) {
MutableBigInt result_storage) {
int input_length = x->length();
// The addition will overflow into a new digit if all existing digits are
// at maximum.
@ -1186,7 +1196,7 @@ MaybeHandle<MutableBigInt> MutableBigInt::AbsoluteAddOne(
}
int result_length = input_length + will_overflow;
Handle<MutableBigInt> result(result_storage, isolate);
if (result_storage == nullptr) {
if (result_storage.is_null()) {
if (!New(isolate, result_length).ToHandle(&result)) {
return MaybeHandle<MutableBigInt>();
}
@ -1261,7 +1271,7 @@ MaybeHandle<MutableBigInt> MutableBigInt::AbsoluteSubOne(Isolate* isolate,
// result_storage: [ 0 ][ x3 ][ r2 ][ r1 ][ r0 ]
inline Handle<MutableBigInt> MutableBigInt::AbsoluteBitwiseOp(
Isolate* isolate, Handle<BigIntBase> x, Handle<BigIntBase> y,
MutableBigInt* result_storage, ExtraDigitsHandling extra_digits,
MutableBigInt result_storage, ExtraDigitsHandling extra_digits,
SymmetricOp symmetric, const std::function<digit_t(digit_t, digit_t)>& op) {
int x_length = x->length();
int y_length = y->length();
@ -1276,7 +1286,7 @@ inline Handle<MutableBigInt> MutableBigInt::AbsoluteBitwiseOp(
DCHECK(num_pairs == Min(x_length, y_length));
Handle<MutableBigInt> result(result_storage, isolate);
int result_length = extra_digits == kCopy ? x_length : num_pairs;
if (result_storage == nullptr) {
if (result_storage.is_null()) {
result = New(isolate, result_length).ToHandleChecked();
} else {
DCHECK(result_storage->length() >= result_length);
@ -1300,9 +1310,10 @@ inline Handle<MutableBigInt> MutableBigInt::AbsoluteBitwiseOp(
// If {result_storage} is non-nullptr, it will be used for the result,
// otherwise a new BigInt of appropriate length will be allocated.
// {result_storage} may alias {x} or {y} for in-place modification.
Handle<MutableBigInt> MutableBigInt::AbsoluteAnd(
Isolate* isolate, Handle<BigIntBase> x, Handle<BigIntBase> y,
MutableBigInt* result_storage) {
Handle<MutableBigInt> MutableBigInt::AbsoluteAnd(Isolate* isolate,
Handle<BigIntBase> x,
Handle<BigIntBase> y,
MutableBigInt result_storage) {
return AbsoluteBitwiseOp(isolate, x, y, result_storage, kSkip, kSymmetric,
[](digit_t a, digit_t b) { return a & b; });
}
@ -1312,7 +1323,7 @@ Handle<MutableBigInt> MutableBigInt::AbsoluteAnd(
// {result_storage} may alias {x} or {y} for in-place modification.
Handle<MutableBigInt> MutableBigInt::AbsoluteAndNot(
Isolate* isolate, Handle<BigIntBase> x, Handle<BigIntBase> y,
MutableBigInt* result_storage) {
MutableBigInt result_storage) {
return AbsoluteBitwiseOp(isolate, x, y, result_storage, kCopy, kNotSymmetric,
[](digit_t a, digit_t b) { return a & ~b; });
}
@ -1323,7 +1334,7 @@ Handle<MutableBigInt> MutableBigInt::AbsoluteAndNot(
Handle<MutableBigInt> MutableBigInt::AbsoluteOr(Isolate* isolate,
Handle<BigIntBase> x,
Handle<BigIntBase> y,
MutableBigInt* result_storage) {
MutableBigInt result_storage) {
return AbsoluteBitwiseOp(isolate, x, y, result_storage, kCopy, kSymmetric,
[](digit_t a, digit_t b) { return a | b; });
}
@ -1331,9 +1342,10 @@ Handle<MutableBigInt> MutableBigInt::AbsoluteOr(Isolate* isolate,
// If {result_storage} is non-nullptr, it will be used for the result,
// otherwise a new BigInt of appropriate length will be allocated.
// {result_storage} may alias {x} or {y} for in-place modification.
Handle<MutableBigInt> MutableBigInt::AbsoluteXor(
Isolate* isolate, Handle<BigIntBase> x, Handle<BigIntBase> y,
MutableBigInt* result_storage) {
Handle<MutableBigInt> MutableBigInt::AbsoluteXor(Isolate* isolate,
Handle<BigIntBase> x,
Handle<BigIntBase> y,
MutableBigInt result_storage) {
return AbsoluteBitwiseOp(isolate, x, y, result_storage, kCopy, kSymmetric,
[](digit_t a, digit_t b) { return a ^ b; });
}
@ -1391,9 +1403,9 @@ void MutableBigInt::MultiplyAccumulate(Handle<BigIntBase> multiplicand,
// Multiplies {source} with {factor} and adds {summand} to the result.
// {result} and {source} may be the same BigInt for inplace modification.
void MutableBigInt::InternalMultiplyAdd(BigIntBase* source, digit_t factor,
void MutableBigInt::InternalMultiplyAdd(BigIntBase source, digit_t factor,
digit_t summand, int n,
MutableBigInt* result) {
MutableBigInt result) {
DCHECK(source->length() >= n);
DCHECK(result->length() >= n);
digit_t carry = summand;
@ -1869,8 +1881,8 @@ int BigInt::DigitsByteLengthForBitfield(uint32_t bitfield) {
// The serialization format MUST NOT CHANGE without updating the format
// version in value-serializer.cc!
void BigInt::SerializeDigits(uint8_t* storage) {
void* digits = reinterpret_cast<void*>(reinterpret_cast<Address>(this) +
kDigitsOffset - kHeapObjectTag);
void* digits =
reinterpret_cast<void*>(ptr() + kDigitsOffset - kHeapObjectTag);
#if defined(V8_TARGET_LITTLE_ENDIAN)
int bytelength = length() * kDigitSize;
memcpy(storage, digits, bytelength);
@ -1897,8 +1909,8 @@ MaybeHandle<BigInt> BigInt::FromSerializedDigits(
Handle<MutableBigInt> result =
MutableBigInt::Cast(isolate->factory()->NewBigInt(length, pretenure));
result->initialize_bitfield(sign, length);
void* digits = reinterpret_cast<void*>(reinterpret_cast<Address>(*result) +
kDigitsOffset - kHeapObjectTag);
void* digits =
reinterpret_cast<void*>(result->ptr() + kDigitsOffset - kHeapObjectTag);
#if defined(V8_TARGET_LITTLE_ENDIAN)
memcpy(digits, digits_storage.start(), bytelength);
void* padding_start =
@ -2380,7 +2392,7 @@ void BigInt::ToWordsArray64(int* sign_bit, int* words64_count,
}
}
uint64_t MutableBigInt::GetRawBits(BigIntBase* x, bool* lossless) {
uint64_t MutableBigInt::GetRawBits(BigIntBase x, bool* lossless) {
if (lossless != nullptr) *lossless = true;
if (x->is_zero()) return 0;
int len = x->length();
@ -2395,14 +2407,14 @@ uint64_t MutableBigInt::GetRawBits(BigIntBase* x, bool* lossless) {
}
int64_t BigInt::AsInt64(bool* lossless) {
uint64_t raw = MutableBigInt::GetRawBits(this, lossless);
uint64_t raw = MutableBigInt::GetRawBits(*this, lossless);
int64_t result = static_cast<int64_t>(raw);
if (lossless != nullptr && (result < 0) != sign()) *lossless = false;
return result;
}
uint64_t BigInt::AsUint64(bool* lossless) {
uint64_t result = MutableBigInt::GetRawBits(this, lossless);
uint64_t result = MutableBigInt::GetRawBits(*this, lossless);
if (lossless != nullptr && sign()) *lossless = false;
return result;
}
@ -2585,7 +2597,7 @@ void MutableBigInt::set_64_bits(uint64_t bits) {
#ifdef OBJECT_PRINT
void BigInt::BigIntPrint(std::ostream& os) {
DisallowHeapAllocation no_gc;
HeapObject::PrintHeader(os, "BigInt");
PrintHeader(os, "BigInt");
int len = length();
os << "\n- length: " << len;
os << "\n- sign: " << sign();

View File

@ -7,6 +7,7 @@
#include "src/globals.h"
#include "src/objects.h"
#include "src/objects/heap-object.h"
#include "src/utils.h"
// Has to be the last include (doesn't have include guards):
@ -21,7 +22,7 @@ class ValueSerializer;
// BigIntBase is just the raw data object underlying a BigInt. Use with care!
// Most code should be using BigInts instead.
class BigIntBase : public HeapObject {
class BigIntBase : public HeapObjectPtr {
public:
inline int length() const {
int32_t bitfield = RELAXED_READ_INT32_FIELD(this, kBitfieldOffset);
@ -34,6 +35,9 @@ class BigIntBase : public HeapObject {
return LengthBits::decode(static_cast<uint32_t>(bitfield));
}
static inline BigIntBase unchecked_cast(ObjectPtr o) {
return bit_cast<BigIntBase>(o);
}
// Increasing kMaxLength will require code changes.
static const int kMaxLengthBits =
kMaxInt - kSystemPointerSize * kBitsPerByte - 1;
@ -86,7 +90,10 @@ class BigIntBase : public HeapObject {
bool is_zero() const { return length() == 0; }
DISALLOW_IMPLICIT_CONSTRUCTORS(BigIntBase);
// Only serves to make macros happy; other code should use IsBigInt.
bool IsBigIntBase() const { return true; }
OBJECT_CONSTRUCTORS(BigIntBase, HeapObjectPtr);
};
class FreshlyAllocatedBigInt : public BigIntBase {
@ -102,7 +109,10 @@ class FreshlyAllocatedBigInt : public BigIntBase {
// (and no explicit operator is provided either).
public:
inline static FreshlyAllocatedBigInt* cast(Object* object);
inline static FreshlyAllocatedBigInt cast(Object* object);
inline static FreshlyAllocatedBigInt unchecked_cast(ObjectPtr o) {
return bit_cast<FreshlyAllocatedBigInt>(o);
}
// Clear uninitialized padding space.
inline void clear_padding() {
@ -114,10 +124,12 @@ class FreshlyAllocatedBigInt : public BigIntBase {
}
private:
DISALLOW_IMPLICIT_CONSTRUCTORS(FreshlyAllocatedBigInt);
// Only serves to make macros happy; other code should use IsBigInt.
bool IsFreshlyAllocatedBigInt() const { return true; }
OBJECT_CONSTRUCTORS(FreshlyAllocatedBigInt, BigIntBase);
};
// UNDER CONSTRUCTION!
// Arbitrary precision integers in JavaScript.
class V8_EXPORT_PRIVATE BigInt : public BigIntBase {
public:
@ -148,7 +160,7 @@ class V8_EXPORT_PRIVATE BigInt : public BigIntBase {
Handle<BigInt> y);
// More convenient version of "bool LessThan(x, y)".
static ComparisonResult CompareToBigInt(Handle<BigInt> x, Handle<BigInt> y);
static bool EqualToBigInt(BigInt* x, BigInt* y);
static bool EqualToBigInt(BigInt x, BigInt y);
static MaybeHandle<BigInt> BitwiseAnd(Isolate* isolate, Handle<BigInt> x,
Handle<BigInt> y);
static MaybeHandle<BigInt> BitwiseXor(Isolate* isolate, Handle<BigInt> x,
@ -189,7 +201,7 @@ class V8_EXPORT_PRIVATE BigInt : public BigIntBase {
int Words64Count();
void ToWordsArray64(int* sign_bit, int* words64_count, uint64_t* words);
DECL_CAST(BigInt)
DECL_CAST2(BigInt)
DECL_VERIFIER(BigInt)
DECL_PRINTER(BigInt)
void BigIntShortPrint(std::ostream& os);
@ -239,7 +251,7 @@ class V8_EXPORT_PRIVATE BigInt : public BigIntBase {
Isolate* isolate, uint32_t bitfield, Vector<const uint8_t> digits_storage,
PretenureFlag pretenure);
DISALLOW_IMPLICIT_CONSTRUCTORS(BigInt);
OBJECT_CONSTRUCTORS(BigInt, BigIntBase);
};
} // namespace internal

View File

@ -265,7 +265,7 @@ void ValueSerializer::WriteTwoByteString(Vector<const uc16> chars) {
WriteRawBytes(chars.begin(), chars.length() * sizeof(uc16));
}
void ValueSerializer::WriteBigIntContents(BigInt* bigint) {
void ValueSerializer::WriteBigIntContents(BigInt bigint) {
uint32_t bitfield = bigint->GetBitfieldForSerialization();
int bytelength = BigInt::DigitsByteLengthForBitfield(bitfield);
WriteVarint<uint32_t>(bitfield);
@ -435,7 +435,7 @@ void ValueSerializer::WriteMutableHeapNumber(MutableHeapNumber* number) {
WriteDouble(number->value());
}
void ValueSerializer::WriteBigInt(BigInt* bigint) {
void ValueSerializer::WriteBigInt(BigInt bigint) {
WriteTag(SerializationTag::kBigInt);
WriteBigIntContents(bigint);
}

View File

@ -110,7 +110,7 @@ class ValueSerializer {
void WriteZigZag(T value);
void WriteOneByteString(Vector<const uint8_t> chars);
void WriteTwoByteString(Vector<const uc16> chars);
void WriteBigIntContents(BigInt* bigint);
void WriteBigIntContents(BigInt bigint);
Maybe<uint8_t*> ReserveRawBytes(size_t bytes);
// Writing V8 objects of various kinds.
@ -118,7 +118,7 @@ class ValueSerializer {
void WriteSmi(Smi smi);
void WriteHeapNumber(HeapNumber* number);
void WriteMutableHeapNumber(MutableHeapNumber* number);
void WriteBigInt(BigInt* bigint);
void WriteBigInt(BigInt bigint);
void WriteString(Handle<String> string);
Maybe<bool> WriteJSReceiver(Handle<JSReceiver> receiver)
V8_WARN_UNUSED_RESULT;