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
...@@ -453,14 +453,14 @@ struct HandleTraits<Isolate> { ...@@ -453,14 +453,14 @@ struct HandleTraits<Isolate> {
template <typename T> template <typename T>
using HandleType = Handle<T>; using HandleType = Handle<T>;
template <typename 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 // HiddenFactory exists so Isolate can privately inherit from it without making
// Factory's members available to Isolate directly. // Factory's members available to Isolate directly.
class V8_EXPORT_PRIVATE HiddenFactory : private Factory {}; 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 // These forward declarations are required to make the friend declarations in
// PerIsolateThreadData work on some older versions of gcc. // PerIsolateThreadData work on some older versions of gcc.
class ThreadDataTable; class ThreadDataTable;
...@@ -519,7 +519,7 @@ class Isolate final : private HiddenFactory { ...@@ -519,7 +519,7 @@ class Isolate final : private HiddenFactory {
// Creates Isolate object. Must be used instead of constructing Isolate with // Creates Isolate object. Must be used instead of constructing Isolate with
// new operator. // new operator.
static V8_EXPORT_PRIVATE Isolate* New( static Isolate* New(
IsolateAllocationMode mode = IsolateAllocationMode::kDefault); IsolateAllocationMode mode = IsolateAllocationMode::kDefault);
// Deletes Isolate object. Must be used instead of delete operator. // Deletes Isolate object. Must be used instead of delete operator.
...@@ -623,7 +623,7 @@ class Isolate final : private HiddenFactory { ...@@ -623,7 +623,7 @@ class Isolate final : private HiddenFactory {
inline void set_pending_exception(Object exception_obj); inline void set_pending_exception(Object exception_obj);
inline void clear_pending_exception(); 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) THREAD_LOCAL_TOP_ADDRESS(Object, pending_exception)
...@@ -686,9 +686,9 @@ class Isolate final : private HiddenFactory { ...@@ -686,9 +686,9 @@ class Isolate final : private HiddenFactory {
return &thread_local_top()->js_entry_sp_; 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 // Returns the global object of the current context. It could be
// a builtin object, or a JS global object. // a builtin object, or a JS global object.
...@@ -704,7 +704,7 @@ class Isolate final : private HiddenFactory { ...@@ -704,7 +704,7 @@ class Isolate final : private HiddenFactory {
// exceptions. If an exception was thrown and not handled by an external // 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 // handler the exception is scheduled to be rethrown when we return to running
// JavaScript code. If an exception is scheduled true is returned. // 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. // Push and pop a promise and the current try-catch handler.
void PushPromise(Handle<JSObject> promise); void PushPromise(Handle<JSObject> promise);
...@@ -729,7 +729,7 @@ class Isolate final : private HiddenFactory { ...@@ -729,7 +729,7 @@ class Isolate final : private HiddenFactory {
Handle<Object> pending_exception_; Handle<Object> pending_exception_;
}; };
V8_EXPORT_PRIVATE void SetCaptureStackTraceForUncaughtExceptions( void SetCaptureStackTraceForUncaughtExceptions(
bool capture, int frame_limit, StackTrace::StackTraceOptions options); bool capture, int frame_limit, StackTrace::StackTraceOptions options);
void SetAbortOnUncaughtExceptionCallback( void SetAbortOnUncaughtExceptionCallback(
...@@ -739,8 +739,7 @@ class Isolate final : private HiddenFactory { ...@@ -739,8 +739,7 @@ class Isolate final : private HiddenFactory {
void PrintCurrentStackTrace(FILE* out); void PrintCurrentStackTrace(FILE* out);
void PrintStack(StringStream* accumulator, void PrintStack(StringStream* accumulator,
PrintStackMode mode = kPrintStackVerbose); PrintStackMode mode = kPrintStackVerbose);
V8_EXPORT_PRIVATE void PrintStack(FILE* out, void PrintStack(FILE* out, PrintStackMode mode = kPrintStackVerbose);
PrintStackMode mode = kPrintStackVerbose);
Handle<String> StackTraceString(); Handle<String> StackTraceString();
// Stores a stack trace in a stack-allocated temporary buffer which will // Stores a stack trace in a stack-allocated temporary buffer which will
// end up in the minidump for debugging purposes. // end up in the minidump for debugging purposes.
...@@ -821,7 +820,7 @@ class Isolate final : private HiddenFactory { ...@@ -821,7 +820,7 @@ class Isolate final : private HiddenFactory {
}; };
CatchType PredictExceptionCatcher(); CatchType PredictExceptionCatcher();
V8_EXPORT_PRIVATE void ScheduleThrow(Object exception); void ScheduleThrow(Object exception);
// Re-set pending message, script and positions reported to the TryCatch // Re-set pending message, script and positions reported to the TryCatch
// back to the TLS for re-use when rethrowing. // back to the TLS for re-use when rethrowing.
void RestorePendingMessageFromTryCatch(v8::TryCatch* handler); void RestorePendingMessageFromTryCatch(v8::TryCatch* handler);
...@@ -843,19 +842,18 @@ class Isolate final : private HiddenFactory { ...@@ -843,19 +842,18 @@ class Isolate final : private HiddenFactory {
bool ComputeLocation(MessageLocation* target); bool ComputeLocation(MessageLocation* target);
bool ComputeLocationFromException(MessageLocation* target, bool ComputeLocationFromException(MessageLocation* target,
Handle<Object> exception); Handle<Object> exception);
V8_EXPORT_PRIVATE bool ComputeLocationFromStackTrace( bool ComputeLocationFromStackTrace(MessageLocation* target,
MessageLocation* target, Handle<Object> exception); Handle<Object> exception);
V8_EXPORT_PRIVATE Handle<JSMessageObject> CreateMessage( Handle<JSMessageObject> CreateMessage(Handle<Object> exception,
Handle<Object> exception, MessageLocation* location); MessageLocation* location);
// Out of resource exception helpers. // Out of resource exception helpers.
Object StackOverflow(); Object StackOverflow();
Object TerminateExecution(); Object TerminateExecution();
void CancelTerminateExecution(); void CancelTerminateExecution();
V8_EXPORT_PRIVATE void RequestInterrupt(InterruptCallback callback, void RequestInterrupt(InterruptCallback callback, void* data);
void* data);
void InvokeApiInterruptCallbacks(); void InvokeApiInterruptCallbacks();
// Administration // Administration
...@@ -1099,13 +1097,13 @@ class Isolate final : private HiddenFactory { ...@@ -1099,13 +1097,13 @@ class Isolate final : private HiddenFactory {
bool IsDead() { return has_fatal_error_; } bool IsDead() { return has_fatal_error_; }
void SignalFatalError() { has_fatal_error_ = true; } void SignalFatalError() { has_fatal_error_ = true; }
V8_EXPORT_PRIVATE bool use_optimizer(); bool use_optimizer();
bool initialized_from_snapshot() { return initialized_from_snapshot_; } bool initialized_from_snapshot() { return initialized_from_snapshot_; }
bool NeedsSourcePositionsForProfiling() const; bool NeedsSourcePositionsForProfiling() const;
V8_EXPORT_PRIVATE bool NeedsDetailedOptimizedCodeLineInfo() const; bool NeedsDetailedOptimizedCodeLineInfo() const;
bool is_best_effort_code_coverage() const { bool is_best_effort_code_coverage() const {
return code_coverage_mode() == debug::CoverageMode::kBestEffort; return code_coverage_mode() == debug::CoverageMode::kBestEffort;
...@@ -1158,7 +1156,7 @@ class Isolate final : private HiddenFactory { ...@@ -1158,7 +1156,7 @@ class Isolate final : private HiddenFactory {
DateCache* date_cache() { return date_cache_; } 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 #ifdef V8_INTL_SUPPORT
...@@ -1230,7 +1228,7 @@ class Isolate final : private HiddenFactory { ...@@ -1230,7 +1228,7 @@ class Isolate final : private HiddenFactory {
int id() const { return id_; } int id() const { return id_; }
CompilationStatistics* GetTurboStatistics(); CompilationStatistics* GetTurboStatistics();
V8_EXPORT_PRIVATE CodeTracer* GetCodeTracer(); CodeTracer* GetCodeTracer();
void DumpAndResetStats(); void DumpAndResetStats();
...@@ -1244,16 +1242,16 @@ class Isolate final : private HiddenFactory { ...@@ -1244,16 +1242,16 @@ class Isolate final : private HiddenFactory {
return &debug_execution_mode_; 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 // Generates a random number that is non-zero when masked
// with the provided mask. // with the provided mask.
int GenerateIdentityHash(uint32_t mask); int GenerateIdentityHash(uint32_t mask);
// Given an address occupied by a live code object, return that object. // 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 NextOptimizationId() {
int id = next_optimization_id_++; int id = next_optimization_id_++;
...@@ -1283,8 +1281,7 @@ class Isolate final : private HiddenFactory { ...@@ -1283,8 +1281,7 @@ class Isolate final : private HiddenFactory {
Handle<Symbol> SymbolFor(RootIndex dictionary_index, Handle<String> name, Handle<Symbol> SymbolFor(RootIndex dictionary_index, Handle<String> name,
bool private_symbol); bool private_symbol);
V8_EXPORT_PRIVATE void SetUseCounterCallback( void SetUseCounterCallback(v8::Isolate::UseCounterCallback callback);
v8::Isolate::UseCounterCallback callback);
void CountUsage(v8::Isolate::UseCounterFeature feature); void CountUsage(v8::Isolate::UseCounterFeature feature);
static std::string GetTurboCfgFileName(Isolate* isolate); static std::string GetTurboCfgFileName(Isolate* isolate);
...@@ -1322,9 +1319,8 @@ class Isolate final : private HiddenFactory { ...@@ -1322,9 +1319,8 @@ class Isolate final : private HiddenFactory {
double timeout_in_ms, double timeout_in_ms,
AtomicsWaitWakeHandle* stop_handle); AtomicsWaitWakeHandle* stop_handle);
V8_EXPORT_PRIVATE void SetPromiseHook(PromiseHook hook); void SetPromiseHook(PromiseHook hook);
V8_EXPORT_PRIVATE void RunPromiseHook(PromiseHookType type, void RunPromiseHook(PromiseHookType type, Handle<JSPromise> promise,
Handle<JSPromise> promise,
Handle<Object> parent); Handle<Object> parent);
void PromiseHookStateUpdated(); void PromiseHookStateUpdated();
...@@ -1350,14 +1346,14 @@ class Isolate final : private HiddenFactory { ...@@ -1350,14 +1346,14 @@ class Isolate final : private HiddenFactory {
// builtins constants table to remain unchanged from build-time. // builtins constants table to remain unchanged from build-time.
size_t HashIsolateForEmbeddedBlob(); size_t HashIsolateForEmbeddedBlob();
V8_EXPORT_PRIVATE static const uint8_t* CurrentEmbeddedBlob(); static const uint8_t* CurrentEmbeddedBlob();
V8_EXPORT_PRIVATE static uint32_t CurrentEmbeddedBlobSize(); static uint32_t CurrentEmbeddedBlobSize();
static bool CurrentEmbeddedBlobIsBinaryEmbedded(); static bool CurrentEmbeddedBlobIsBinaryEmbedded();
// These always return the same result as static methods above, but don't // These always return the same result as static methods above, but don't
// access the global atomic variable (and thus *might be* slightly faster). // access the global atomic variable (and thus *might be* slightly faster).
V8_EXPORT_PRIVATE const uint8_t* embedded_blob() const; const uint8_t* embedded_blob() const;
V8_EXPORT_PRIVATE uint32_t embedded_blob_size() const; uint32_t embedded_blob_size() const;
void set_array_buffer_allocator(v8::ArrayBuffer::Allocator* allocator) { void set_array_buffer_allocator(v8::ArrayBuffer::Allocator* allocator) {
array_buffer_allocator_ = allocator; array_buffer_allocator_ = allocator;
...@@ -1411,13 +1407,12 @@ class Isolate final : private HiddenFactory { ...@@ -1411,13 +1407,12 @@ class Isolate final : private HiddenFactory {
void SetHostImportModuleDynamicallyCallback( void SetHostImportModuleDynamicallyCallback(
HostImportModuleDynamicallyCallback callback); HostImportModuleDynamicallyCallback callback);
V8_EXPORT_PRIVATE MaybeHandle<JSPromise> MaybeHandle<JSPromise> RunHostImportModuleDynamicallyCallback(
RunHostImportModuleDynamicallyCallback(Handle<Script> referrer, Handle<Script> referrer, Handle<Object> specifier);
Handle<Object> specifier);
void SetHostInitializeImportMetaObjectCallback( void SetHostInitializeImportMetaObjectCallback(
HostInitializeImportMetaObjectCallback callback); HostInitializeImportMetaObjectCallback callback);
V8_EXPORT_PRIVATE Handle<JSObject> RunHostInitializeImportMetaObjectCallback( Handle<JSObject> RunHostInitializeImportMetaObjectCallback(
Handle<SourceTextModule> module); Handle<SourceTextModule> module);
void RegisterEmbeddedFileWriter(EmbeddedFileWriterInterface* writer) { void RegisterEmbeddedFileWriter(EmbeddedFileWriterInterface* writer) {
...@@ -1476,8 +1471,7 @@ class Isolate final : private HiddenFactory { ...@@ -1476,8 +1471,7 @@ class Isolate final : private HiddenFactory {
bool allow_atomics_wait() { return allow_atomics_wait_; } bool allow_atomics_wait() { return allow_atomics_wait_; }
// Register a finalizer to be called at isolate teardown. // Register a finalizer to be called at isolate teardown.
V8_EXPORT_PRIVATE void RegisterManagedPtrDestructor( void RegisterManagedPtrDestructor(ManagedPtrDestructor* finalizer);
ManagedPtrDestructor* finalizer);
// Removes a previously-registered shared object finalizer. // Removes a previously-registered shared object finalizer.
void UnregisterManagedPtrDestructor(ManagedPtrDestructor* finalizer); void UnregisterManagedPtrDestructor(ManagedPtrDestructor* finalizer);
...@@ -1488,8 +1482,7 @@ class Isolate final : private HiddenFactory { ...@@ -1488,8 +1482,7 @@ class Isolate final : private HiddenFactory {
} }
wasm::WasmEngine* wasm_engine() const { return wasm_engine_.get(); } wasm::WasmEngine* wasm_engine() const { return wasm_engine_.get(); }
V8_EXPORT_PRIVATE void SetWasmEngine( void SetWasmEngine(std::shared_ptr<wasm::WasmEngine> engine);
std::shared_ptr<wasm::WasmEngine> engine);
const v8::Context::BackupIncumbentScope* top_backup_incumbent_scope() const { const v8::Context::BackupIncumbentScope* top_backup_incumbent_scope() const {
return top_backup_incumbent_scope_; return top_backup_incumbent_scope_;
...@@ -1499,22 +1492,22 @@ class Isolate final : private HiddenFactory { ...@@ -1499,22 +1492,22 @@ class Isolate final : private HiddenFactory {
top_backup_incumbent_scope_ = top_backup_incumbent_scope; 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 // Changing various modes can cause differences in generated bytecode which
// interferes with lazy source positions, so this should be called immediately // interferes with lazy source positions, so this should be called immediately
// before such a mode change to ensure that this cannot happen. // before such a mode change to ensure that this cannot happen.
V8_EXPORT_PRIVATE void CollectSourcePositionsForAllBytecodeArrays(); void CollectSourcePositionsForAllBytecodeArrays();
void AddCodeMemoryChunk(MemoryChunk* chunk); void AddCodeMemoryChunk(MemoryChunk* chunk);
void RemoveCodeMemoryChunk(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: private:
explicit Isolate(std::unique_ptr<IsolateAllocator> isolate_allocator); explicit Isolate(std::unique_ptr<IsolateAllocator> isolate_allocator);
~Isolate(); ~Isolate();
V8_EXPORT_PRIVATE bool Init(ReadOnlyDeserializer* read_only_deserializer, bool Init(ReadOnlyDeserializer* read_only_deserializer,
StartupDeserializer* startup_deserializer); StartupDeserializer* startup_deserializer);
void CheckIsolateLayout(); void CheckIsolateLayout();
...@@ -1712,7 +1705,7 @@ class Isolate final : private HiddenFactory { ...@@ -1712,7 +1705,7 @@ class Isolate final : private HiddenFactory {
double time_millis_at_init_ = 0; double time_millis_at_init_ = 0;
#ifdef DEBUG #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_; JSObject::SpillInformation js_spill_information_;
#endif #endif
...@@ -1748,7 +1741,7 @@ class Isolate final : private HiddenFactory { ...@@ -1748,7 +1741,7 @@ class Isolate final : private HiddenFactory {
// preprocessor defines. Make sure the offsets of these fields agree // preprocessor defines. Make sure the offsets of these fields agree
// between compilation units. // between compilation units.
#define ISOLATE_FIELD_OFFSET(type, name, ignored) \ #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_LIST(ISOLATE_FIELD_OFFSET)
ISOLATE_INIT_ARRAY_LIST(ISOLATE_FIELD_OFFSET) ISOLATE_INIT_ARRAY_LIST(ISOLATE_FIELD_OFFSET)
#undef ISOLATE_FIELD_OFFSET #undef ISOLATE_FIELD_OFFSET
......
...@@ -173,6 +173,19 @@ HandleFor<Impl, String> FactoryBase<Impl>::NewConsString( ...@@ -173,6 +173,19 @@ HandleFor<Impl, String> FactoryBase<Impl>::NewConsString(
return result; 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> template <typename Impl>
HandleFor<Impl, SeqOneByteString> HandleFor<Impl, SeqOneByteString>
FactoryBase<Impl>::AllocateRawOneByteInternalizedString(int length, FactoryBase<Impl>::AllocateRawOneByteInternalizedString(int length,
......
...@@ -15,6 +15,7 @@ namespace internal { ...@@ -15,6 +15,7 @@ namespace internal {
class HeapObject; class HeapObject;
class SeqOneByteString; class SeqOneByteString;
class SeqTwoByteString; class SeqTwoByteString;
class FreshlyAllocatedBigInt;
template <typename Impl> template <typename Impl>
class V8_EXPORT_PRIVATE FactoryBase { class V8_EXPORT_PRIVATE FactoryBase {
...@@ -47,6 +48,11 @@ class V8_EXPORT_PRIVATE FactoryBase { ...@@ -47,6 +48,11 @@ class V8_EXPORT_PRIVATE FactoryBase {
HandleFor<Impl, String> left, HandleFor<Impl, String> right, int length, HandleFor<Impl, String> left, HandleFor<Impl, String> right, int length,
bool one_byte, AllocationType allocation = AllocationType::kYoung); 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: protected:
HeapObject AllocateRawWithImmortalMap( HeapObject AllocateRawWithImmortalMap(
int size, AllocationType allocation, Map map, int size, AllocationType allocation, Map map,
......
...@@ -2071,18 +2071,6 @@ Handle<HeapNumber> Factory::NewHeapNumberForCodeAssembler(double value) { ...@@ -2071,18 +2071,6 @@ Handle<HeapNumber> Factory::NewHeapNumberForCodeAssembler(double value) {
: NewHeapNumber<AllocationType::kOld>(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, Handle<JSObject> Factory::NewError(Handle<JSFunction> constructor,
MessageTemplate template_index, MessageTemplate template_index,
Handle<Object> arg0, Handle<Object> arg1, Handle<Object> arg0, Handle<Object> arg1,
......
...@@ -113,7 +113,7 @@ struct HandleTraits<Factory> { ...@@ -113,7 +113,7 @@ struct HandleTraits<Factory> {
template <typename T> template <typename T>
using HandleType = Handle<T>; using HandleType = Handle<T>;
template <typename T> template <typename T>
using MaybeHandleType = v8::internal::MaybeHandle<T>; using MaybeHandleType = MaybeHandle<T>;
}; };
// Interface for handle based allocation. // Interface for handle based allocation.
...@@ -556,11 +556,6 @@ class V8_EXPORT_PRIVATE Factory : public FactoryBase<Factory> { ...@@ -556,11 +556,6 @@ class V8_EXPORT_PRIVATE Factory : public FactoryBase<Factory> {
inline Handle<HeapNumber> NewHeapNumberWithHoleNaN(); 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); Handle<JSObject> NewArgumentsObject(Handle<JSFunction> callee, int length);
// Allocates and initializes a new JavaScript object based on a // Allocates and initializes a new JavaScript object based on a
......
...@@ -162,11 +162,6 @@ void OffThreadFactory::Publish(Isolate* isolate) { ...@@ -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. // Hacky method for creating a simple object with a slot pointing to a string.
// TODO(leszeks): Remove once we have full FixedArray support. // TODO(leszeks): Remove once we have full FixedArray support.
OffThreadHandle<FixedArray> OffThreadFactory::StringWrapperForTest( OffThreadHandle<FixedArray> OffThreadFactory::StringWrapperForTest(
......
...@@ -7,6 +7,7 @@ ...@@ -7,6 +7,7 @@
#include <map> #include <map>
#include <vector> #include <vector>
#include "src/base/logging.h"
#include "src/common/globals.h" #include "src/common/globals.h"
#include "src/handles/handles.h" #include "src/handles/handles.h"
#include "src/heap/factory-base.h" #include "src/heap/factory-base.h"
...@@ -59,7 +60,12 @@ class V8_EXPORT_PRIVATE OffThreadFactory ...@@ -59,7 +60,12 @@ class V8_EXPORT_PRIVATE OffThreadFactory
void FinishOffThread(); void FinishOffThread();
void Publish(Isolate* isolate); 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<FixedArray> StringWrapperForTest(
OffThreadHandle<String> string); OffThreadHandle<String> string);
......
...@@ -9,6 +9,7 @@ ...@@ -9,6 +9,7 @@
#include <cmath> #include <cmath>
#include "src/common/assert-scope.h" #include "src/common/assert-scope.h"
#include "src/execution/off-thread-isolate.h"
#include "src/handles/handles.h" #include "src/handles/handles.h"
#include "src/heap/factory.h" #include "src/heap/factory.h"
#include "src/numbers/dtoa.h" #include "src/numbers/dtoa.h"
...@@ -167,18 +168,29 @@ double InternalStringToIntDouble(Iterator current, EndMark end, bool negative, ...@@ -167,18 +168,29 @@ double InternalStringToIntDouble(Iterator current, EndMark end, bool negative,
return std::ldexp(static_cast<double>(negative ? -number : number), exponent); 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); // ES6 18.2.5 parseInt(string, radix) (with NumberParseIntHelper subclass);
// and BigInt parsing cases from https://tc39.github.io/proposal-bigint/ // and BigInt parsing cases from https://tc39.github.io/proposal-bigint/
// (with StringToBigIntHelper subclass). // (with StringToBigIntHelper subclass).
template <typename Isolate>
class StringToIntHelper { class StringToIntHelper {
public: public:
StringToIntHelper(Isolate* isolate, Handle<String> subject, int radix) StringToIntHelper(Isolate* isolate, HandleFor<Isolate, String> subject,
int radix)
: isolate_(isolate), subject_(subject), radix_(radix) { : isolate_(isolate), subject_(subject), radix_(radix) {
DCHECK(subject->IsFlat()); DCHECK(subject->IsFlat());
} }
// Used for the StringToBigInt operation. // Used for the StringToBigInt operation.
StringToIntHelper(Isolate* isolate, Handle<String> subject) StringToIntHelper(Isolate* isolate, HandleFor<Isolate, String> subject)
: isolate_(isolate), subject_(subject) { : isolate_(isolate), subject_(subject) {
DCHECK(subject->IsFlat()); DCHECK(subject->IsFlat());
} }
...@@ -225,11 +237,6 @@ class StringToIntHelper { ...@@ -225,11 +237,6 @@ class StringToIntHelper {
return subject_->GetFlatContent(no_gc).ToUC16Vector(); 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_; } Isolate* isolate() { return isolate_; }
int radix() { return radix_; } int radix() { return radix_; }
int cursor() { return cursor_; } int cursor() { return cursor_; }
...@@ -246,7 +253,7 @@ class StringToIntHelper { ...@@ -246,7 +253,7 @@ class StringToIntHelper {
void ParseInternal(Char start); void ParseInternal(Char start);
Isolate* isolate_; Isolate* isolate_;
Handle<String> subject_; HandleFor<Isolate, String> subject_;
const uint8_t* raw_one_byte_subject_ = nullptr; const uint8_t* raw_one_byte_subject_ = nullptr;
int radix_ = 0; int radix_ = 0;
int cursor_ = 0; int cursor_ = 0;
...@@ -255,10 +262,11 @@ class StringToIntHelper { ...@@ -255,10 +262,11 @@ class StringToIntHelper {
bool leading_zero_ = false; bool leading_zero_ = false;
bool allow_binary_and_octal_prefixes_ = false; bool allow_binary_and_octal_prefixes_ = false;
bool allow_trailing_junk_ = true; 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; DisallowHeapAllocation no_gc;
if (IsOneByte()) { if (IsOneByte()) {
...@@ -269,10 +277,10 @@ void StringToIntHelper::ParseInt() { ...@@ -269,10 +277,10 @@ void StringToIntHelper::ParseInt() {
DetectRadixInternal(vector.begin(), vector.length()); DetectRadixInternal(vector.begin(), vector.length());
} }
} }
if (state_ != kRunning) return; if (state_ != State::kRunning) return;
AllocateResult(); AllocateResult();
HandleSpecialCases(); HandleSpecialCases();
if (state_ != kRunning) return; if (state_ != State::kRunning) return;
{ {
DisallowHeapAllocation no_gc; DisallowHeapAllocation no_gc;
if (IsOneByte()) { if (IsOneByte()) {
...@@ -285,30 +293,31 @@ void StringToIntHelper::ParseInt() { ...@@ -285,30 +293,31 @@ void StringToIntHelper::ParseInt() {
ParseInternal(vector.begin()); ParseInternal(vector.begin());
} }
} }
DCHECK_NE(state_, kRunning); DCHECK_NE(state_, State::kRunning);
} }
template <typename Isolate>
template <class Char> template <class Char>
void StringToIntHelper::DetectRadixInternal(Char current, int length) { void StringToIntHelper<Isolate>::DetectRadixInternal(Char current, int length) {
Char start = current; Char start = current;
length_ = length; length_ = length;
Char end = start + length; Char end = start + length;
if (!AdvanceToNonspace(&current, end)) { if (!AdvanceToNonspace(&current, end)) {
return set_state(kEmpty); return set_state(State::kEmpty);
} }
if (*current == '+') { if (*current == '+') {
// Ignore leading sign; skip following spaces. // Ignore leading sign; skip following spaces.
++current; ++current;
if (current == end) { if (current == end) {
return set_state(kJunk); return set_state(State::kJunk);
} }
sign_ = Sign::kPositive; sign_ = Sign::kPositive;
} else if (*current == '-') { } else if (*current == '-') {
++current; ++current;
if (current == end) { if (current == end) {
return set_state(kJunk); return set_state(State::kJunk);
} }
sign_ = Sign::kNegative; sign_ = Sign::kNegative;
} }
...@@ -318,21 +327,21 @@ void StringToIntHelper::DetectRadixInternal(Char current, int length) { ...@@ -318,21 +327,21 @@ void StringToIntHelper::DetectRadixInternal(Char current, int length) {
radix_ = 10; radix_ = 10;
if (*current == '0') { if (*current == '0') {
++current; ++current;
if (current == end) return set_state(kZero); if (current == end) return set_state(State::kZero);
if (*current == 'x' || *current == 'X') { if (*current == 'x' || *current == 'X') {
radix_ = 16; radix_ = 16;
++current; ++current;
if (current == end) return set_state(kJunk); if (current == end) return set_state(State::kJunk);
} else if (allow_binary_and_octal_prefixes_ && } else if (allow_binary_and_octal_prefixes_ &&
(*current == 'o' || *current == 'O')) { (*current == 'o' || *current == 'O')) {
radix_ = 8; radix_ = 8;
++current; ++current;
if (current == end) return set_state(kJunk); if (current == end) return set_state(State::kJunk);
} else if (allow_binary_and_octal_prefixes_ && } else if (allow_binary_and_octal_prefixes_ &&
(*current == 'b' || *current == 'B')) { (*current == 'b' || *current == 'B')) {
radix_ = 2; radix_ = 2;
++current; ++current;
if (current == end) return set_state(kJunk); if (current == end) return set_state(State::kJunk);
} else { } else {
leading_zero_ = true; leading_zero_ = true;
} }
...@@ -341,10 +350,10 @@ void StringToIntHelper::DetectRadixInternal(Char current, int length) { ...@@ -341,10 +350,10 @@ void StringToIntHelper::DetectRadixInternal(Char current, int length) {
if (*current == '0') { if (*current == '0') {
// Allow "0x" prefix. // Allow "0x" prefix.
++current; ++current;
if (current == end) return set_state(kZero); if (current == end) return set_state(State::kZero);
if (*current == 'x' || *current == 'X') { if (*current == 'x' || *current == 'X') {
++current; ++current;
if (current == end) return set_state(kJunk); if (current == end) return set_state(State::kJunk);
} else { } else {
leading_zero_ = true; leading_zero_ = true;
} }
...@@ -354,11 +363,11 @@ void StringToIntHelper::DetectRadixInternal(Char current, int length) { ...@@ -354,11 +363,11 @@ void StringToIntHelper::DetectRadixInternal(Char current, int length) {
while (*current == '0') { while (*current == '0') {
leading_zero_ = true; leading_zero_ = true;
++current; ++current;
if (current == end) return set_state(kZero); if (current == end) return set_state(State::kZero);
} }
if (!leading_zero_ && !isDigit(*current, radix_)) { if (!leading_zero_ && !isDigit(*current, radix_)) {
return set_state(kJunk); return set_state(State::kJunk);
} }
DCHECK(radix_ >= 2 && radix_ <= 36); DCHECK(radix_ >= 2 && radix_ <= 36);
...@@ -366,8 +375,9 @@ void StringToIntHelper::DetectRadixInternal(Char current, int length) { ...@@ -366,8 +375,9 @@ void StringToIntHelper::DetectRadixInternal(Char current, int length) {
cursor_ = static_cast<int>(current - start); cursor_ = static_cast<int>(current - start);
} }
template <typename Isolate>
template <class Char> template <class Char>
void StringToIntHelper::ParseInternal(Char start) { void StringToIntHelper<Isolate>::ParseInternal(Char start) {
Char current = start + cursor_; Char current = start + cursor_;
Char end = start + length_; Char end = start + length_;
...@@ -426,13 +436,13 @@ void StringToIntHelper::ParseInternal(Char start) { ...@@ -426,13 +436,13 @@ void StringToIntHelper::ParseInternal(Char start) {
} while (!done); } while (!done);
if (!allow_trailing_junk_ && AdvanceToNonspace(&current, end)) { if (!allow_trailing_junk_ && AdvanceToNonspace(&current, 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: public:
NumberParseIntHelper(Isolate* isolate, Handle<String> string, int radix) NumberParseIntHelper(Isolate* isolate, Handle<String> string, int radix)
: StringToIntHelper(isolate, string, radix) {} : StringToIntHelper(isolate, string, radix) {}
...@@ -440,15 +450,15 @@ class NumberParseIntHelper : public StringToIntHelper { ...@@ -440,15 +450,15 @@ class NumberParseIntHelper : public StringToIntHelper {
double GetResult() { double GetResult() {
ParseInt(); ParseInt();
switch (state()) { switch (state()) {
case kJunk: case State::kJunk:
case kEmpty: case State::kEmpty:
return JunkStringValue(); return JunkStringValue();
case kZero: case State::kZero:
return SignedZero(negative()); return SignedZero(negative());
case kDone: case State::kDone:
return negative() ? -result_ : result_; return negative() ? -result_ : result_;
case kError: case State::kError:
case kRunning: case State::kRunning:
break; break;
} }
UNREACHABLE(); UNREACHABLE();
...@@ -476,7 +486,7 @@ class NumberParseIntHelper : public StringToIntHelper { ...@@ -476,7 +486,7 @@ class NumberParseIntHelper : public StringToIntHelper {
result_ = is_power_of_two ? HandlePowerOfTwoCase(vector.begin()) result_ = is_power_of_two ? HandlePowerOfTwoCase(vector.begin())
: HandleBaseTenCase(vector.begin()); : HandleBaseTenCase(vector.begin());
} }
set_state(kDone); set_state(State::kDone);
} }
template <class Char> template <class Char>
...@@ -825,59 +835,50 @@ double StringToInt(Isolate* isolate, Handle<String> string, int radix) { ...@@ -825,59 +835,50 @@ double StringToInt(Isolate* isolate, Handle<String> string, int radix) {
return helper.GetResult(); return helper.GetResult();
} }
class StringToBigIntHelper : public StringToIntHelper { template <typename Isolate>
class StringToBigIntHelper : public StringToIntHelper<Isolate> {
public: public:
enum class Behavior { kStringToBigInt, kLiteral }; enum class Behavior { kStringToBigInt, kLiteral };
// Used for StringToBigInt operation (BigInt constructor and == operator). // Used for StringToBigInt operation (BigInt constructor and == operator).
StringToBigIntHelper(Isolate* isolate, Handle<String> string) StringToBigIntHelper(Isolate* isolate, HandleFor<Isolate, String> string)
: StringToIntHelper(isolate, string), : StringToIntHelper<Isolate>(isolate, string),
behavior_(Behavior::kStringToBigInt) { behavior_(Behavior::kStringToBigInt) {
set_allow_binary_and_octal_prefixes(); this->set_allow_binary_and_octal_prefixes();
set_disallow_trailing_junk(); this->set_disallow_trailing_junk();
} }
// Used for parsing BigInt literals, where the input is a buffer of // Used for parsing BigInt literals, where the input is a buffer of
// one-byte ASCII digits, along with an optional radix prefix. // one-byte ASCII digits, along with an optional radix prefix.
StringToBigIntHelper(Isolate* isolate, const uint8_t* string, int length) StringToBigIntHelper(Isolate* isolate, const uint8_t* string, int length)
: StringToIntHelper(isolate, string, length), : StringToIntHelper<Isolate>(isolate, string, length),
behavior_(Behavior::kLiteral) { behavior_(Behavior::kLiteral) {
set_allow_binary_and_octal_prefixes(); this->set_allow_binary_and_octal_prefixes();
} }
MaybeHandle<BigInt> GetResult() { MaybeHandleFor<Isolate, BigInt> GetResult() {
ParseInt(); this->ParseInt();
if (behavior_ == Behavior::kStringToBigInt && sign() != Sign::kNone && if (behavior_ == Behavior::kStringToBigInt && this->sign() != Sign::kNone &&
radix() != 10) { this->radix() != 10) {
return MaybeHandle<BigInt>(); return MaybeHandleFor<Isolate, BigInt>();
} }
if (state() == kEmpty) { if (this->state() == State::kEmpty) {
if (behavior_ == Behavior::kStringToBigInt) { if (behavior_ == Behavior::kStringToBigInt) {
set_state(kZero); this->set_state(State::kZero);
} else { } else {
UNREACHABLE(); UNREACHABLE();
} }
} }
switch (state()) { switch (this->state()) {
case kJunk: case State::kJunk:
if (should_throw() == kThrowOnError) { case State::kError:
THROW_NEW_ERROR(isolate(), return MaybeHandleFor<Isolate, BigInt>();
NewSyntaxError(MessageTemplate::kBigIntInvalidString), case State::kZero:
BigInt); return BigInt::Zero(this->isolate());
} else { case State::kDone:
DCHECK_EQ(should_throw(), kDontThrow); return BigInt::Finalize<Isolate>(result_, this->negative());
return MaybeHandle<BigInt>(); case State::kEmpty:
} case State::kRunning:
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:
break; break;
} }
UNREACHABLE(); UNREACHABLE();
...@@ -889,42 +890,48 @@ class StringToBigIntHelper : public StringToIntHelper { ...@@ -889,42 +890,48 @@ class StringToBigIntHelper : public StringToIntHelper {
// Conseratively assume that all remaining digits are significant. // Conseratively assume that all remaining digits are significant.
// Optimization opportunity: Would it makes sense to scan for trailing // Optimization opportunity: Would it makes sense to scan for trailing
// junk before allocating the result? // 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 // For literals, we pretenure the allocated BigInt, since it's about
// to be stored in the interpreter's constants array. // to be stored in the interpreter's constants array.
AllocationType allocation = behavior_ == Behavior::kLiteral AllocationType allocation = behavior_ == Behavior::kLiteral
? AllocationType::kOld ? AllocationType::kOld
: AllocationType::kYoung; : AllocationType::kYoung;
MaybeHandle<FreshlyAllocatedBigInt> maybe = BigInt::AllocateFor( MaybeHandleFor<Isolate, FreshlyAllocatedBigInt> maybe = BigInt::AllocateFor(
isolate(), radix(), charcount, should_throw(), allocation); this->isolate(), this->radix(), charcount, kDontThrow, allocation);
if (!maybe.ToHandle(&result_)) { if (!maybe.ToHandle(&result_)) {
set_state(kError); this->set_state(State::kError);
} }
} }
void ResultMultiplyAdd(uint32_t multiplier, uint32_t part) override { 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)); static_cast<uintptr_t>(part));
} }
private: private:
ShouldThrow should_throw() const { return kDontThrow; } HandleFor<Isolate, FreshlyAllocatedBigInt> result_;
Handle<FreshlyAllocatedBigInt> result_;
Behavior behavior_; Behavior behavior_;
}; };
MaybeHandle<BigInt> StringToBigInt(Isolate* isolate, Handle<String> string) { MaybeHandle<BigInt> StringToBigInt(Isolate* isolate, Handle<String> string) {
string = String::Flatten(isolate, string); string = String::Flatten(isolate, string);
StringToBigIntHelper helper(isolate, string); StringToBigIntHelper<Isolate> helper(isolate, string);
return helper.GetResult(); return helper.GetResult();
} }
MaybeHandle<BigInt> BigIntLiteral(Isolate* isolate, const char* string) { template <typename Isolate>
StringToBigIntHelper helper(isolate, reinterpret_cast<const uint8_t*>(string), MaybeHandleFor<Isolate, BigInt> BigIntLiteral(Isolate* isolate,
const char* string) {
StringToBigIntHelper<Isolate> helper(isolate,
reinterpret_cast<const uint8_t*>(string),
static_cast<int>(strlen(string))); static_cast<int>(strlen(string)));
return helper.GetResult(); 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) { const char* DoubleToCString(double v, Vector<char> buffer) {
switch (FPCLASSIFY_NAMESPACE::fpclassify(v)) { switch (FPCLASSIFY_NAMESPACE::fpclassify(v)) {
......
...@@ -5,8 +5,10 @@ ...@@ -5,8 +5,10 @@
#ifndef V8_NUMBERS_CONVERSIONS_H_ #ifndef V8_NUMBERS_CONVERSIONS_H_
#define V8_NUMBERS_CONVERSIONS_H_ #define V8_NUMBERS_CONVERSIONS_H_
#include "src/base/export-template.h"
#include "src/base/logging.h" #include "src/base/logging.h"
#include "src/common/globals.h" #include "src/common/globals.h"
#include "src/handles/handle-for.h"
#include "src/utils/vector.h" #include "src/utils/vector.h"
namespace v8 { namespace v8 {
...@@ -99,7 +101,9 @@ MaybeHandle<BigInt> StringToBigInt(Isolate* isolate, Handle<String> string); ...@@ -99,7 +101,9 @@ MaybeHandle<BigInt> StringToBigInt(Isolate* isolate, Handle<String> string);
// 0x -> hex // 0x -> hex
// 0o -> octal // 0o -> octal
// 0b -> binary // 0b -> binary
V8_EXPORT_PRIVATE MaybeHandle<BigInt> BigIntLiteral(Isolate* isolate, template <typename Isolate>
EXPORT_TEMPLATE_DECLARE(V8_EXPORT_PRIVATE)
MaybeHandleFor<Isolate, BigInt> BigIntLiteral(Isolate* isolate,
const char* string); const char* string);
const int kDoubleToCStringMinBufferSize = 100; const int kDoubleToCStringMinBufferSize = 100;
......
...@@ -20,6 +20,7 @@ ...@@ -20,6 +20,7 @@
#include "src/objects/bigint.h" #include "src/objects/bigint.h"
#include "src/execution/isolate-inl.h" #include "src/execution/isolate-inl.h"
#include "src/execution/off-thread-isolate.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"
#include "src/numbers/conversions.h" #include "src/numbers/conversions.h"
...@@ -44,12 +45,15 @@ class MutableBigInt : public FreshlyAllocatedBigInt { ...@@ -44,12 +45,15 @@ class MutableBigInt : public FreshlyAllocatedBigInt {
public: public:
// Bottleneck for converting MutableBigInts to BigInts. // Bottleneck for converting MutableBigInts to BigInts.
static MaybeHandle<BigInt> MakeImmutable(MaybeHandle<MutableBigInt> maybe); 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); static void Canonicalize(MutableBigInt result);
// Allocation helpers. // Allocation helpers.
static MaybeHandle<MutableBigInt> New( template <typename Isolate>
static MaybeHandleFor<Isolate, MutableBigInt> New(
Isolate* isolate, int length, Isolate* isolate, int length,
AllocationType allocation = AllocationType::kYoung); AllocationType allocation = AllocationType::kYoung);
static Handle<BigInt> NewFromInt(Isolate* isolate, int value); static Handle<BigInt> NewFromInt(Isolate* isolate, int value);
...@@ -57,15 +61,21 @@ class MutableBigInt : public FreshlyAllocatedBigInt { ...@@ -57,15 +61,21 @@ class MutableBigInt : public FreshlyAllocatedBigInt {
void InitializeDigits(int length, byte value = 0); void InitializeDigits(int length, byte value = 0);
static Handle<MutableBigInt> Copy(Isolate* isolate, static Handle<MutableBigInt> Copy(Isolate* isolate,
Handle<BigIntBase> source); 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. // 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) { static Handle<MutableBigInt> Cast(Handle<FreshlyAllocatedBigInt> bigint) {
SLOW_DCHECK(bigint->IsBigInt()); SLOW_DCHECK(bigint->IsBigInt());
return Handle<MutableBigInt>::cast(bigint); 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) { static MutableBigInt cast(Object o) {
SLOW_DCHECK(o.IsBigInt()); SLOW_DCHECK(o.IsBigInt());
return MutableBigInt(o.ptr()); return MutableBigInt(o.ptr());
...@@ -236,8 +246,8 @@ NEVER_READ_ONLY_SPACE_IMPL(MutableBigInt) ...@@ -236,8 +246,8 @@ NEVER_READ_ONLY_SPACE_IMPL(MutableBigInt)
#include "src/objects/object-macros-undef.h" #include "src/objects/object-macros-undef.h"
template <typename T> template <typename T, typename Isolate>
MaybeHandle<T> ThrowBigIntTooBig(Isolate* isolate) { MaybeHandleFor<Isolate, 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
// can sometimes truncate intermediate results already, which can prevent // can sometimes truncate intermediate results already, which can prevent
// those from exceeding the maximum length, effectively preventing a // those from exceeding the maximum length, effectively preventing a
...@@ -250,12 +260,13 @@ MaybeHandle<T> ThrowBigIntTooBig(Isolate* isolate) { ...@@ -250,12 +260,13 @@ MaybeHandle<T> ThrowBigIntTooBig(Isolate* isolate) {
THROW_NEW_ERROR(isolate, NewRangeError(MessageTemplate::kBigIntTooBig), T); THROW_NEW_ERROR(isolate, NewRangeError(MessageTemplate::kBigIntTooBig), T);
} }
MaybeHandle<MutableBigInt> MutableBigInt::New(Isolate* isolate, int length, template <typename Isolate>
AllocationType allocation) { MaybeHandleFor<Isolate, MutableBigInt> MutableBigInt::New(
Isolate* isolate, int length, AllocationType allocation) {
if (length > BigInt::kMaxLength) { if (length > BigInt::kMaxLength) {
return ThrowBigIntTooBig<MutableBigInt>(isolate); return ThrowBigIntTooBig<MutableBigInt>(isolate);
} }
Handle<MutableBigInt> result = HandleFor<Isolate, MutableBigInt> result =
Cast(isolate->factory()->NewBigInt(length, allocation)); Cast(isolate->factory()->NewBigInt(length, allocation));
result->initialize_bitfield(false, length); result->initialize_bitfield(false, length);
#if DEBUG #if DEBUG
...@@ -367,14 +378,16 @@ void MutableBigInt::InitializeDigits(int length, byte value) { ...@@ -367,14 +378,16 @@ void MutableBigInt::InitializeDigits(int length, byte value) {
MaybeHandle<BigInt> MutableBigInt::MakeImmutable( MaybeHandle<BigInt> MutableBigInt::MakeImmutable(
MaybeHandle<MutableBigInt> maybe) { MaybeHandle<MutableBigInt> maybe) {
Handle<MutableBigInt> result; HandleFor<Isolate, MutableBigInt> result;
if (!maybe.ToHandle(&result)) return MaybeHandle<BigInt>(); if (!maybe.ToHandle(&result)) return MaybeHandleFor<Isolate, BigInt>();
return MakeImmutable(result); 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); MutableBigInt::Canonicalize(*result);
return Handle<BigInt>::cast(result); return HandleFor<Isolate, BigInt>::cast(result);
} }
void MutableBigInt::Canonicalize(MutableBigInt result) { void MutableBigInt::Canonicalize(MutableBigInt result) {
...@@ -405,9 +418,13 @@ void MutableBigInt::Canonicalize(MutableBigInt result) { ...@@ -405,9 +418,13 @@ void MutableBigInt::Canonicalize(MutableBigInt result) {
result.digit(result.length() - 1) != 0); // MSD is non-zero. 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); 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) { Handle<BigInt> BigInt::UnaryMinus(Isolate* isolate, Handle<BigInt> x) {
// Special case: There is no -0n. // Special case: There is no -0n.
...@@ -1505,13 +1522,13 @@ void MutableBigInt::InternalMultiplyAdd(BigIntBase source, digit_t factor, ...@@ -1505,13 +1522,13 @@ void MutableBigInt::InternalMultiplyAdd(BigIntBase source, digit_t factor,
} }
// Multiplies {x} with {factor} and then adds {summand} to it. // Multiplies {x} with {factor} and then adds {summand} to it.
void BigInt::InplaceMultiplyAdd(Handle<FreshlyAllocatedBigInt> x, void BigInt::InplaceMultiplyAdd(FreshlyAllocatedBigInt x, uintptr_t factor,
uintptr_t factor, uintptr_t summand) { uintptr_t summand) {
STATIC_ASSERT(sizeof(factor) == sizeof(digit_t)); STATIC_ASSERT(sizeof(factor) == sizeof(digit_t));
STATIC_ASSERT(sizeof(summand) == sizeof(digit_t)); STATIC_ASSERT(sizeof(summand) == sizeof(digit_t));
Handle<MutableBigInt> bigint = MutableBigInt::Cast(x); MutableBigInt bigint = MutableBigInt::cast(x);
MutableBigInt::InternalMultiplyAdd(*bigint, factor, summand, bigint->length(), MutableBigInt::InternalMultiplyAdd(bigint, factor, summand, bigint.length(),
*bigint); bigint);
} }
// Divides {x} by {divisor}, returning the result in {quotient} and {remainder}. // Divides {x} by {divisor}, returning the result in {quotient} and {remainder}.
...@@ -1907,7 +1924,8 @@ constexpr uint8_t kMaxBitsPerChar[] = { ...@@ -1907,7 +1924,8 @@ constexpr uint8_t kMaxBitsPerChar[] = {
static const int kBitsPerCharTableShift = 5; static const int kBitsPerCharTableShift = 5;
static const size_t kBitsPerCharTableMultiplier = 1u << kBitsPerCharTableShift; 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, Isolate* isolate, int radix, int charcount, ShouldThrow should_throw,
AllocationType allocation) { AllocationType allocation) {
DCHECK(2 <= radix && radix <= 36); DCHECK(2 <= radix && radix <= 36);
...@@ -1923,7 +1941,7 @@ MaybeHandle<FreshlyAllocatedBigInt> BigInt::AllocateFor( ...@@ -1923,7 +1941,7 @@ MaybeHandle<FreshlyAllocatedBigInt> BigInt::AllocateFor(
// Divide by kDigitsBits, rounding up. // Divide by kDigitsBits, rounding up.
int length = static_cast<int>((bits_min + kDigitBits - 1) / kDigitBits); int length = static_cast<int>((bits_min + kDigitBits - 1) / kDigitBits);
if (length <= kMaxLength) { if (length <= kMaxLength) {
Handle<MutableBigInt> result = HandleFor<Isolate, MutableBigInt> result =
MutableBigInt::New(isolate, length, allocation).ToHandleChecked(); MutableBigInt::New(isolate, length, allocation).ToHandleChecked();
result->InitializeDigits(length); result->InitializeDigits(length);
return result; return result;
...@@ -1934,16 +1952,31 @@ MaybeHandle<FreshlyAllocatedBigInt> BigInt::AllocateFor( ...@@ -1934,16 +1952,31 @@ MaybeHandle<FreshlyAllocatedBigInt> BigInt::AllocateFor(
if (should_throw == kThrowOnError) { if (should_throw == kThrowOnError) {
return ThrowBigIntTooBig<FreshlyAllocatedBigInt>(isolate); return ThrowBigIntTooBig<FreshlyAllocatedBigInt>(isolate);
} else { } else {
return MaybeHandle<FreshlyAllocatedBigInt>(); return MaybeHandleFor<Isolate, FreshlyAllocatedBigInt>();
} }
} }
template MaybeHandle<FreshlyAllocatedBigInt> BigInt::AllocateFor<Isolate>(
Handle<BigInt> BigInt::Finalize(Handle<FreshlyAllocatedBigInt> x, bool sign) { Isolate* isolate, int radix, int charcount, ShouldThrow should_throw,
Handle<MutableBigInt> bigint = MutableBigInt::Cast(x); 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); 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 // The serialization format MUST NOT CHANGE without updating the format
// version in value-serializer.cc! // version in value-serializer.cc!
uint32_t BigInt::GetBitfieldForSerialization() const { uint32_t BigInt::GetBitfieldForSerialization() const {
......
...@@ -6,6 +6,7 @@ ...@@ -6,6 +6,7 @@
#define V8_OBJECTS_BIGINT_H_ #define V8_OBJECTS_BIGINT_H_
#include "src/common/globals.h" #include "src/common/globals.h"
#include "src/handles/handle-for.h"
#include "src/objects/objects.h" #include "src/objects/objects.h"
#include "src/objects/primitive-heap-object.h" #include "src/objects/primitive-heap-object.h"
#include "src/utils/utils.h" #include "src/utils/utils.h"
...@@ -238,18 +239,23 @@ class BigInt : public BigIntBase { ...@@ -238,18 +239,23 @@ class BigInt : public BigIntBase {
class BodyDescriptor; class BodyDescriptor;
private: private:
template <typename Isolate>
friend class StringToBigIntHelper; friend class StringToBigIntHelper;
friend class ValueDeserializer; friend class ValueDeserializer;
friend class ValueSerializer; friend class ValueSerializer;
// Special functions for StringToBigIntHelper: // Special functions for StringToBigIntHelper:
static Handle<BigInt> Zero(Isolate* isolate); template <typename Isolate>
static MaybeHandle<FreshlyAllocatedBigInt> AllocateFor( static HandleFor<Isolate, BigInt> Zero(Isolate* isolate);
template <typename Isolate>
static MaybeHandleFor<Isolate, FreshlyAllocatedBigInt> AllocateFor(
Isolate* isolate, int radix, int charcount, ShouldThrow should_throw, Isolate* isolate, int radix, int charcount, ShouldThrow should_throw,
AllocationType allocation); AllocationType allocation);
static void InplaceMultiplyAdd(Handle<FreshlyAllocatedBigInt> x, static void InplaceMultiplyAdd(FreshlyAllocatedBigInt x, uintptr_t factor,
uintptr_t factor, uintptr_t summand); uintptr_t summand);
static Handle<BigInt> Finalize(Handle<FreshlyAllocatedBigInt> x, bool sign); template <typename Isolate>
static HandleFor<Isolate, BigInt> Finalize(
HandleFor<Isolate, FreshlyAllocatedBigInt> x, bool sign);
// Special functions for ValueSerializer/ValueDeserializer: // Special functions for ValueSerializer/ValueDeserializer:
uint32_t GetBitfieldForSerialization() const; 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