summaryrefslogtreecommitdiff
path: root/deps/v8/src/api/api.cc
diff options
context:
space:
mode:
Diffstat (limited to 'deps/v8/src/api/api.cc')
-rw-r--r--deps/v8/src/api/api.cc606
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