Commit aa3aaa76 authored by Leszek Swirski's avatar Leszek Swirski Committed by Commit Bot

[offthread] OffThreadFactory support for BigInt

This CL templatizes some methods in BigInt on the Isolate type, to allow
BigInts to be allocated off-thread from a BigInt literal.

A necessary side-effect is exporting the Isolate class in its entirety,
to allow it to be used as a specializing type for ' HandleFor' in
unittests.

Bug: chromium:1011762
Change-Id: I768f9e4d46a4532d6818d9a67c13801bc5952e5d
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/2036079
Commit-Queue: Leszek Swirski <leszeks@chromium.org>
Reviewed-by: 's avatarUlan Degenbaev <ulan@chromium.org>
Reviewed-by: 's avatarJakob Kummerow <jkummerow@chromium.org>
Cr-Commit-Position: refs/heads/master@{#66105}
parent e9559993
This diff is collapsed.
......@@ -173,6 +173,19 @@ HandleFor<Impl, String> FactoryBase<Impl>::NewConsString(
return result;
}
template <typename Impl>
HandleFor<Impl, FreshlyAllocatedBigInt> FactoryBase<Impl>::NewBigInt(
int length, AllocationType allocation) {
if (length < 0 || length > BigInt::kMaxLength) {
isolate()->FatalProcessOutOfHeapMemory("invalid BigInt length");
}
HeapObject result = AllocateRawWithImmortalMap(
BigInt::SizeFor(length), allocation, read_only_roots().bigint_map());
FreshlyAllocatedBigInt bigint = FreshlyAllocatedBigInt::cast(result);
bigint.clear_padding();
return handle(bigint, isolate());
}
template <typename Impl>
HandleFor<Impl, SeqOneByteString>
FactoryBase<Impl>::AllocateRawOneByteInternalizedString(int length,
......
......@@ -15,6 +15,7 @@ namespace internal {
class HeapObject;
class SeqOneByteString;
class SeqTwoByteString;
class FreshlyAllocatedBigInt;
template <typename Impl>
class V8_EXPORT_PRIVATE FactoryBase {
......@@ -47,6 +48,11 @@ class V8_EXPORT_PRIVATE FactoryBase {
HandleFor<Impl, String> left, HandleFor<Impl, String> right, int length,
bool one_byte, AllocationType allocation = AllocationType::kYoung);
// Allocates a new BigInt with {length} digits. Only to be used by
// MutableBigInt::New*.
HandleFor<Impl, FreshlyAllocatedBigInt> NewBigInt(
int length, AllocationType allocation = AllocationType::kYoung);
protected:
HeapObject AllocateRawWithImmortalMap(
int size, AllocationType allocation, Map map,
......
......@@ -2071,18 +2071,6 @@ Handle<HeapNumber> Factory::NewHeapNumberForCodeAssembler(double value) {
: NewHeapNumber<AllocationType::kOld>(value);
}
Handle<FreshlyAllocatedBigInt> Factory::NewBigInt(int length,
AllocationType allocation) {
if (length < 0 || length > BigInt::kMaxLength) {
isolate()->heap()->FatalProcessOutOfMemory("invalid BigInt length");
}
HeapObject result = AllocateRawWithImmortalMap(BigInt::SizeFor(length),
allocation, *bigint_map());
FreshlyAllocatedBigInt bigint = FreshlyAllocatedBigInt::cast(result);
bigint.clear_padding();
return handle(bigint, isolate());
}
Handle<JSObject> Factory::NewError(Handle<JSFunction> constructor,
MessageTemplate template_index,
Handle<Object> arg0, Handle<Object> arg1,
......
......@@ -113,7 +113,7 @@ struct HandleTraits<Factory> {
template <typename T>
using HandleType = Handle<T>;
template <typename T>
using MaybeHandleType = v8::internal::MaybeHandle<T>;
using MaybeHandleType = MaybeHandle<T>;
};
// Interface for handle based allocation.
......@@ -556,11 +556,6 @@ class V8_EXPORT_PRIVATE Factory : public FactoryBase<Factory> {
inline Handle<HeapNumber> NewHeapNumberWithHoleNaN();
// Allocates a new BigInt with {length} digits. Only to be used by
// MutableBigInt::New*.
Handle<FreshlyAllocatedBigInt> NewBigInt(
int length, AllocationType allocation = AllocationType::kYoung);
Handle<JSObject> NewArgumentsObject(Handle<JSFunction> callee, int length);
// Allocates and initializes a new JavaScript object based on a
......
......@@ -162,11 +162,6 @@ void OffThreadFactory::Publish(Isolate* isolate) {
}
}
OffThreadHandle<Object> OffThreadFactory::NewInvalidStringLengthError() {
// TODO(leszeks): Implement.
UNREACHABLE();
}
// Hacky method for creating a simple object with a slot pointing to a string.
// TODO(leszeks): Remove once we have full FixedArray support.
OffThreadHandle<FixedArray> OffThreadFactory::StringWrapperForTest(
......
......@@ -7,6 +7,7 @@
#include <map>
#include <vector>
#include "src/base/logging.h"
#include "src/common/globals.h"
#include "src/handles/handles.h"
#include "src/heap/factory-base.h"
......@@ -59,7 +60,12 @@ class V8_EXPORT_PRIVATE OffThreadFactory
void FinishOffThread();
void Publish(Isolate* isolate);
OffThreadHandle<Object> NewInvalidStringLengthError();
// The parser shouldn't allow the OffThreadFactory to get into a state where
// it generates errors.
OffThreadHandle<Object> NewInvalidStringLengthError() { UNREACHABLE(); }
OffThreadHandle<Object> NewRangeError(MessageTemplate template_index) {
UNREACHABLE();
}
OffThreadHandle<FixedArray> StringWrapperForTest(
OffThreadHandle<String> string);
......
This diff is collapsed.
......@@ -5,8 +5,10 @@
#ifndef V8_NUMBERS_CONVERSIONS_H_
#define V8_NUMBERS_CONVERSIONS_H_
#include "src/base/export-template.h"
#include "src/base/logging.h"
#include "src/common/globals.h"
#include "src/handles/handle-for.h"
#include "src/utils/vector.h"
namespace v8 {
......@@ -99,8 +101,10 @@ MaybeHandle<BigInt> StringToBigInt(Isolate* isolate, Handle<String> string);
// 0x -> hex
// 0o -> octal
// 0b -> binary
V8_EXPORT_PRIVATE MaybeHandle<BigInt> BigIntLiteral(Isolate* isolate,
const char* string);
template <typename Isolate>
EXPORT_TEMPLATE_DECLARE(V8_EXPORT_PRIVATE)
MaybeHandleFor<Isolate, BigInt> BigIntLiteral(Isolate* isolate,
const char* string);
const int kDoubleToCStringMinBufferSize = 100;
......
......@@ -20,6 +20,7 @@
#include "src/objects/bigint.h"
#include "src/execution/isolate-inl.h"
#include "src/execution/off-thread-isolate.h"
#include "src/heap/factory.h"
#include "src/heap/heap-write-barrier-inl.h"
#include "src/numbers/conversions.h"
......@@ -44,12 +45,15 @@ class MutableBigInt : public FreshlyAllocatedBigInt {
public:
// Bottleneck for converting MutableBigInts to BigInts.
static MaybeHandle<BigInt> MakeImmutable(MaybeHandle<MutableBigInt> maybe);
static Handle<BigInt> MakeImmutable(Handle<MutableBigInt> result);
template <typename Isolate = v8::internal::Isolate>
static HandleFor<Isolate, BigInt> MakeImmutable(
HandleFor<Isolate, MutableBigInt> result);
static void Canonicalize(MutableBigInt result);
// Allocation helpers.
static MaybeHandle<MutableBigInt> New(
template <typename Isolate>
static MaybeHandleFor<Isolate, MutableBigInt> New(
Isolate* isolate, int length,
AllocationType allocation = AllocationType::kYoung);
static Handle<BigInt> NewFromInt(Isolate* isolate, int value);
......@@ -57,15 +61,21 @@ class MutableBigInt : public FreshlyAllocatedBigInt {
void InitializeDigits(int length, byte value = 0);
static Handle<MutableBigInt> Copy(Isolate* isolate,
Handle<BigIntBase> source);
static Handle<BigInt> Zero(Isolate* isolate) {
template <typename Isolate>
static HandleFor<Isolate, BigInt> Zero(Isolate* isolate) {
// TODO(jkummerow): Consider caching a canonical zero-BigInt.
return MakeImmutable(New(isolate, 0)).ToHandleChecked();
return MakeImmutable<Isolate>(New(isolate, 0).ToHandleChecked());
}
static Handle<MutableBigInt> Cast(Handle<FreshlyAllocatedBigInt> bigint) {
SLOW_DCHECK(bigint->IsBigInt());
return Handle<MutableBigInt>::cast(bigint);
}
static OffThreadHandle<MutableBigInt> Cast(
OffThreadHandle<FreshlyAllocatedBigInt> bigint) {
SLOW_DCHECK(bigint->IsBigInt());
return OffThreadHandle<MutableBigInt>::cast(bigint);
}
static MutableBigInt cast(Object o) {
SLOW_DCHECK(o.IsBigInt());
return MutableBigInt(o.ptr());
......@@ -236,8 +246,8 @@ NEVER_READ_ONLY_SPACE_IMPL(MutableBigInt)
#include "src/objects/object-macros-undef.h"
template <typename T>
MaybeHandle<T> ThrowBigIntTooBig(Isolate* isolate) {
template <typename T, typename Isolate>
MaybeHandleFor<Isolate, T> ThrowBigIntTooBig(Isolate* isolate) {
// If the result of a BigInt computation is truncated to 64 bit, Turbofan
// can sometimes truncate intermediate results already, which can prevent
// those from exceeding the maximum length, effectively preventing a
......@@ -250,12 +260,13 @@ MaybeHandle<T> ThrowBigIntTooBig(Isolate* isolate) {
THROW_NEW_ERROR(isolate, NewRangeError(MessageTemplate::kBigIntTooBig), T);
}
MaybeHandle<MutableBigInt> MutableBigInt::New(Isolate* isolate, int length,
AllocationType allocation) {
template <typename Isolate>
MaybeHandleFor<Isolate, MutableBigInt> MutableBigInt::New(
Isolate* isolate, int length, AllocationType allocation) {
if (length > BigInt::kMaxLength) {
return ThrowBigIntTooBig<MutableBigInt>(isolate);
}
Handle<MutableBigInt> result =
HandleFor<Isolate, MutableBigInt> result =
Cast(isolate->factory()->NewBigInt(length, allocation));
result->initialize_bitfield(false, length);
#if DEBUG
......@@ -367,14 +378,16 @@ void MutableBigInt::InitializeDigits(int length, byte value) {
MaybeHandle<BigInt> MutableBigInt::MakeImmutable(
MaybeHandle<MutableBigInt> maybe) {
Handle<MutableBigInt> result;
if (!maybe.ToHandle(&result)) return MaybeHandle<BigInt>();
HandleFor<Isolate, MutableBigInt> result;
if (!maybe.ToHandle(&result)) return MaybeHandleFor<Isolate, BigInt>();
return MakeImmutable(result);
}
Handle<BigInt> MutableBigInt::MakeImmutable(Handle<MutableBigInt> result) {
template <typename Isolate>
HandleFor<Isolate, BigInt> MutableBigInt::MakeImmutable(
HandleFor<Isolate, MutableBigInt> result) {
MutableBigInt::Canonicalize(*result);
return Handle<BigInt>::cast(result);
return HandleFor<Isolate, BigInt>::cast(result);
}
void MutableBigInt::Canonicalize(MutableBigInt result) {
......@@ -405,9 +418,13 @@ void MutableBigInt::Canonicalize(MutableBigInt result) {
result.digit(result.length() - 1) != 0); // MSD is non-zero.
}
Handle<BigInt> BigInt::Zero(Isolate* isolate) {
template <typename Isolate>
HandleFor<Isolate, BigInt> BigInt::Zero(Isolate* isolate) {
return MutableBigInt::Zero(isolate);
}
template Handle<BigInt> BigInt::Zero<Isolate>(Isolate* isolate);
template OffThreadHandle<BigInt> BigInt::Zero<OffThreadIsolate>(
OffThreadIsolate* isolate);
Handle<BigInt> BigInt::UnaryMinus(Isolate* isolate, Handle<BigInt> x) {
// Special case: There is no -0n.
......@@ -1505,13 +1522,13 @@ void MutableBigInt::InternalMultiplyAdd(BigIntBase source, digit_t factor,
}
// Multiplies {x} with {factor} and then adds {summand} to it.
void BigInt::InplaceMultiplyAdd(Handle<FreshlyAllocatedBigInt> x,
uintptr_t factor, uintptr_t summand) {
void BigInt::InplaceMultiplyAdd(FreshlyAllocatedBigInt x, uintptr_t factor,
uintptr_t summand) {
STATIC_ASSERT(sizeof(factor) == sizeof(digit_t));
STATIC_ASSERT(sizeof(summand) == sizeof(digit_t));
Handle<MutableBigInt> bigint = MutableBigInt::Cast(x);
MutableBigInt::InternalMultiplyAdd(*bigint, factor, summand, bigint->length(),
*bigint);
MutableBigInt bigint = MutableBigInt::cast(x);
MutableBigInt::InternalMultiplyAdd(bigint, factor, summand, bigint.length(),
bigint);
}
// Divides {x} by {divisor}, returning the result in {quotient} and {remainder}.
......@@ -1907,7 +1924,8 @@ constexpr uint8_t kMaxBitsPerChar[] = {
static const int kBitsPerCharTableShift = 5;
static const size_t kBitsPerCharTableMultiplier = 1u << kBitsPerCharTableShift;
MaybeHandle<FreshlyAllocatedBigInt> BigInt::AllocateFor(
template <typename Isolate>
MaybeHandleFor<Isolate, FreshlyAllocatedBigInt> BigInt::AllocateFor(
Isolate* isolate, int radix, int charcount, ShouldThrow should_throw,
AllocationType allocation) {
DCHECK(2 <= radix && radix <= 36);
......@@ -1923,7 +1941,7 @@ MaybeHandle<FreshlyAllocatedBigInt> BigInt::AllocateFor(
// Divide by kDigitsBits, rounding up.
int length = static_cast<int>((bits_min + kDigitBits - 1) / kDigitBits);
if (length <= kMaxLength) {
Handle<MutableBigInt> result =
HandleFor<Isolate, MutableBigInt> result =
MutableBigInt::New(isolate, length, allocation).ToHandleChecked();
result->InitializeDigits(length);
return result;
......@@ -1934,16 +1952,31 @@ MaybeHandle<FreshlyAllocatedBigInt> BigInt::AllocateFor(
if (should_throw == kThrowOnError) {
return ThrowBigIntTooBig<FreshlyAllocatedBigInt>(isolate);
} else {
return MaybeHandle<FreshlyAllocatedBigInt>();
return MaybeHandleFor<Isolate, FreshlyAllocatedBigInt>();
}
}
Handle<BigInt> BigInt::Finalize(Handle<FreshlyAllocatedBigInt> x, bool sign) {
Handle<MutableBigInt> bigint = MutableBigInt::Cast(x);
template MaybeHandle<FreshlyAllocatedBigInt> BigInt::AllocateFor<Isolate>(
Isolate* isolate, int radix, int charcount, ShouldThrow should_throw,
AllocationType allocation);
template OffThreadHandle<FreshlyAllocatedBigInt>
BigInt::AllocateFor<OffThreadIsolate>(OffThreadIsolate* isolate, int radix,
int charcount, ShouldThrow should_throw,
AllocationType allocation);
template <typename Isolate>
HandleFor<Isolate, BigInt> BigInt::Finalize(
HandleFor<Isolate, FreshlyAllocatedBigInt> x, bool sign) {
HandleFor<Isolate, MutableBigInt> bigint =
HandleFor<Isolate, MutableBigInt>::cast(x);
bigint->set_sign(sign);
return MutableBigInt::MakeImmutable(bigint);
return MutableBigInt::MakeImmutable<Isolate>(bigint);
}
template Handle<BigInt> BigInt::Finalize<Isolate>(
Handle<FreshlyAllocatedBigInt>, bool);
template OffThreadHandle<BigInt> BigInt::Finalize<OffThreadIsolate>(
OffThreadHandle<FreshlyAllocatedBigInt>, bool);
// The serialization format MUST NOT CHANGE without updating the format
// version in value-serializer.cc!
uint32_t BigInt::GetBitfieldForSerialization() const {
......
......@@ -6,6 +6,7 @@
#define V8_OBJECTS_BIGINT_H_
#include "src/common/globals.h"
#include "src/handles/handle-for.h"
#include "src/objects/objects.h"
#include "src/objects/primitive-heap-object.h"
#include "src/utils/utils.h"
......@@ -238,18 +239,23 @@ class BigInt : public BigIntBase {
class BodyDescriptor;
private:
template <typename Isolate>
friend class StringToBigIntHelper;
friend class ValueDeserializer;
friend class ValueSerializer;
// Special functions for StringToBigIntHelper:
static Handle<BigInt> Zero(Isolate* isolate);
static MaybeHandle<FreshlyAllocatedBigInt> AllocateFor(
template <typename Isolate>
static HandleFor<Isolate, BigInt> Zero(Isolate* isolate);
template <typename Isolate>
static MaybeHandleFor<Isolate, FreshlyAllocatedBigInt> AllocateFor(
Isolate* isolate, int radix, int charcount, ShouldThrow should_throw,
AllocationType allocation);
static void InplaceMultiplyAdd(Handle<FreshlyAllocatedBigInt> x,
uintptr_t factor, uintptr_t summand);
static Handle<BigInt> Finalize(Handle<FreshlyAllocatedBigInt> x, bool sign);
static void InplaceMultiplyAdd(FreshlyAllocatedBigInt x, uintptr_t factor,
uintptr_t summand);
template <typename Isolate>
static HandleFor<Isolate, BigInt> Finalize(
HandleFor<Isolate, FreshlyAllocatedBigInt> x, bool sign);
// Special functions for ValueSerializer/ValueDeserializer:
uint32_t GetBitfieldForSerialization() const;
......
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