diff options
Diffstat (limited to 'deps/v8/src/api/api.cc')
-rw-r--r-- | deps/v8/src/api/api.cc | 606 |
1 files changed, 414 insertions, 192 deletions
diff --git a/deps/v8/src/api/api.cc b/deps/v8/src/api/api.cc index 8be7f8558c..0d80f986f1 100644 --- a/deps/v8/src/api/api.cc +++ b/deps/v8/src/api/api.cc @@ -127,6 +127,11 @@ #endif // V8_OS_WIN64 #endif // V8_OS_WIN +#define TRACE_BS(...) \ + do { \ + if (i::FLAG_trace_backing_store) PrintF(__VA_ARGS__); \ + } while (false) + namespace v8 { /* @@ -902,11 +907,6 @@ void V8::SetFlagsFromString(const char* str, size_t length) { i::FlagList::EnforceFlagImplications(); } -void V8::SetFlagsFromString(const char* str, int length) { - CHECK_LE(0, length); - SetFlagsFromString(str, static_cast<size_t>(length)); -} - void V8::SetFlagsFromCommandLine(int* argc, char** argv, bool remove_flags) { i::FlagList::SetFlagsFromCommandLine(argc, argv, remove_flags); } @@ -1314,7 +1314,6 @@ void Context::SetEmbedderData(int index, v8::Local<Value> value) { void* Context::SlowGetAlignedPointerFromEmbedderData(int index) { const char* location = "v8::Context::GetAlignedPointerFromEmbedderData()"; - HandleScope handle_scope(GetIsolate()); i::Handle<i::EmbedderDataArray> data = EmbedderDataFor(this, index, false, location); if (data.is_null()) return nullptr; @@ -2363,28 +2362,6 @@ Local<Module> Module::CreateSyntheticModule( i_module_name, i_export_names, evaluation_steps))); } -Maybe<bool> Module::SetSyntheticModuleExport(Isolate* isolate, - Local<String> export_name, - Local<v8::Value> export_value) { - auto i_isolate = reinterpret_cast<i::Isolate*>(isolate); - i::Handle<i::String> i_export_name = Utils::OpenHandle(*export_name); - i::Handle<i::Object> i_export_value = Utils::OpenHandle(*export_value); - i::Handle<i::Module> self = Utils::OpenHandle(this); - Utils::ApiCheck(self->IsSyntheticModule(), - "v8::Module::SyntheticModuleSetExport", - "v8::Module::SyntheticModuleSetExport must only be called on " - "a SyntheticModule"); - ENTER_V8_NO_SCRIPT(i_isolate, isolate->GetCurrentContext(), Module, - SetSyntheticModuleExport, Nothing<bool>(), i::HandleScope); - has_pending_exception = - i::SyntheticModule::SetExport(i_isolate, - i::Handle<i::SyntheticModule>::cast(self), - i_export_name, i_export_value) - .IsNothing(); - RETURN_ON_FAILED_EXECUTION_PRIMITIVE(bool); - return Just(true); -} - void Module::SetSyntheticModuleExport(Local<String> export_name, Local<v8::Value> export_value) { i::Handle<i::String> i_export_name = Utils::OpenHandle(*export_name); @@ -2394,9 +2371,9 @@ void Module::SetSyntheticModuleExport(Local<String> export_name, "v8::Module::SetSyntheticModuleExport", "v8::Module::SetSyntheticModuleExport must only be called on " "a SyntheticModule"); - i::SyntheticModule::SetExportStrict(self->GetIsolate(), - i::Handle<i::SyntheticModule>::cast(self), - i_export_name, i_export_value); + i::SyntheticModule::SetExport(self->GetIsolate(), + i::Handle<i::SyntheticModule>::cast(self), + i_export_name, i_export_value); } namespace { @@ -2631,7 +2608,7 @@ ScriptCompiler::ScriptStreamingTask* ScriptCompiler::StartStreamingScript( i::Isolate* isolate = reinterpret_cast<i::Isolate*>(v8_isolate); i::ScriptStreamingData* data = source->impl(); std::unique_ptr<i::BackgroundCompileTask> task = - base::make_unique<i::BackgroundCompileTask>(data, isolate); + std::make_unique<i::BackgroundCompileTask>(data, isolate); data->task = std::move(task); return new ScriptCompiler::ScriptStreamingTask(data); } @@ -3743,6 +3720,42 @@ void v8::WasmModuleObject::CheckCast(Value* that) { "Could not convert to wasm module object"); } +v8::BackingStore::~BackingStore() { + auto i_this = reinterpret_cast<const i::BackingStore*>(this); + i_this->~BackingStore(); // manually call internal destructor +} + +void* v8::BackingStore::Data() const { + return reinterpret_cast<const i::BackingStore*>(this)->buffer_start(); +} + +size_t v8::BackingStore::ByteLength() const { + return reinterpret_cast<const i::BackingStore*>(this)->byte_length(); +} + +std::shared_ptr<v8::BackingStore> v8::ArrayBuffer::GetBackingStore() { + i::Handle<i::JSArrayBuffer> self = Utils::OpenHandle(this); + std::shared_ptr<i::BackingStore> backing_store = self->GetBackingStore(); + if (!backing_store) { + backing_store = + i::BackingStore::EmptyBackingStore(i::SharedFlag::kNotShared); + } + i::GlobalBackingStoreRegistry::Register(backing_store); + std::shared_ptr<i::BackingStoreBase> bs_base = backing_store; + return std::static_pointer_cast<v8::BackingStore>(bs_base); +} + +std::shared_ptr<v8::BackingStore> v8::SharedArrayBuffer::GetBackingStore() { + i::Handle<i::JSArrayBuffer> self = Utils::OpenHandle(this); + std::shared_ptr<i::BackingStore> backing_store = self->GetBackingStore(); + if (!backing_store) { + backing_store = i::BackingStore::EmptyBackingStore(i::SharedFlag::kShared); + } + i::GlobalBackingStoreRegistry::Register(backing_store); + std::shared_ptr<i::BackingStoreBase> bs_base = backing_store; + return std::static_pointer_cast<v8::BackingStore>(bs_base); +} + void v8::ArrayBuffer::CheckCast(Value* that) { i::Handle<i::Object> obj = Utils::OpenHandle(that); Utils::ApiCheck( @@ -5307,7 +5320,7 @@ static inline int WriteHelper(i::Isolate* isolate, const String* string, int end = start + length; if ((length == -1) || (length > str->length() - start)) end = str->length(); if (end < 0) return 0; - i::String::WriteToFlat(*str, buffer, start, end); + if (start < end) i::String::WriteToFlat(*str, buffer, start, end); if (!(options & String::NO_NULL_TERMINATION) && (length == -1 || end - start < length)) { buffer[end - start] = '\0'; @@ -5704,6 +5717,11 @@ void v8::V8::InitializeExternalStartupData(const char* natives_blob, i::InitializeExternalStartupData(natives_blob, snapshot_blob); } +// static +void v8::V8::InitializeExternalStartupDataFromFile(const char* snapshot_blob) { + i::InitializeExternalStartupDataFromFile(snapshot_blob); +} + const char* v8::V8::GetVersion() { return i::Version::GetVersion(); } template <typename ObjectType> @@ -7070,21 +7088,7 @@ MemorySpan<const uint8_t> CompiledWasmModule::GetWireBytesRef() { WasmModuleObject::TransferrableModule WasmModuleObject::GetTransferrableModule() { - if (i::FLAG_wasm_shared_code) { - i::Handle<i::WasmModuleObject> obj = - i::Handle<i::WasmModuleObject>::cast(Utils::OpenHandle(this)); - return TransferrableModule(obj->shared_native_module()); - } else { - CompiledWasmModule compiled_module = GetCompiledModule(); - OwnedBuffer serialized_module = compiled_module.Serialize(); - MemorySpan<const uint8_t> wire_bytes_ref = - compiled_module.GetWireBytesRef(); - size_t wire_size = wire_bytes_ref.size(); - std::unique_ptr<uint8_t[]> wire_bytes_copy(new uint8_t[wire_size]); - memcpy(wire_bytes_copy.get(), wire_bytes_ref.data(), wire_size); - return TransferrableModule(std::move(serialized_module), - {std::move(wire_bytes_copy), wire_size}); - } + return GetCompiledModule(); } CompiledWasmModule WasmModuleObject::GetCompiledModule() { @@ -7096,17 +7100,17 @@ CompiledWasmModule WasmModuleObject::GetCompiledModule() { MaybeLocal<WasmModuleObject> WasmModuleObject::FromTransferrableModule( Isolate* isolate, const WasmModuleObject::TransferrableModule& transferrable_module) { - if (i::FLAG_wasm_shared_code) { - i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate); - i::Handle<i::WasmModuleObject> module_object = - i_isolate->wasm_engine()->ImportNativeModule( - i_isolate, transferrable_module.shared_module_); - return Local<WasmModuleObject>::Cast( - Utils::ToLocal(i::Handle<i::JSObject>::cast(module_object))); - } else { - return Deserialize(isolate, AsReference(transferrable_module.serialized_), - AsReference(transferrable_module.wire_bytes_)); - } + return FromCompiledModule(isolate, transferrable_module); +} + +MaybeLocal<WasmModuleObject> WasmModuleObject::FromCompiledModule( + Isolate* isolate, const CompiledWasmModule& compiled_module) { + i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate); + i::Handle<i::WasmModuleObject> module_object = + i_isolate->wasm_engine()->ImportNativeModule( + i_isolate, Utils::Open(compiled_module)); + return Local<WasmModuleObject>::Cast( + Utils::ToLocal(i::Handle<i::JSObject>::cast(module_object))); } MaybeLocal<WasmModuleObject> WasmModuleObject::Deserialize( @@ -7219,20 +7223,78 @@ bool v8::ArrayBuffer::IsDetachable() const { return Utils::OpenHandle(this)->is_detachable(); } -v8::ArrayBuffer::Contents v8::ArrayBuffer::Externalize() { - i::Handle<i::JSArrayBuffer> self = Utils::OpenHandle(this); - i::Isolate* isolate = self->GetIsolate(); - Utils::ApiCheck(!self->is_external(), "v8_ArrayBuffer_Externalize", - "ArrayBuffer already externalized"); - self->set_is_external(true); +namespace { +// The backing store deleter just deletes the indirection, which downrefs +// the shared pointer. It will get collected normally. +void BackingStoreDeleter(void* buffer, size_t length, void* info) { + std::shared_ptr<i::BackingStore>* bs_indirection = + reinterpret_cast<std::shared_ptr<i::BackingStore>*>(info); + if (bs_indirection) { + i::BackingStore* backing_store = bs_indirection->get(); + TRACE_BS("API:delete bs=%p mem=%p (length=%zu)\n", backing_store, + backing_store->buffer_start(), backing_store->byte_length()); + USE(backing_store); + } + delete bs_indirection; +} - const v8::ArrayBuffer::Contents contents = GetContents(); - isolate->heap()->UnregisterArrayBuffer(*self); +void* MakeDeleterData(std::shared_ptr<i::BackingStore> backing_store) { + if (!backing_store) return nullptr; + TRACE_BS("API:extern bs=%p mem=%p (length=%zu)\n", backing_store.get(), + backing_store->buffer_start(), backing_store->byte_length()); + return new std::shared_ptr<i::BackingStore>(backing_store); +} - // A regular copy is good enough. No move semantics needed. - return contents; +std::shared_ptr<i::BackingStore> LookupOrCreateBackingStore( + i::Isolate* i_isolate, void* data, size_t byte_length, i::SharedFlag shared, + ArrayBufferCreationMode mode) { + // "internalized" means that the storage was allocated by the + // ArrayBufferAllocator and thus should be freed upon destruction. + bool free_on_destruct = mode == ArrayBufferCreationMode::kInternalized; + + // Try to lookup a previously-registered backing store in the global + // registry. If found, use that instead of wrapping an embedder allocation. + std::shared_ptr<i::BackingStore> backing_store = + i::GlobalBackingStoreRegistry::Lookup(data, byte_length); + + if (backing_store) { + // Check invariants for a previously-found backing store. + + // 1. We cannot allow an embedder to first allocate a backing store that + // should not be freed upon destruct, and then allocate an alias that should + // destruct it. The other order is fine. + bool changing_destruct_mode = + free_on_destruct && !backing_store->free_on_destruct(); + Utils::ApiCheck( + !changing_destruct_mode, "v8_[Shared]ArrayBuffer_New", + "previous backing store found that should not be freed on destruct"); + + // 2. We cannot allow embedders to use the same backing store for both + // SharedArrayBuffers and regular ArrayBuffers. + bool changing_shared_flag = + (shared == i::SharedFlag::kShared) != backing_store->is_shared(); + Utils::ApiCheck( + !changing_shared_flag, "v8_[Shared]ArrayBuffer_New", + "previous backing store found that does not match shared flag"); + } else { + // No previous backing store found. + backing_store = i::BackingStore::WrapAllocation( + i_isolate, data, byte_length, shared, free_on_destruct); + + // The embedder already has a direct pointer to the buffer start, so + // globally register the backing store in case they come back with the + // same buffer start and the backing store is marked as free_on_destruct. + i::GlobalBackingStoreRegistry::Register(backing_store); + } + return backing_store; } +std::shared_ptr<i::BackingStore> ToInternal( + std::shared_ptr<i::BackingStoreBase> backing_store) { + return std::static_pointer_cast<i::BackingStore>(backing_store); +} +} // namespace + v8::ArrayBuffer::Contents::Contents(void* data, size_t byte_length, void* allocation_base, size_t allocation_length, @@ -7249,29 +7311,70 @@ v8::ArrayBuffer::Contents::Contents(void* data, size_t byte_length, DCHECK_LE(byte_length_, allocation_length_); } -void WasmMemoryDeleter(void* buffer, size_t lenght, void* info) { - internal::wasm::WasmEngine* engine = - reinterpret_cast<internal::wasm::WasmEngine*>(info); - CHECK(engine->memory_tracker()->FreeWasmMemory(nullptr, buffer)); +v8::ArrayBuffer::Contents v8::ArrayBuffer::Externalize() { + return GetContents(true); } -void ArrayBufferDeleter(void* buffer, size_t length, void* info) { - v8::ArrayBuffer::Allocator* allocator = - reinterpret_cast<v8::ArrayBuffer::Allocator*>(info); - allocator->Free(buffer, length); +void v8::ArrayBuffer::Externalize( + const std::shared_ptr<BackingStore>& backing_store) { + i::Handle<i::JSArrayBuffer> self = Utils::OpenHandle(this); + Utils::ApiCheck(!self->is_external(), "v8_ArrayBuffer_Externalize", + "ArrayBuffer already externalized"); + self->set_is_external(true); + DCHECK_EQ(self->backing_store(), backing_store->Data()); } v8::ArrayBuffer::Contents v8::ArrayBuffer::GetContents() { + return GetContents(false); +} + +v8::ArrayBuffer::Contents v8::ArrayBuffer::GetContents(bool externalize) { + // TODO(titzer): reduce duplication between shared/unshared GetContents() + using BufferType = v8::ArrayBuffer; + i::Handle<i::JSArrayBuffer> self = Utils::OpenHandle(this); - Contents contents( - self->backing_store(), self->byte_length(), self->allocation_base(), - self->allocation_length(), - self->is_wasm_memory() ? Allocator::AllocationMode::kReservation - : Allocator::AllocationMode::kNormal, - self->is_wasm_memory() ? WasmMemoryDeleter : ArrayBufferDeleter, - self->is_wasm_memory() - ? static_cast<void*>(self->GetIsolate()->wasm_engine()) - : static_cast<void*>(self->GetIsolate()->array_buffer_allocator())); + + std::shared_ptr<i::BackingStore> backing_store = self->GetBackingStore(); + + void* deleter_data = nullptr; + if (externalize) { + Utils::ApiCheck(!self->is_external(), "v8_ArrayBuffer_Externalize", + "ArrayBuffer already externalized"); + self->set_is_external(true); + // When externalizing, upref the shared pointer to the backing store + // and store that as the deleter data. When the embedder calls the deleter + // callback, we will delete the additional (on-heap) shared_ptr. + deleter_data = MakeDeleterData(backing_store); + } + + if (!backing_store) { + // If the array buffer has zero length or was detached, return empty + // contents. + DCHECK_EQ(0, self->byte_length()); + BufferType::Contents contents( + nullptr, 0, nullptr, 0, + v8::ArrayBuffer::Allocator::AllocationMode::kNormal, + BackingStoreDeleter, deleter_data); + return contents; + } + + // Backing stores that given to the embedder might be passed back through + // the API using only the start of the buffer. We need to find such + // backing stores using global registration until the API is changed. + i::GlobalBackingStoreRegistry::Register(backing_store); + + auto allocation_mode = + backing_store->is_wasm_memory() + ? v8::ArrayBuffer::Allocator::AllocationMode::kReservation + : v8::ArrayBuffer::Allocator::AllocationMode::kNormal; + + BufferType::Contents contents(backing_store->buffer_start(), // -- + backing_store->byte_length(), // -- + backing_store->buffer_start(), // -- + backing_store->byte_length(), // -- + allocation_mode, // -- + BackingStoreDeleter, // -- + deleter_data); return contents; } @@ -7296,30 +7399,56 @@ Local<ArrayBuffer> v8::ArrayBuffer::New(Isolate* isolate, size_t byte_length) { i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate); LOG_API(i_isolate, ArrayBuffer, New); ENTER_V8_NO_SCRIPT_NO_EXCEPTION(i_isolate); - i::Handle<i::JSArrayBuffer> obj = - i_isolate->factory()->NewJSArrayBuffer(i::SharedFlag::kNotShared); - // TODO(jbroman): It may be useful in the future to provide a MaybeLocal - // version that throws an exception or otherwise does not crash. - if (!i::JSArrayBuffer::SetupAllocatingData(obj, i_isolate, byte_length)) { + i::MaybeHandle<i::JSArrayBuffer> result = + i_isolate->factory()->NewJSArrayBufferAndBackingStore( + byte_length, i::InitializedFlag::kZeroInitialized); + + i::Handle<i::JSArrayBuffer> array_buffer; + if (!result.ToHandle(&array_buffer)) { + // TODO(jbroman): It may be useful in the future to provide a MaybeLocal + // version that throws an exception or otherwise does not crash. i::FatalProcessOutOfMemory(i_isolate, "v8::ArrayBuffer::New"); } - return Utils::ToLocal(obj); + + return Utils::ToLocal(array_buffer); } Local<ArrayBuffer> v8::ArrayBuffer::New(Isolate* isolate, void* data, size_t byte_length, ArrayBufferCreationMode mode) { // Embedders must guarantee that the external backing store is valid. - CHECK(byte_length == 0 || data != nullptr); + CHECK_IMPLIES(byte_length != 0, data != nullptr); CHECK_LE(byte_length, i::JSArrayBuffer::kMaxByteLength); i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate); LOG_API(i_isolate, ArrayBuffer, New); ENTER_V8_NO_SCRIPT_NO_EXCEPTION(i_isolate); + + std::shared_ptr<i::BackingStore> backing_store = LookupOrCreateBackingStore( + i_isolate, data, byte_length, i::SharedFlag::kNotShared, mode); + + i::Handle<i::JSArrayBuffer> obj = + i_isolate->factory()->NewJSArrayBuffer(std::move(backing_store)); + if (mode == ArrayBufferCreationMode::kExternalized) { + obj->set_is_external(true); + } + return Utils::ToLocal(obj); +} + +Local<ArrayBuffer> v8::ArrayBuffer::New( + Isolate* isolate, std::shared_ptr<BackingStore> backing_store) { + CHECK_IMPLIES(backing_store->ByteLength() != 0, + backing_store->Data() != nullptr); + CHECK_LE(backing_store->ByteLength(), i::JSArrayBuffer::kMaxByteLength); + i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate); + LOG_API(i_isolate, ArrayBuffer, New); + ENTER_V8_NO_SCRIPT_NO_EXCEPTION(i_isolate); + std::shared_ptr<i::BackingStore> i_backing_store( + ToInternal(std::move(backing_store))); + Utils::ApiCheck( + !i_backing_store->is_shared(), "v8_ArrayBuffer_New", + "Cannot construct ArrayBuffer with a BackingStore of SharedArrayBuffer"); i::Handle<i::JSArrayBuffer> obj = - i_isolate->factory()->NewJSArrayBuffer(i::SharedFlag::kNotShared); - i::JSArrayBuffer::Setup(obj, i_isolate, - mode == ArrayBufferCreationMode::kExternalized, data, - byte_length); + i_isolate->factory()->NewJSArrayBuffer(std::move(i_backing_store)); return Utils::ToLocal(obj); } @@ -7362,9 +7491,9 @@ size_t v8::ArrayBufferView::CopyContents(void* dest, size_t byte_length) { bool v8::ArrayBufferView::HasBuffer() const { i::Handle<i::JSArrayBufferView> self = Utils::OpenHandle(this); - i::Handle<i::JSArrayBuffer> buffer(i::JSArrayBuffer::cast(self->buffer()), - self->GetIsolate()); - return buffer->backing_store() != nullptr; + if (!self->IsJSTypedArray()) return true; + auto typed_array = i::Handle<i::JSTypedArray>::cast(self); + return !typed_array->is_on_heap(); } size_t v8::ArrayBufferView::ByteOffset() { @@ -7460,13 +7589,16 @@ i::Handle<i::JSArrayBuffer> SetupSharedArrayBuffer( i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate); LOG_API(i_isolate, SharedArrayBuffer, New); ENTER_V8_NO_SCRIPT_NO_EXCEPTION(i_isolate); + + std::shared_ptr<i::BackingStore> backing_store = LookupOrCreateBackingStore( + i_isolate, data, byte_length, i::SharedFlag::kShared, mode); + i::Handle<i::JSArrayBuffer> obj = - i_isolate->factory()->NewJSArrayBuffer(i::SharedFlag::kShared); - bool is_wasm_memory = - i_isolate->wasm_engine()->memory_tracker()->IsWasmMemory(data); - i::JSArrayBuffer::Setup(obj, i_isolate, - mode == ArrayBufferCreationMode::kExternalized, data, - byte_length, i::SharedFlag::kShared, is_wasm_memory); + i_isolate->factory()->NewJSSharedArrayBuffer(std::move(backing_store)); + + if (mode == ArrayBufferCreationMode::kExternalized) { + obj->set_is_external(true); + } return obj; } @@ -7476,20 +7608,6 @@ bool v8::SharedArrayBuffer::IsExternal() const { return Utils::OpenHandle(this)->is_external(); } -v8::SharedArrayBuffer::Contents v8::SharedArrayBuffer::Externalize() { - i::Handle<i::JSArrayBuffer> self = Utils::OpenHandle(this); - i::Isolate* isolate = self->GetIsolate(); - Utils::ApiCheck(!self->is_external(), "v8_SharedArrayBuffer_Externalize", - "SharedArrayBuffer already externalized"); - self->set_is_external(true); - - const v8::SharedArrayBuffer::Contents contents = GetContents(); - isolate->heap()->UnregisterArrayBuffer(*self); - - // A regular copy is good enough. No move semantics needed. - return contents; -} - v8::SharedArrayBuffer::Contents::Contents( void* data, size_t byte_length, void* allocation_base, size_t allocation_length, Allocator::AllocationMode allocation_mode, @@ -7505,20 +7623,72 @@ v8::SharedArrayBuffer::Contents::Contents( DCHECK_LE(byte_length_, allocation_length_); } +v8::SharedArrayBuffer::Contents v8::SharedArrayBuffer::Externalize() { + return GetContents(true); +} + +void v8::SharedArrayBuffer::Externalize( + const std::shared_ptr<BackingStore>& backing_store) { + i::Handle<i::JSArrayBuffer> self = Utils::OpenHandle(this); + Utils::ApiCheck(!self->is_external(), "v8_SharedArrayBuffer_Externalize", + "SharedArrayBuffer already externalized"); + self->set_is_external(true); + + DCHECK_EQ(self->backing_store(), backing_store->Data()); +} + v8::SharedArrayBuffer::Contents v8::SharedArrayBuffer::GetContents() { + return GetContents(false); +} + +v8::SharedArrayBuffer::Contents v8::SharedArrayBuffer::GetContents( + bool externalize) { + // TODO(titzer): reduce duplication between shared/unshared GetContents() + using BufferType = v8::SharedArrayBuffer; + i::Handle<i::JSArrayBuffer> self = Utils::OpenHandle(this); - Contents contents( - self->backing_store(), self->byte_length(), self->allocation_base(), - self->allocation_length(), - self->is_wasm_memory() - ? ArrayBuffer::Allocator::AllocationMode::kReservation - : ArrayBuffer::Allocator::AllocationMode::kNormal, - self->is_wasm_memory() - ? reinterpret_cast<Contents::DeleterCallback>(WasmMemoryDeleter) - : reinterpret_cast<Contents::DeleterCallback>(ArrayBufferDeleter), - self->is_wasm_memory() - ? static_cast<void*>(self->GetIsolate()->wasm_engine()) - : static_cast<void*>(self->GetIsolate()->array_buffer_allocator())); + + std::shared_ptr<i::BackingStore> backing_store = self->GetBackingStore(); + + void* deleter_data = nullptr; + if (externalize) { + Utils::ApiCheck(!self->is_external(), "v8_SharedArrayBuffer_Externalize", + "SharedArrayBuffer already externalized"); + self->set_is_external(true); + // When externalizing, upref the shared pointer to the backing store + // and store that as the deleter data. When the embedder calls the deleter + // callback, we will delete the additional (on-heap) shared_ptr. + deleter_data = MakeDeleterData(backing_store); + } + + if (!backing_store) { + // If the array buffer has zero length or was detached, return empty + // contents. + DCHECK_EQ(0, self->byte_length()); + BufferType::Contents contents( + nullptr, 0, nullptr, 0, + v8::ArrayBuffer::Allocator::AllocationMode::kNormal, + BackingStoreDeleter, deleter_data); + return contents; + } + + // Backing stores that given to the embedder might be passed back through + // the API using only the start of the buffer. We need to find such + // backing stores using global registration until the API is changed. + i::GlobalBackingStoreRegistry::Register(backing_store); + + auto allocation_mode = + backing_store->is_wasm_memory() + ? v8::ArrayBuffer::Allocator::AllocationMode::kReservation + : v8::ArrayBuffer::Allocator::AllocationMode::kNormal; + + BufferType::Contents contents(backing_store->buffer_start(), // -- + backing_store->byte_length(), // -- + backing_store->buffer_start(), // -- + backing_store->byte_length(), // -- + allocation_mode, // -- + BackingStoreDeleter, // -- + deleter_data); return contents; } @@ -7533,14 +7703,19 @@ Local<SharedArrayBuffer> v8::SharedArrayBuffer::New(Isolate* isolate, i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate); LOG_API(i_isolate, SharedArrayBuffer, New); ENTER_V8_NO_SCRIPT_NO_EXCEPTION(i_isolate); - i::Handle<i::JSArrayBuffer> obj = - i_isolate->factory()->NewJSArrayBuffer(i::SharedFlag::kShared); - // TODO(jbroman): It may be useful in the future to provide a MaybeLocal - // version that throws an exception or otherwise does not crash. - if (!i::JSArrayBuffer::SetupAllocatingData(obj, i_isolate, byte_length, true, - i::SharedFlag::kShared)) { + + std::unique_ptr<i::BackingStore> backing_store = + i::BackingStore::Allocate(i_isolate, byte_length, i::SharedFlag::kShared, + i::InitializedFlag::kZeroInitialized); + + if (!backing_store) { + // TODO(jbroman): It may be useful in the future to provide a MaybeLocal + // version that throws an exception or otherwise does not crash. i::FatalProcessOutOfMemory(i_isolate, "v8::SharedArrayBuffer::New"); } + + i::Handle<i::JSArrayBuffer> obj = + i_isolate->factory()->NewJSSharedArrayBuffer(std::move(backing_store)); return Utils::ToLocalShared(obj); } @@ -7553,6 +7728,24 @@ Local<SharedArrayBuffer> v8::SharedArrayBuffer::New( } Local<SharedArrayBuffer> v8::SharedArrayBuffer::New( + Isolate* isolate, std::shared_ptr<BackingStore> backing_store) { + CHECK(i::FLAG_harmony_sharedarraybuffer); + CHECK_IMPLIES(backing_store->ByteLength() != 0, + backing_store->Data() != nullptr); + CHECK_LE(backing_store->ByteLength(), i::JSArrayBuffer::kMaxByteLength); + i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate); + LOG_API(i_isolate, SharedArrayBuffer, New); + ENTER_V8_NO_SCRIPT_NO_EXCEPTION(i_isolate); + std::shared_ptr<i::BackingStore> i_backing_store(ToInternal(backing_store)); + Utils::ApiCheck( + i_backing_store->is_shared(), "v8_SharedArrayBuffer_New", + "Cannot construct SharedArrayBuffer with BackingStore of ArrayBuffer"); + i::Handle<i::JSArrayBuffer> obj = + i_isolate->factory()->NewJSSharedArrayBuffer(std::move(i_backing_store)); + return Utils::ToLocalShared(obj); +} + +Local<SharedArrayBuffer> v8::SharedArrayBuffer::New( Isolate* isolate, const SharedArrayBuffer::Contents& contents, ArrayBufferCreationMode mode) { i::Handle<i::JSArrayBuffer> buffer = SetupSharedArrayBuffer( @@ -8235,6 +8428,15 @@ bool Isolate::GetHeapCodeAndMetadataStatistics( return true; } +v8::MaybeLocal<v8::Promise> Isolate::MeasureMemory( + v8::Local<v8::Context> context, MeasureMemoryMode mode) { + i::Isolate* isolate = reinterpret_cast<i::Isolate*>(this); + i::Handle<i::NativeContext> native_context = + handle(Utils::OpenHandle(*context)->native_context(), isolate); + return v8::Utils::PromiseToLocal( + isolate->heap()->MeasureMemory(native_context, mode)); +} + void Isolate::GetStackSample(const RegisterState& state, void** frames, size_t frames_limit, SampleInfo* sample_info) { RegisterState regs = state; @@ -9062,9 +9264,9 @@ bool debug::Script::GetPossibleBreakpoints( i::Handle<i::Script> script = Utils::OpenHandle(this); if (script->type() == i::Script::TYPE_WASM && this->SourceMappingURL().IsEmpty()) { - i::WasmModuleObject module_object = - i::WasmModuleObject::cast(script->wasm_module_object()); - return module_object.GetPossibleBreakpoints(start, end, locations); + i::wasm::NativeModule* native_module = script->wasm_native_module(); + return i::WasmModuleObject::GetPossibleBreakpoints(native_module, start, + end, locations); } i::Script::InitLineEnds(script); @@ -9113,8 +9315,9 @@ int debug::Script::GetSourceOffset(const debug::Location& location) const { i::Handle<i::Script> script = Utils::OpenHandle(this); if (script->type() == i::Script::TYPE_WASM) { if (this->SourceMappingURL().IsEmpty()) { - return i::WasmModuleObject::cast(script->wasm_module_object()) - .GetFunctionOffset(location.GetLineNumber()) + + i::wasm::NativeModule* native_module = script->wasm_native_module(); + const i::wasm::WasmModule* module = native_module->module(); + return i::wasm::GetWasmFunctionOffset(module, location.GetLineNumber()) + location.GetColumnNumber(); } DCHECK_EQ(0, location.GetLineNumber()); @@ -9202,9 +9405,8 @@ int debug::WasmScript::NumFunctions() const { i::DisallowHeapAllocation no_gc; i::Handle<i::Script> script = Utils::OpenHandle(this); DCHECK_EQ(i::Script::TYPE_WASM, script->type()); - i::WasmModuleObject module_object = - i::WasmModuleObject::cast(script->wasm_module_object()); - const i::wasm::WasmModule* module = module_object.module(); + i::wasm::NativeModule* native_module = script->wasm_native_module(); + const i::wasm::WasmModule* module = native_module->module(); DCHECK_GE(i::kMaxInt, module->functions.size()); return static_cast<int>(module->functions.size()); } @@ -9213,21 +9415,26 @@ int debug::WasmScript::NumImportedFunctions() const { i::DisallowHeapAllocation no_gc; i::Handle<i::Script> script = Utils::OpenHandle(this); DCHECK_EQ(i::Script::TYPE_WASM, script->type()); - i::WasmModuleObject module_object = - i::WasmModuleObject::cast(script->wasm_module_object()); - const i::wasm::WasmModule* module = module_object.module(); + i::wasm::NativeModule* native_module = script->wasm_native_module(); + const i::wasm::WasmModule* module = native_module->module(); DCHECK_GE(i::kMaxInt, module->num_imported_functions); return static_cast<int>(module->num_imported_functions); } +MemorySpan<const uint8_t> debug::WasmScript::Bytecode() const { + i::Handle<i::Script> script = Utils::OpenHandle(this); + i::Vector<const uint8_t> wire_bytes = + script->wasm_native_module()->wire_bytes(); + return {wire_bytes.begin(), wire_bytes.size()}; +} + std::pair<int, int> debug::WasmScript::GetFunctionRange( int function_index) const { i::DisallowHeapAllocation no_gc; i::Handle<i::Script> script = Utils::OpenHandle(this); DCHECK_EQ(i::Script::TYPE_WASM, script->type()); - i::WasmModuleObject module_object = - i::WasmModuleObject::cast(script->wasm_module_object()); - const i::wasm::WasmModule* module = module_object.module(); + i::wasm::NativeModule* native_module = script->wasm_native_module(); + const i::wasm::WasmModule* module = native_module->module(); DCHECK_LE(0, function_index); DCHECK_GT(module->functions.size(), function_index); const i::wasm::WasmFunction& func = module->functions[function_index]; @@ -9241,14 +9448,12 @@ uint32_t debug::WasmScript::GetFunctionHash(int function_index) { i::DisallowHeapAllocation no_gc; i::Handle<i::Script> script = Utils::OpenHandle(this); DCHECK_EQ(i::Script::TYPE_WASM, script->type()); - i::WasmModuleObject module_object = - i::WasmModuleObject::cast(script->wasm_module_object()); - const i::wasm::WasmModule* module = module_object.module(); + i::wasm::NativeModule* native_module = script->wasm_native_module(); + const i::wasm::WasmModule* module = native_module->module(); DCHECK_LE(0, function_index); DCHECK_GT(module->functions.size(), function_index); const i::wasm::WasmFunction& func = module->functions[function_index]; - i::wasm::ModuleWireBytes wire_bytes( - module_object.native_module()->wire_bytes()); + i::wasm::ModuleWireBytes wire_bytes(native_module->wire_bytes()); i::Vector<const i::byte> function_bytes = wire_bytes.GetFunctionBytes(&func); // TODO(herhut): Maybe also take module, name and signature into account. return i::StringHasher::HashSequentialString(function_bytes.begin(), @@ -9260,9 +9465,10 @@ debug::WasmDisassembly debug::WasmScript::DisassembleFunction( i::DisallowHeapAllocation no_gc; i::Handle<i::Script> script = Utils::OpenHandle(this); DCHECK_EQ(i::Script::TYPE_WASM, script->type()); - i::WasmModuleObject module_object = - i::WasmModuleObject::cast(script->wasm_module_object()); - return module_object.DisassembleFunction(function_index); + i::wasm::NativeModule* native_module = script->wasm_native_module(); + const i::wasm::WasmModule* module = native_module->module(); + i::wasm::ModuleWireBytes wire_bytes(native_module->wire_bytes()); + return DisassembleWasmFunction(module, wire_bytes, function_index); } debug::Location::Location(int line_number, int column_number) @@ -9438,7 +9644,7 @@ debug::ConsoleCallArguments::ConsoleCallArguments( } debug::ConsoleCallArguments::ConsoleCallArguments( - internal::BuiltinArguments& args) + const internal::BuiltinArguments& args) : v8::FunctionCallbackInfo<v8::Value>( nullptr, // Drop the first argument (receiver, i.e. the "console" object). @@ -9501,14 +9707,14 @@ v8::Local<debug::GeneratorObject> debug::GeneratorObject::Cast( MaybeLocal<v8::Value> debug::EvaluateGlobal(v8::Isolate* isolate, v8::Local<v8::String> source, - bool throw_on_side_effect) { + EvaluateGlobalMode mode) { i::Isolate* internal_isolate = reinterpret_cast<i::Isolate*>(isolate); PREPARE_FOR_DEBUG_INTERFACE_EXECUTION_WITH_ISOLATE(internal_isolate, Value); Local<Value> result; - has_pending_exception = !ToLocal<Value>( - i::DebugEvaluate::Global(internal_isolate, Utils::OpenHandle(*source), - throw_on_side_effect), - &result); + has_pending_exception = + !ToLocal<Value>(i::DebugEvaluate::Global( + internal_isolate, Utils::OpenHandle(*source), mode), + &result); RETURN_ON_FAILED_EXECUTION(Value); RETURN_ESCAPED(result); } @@ -9933,10 +10139,6 @@ void CpuProfiler::SetUsePreciseSampling(bool use_precise_sampling) { use_precise_sampling); } -void CpuProfiler::CollectSample() { - reinterpret_cast<i::CpuProfiler*>(this)->CollectSample(); -} - void CpuProfiler::StartProfiling(Local<String> title, CpuProfilingOptions options) { reinterpret_cast<i::CpuProfiler*>(this)->StartProfiling( @@ -9964,12 +10166,6 @@ CpuProfile* CpuProfiler::StopProfiling(Local<String> title) { *Utils::OpenHandle(*title))); } -void CpuProfiler::SetIdle(bool is_idle) { - i::CpuProfiler* profiler = reinterpret_cast<i::CpuProfiler*>(this); - i::Isolate* isolate = profiler->isolate(); - isolate->SetIdle(is_idle); -} - void CpuProfiler::UseDetailedSourcePositionsForProfiling(Isolate* isolate) { reinterpret_cast<i::Isolate*>(isolate) ->set_detailed_source_positions_for_profiling(true); @@ -10009,6 +10205,10 @@ const char* CodeEvent::GetComment() { return reinterpret_cast<i::CodeEvent*>(this)->comment; } +uintptr_t CodeEvent::GetPreviousCodeStartAddress() { + return reinterpret_cast<i::CodeEvent*>(this)->previous_code_start_address; +} + const char* CodeEvent::GetCodeEventTypeName(CodeEventType code_event_type) { switch (code_event_type) { case kUnknownType: @@ -10303,17 +10503,6 @@ void Testing::DeoptimizeAll(Isolate* isolate) { i::Deoptimizer::DeoptimizeAll(i_isolate); } -void EmbedderHeapTracer::TracePrologue(TraceFlags flags) { -#if __clang__ -#pragma clang diagnostic push -#pragma clang diagnostic ignored "-Wdeprecated" -#endif - TracePrologue(); -#if __clang__ -#pragma clang diagnostic pop -#endif -} - void EmbedderHeapTracer::TraceEpilogue(TraceSummary* trace_summary) { #if __clang__ #pragma clang diagnostic push @@ -10369,11 +10558,21 @@ void EmbedderHeapTracer::DecreaseAllocatedSize(size_t bytes) { } void EmbedderHeapTracer::RegisterEmbedderReference( - const TracedGlobal<v8::Value>& ref) { + const TracedReferenceBase<v8::Data>& ref) { if (ref.IsEmpty()) return; i::Heap* const heap = reinterpret_cast<i::Isolate*>(isolate_)->heap(); - heap->RegisterExternallyReferencedObject(reinterpret_cast<i::Address*>(*ref)); + heap->RegisterExternallyReferencedObject( + reinterpret_cast<i::Address*>(ref.val_)); +} + +void EmbedderHeapTracer::RegisterEmbedderReference( + const TracedReferenceBase<v8::Value>& ref) { + if (ref.IsEmpty()) return; + + i::Heap* const heap = reinterpret_cast<i::Isolate*>(isolate_)->heap(); + heap->RegisterExternallyReferencedObject( + reinterpret_cast<i::Address*>(ref.val_)); } void EmbedderHeapTracer::IterateTracedGlobalHandles( @@ -10383,6 +10582,26 @@ void EmbedderHeapTracer::IterateTracedGlobalHandles( isolate->global_handles()->IterateTracedNodes(visitor); } +bool EmbedderHeapTracer::IsRootForNonTracingGC( + const v8::TracedReference<v8::Value>& handle) { + return true; +} + +bool EmbedderHeapTracer::IsRootForNonTracingGC( + const v8::TracedGlobal<v8::Value>& handle) { + return true; +} + +void EmbedderHeapTracer::ResetHandleInNonTracingGC( + const v8::TracedReference<v8::Value>& handle) { + UNREACHABLE(); +} + +void EmbedderHeapTracer::ResetHandleInNonTracingGC( + const v8::TracedGlobal<v8::Value>& handle) { + UNREACHABLE(); +} + namespace internal { const size_t HandleScopeImplementer::kEnteredContextsOffset = @@ -10473,9 +10692,10 @@ char* HandleScopeImplementer::Iterate(RootVisitor* v, char* storage) { return storage + ArchiveSpacePerThread(); } -DeferredHandles* HandleScopeImplementer::Detach(Address* prev_limit) { - DeferredHandles* deferred = - new DeferredHandles(isolate()->handle_scope_data()->next, isolate()); +std::unique_ptr<DeferredHandles> HandleScopeImplementer::Detach( + Address* prev_limit) { + std::unique_ptr<DeferredHandles> deferred( + new DeferredHandles(isolate()->handle_scope_data()->next, isolate())); while (!blocks_.empty()) { Address* block_start = blocks_.back(); @@ -10584,3 +10804,5 @@ void InvokeFunctionCallback(const v8::FunctionCallbackInfo<v8::Value>& info, } // namespace internal } // namespace v8 + +#undef TRACE_BS |