[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: Ulan Degenbaev <ulan@chromium.org> Reviewed-by: Jakob Kummerow <jkummerow@chromium.org> Cr-Commit-Position: refs/heads/master@{#66105}
This commit is contained in:
parent
e955999356
commit
aa3aaa76b6
@ -453,14 +453,14 @@ struct HandleTraits<Isolate> {
|
||||
template <typename T>
|
||||
using HandleType = Handle<T>;
|
||||
template <typename T>
|
||||
using MaybeHandleType = v8::internal::MaybeHandle<T>;
|
||||
using MaybeHandleType = MaybeHandle<T>;
|
||||
};
|
||||
|
||||
// HiddenFactory exists so Isolate can privately inherit from it without making
|
||||
// Factory's members available to Isolate directly.
|
||||
class V8_EXPORT_PRIVATE HiddenFactory : private Factory {};
|
||||
|
||||
class Isolate final : private HiddenFactory {
|
||||
class V8_EXPORT_PRIVATE Isolate final : private HiddenFactory {
|
||||
// These forward declarations are required to make the friend declarations in
|
||||
// PerIsolateThreadData work on some older versions of gcc.
|
||||
class ThreadDataTable;
|
||||
@ -519,7 +519,7 @@ class Isolate final : private HiddenFactory {
|
||||
|
||||
// Creates Isolate object. Must be used instead of constructing Isolate with
|
||||
// new operator.
|
||||
static V8_EXPORT_PRIVATE Isolate* New(
|
||||
static Isolate* New(
|
||||
IsolateAllocationMode mode = IsolateAllocationMode::kDefault);
|
||||
|
||||
// Deletes Isolate object. Must be used instead of delete operator.
|
||||
@ -623,7 +623,7 @@ class Isolate final : private HiddenFactory {
|
||||
inline void set_pending_exception(Object exception_obj);
|
||||
inline void clear_pending_exception();
|
||||
|
||||
V8_EXPORT_PRIVATE bool AreWasmThreadsEnabled(Handle<Context> context);
|
||||
bool AreWasmThreadsEnabled(Handle<Context> context);
|
||||
|
||||
THREAD_LOCAL_TOP_ADDRESS(Object, pending_exception)
|
||||
|
||||
@ -686,9 +686,9 @@ class Isolate final : private HiddenFactory {
|
||||
return &thread_local_top()->js_entry_sp_;
|
||||
}
|
||||
|
||||
V8_EXPORT_PRIVATE std::vector<MemoryRange>* GetCodePages() const;
|
||||
std::vector<MemoryRange>* GetCodePages() const;
|
||||
|
||||
V8_EXPORT_PRIVATE void SetCodePages(std::vector<MemoryRange>* new_code_pages);
|
||||
void SetCodePages(std::vector<MemoryRange>* new_code_pages);
|
||||
|
||||
// Returns the global object of the current context. It could be
|
||||
// a builtin object, or a JS global object.
|
||||
@ -704,7 +704,7 @@ class Isolate final : private HiddenFactory {
|
||||
// exceptions. If an exception was thrown and not handled by an external
|
||||
// handler the exception is scheduled to be rethrown when we return to running
|
||||
// JavaScript code. If an exception is scheduled true is returned.
|
||||
V8_EXPORT_PRIVATE bool OptionalRescheduleException(bool clear_exception);
|
||||
bool OptionalRescheduleException(bool clear_exception);
|
||||
|
||||
// Push and pop a promise and the current try-catch handler.
|
||||
void PushPromise(Handle<JSObject> promise);
|
||||
@ -729,7 +729,7 @@ class Isolate final : private HiddenFactory {
|
||||
Handle<Object> pending_exception_;
|
||||
};
|
||||
|
||||
V8_EXPORT_PRIVATE void SetCaptureStackTraceForUncaughtExceptions(
|
||||
void SetCaptureStackTraceForUncaughtExceptions(
|
||||
bool capture, int frame_limit, StackTrace::StackTraceOptions options);
|
||||
|
||||
void SetAbortOnUncaughtExceptionCallback(
|
||||
@ -739,8 +739,7 @@ class Isolate final : private HiddenFactory {
|
||||
void PrintCurrentStackTrace(FILE* out);
|
||||
void PrintStack(StringStream* accumulator,
|
||||
PrintStackMode mode = kPrintStackVerbose);
|
||||
V8_EXPORT_PRIVATE void PrintStack(FILE* out,
|
||||
PrintStackMode mode = kPrintStackVerbose);
|
||||
void PrintStack(FILE* out, PrintStackMode mode = kPrintStackVerbose);
|
||||
Handle<String> StackTraceString();
|
||||
// Stores a stack trace in a stack-allocated temporary buffer which will
|
||||
// end up in the minidump for debugging purposes.
|
||||
@ -821,7 +820,7 @@ class Isolate final : private HiddenFactory {
|
||||
};
|
||||
CatchType PredictExceptionCatcher();
|
||||
|
||||
V8_EXPORT_PRIVATE void ScheduleThrow(Object exception);
|
||||
void ScheduleThrow(Object exception);
|
||||
// Re-set pending message, script and positions reported to the TryCatch
|
||||
// back to the TLS for re-use when rethrowing.
|
||||
void RestorePendingMessageFromTryCatch(v8::TryCatch* handler);
|
||||
@ -843,19 +842,18 @@ class Isolate final : private HiddenFactory {
|
||||
bool ComputeLocation(MessageLocation* target);
|
||||
bool ComputeLocationFromException(MessageLocation* target,
|
||||
Handle<Object> exception);
|
||||
V8_EXPORT_PRIVATE bool ComputeLocationFromStackTrace(
|
||||
MessageLocation* target, Handle<Object> exception);
|
||||
bool ComputeLocationFromStackTrace(MessageLocation* target,
|
||||
Handle<Object> exception);
|
||||
|
||||
V8_EXPORT_PRIVATE Handle<JSMessageObject> CreateMessage(
|
||||
Handle<Object> exception, MessageLocation* location);
|
||||
Handle<JSMessageObject> CreateMessage(Handle<Object> exception,
|
||||
MessageLocation* location);
|
||||
|
||||
// Out of resource exception helpers.
|
||||
Object StackOverflow();
|
||||
Object TerminateExecution();
|
||||
void CancelTerminateExecution();
|
||||
|
||||
V8_EXPORT_PRIVATE void RequestInterrupt(InterruptCallback callback,
|
||||
void* data);
|
||||
void RequestInterrupt(InterruptCallback callback, void* data);
|
||||
void InvokeApiInterruptCallbacks();
|
||||
|
||||
// Administration
|
||||
@ -1099,13 +1097,13 @@ class Isolate final : private HiddenFactory {
|
||||
bool IsDead() { return has_fatal_error_; }
|
||||
void SignalFatalError() { has_fatal_error_ = true; }
|
||||
|
||||
V8_EXPORT_PRIVATE bool use_optimizer();
|
||||
bool use_optimizer();
|
||||
|
||||
bool initialized_from_snapshot() { return initialized_from_snapshot_; }
|
||||
|
||||
bool NeedsSourcePositionsForProfiling() const;
|
||||
|
||||
V8_EXPORT_PRIVATE bool NeedsDetailedOptimizedCodeLineInfo() const;
|
||||
bool NeedsDetailedOptimizedCodeLineInfo() const;
|
||||
|
||||
bool is_best_effort_code_coverage() const {
|
||||
return code_coverage_mode() == debug::CoverageMode::kBestEffort;
|
||||
@ -1158,7 +1156,7 @@ class Isolate final : private HiddenFactory {
|
||||
|
||||
DateCache* date_cache() { return date_cache_; }
|
||||
|
||||
V8_EXPORT_PRIVATE void set_date_cache(DateCache* date_cache);
|
||||
void set_date_cache(DateCache* date_cache);
|
||||
|
||||
#ifdef V8_INTL_SUPPORT
|
||||
|
||||
@ -1230,7 +1228,7 @@ class Isolate final : private HiddenFactory {
|
||||
int id() const { return id_; }
|
||||
|
||||
CompilationStatistics* GetTurboStatistics();
|
||||
V8_EXPORT_PRIVATE CodeTracer* GetCodeTracer();
|
||||
CodeTracer* GetCodeTracer();
|
||||
|
||||
void DumpAndResetStats();
|
||||
|
||||
@ -1244,16 +1242,16 @@ class Isolate final : private HiddenFactory {
|
||||
return &debug_execution_mode_;
|
||||
}
|
||||
|
||||
V8_EXPORT_PRIVATE base::RandomNumberGenerator* random_number_generator();
|
||||
base::RandomNumberGenerator* random_number_generator();
|
||||
|
||||
V8_EXPORT_PRIVATE base::RandomNumberGenerator* fuzzer_rng();
|
||||
base::RandomNumberGenerator* fuzzer_rng();
|
||||
|
||||
// Generates a random number that is non-zero when masked
|
||||
// with the provided mask.
|
||||
int GenerateIdentityHash(uint32_t mask);
|
||||
|
||||
// Given an address occupied by a live code object, return that object.
|
||||
V8_EXPORT_PRIVATE Code FindCodeObject(Address a);
|
||||
Code FindCodeObject(Address a);
|
||||
|
||||
int NextOptimizationId() {
|
||||
int id = next_optimization_id_++;
|
||||
@ -1283,8 +1281,7 @@ class Isolate final : private HiddenFactory {
|
||||
Handle<Symbol> SymbolFor(RootIndex dictionary_index, Handle<String> name,
|
||||
bool private_symbol);
|
||||
|
||||
V8_EXPORT_PRIVATE void SetUseCounterCallback(
|
||||
v8::Isolate::UseCounterCallback callback);
|
||||
void SetUseCounterCallback(v8::Isolate::UseCounterCallback callback);
|
||||
void CountUsage(v8::Isolate::UseCounterFeature feature);
|
||||
|
||||
static std::string GetTurboCfgFileName(Isolate* isolate);
|
||||
@ -1322,10 +1319,9 @@ class Isolate final : private HiddenFactory {
|
||||
double timeout_in_ms,
|
||||
AtomicsWaitWakeHandle* stop_handle);
|
||||
|
||||
V8_EXPORT_PRIVATE void SetPromiseHook(PromiseHook hook);
|
||||
V8_EXPORT_PRIVATE void RunPromiseHook(PromiseHookType type,
|
||||
Handle<JSPromise> promise,
|
||||
Handle<Object> parent);
|
||||
void SetPromiseHook(PromiseHook hook);
|
||||
void RunPromiseHook(PromiseHookType type, Handle<JSPromise> promise,
|
||||
Handle<Object> parent);
|
||||
void PromiseHookStateUpdated();
|
||||
|
||||
void AddDetachedContext(Handle<Context> context);
|
||||
@ -1350,14 +1346,14 @@ class Isolate final : private HiddenFactory {
|
||||
// builtins constants table to remain unchanged from build-time.
|
||||
size_t HashIsolateForEmbeddedBlob();
|
||||
|
||||
V8_EXPORT_PRIVATE static const uint8_t* CurrentEmbeddedBlob();
|
||||
V8_EXPORT_PRIVATE static uint32_t CurrentEmbeddedBlobSize();
|
||||
static const uint8_t* CurrentEmbeddedBlob();
|
||||
static uint32_t CurrentEmbeddedBlobSize();
|
||||
static bool CurrentEmbeddedBlobIsBinaryEmbedded();
|
||||
|
||||
// These always return the same result as static methods above, but don't
|
||||
// access the global atomic variable (and thus *might be* slightly faster).
|
||||
V8_EXPORT_PRIVATE const uint8_t* embedded_blob() const;
|
||||
V8_EXPORT_PRIVATE uint32_t embedded_blob_size() const;
|
||||
const uint8_t* embedded_blob() const;
|
||||
uint32_t embedded_blob_size() const;
|
||||
|
||||
void set_array_buffer_allocator(v8::ArrayBuffer::Allocator* allocator) {
|
||||
array_buffer_allocator_ = allocator;
|
||||
@ -1411,13 +1407,12 @@ class Isolate final : private HiddenFactory {
|
||||
|
||||
void SetHostImportModuleDynamicallyCallback(
|
||||
HostImportModuleDynamicallyCallback callback);
|
||||
V8_EXPORT_PRIVATE MaybeHandle<JSPromise>
|
||||
RunHostImportModuleDynamicallyCallback(Handle<Script> referrer,
|
||||
Handle<Object> specifier);
|
||||
MaybeHandle<JSPromise> RunHostImportModuleDynamicallyCallback(
|
||||
Handle<Script> referrer, Handle<Object> specifier);
|
||||
|
||||
void SetHostInitializeImportMetaObjectCallback(
|
||||
HostInitializeImportMetaObjectCallback callback);
|
||||
V8_EXPORT_PRIVATE Handle<JSObject> RunHostInitializeImportMetaObjectCallback(
|
||||
Handle<JSObject> RunHostInitializeImportMetaObjectCallback(
|
||||
Handle<SourceTextModule> module);
|
||||
|
||||
void RegisterEmbeddedFileWriter(EmbeddedFileWriterInterface* writer) {
|
||||
@ -1476,8 +1471,7 @@ class Isolate final : private HiddenFactory {
|
||||
bool allow_atomics_wait() { return allow_atomics_wait_; }
|
||||
|
||||
// Register a finalizer to be called at isolate teardown.
|
||||
V8_EXPORT_PRIVATE void RegisterManagedPtrDestructor(
|
||||
ManagedPtrDestructor* finalizer);
|
||||
void RegisterManagedPtrDestructor(ManagedPtrDestructor* finalizer);
|
||||
|
||||
// Removes a previously-registered shared object finalizer.
|
||||
void UnregisterManagedPtrDestructor(ManagedPtrDestructor* finalizer);
|
||||
@ -1488,8 +1482,7 @@ class Isolate final : private HiddenFactory {
|
||||
}
|
||||
|
||||
wasm::WasmEngine* wasm_engine() const { return wasm_engine_.get(); }
|
||||
V8_EXPORT_PRIVATE void SetWasmEngine(
|
||||
std::shared_ptr<wasm::WasmEngine> engine);
|
||||
void SetWasmEngine(std::shared_ptr<wasm::WasmEngine> engine);
|
||||
|
||||
const v8::Context::BackupIncumbentScope* top_backup_incumbent_scope() const {
|
||||
return top_backup_incumbent_scope_;
|
||||
@ -1499,23 +1492,23 @@ class Isolate final : private HiddenFactory {
|
||||
top_backup_incumbent_scope_ = top_backup_incumbent_scope;
|
||||
}
|
||||
|
||||
V8_EXPORT_PRIVATE void SetIdle(bool is_idle);
|
||||
void SetIdle(bool is_idle);
|
||||
|
||||
// Changing various modes can cause differences in generated bytecode which
|
||||
// interferes with lazy source positions, so this should be called immediately
|
||||
// before such a mode change to ensure that this cannot happen.
|
||||
V8_EXPORT_PRIVATE void CollectSourcePositionsForAllBytecodeArrays();
|
||||
void CollectSourcePositionsForAllBytecodeArrays();
|
||||
|
||||
void AddCodeMemoryChunk(MemoryChunk* chunk);
|
||||
void RemoveCodeMemoryChunk(MemoryChunk* chunk);
|
||||
V8_EXPORT_PRIVATE void AddCodeRange(Address begin, size_t length_in_bytes);
|
||||
void AddCodeRange(Address begin, size_t length_in_bytes);
|
||||
|
||||
private:
|
||||
explicit Isolate(std::unique_ptr<IsolateAllocator> isolate_allocator);
|
||||
~Isolate();
|
||||
|
||||
V8_EXPORT_PRIVATE bool Init(ReadOnlyDeserializer* read_only_deserializer,
|
||||
StartupDeserializer* startup_deserializer);
|
||||
bool Init(ReadOnlyDeserializer* read_only_deserializer,
|
||||
StartupDeserializer* startup_deserializer);
|
||||
|
||||
void CheckIsolateLayout();
|
||||
|
||||
@ -1712,7 +1705,7 @@ class Isolate final : private HiddenFactory {
|
||||
double time_millis_at_init_ = 0;
|
||||
|
||||
#ifdef DEBUG
|
||||
V8_EXPORT_PRIVATE static std::atomic<size_t> non_disposed_isolates_;
|
||||
static std::atomic<size_t> non_disposed_isolates_;
|
||||
|
||||
JSObject::SpillInformation js_spill_information_;
|
||||
#endif
|
||||
@ -1748,7 +1741,7 @@ class Isolate final : private HiddenFactory {
|
||||
// preprocessor defines. Make sure the offsets of these fields agree
|
||||
// between compilation units.
|
||||
#define ISOLATE_FIELD_OFFSET(type, name, ignored) \
|
||||
V8_EXPORT_PRIVATE static const intptr_t name##_debug_offset_;
|
||||
static const intptr_t name##_debug_offset_;
|
||||
ISOLATE_INIT_LIST(ISOLATE_FIELD_OFFSET)
|
||||
ISOLATE_INIT_ARRAY_LIST(ISOLATE_FIELD_OFFSET)
|
||||
#undef ISOLATE_FIELD_OFFSET
|
||||
|
@ -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);
|
||||
|
@ -9,6 +9,7 @@
|
||||
#include <cmath>
|
||||
|
||||
#include "src/common/assert-scope.h"
|
||||
#include "src/execution/off-thread-isolate.h"
|
||||
#include "src/handles/handles.h"
|
||||
#include "src/heap/factory.h"
|
||||
#include "src/numbers/dtoa.h"
|
||||
@ -167,18 +168,29 @@ double InternalStringToIntDouble(Iterator current, EndMark end, bool negative,
|
||||
return std::ldexp(static_cast<double>(negative ? -number : number), exponent);
|
||||
}
|
||||
|
||||
namespace {
|
||||
|
||||
// Subclasses of StringToIntHelper get access to internal state:
|
||||
enum class State { kRunning, kError, kJunk, kEmpty, kZero, kDone };
|
||||
|
||||
enum class Sign { kNegative, kPositive, kNone };
|
||||
|
||||
} // namespace
|
||||
|
||||
// ES6 18.2.5 parseInt(string, radix) (with NumberParseIntHelper subclass);
|
||||
// and BigInt parsing cases from https://tc39.github.io/proposal-bigint/
|
||||
// (with StringToBigIntHelper subclass).
|
||||
template <typename Isolate>
|
||||
class StringToIntHelper {
|
||||
public:
|
||||
StringToIntHelper(Isolate* isolate, Handle<String> subject, int radix)
|
||||
StringToIntHelper(Isolate* isolate, HandleFor<Isolate, String> subject,
|
||||
int radix)
|
||||
: isolate_(isolate), subject_(subject), radix_(radix) {
|
||||
DCHECK(subject->IsFlat());
|
||||
}
|
||||
|
||||
// Used for the StringToBigInt operation.
|
||||
StringToIntHelper(Isolate* isolate, Handle<String> subject)
|
||||
StringToIntHelper(Isolate* isolate, HandleFor<Isolate, String> subject)
|
||||
: isolate_(isolate), subject_(subject) {
|
||||
DCHECK(subject->IsFlat());
|
||||
}
|
||||
@ -225,11 +237,6 @@ class StringToIntHelper {
|
||||
return subject_->GetFlatContent(no_gc).ToUC16Vector();
|
||||
}
|
||||
|
||||
// Subclasses get access to internal state:
|
||||
enum State { kRunning, kError, kJunk, kEmpty, kZero, kDone };
|
||||
|
||||
enum class Sign { kNegative, kPositive, kNone };
|
||||
|
||||
Isolate* isolate() { return isolate_; }
|
||||
int radix() { return radix_; }
|
||||
int cursor() { return cursor_; }
|
||||
@ -246,7 +253,7 @@ class StringToIntHelper {
|
||||
void ParseInternal(Char start);
|
||||
|
||||
Isolate* isolate_;
|
||||
Handle<String> subject_;
|
||||
HandleFor<Isolate, String> subject_;
|
||||
const uint8_t* raw_one_byte_subject_ = nullptr;
|
||||
int radix_ = 0;
|
||||
int cursor_ = 0;
|
||||
@ -255,10 +262,11 @@ class StringToIntHelper {
|
||||
bool leading_zero_ = false;
|
||||
bool allow_binary_and_octal_prefixes_ = false;
|
||||
bool allow_trailing_junk_ = true;
|
||||
State state_ = kRunning;
|
||||
State state_ = State::kRunning;
|
||||
};
|
||||
|
||||
void StringToIntHelper::ParseInt() {
|
||||
template <typename Isolate>
|
||||
void StringToIntHelper<Isolate>::ParseInt() {
|
||||
{
|
||||
DisallowHeapAllocation no_gc;
|
||||
if (IsOneByte()) {
|
||||
@ -269,10 +277,10 @@ void StringToIntHelper::ParseInt() {
|
||||
DetectRadixInternal(vector.begin(), vector.length());
|
||||
}
|
||||
}
|
||||
if (state_ != kRunning) return;
|
||||
if (state_ != State::kRunning) return;
|
||||
AllocateResult();
|
||||
HandleSpecialCases();
|
||||
if (state_ != kRunning) return;
|
||||
if (state_ != State::kRunning) return;
|
||||
{
|
||||
DisallowHeapAllocation no_gc;
|
||||
if (IsOneByte()) {
|
||||
@ -285,30 +293,31 @@ void StringToIntHelper::ParseInt() {
|
||||
ParseInternal(vector.begin());
|
||||
}
|
||||
}
|
||||
DCHECK_NE(state_, kRunning);
|
||||
DCHECK_NE(state_, State::kRunning);
|
||||
}
|
||||
|
||||
template <typename Isolate>
|
||||
template <class Char>
|
||||
void StringToIntHelper::DetectRadixInternal(Char current, int length) {
|
||||
void StringToIntHelper<Isolate>::DetectRadixInternal(Char current, int length) {
|
||||
Char start = current;
|
||||
length_ = length;
|
||||
Char end = start + length;
|
||||
|
||||
if (!AdvanceToNonspace(¤t, end)) {
|
||||
return set_state(kEmpty);
|
||||
return set_state(State::kEmpty);
|
||||
}
|
||||
|
||||
if (*current == '+') {
|
||||
// Ignore leading sign; skip following spaces.
|
||||
++current;
|
||||
if (current == end) {
|
||||
return set_state(kJunk);
|
||||
return set_state(State::kJunk);
|
||||
}
|
||||
sign_ = Sign::kPositive;
|
||||
} else if (*current == '-') {
|
||||
++current;
|
||||
if (current == end) {
|
||||
return set_state(kJunk);
|
||||
return set_state(State::kJunk);
|
||||
}
|
||||
sign_ = Sign::kNegative;
|
||||
}
|
||||
@ -318,21 +327,21 @@ void StringToIntHelper::DetectRadixInternal(Char current, int length) {
|
||||
radix_ = 10;
|
||||
if (*current == '0') {
|
||||
++current;
|
||||
if (current == end) return set_state(kZero);
|
||||
if (current == end) return set_state(State::kZero);
|
||||
if (*current == 'x' || *current == 'X') {
|
||||
radix_ = 16;
|
||||
++current;
|
||||
if (current == end) return set_state(kJunk);
|
||||
if (current == end) return set_state(State::kJunk);
|
||||
} else if (allow_binary_and_octal_prefixes_ &&
|
||||
(*current == 'o' || *current == 'O')) {
|
||||
radix_ = 8;
|
||||
++current;
|
||||
if (current == end) return set_state(kJunk);
|
||||
if (current == end) return set_state(State::kJunk);
|
||||
} else if (allow_binary_and_octal_prefixes_ &&
|
||||
(*current == 'b' || *current == 'B')) {
|
||||
radix_ = 2;
|
||||
++current;
|
||||
if (current == end) return set_state(kJunk);
|
||||
if (current == end) return set_state(State::kJunk);
|
||||
} else {
|
||||
leading_zero_ = true;
|
||||
}
|
||||
@ -341,10 +350,10 @@ void StringToIntHelper::DetectRadixInternal(Char current, int length) {
|
||||
if (*current == '0') {
|
||||
// Allow "0x" prefix.
|
||||
++current;
|
||||
if (current == end) return set_state(kZero);
|
||||
if (current == end) return set_state(State::kZero);
|
||||
if (*current == 'x' || *current == 'X') {
|
||||
++current;
|
||||
if (current == end) return set_state(kJunk);
|
||||
if (current == end) return set_state(State::kJunk);
|
||||
} else {
|
||||
leading_zero_ = true;
|
||||
}
|
||||
@ -354,11 +363,11 @@ void StringToIntHelper::DetectRadixInternal(Char current, int length) {
|
||||
while (*current == '0') {
|
||||
leading_zero_ = true;
|
||||
++current;
|
||||
if (current == end) return set_state(kZero);
|
||||
if (current == end) return set_state(State::kZero);
|
||||
}
|
||||
|
||||
if (!leading_zero_ && !isDigit(*current, radix_)) {
|
||||
return set_state(kJunk);
|
||||
return set_state(State::kJunk);
|
||||
}
|
||||
|
||||
DCHECK(radix_ >= 2 && radix_ <= 36);
|
||||
@ -366,8 +375,9 @@ void StringToIntHelper::DetectRadixInternal(Char current, int length) {
|
||||
cursor_ = static_cast<int>(current - start);
|
||||
}
|
||||
|
||||
template <typename Isolate>
|
||||
template <class Char>
|
||||
void StringToIntHelper::ParseInternal(Char start) {
|
||||
void StringToIntHelper<Isolate>::ParseInternal(Char start) {
|
||||
Char current = start + cursor_;
|
||||
Char end = start + length_;
|
||||
|
||||
@ -426,13 +436,13 @@ void StringToIntHelper::ParseInternal(Char start) {
|
||||
} while (!done);
|
||||
|
||||
if (!allow_trailing_junk_ && AdvanceToNonspace(¤t, end)) {
|
||||
return set_state(kJunk);
|
||||
return set_state(State::kJunk);
|
||||
}
|
||||
|
||||
return set_state(kDone);
|
||||
return set_state(State::kDone);
|
||||
}
|
||||
|
||||
class NumberParseIntHelper : public StringToIntHelper {
|
||||
class NumberParseIntHelper : public StringToIntHelper<Isolate> {
|
||||
public:
|
||||
NumberParseIntHelper(Isolate* isolate, Handle<String> string, int radix)
|
||||
: StringToIntHelper(isolate, string, radix) {}
|
||||
@ -440,15 +450,15 @@ class NumberParseIntHelper : public StringToIntHelper {
|
||||
double GetResult() {
|
||||
ParseInt();
|
||||
switch (state()) {
|
||||
case kJunk:
|
||||
case kEmpty:
|
||||
case State::kJunk:
|
||||
case State::kEmpty:
|
||||
return JunkStringValue();
|
||||
case kZero:
|
||||
case State::kZero:
|
||||
return SignedZero(negative());
|
||||
case kDone:
|
||||
case State::kDone:
|
||||
return negative() ? -result_ : result_;
|
||||
case kError:
|
||||
case kRunning:
|
||||
case State::kError:
|
||||
case State::kRunning:
|
||||
break;
|
||||
}
|
||||
UNREACHABLE();
|
||||
@ -476,7 +486,7 @@ class NumberParseIntHelper : public StringToIntHelper {
|
||||
result_ = is_power_of_two ? HandlePowerOfTwoCase(vector.begin())
|
||||
: HandleBaseTenCase(vector.begin());
|
||||
}
|
||||
set_state(kDone);
|
||||
set_state(State::kDone);
|
||||
}
|
||||
|
||||
template <class Char>
|
||||
@ -825,59 +835,50 @@ double StringToInt(Isolate* isolate, Handle<String> string, int radix) {
|
||||
return helper.GetResult();
|
||||
}
|
||||
|
||||
class StringToBigIntHelper : public StringToIntHelper {
|
||||
template <typename Isolate>
|
||||
class StringToBigIntHelper : public StringToIntHelper<Isolate> {
|
||||
public:
|
||||
enum class Behavior { kStringToBigInt, kLiteral };
|
||||
|
||||
// Used for StringToBigInt operation (BigInt constructor and == operator).
|
||||
StringToBigIntHelper(Isolate* isolate, Handle<String> string)
|
||||
: StringToIntHelper(isolate, string),
|
||||
StringToBigIntHelper(Isolate* isolate, HandleFor<Isolate, String> string)
|
||||
: StringToIntHelper<Isolate>(isolate, string),
|
||||
behavior_(Behavior::kStringToBigInt) {
|
||||
set_allow_binary_and_octal_prefixes();
|
||||
set_disallow_trailing_junk();
|
||||
this->set_allow_binary_and_octal_prefixes();
|
||||
this->set_disallow_trailing_junk();
|
||||
}
|
||||
|
||||
// Used for parsing BigInt literals, where the input is a buffer of
|
||||
// one-byte ASCII digits, along with an optional radix prefix.
|
||||
StringToBigIntHelper(Isolate* isolate, const uint8_t* string, int length)
|
||||
: StringToIntHelper(isolate, string, length),
|
||||
: StringToIntHelper<Isolate>(isolate, string, length),
|
||||
behavior_(Behavior::kLiteral) {
|
||||
set_allow_binary_and_octal_prefixes();
|
||||
this->set_allow_binary_and_octal_prefixes();
|
||||
}
|
||||
|
||||
MaybeHandle<BigInt> GetResult() {
|
||||
ParseInt();
|
||||
if (behavior_ == Behavior::kStringToBigInt && sign() != Sign::kNone &&
|
||||
radix() != 10) {
|
||||
return MaybeHandle<BigInt>();
|
||||
MaybeHandleFor<Isolate, BigInt> GetResult() {
|
||||
this->ParseInt();
|
||||
if (behavior_ == Behavior::kStringToBigInt && this->sign() != Sign::kNone &&
|
||||
this->radix() != 10) {
|
||||
return MaybeHandleFor<Isolate, BigInt>();
|
||||
}
|
||||
if (state() == kEmpty) {
|
||||
if (this->state() == State::kEmpty) {
|
||||
if (behavior_ == Behavior::kStringToBigInt) {
|
||||
set_state(kZero);
|
||||
this->set_state(State::kZero);
|
||||
} else {
|
||||
UNREACHABLE();
|
||||
}
|
||||
}
|
||||
switch (state()) {
|
||||
case kJunk:
|
||||
if (should_throw() == kThrowOnError) {
|
||||
THROW_NEW_ERROR(isolate(),
|
||||
NewSyntaxError(MessageTemplate::kBigIntInvalidString),
|
||||
BigInt);
|
||||
} else {
|
||||
DCHECK_EQ(should_throw(), kDontThrow);
|
||||
return MaybeHandle<BigInt>();
|
||||
}
|
||||
case kZero:
|
||||
return BigInt::Zero(isolate());
|
||||
case kError:
|
||||
DCHECK_EQ(should_throw() == kThrowOnError,
|
||||
isolate()->has_pending_exception());
|
||||
return MaybeHandle<BigInt>();
|
||||
case kDone:
|
||||
return BigInt::Finalize(result_, negative());
|
||||
case kEmpty:
|
||||
case kRunning:
|
||||
switch (this->state()) {
|
||||
case State::kJunk:
|
||||
case State::kError:
|
||||
return MaybeHandleFor<Isolate, BigInt>();
|
||||
case State::kZero:
|
||||
return BigInt::Zero(this->isolate());
|
||||
case State::kDone:
|
||||
return BigInt::Finalize<Isolate>(result_, this->negative());
|
||||
case State::kEmpty:
|
||||
case State::kRunning:
|
||||
break;
|
||||
}
|
||||
UNREACHABLE();
|
||||
@ -889,42 +890,48 @@ class StringToBigIntHelper : public StringToIntHelper {
|
||||
// Conseratively assume that all remaining digits are significant.
|
||||
// Optimization opportunity: Would it makes sense to scan for trailing
|
||||
// junk before allocating the result?
|
||||
int charcount = length() - cursor();
|
||||
int charcount = this->length() - this->cursor();
|
||||
// For literals, we pretenure the allocated BigInt, since it's about
|
||||
// to be stored in the interpreter's constants array.
|
||||
AllocationType allocation = behavior_ == Behavior::kLiteral
|
||||
? AllocationType::kOld
|
||||
: AllocationType::kYoung;
|
||||
MaybeHandle<FreshlyAllocatedBigInt> maybe = BigInt::AllocateFor(
|
||||
isolate(), radix(), charcount, should_throw(), allocation);
|
||||
MaybeHandleFor<Isolate, FreshlyAllocatedBigInt> maybe = BigInt::AllocateFor(
|
||||
this->isolate(), this->radix(), charcount, kDontThrow, allocation);
|
||||
if (!maybe.ToHandle(&result_)) {
|
||||
set_state(kError);
|
||||
this->set_state(State::kError);
|
||||
}
|
||||
}
|
||||
|
||||
void ResultMultiplyAdd(uint32_t multiplier, uint32_t part) override {
|
||||
BigInt::InplaceMultiplyAdd(result_, static_cast<uintptr_t>(multiplier),
|
||||
BigInt::InplaceMultiplyAdd(*result_, static_cast<uintptr_t>(multiplier),
|
||||
static_cast<uintptr_t>(part));
|
||||
}
|
||||
|
||||
private:
|
||||
ShouldThrow should_throw() const { return kDontThrow; }
|
||||
|
||||
Handle<FreshlyAllocatedBigInt> result_;
|
||||
HandleFor<Isolate, FreshlyAllocatedBigInt> result_;
|
||||
Behavior behavior_;
|
||||
};
|
||||
|
||||
MaybeHandle<BigInt> StringToBigInt(Isolate* isolate, Handle<String> string) {
|
||||
string = String::Flatten(isolate, string);
|
||||
StringToBigIntHelper helper(isolate, string);
|
||||
StringToBigIntHelper<Isolate> helper(isolate, string);
|
||||
return helper.GetResult();
|
||||
}
|
||||
|
||||
MaybeHandle<BigInt> BigIntLiteral(Isolate* isolate, const char* string) {
|
||||
StringToBigIntHelper helper(isolate, reinterpret_cast<const uint8_t*>(string),
|
||||
static_cast<int>(strlen(string)));
|
||||
template <typename Isolate>
|
||||
MaybeHandleFor<Isolate, BigInt> BigIntLiteral(Isolate* isolate,
|
||||
const char* string) {
|
||||
StringToBigIntHelper<Isolate> helper(isolate,
|
||||
reinterpret_cast<const uint8_t*>(string),
|
||||
static_cast<int>(strlen(string)));
|
||||
return helper.GetResult();
|
||||
}
|
||||
template EXPORT_TEMPLATE_DEFINE(V8_EXPORT_PRIVATE)
|
||||
MaybeHandle<BigInt> BigIntLiteral(Isolate* isolate, const char* string);
|
||||
template EXPORT_TEMPLATE_DEFINE(V8_EXPORT_PRIVATE)
|
||||
OffThreadHandle<BigInt> BigIntLiteral(OffThreadIsolate* isolate,
|
||||
const char* string);
|
||||
|
||||
const char* DoubleToCString(double v, Vector<char> buffer) {
|
||||
switch (FPCLASSIFY_NAMESPACE::fpclassify(v)) {
|
||||
|
@ -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>();
|
||||
}
|
||||
}
|
||||
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);
|
||||
|
||||
Handle<BigInt> BigInt::Finalize(Handle<FreshlyAllocatedBigInt> x, bool sign) {
|
||||
Handle<MutableBigInt> bigint = MutableBigInt::Cast(x);
|
||||
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;
|
||||
|
Loading…
Reference in New Issue
Block a user