summaryrefslogtreecommitdiff
path: root/deps/v8/src/wasm/wasm-objects.cc
diff options
context:
space:
mode:
authorMichaël Zasso <targos@protonmail.com>2019-03-12 09:01:49 +0100
committerMichaël Zasso <targos@protonmail.com>2019-03-14 18:49:21 +0100
commit7b48713334469818661fe276cf571de9c7899f2d (patch)
tree4dbda49ac88db76ce09dc330a0cb587e68e139ba /deps/v8/src/wasm/wasm-objects.cc
parent8549ac09b256666cf5275224ec58fab9939ff32e (diff)
downloadandroid-node-v8-7b48713334469818661fe276cf571de9c7899f2d.tar.gz
android-node-v8-7b48713334469818661fe276cf571de9c7899f2d.tar.bz2
android-node-v8-7b48713334469818661fe276cf571de9c7899f2d.zip
deps: update V8 to 7.3.492.25
PR-URL: https://github.com/nodejs/node/pull/25852 Reviewed-By: Ujjwal Sharma <usharma1998@gmail.com> Reviewed-By: Matteo Collina <matteo.collina@gmail.com> Reviewed-By: Ali Ijaz Sheikh <ofrobots@google.com>
Diffstat (limited to 'deps/v8/src/wasm/wasm-objects.cc')
-rw-r--r--deps/v8/src/wasm/wasm-objects.cc542
1 files changed, 369 insertions, 173 deletions
diff --git a/deps/v8/src/wasm/wasm-objects.cc b/deps/v8/src/wasm/wasm-objects.cc
index 9d0e20ab2b..392ddd4ca8 100644
--- a/deps/v8/src/wasm/wasm-objects.cc
+++ b/deps/v8/src/wasm/wasm-objects.cc
@@ -9,10 +9,12 @@
#include "src/base/iterator.h"
#include "src/code-factory.h"
#include "src/compiler/wasm-compiler.h"
+#include "src/counters.h"
#include "src/debug/debug-interface.h"
#include "src/objects-inl.h"
#include "src/objects/debug-objects-inl.h"
#include "src/objects/shared-function-info.h"
+#include "src/objects/struct-inl.h"
#include "src/trap-handler/trap-handler.h"
#include "src/wasm/jump-table-assembler.h"
#include "src/wasm/module-compiler.h"
@@ -64,13 +66,24 @@ class WasmInstanceNativeAllocations {
// Allocates initial native storage for a given instance.
WasmInstanceNativeAllocations(Handle<WasmInstanceObject> instance,
size_t num_imported_functions,
- size_t num_imported_mutable_globals) {
+ size_t num_imported_mutable_globals,
+ size_t num_data_segments,
+ size_t num_elem_segments) {
SET(instance, imported_function_targets,
reinterpret_cast<Address*>(
calloc(num_imported_functions, sizeof(Address))));
SET(instance, imported_mutable_globals,
reinterpret_cast<Address*>(
calloc(num_imported_mutable_globals, sizeof(Address))));
+ SET(instance, data_segment_starts,
+ reinterpret_cast<Address*>(calloc(num_data_segments, sizeof(Address))));
+ SET(instance, data_segment_sizes,
+ reinterpret_cast<uint32_t*>(
+ calloc(num_data_segments, sizeof(uint32_t))));
+ SET(instance, dropped_data_segments,
+ reinterpret_cast<uint8_t*>(calloc(num_data_segments, sizeof(uint8_t))));
+ SET(instance, dropped_elem_segments,
+ reinterpret_cast<uint8_t*>(calloc(num_elem_segments, sizeof(uint8_t))));
}
~WasmInstanceNativeAllocations() {
::free(indirect_function_table_sig_ids_);
@@ -81,6 +94,14 @@ class WasmInstanceNativeAllocations {
imported_function_targets_ = nullptr;
::free(imported_mutable_globals_);
imported_mutable_globals_ = nullptr;
+ ::free(data_segment_starts_);
+ data_segment_starts_ = nullptr;
+ ::free(data_segment_sizes_);
+ data_segment_sizes_ = nullptr;
+ ::free(dropped_data_segments_);
+ dropped_data_segments_ = nullptr;
+ ::free(dropped_elem_segments_);
+ dropped_elem_segments_ = nullptr;
}
// Resizes the indirect function table.
void resize_indirect_function_table(Isolate* isolate,
@@ -89,7 +110,7 @@ class WasmInstanceNativeAllocations {
uint32_t old_size = instance->indirect_function_table_size();
void* new_sig_ids = nullptr;
void* new_targets = nullptr;
- Handle<FixedArray> new_instances;
+ Handle<FixedArray> new_refs;
if (indirect_function_table_sig_ids_) {
// Reallocate the old storage.
new_sig_ids = realloc(indirect_function_table_sig_ids_,
@@ -97,16 +118,14 @@ class WasmInstanceNativeAllocations {
new_targets =
realloc(indirect_function_table_targets_, new_size * sizeof(Address));
- Handle<FixedArray> old(instance->indirect_function_table_instances(),
- isolate);
- new_instances = isolate->factory()->CopyFixedArrayAndGrow(
+ Handle<FixedArray> old(instance->indirect_function_table_refs(), isolate);
+ new_refs = isolate->factory()->CopyFixedArrayAndGrow(
old, static_cast<int>(new_size - old_size));
} else {
// Allocate new storage.
new_sig_ids = malloc(new_size * sizeof(uint32_t));
new_targets = malloc(new_size * sizeof(Address));
- new_instances =
- isolate->factory()->NewFixedArray(static_cast<int>(new_size));
+ new_refs = isolate->factory()->NewFixedArray(static_cast<int>(new_size));
}
// Initialize new entries.
instance->set_indirect_function_table_size(new_size);
@@ -115,7 +134,7 @@ class WasmInstanceNativeAllocations {
SET(instance, indirect_function_table_targets,
reinterpret_cast<Address*>(new_targets));
- instance->set_indirect_function_table_instances(*new_instances);
+ instance->set_indirect_function_table_refs(*new_refs);
for (uint32_t j = old_size; j < new_size; j++) {
IndirectFunctionTableEntry(instance, static_cast<int>(j)).clear();
}
@@ -124,22 +143,29 @@ class WasmInstanceNativeAllocations {
Address* indirect_function_table_targets_ = nullptr;
Address* imported_function_targets_ = nullptr;
Address* imported_mutable_globals_ = nullptr;
+ Address* data_segment_starts_ = nullptr;
+ uint32_t* data_segment_sizes_ = nullptr;
+ uint8_t* dropped_data_segments_ = nullptr;
+ uint8_t* dropped_elem_segments_ = nullptr;
#undef SET
};
size_t EstimateNativeAllocationsSize(const WasmModule* module) {
- size_t estimate = sizeof(WasmInstanceNativeAllocations) +
- (1 * kPointerSize * module->num_imported_mutable_globals) +
- (2 * kPointerSize * module->num_imported_functions);
+ size_t estimate =
+ sizeof(WasmInstanceNativeAllocations) +
+ (1 * kSystemPointerSize * module->num_imported_mutable_globals) +
+ (2 * kSystemPointerSize * module->num_imported_functions) +
+ ((kSystemPointerSize + sizeof(uint32_t) + sizeof(uint8_t)) *
+ module->num_declared_data_segments);
for (auto& table : module->tables) {
- estimate += 3 * kPointerSize * table.initial_size;
+ estimate += 3 * kSystemPointerSize * table.initial_size;
}
return estimate;
}
WasmInstanceNativeAllocations* GetNativeAllocations(
- WasmInstanceObject* instance) {
- return reinterpret_cast<Managed<WasmInstanceNativeAllocations>*>(
+ WasmInstanceObject instance) {
+ return Managed<WasmInstanceNativeAllocations>::cast(
instance->managed_native_allocations())
->raw();
}
@@ -177,25 +203,21 @@ enum DispatchTableElements : int {
// static
Handle<WasmModuleObject> WasmModuleObject::New(
Isolate* isolate, const wasm::WasmFeatures& enabled,
- std::shared_ptr<const wasm::WasmModule> shared_module, wasm::ModuleEnv& env,
+ std::shared_ptr<const wasm::WasmModule> shared_module,
OwnedVector<const uint8_t> wire_bytes, Handle<Script> script,
Handle<ByteArray> asm_js_offset_table) {
- DCHECK_EQ(shared_module.get(), env.module);
-
// Create a new {NativeModule} first.
- size_t native_memory_estimate =
- isolate->wasm_engine()->code_manager()->EstimateNativeModuleSize(
- env.module);
+ size_t code_size_estimate =
+ wasm::WasmCodeManager::EstimateNativeModuleCodeSize(shared_module.get());
auto native_module = isolate->wasm_engine()->code_manager()->NewNativeModule(
- isolate, enabled, native_memory_estimate,
- wasm::NativeModule::kCanAllocateMoreMemory, std::move(shared_module),
- env);
- native_module->set_wire_bytes(std::move(wire_bytes));
+ isolate, enabled, code_size_estimate,
+ wasm::NativeModule::kCanAllocateMoreMemory, std::move(shared_module));
+ native_module->SetWireBytes(std::move(wire_bytes));
native_module->SetRuntimeStubs(isolate);
// Delegate to the shared {WasmModuleObject::New} allocator.
Handle<WasmModuleObject> module_object =
- New(isolate, std::move(native_module), script);
+ New(isolate, std::move(native_module), script, code_size_estimate);
if (!asm_js_offset_table.is_null()) {
module_object->set_asm_js_offset_table(*asm_js_offset_table);
}
@@ -205,19 +227,27 @@ Handle<WasmModuleObject> WasmModuleObject::New(
// static
Handle<WasmModuleObject> WasmModuleObject::New(
Isolate* isolate, std::shared_ptr<wasm::NativeModule> native_module,
- Handle<Script> script) {
- int export_wrapper_size =
- static_cast<int>(native_module->module()->num_exported_functions);
+ Handle<Script> script, size_t code_size_estimate) {
+ const WasmModule* module = native_module->module();
+ int export_wrapper_size = static_cast<int>(module->num_exported_functions);
Handle<FixedArray> export_wrappers =
isolate->factory()->NewFixedArray(export_wrapper_size, TENURED);
+ return New(isolate, std::move(native_module), script, export_wrappers,
+ code_size_estimate);
+}
+
+// static
+Handle<WasmModuleObject> WasmModuleObject::New(
+ Isolate* isolate, std::shared_ptr<wasm::NativeModule> native_module,
+ Handle<Script> script, Handle<FixedArray> export_wrappers,
+ size_t code_size_estimate) {
+ const WasmModule* module = native_module->module();
// Use the given shared {NativeModule}, but increase its reference count by
// allocating a new {Managed<T>} that the {WasmModuleObject} references.
- size_t native_memory_estimate =
- isolate->wasm_engine()->code_manager()->EstimateNativeModuleSize(
- native_module->module());
size_t memory_estimate =
- EstimateWasmModuleSize(native_module->module()) + native_memory_estimate;
+ code_size_estimate +
+ wasm::WasmCodeManager::EstimateNativeModuleNonCodeSize(module);
Handle<Managed<wasm::NativeModule>> managed_native_module =
Managed<wasm::NativeModule>::FromSharedPtr(isolate, memory_estimate,
std::move(native_module));
@@ -259,7 +289,7 @@ bool WasmModuleObject::SetBreakPoint(Handle<WasmModuleObject> module_object,
Handle<WeakArrayList> weak_instance_list(module_object->weak_instance_list(),
isolate);
for (int i = 0; i < weak_instance_list->length(); ++i) {
- MaybeObject* maybe_instance = weak_instance_list->Get(i);
+ MaybeObject maybe_instance = weak_instance_list->Get(i);
if (maybe_instance->IsWeak()) {
Handle<WasmInstanceObject> instance(
WasmInstanceObject::cast(maybe_instance->GetHeapObjectAssumeWeak()),
@@ -275,7 +305,7 @@ bool WasmModuleObject::SetBreakPoint(Handle<WasmModuleObject> module_object,
namespace {
-int GetBreakpointPos(Isolate* isolate, Object* break_point_info_or_undef) {
+int GetBreakpointPos(Isolate* isolate, Object break_point_info_or_undef) {
if (break_point_info_or_undef->IsUndefined(isolate)) return kMaxInt;
return BreakPointInfo::cast(break_point_info_or_undef)->source_position();
}
@@ -291,7 +321,7 @@ int FindBreakpointInfoInsertPos(Isolate* isolate,
int right = breakpoint_infos->length(); // exclusive
while (right - left > 1) {
int mid = left + (right - left) / 2;
- Object* mid_obj = breakpoint_infos->get(mid);
+ Object mid_obj = breakpoint_infos->get(mid);
if (GetBreakpointPos(isolate, mid_obj) <= position) {
left = mid;
} else {
@@ -346,7 +376,7 @@ void WasmModuleObject::AddBreakpoint(Handle<WasmModuleObject> module_object,
// Move elements [insert_pos, ...] up by one.
for (int i = breakpoint_infos->length() - 1; i >= insert_pos; --i) {
- Object* entry = breakpoint_infos->get(i);
+ Object entry = breakpoint_infos->get(i);
if (entry->IsUndefined(isolate)) continue;
new_breakpoint_infos->set(i + 1, entry);
}
@@ -414,25 +444,24 @@ Handle<ByteArray> GetDecodedAsmJsOffsetTable(
DCHECK(table_type == Encoded || table_type == Decoded);
if (table_type == Decoded) return offset_table;
- wasm::AsmJsOffsetsResult asm_offsets;
+ wasm::AsmJsOffsets asm_offsets;
{
DisallowHeapAllocation no_gc;
byte* bytes_start = offset_table->GetDataStartAddress();
byte* bytes_end = reinterpret_cast<byte*>(
reinterpret_cast<Address>(bytes_start) + offset_table->length() - 1);
- asm_offsets = wasm::DecodeAsmJsOffsets(bytes_start, bytes_end);
+ asm_offsets = wasm::DecodeAsmJsOffsets(bytes_start, bytes_end).value();
}
// Wasm bytes must be valid and must contain asm.js offset table.
- DCHECK(asm_offsets.ok());
- DCHECK_GE(kMaxInt, asm_offsets.val.size());
- int num_functions = static_cast<int>(asm_offsets.val.size());
+ DCHECK_GE(kMaxInt, asm_offsets.size());
+ int num_functions = static_cast<int>(asm_offsets.size());
int num_imported_functions =
static_cast<int>(module_object->module()->num_imported_functions);
DCHECK_EQ(module_object->module()->functions.size(),
static_cast<size_t>(num_functions) + num_imported_functions);
int num_entries = 0;
for (int func = 0; func < num_functions; ++func) {
- size_t new_size = asm_offsets.val[func].size();
+ size_t new_size = asm_offsets[func].size();
DCHECK_LE(new_size, static_cast<size_t>(kMaxInt) - num_entries);
num_entries += static_cast<int>(new_size);
}
@@ -449,8 +478,7 @@ Handle<ByteArray> GetDecodedAsmJsOffsetTable(
const std::vector<WasmFunction>& wasm_funs =
module_object->module()->functions;
for (int func = 0; func < num_functions; ++func) {
- std::vector<wasm::AsmJsOffsetEntry>& func_asm_offsets =
- asm_offsets.val[func];
+ std::vector<wasm::AsmJsOffsetEntry>& func_asm_offsets = asm_offsets[func];
if (func_asm_offsets.empty()) continue;
int func_offset = wasm_funs[num_imported_functions + func].code.offset();
for (wasm::AsmJsOffsetEntry& e : func_asm_offsets) {
@@ -520,7 +548,7 @@ v8::debug::WasmDisassembly WasmModuleObject::DisassembleFunction(
static_cast<uint32_t>(func_index) >= module()->functions.size())
return {};
- Vector<const byte> wire_bytes = native_module()->wire_bytes();
+ wasm::ModuleWireBytes wire_bytes(native_module()->wire_bytes());
std::ostringstream disassembly_os;
v8::debug::WasmDisassembly::OffsetTable offset_table;
@@ -747,7 +775,7 @@ bool WasmModuleObject::GetPositionInfo(uint32_t position,
}
Handle<WasmTableObject> WasmTableObject::New(Isolate* isolate, uint32_t initial,
- int64_t maximum,
+ uint32_t maximum,
Handle<FixedArray>* js_functions) {
Handle<JSFunction> table_ctor(
isolate->native_context()->wasm_table_constructor(), isolate);
@@ -755,13 +783,12 @@ Handle<WasmTableObject> WasmTableObject::New(Isolate* isolate, uint32_t initial,
isolate->factory()->NewJSObject(table_ctor));
*js_functions = isolate->factory()->NewFixedArray(initial);
- Object* null = ReadOnlyRoots(isolate).null_value();
+ Object null = ReadOnlyRoots(isolate).null_value();
for (int i = 0; i < static_cast<int>(initial); ++i) {
(*js_functions)->set(i, null);
}
table_obj->set_functions(**js_functions);
- DCHECK_EQ(maximum, static_cast<int>(maximum));
- Handle<Object> max = isolate->factory()->NewNumber(maximum);
+ Handle<Object> max = isolate->factory()->NewNumberFromUint(maximum);
table_obj->set_maximum_length(*max);
table_obj->set_dispatch_tables(ReadOnlyRoots(isolate).empty_fixed_array());
@@ -817,7 +844,7 @@ void WasmTableObject::Grow(Isolate* isolate, uint32_t count) {
}
void WasmTableObject::Set(Isolate* isolate, Handle<WasmTableObject> table,
- int32_t table_index, Handle<JSFunction> function) {
+ uint32_t table_index, Handle<JSFunction> function) {
Handle<FixedArray> array(table->functions(), isolate);
if (function.is_null()) {
ClearDispatchTables(isolate, table, table_index); // Degenerate case.
@@ -825,26 +852,23 @@ void WasmTableObject::Set(Isolate* isolate, Handle<WasmTableObject> table,
return;
}
- // TODO(titzer): Change this to MaybeHandle<WasmExportedFunction>
- DCHECK(WasmExportedFunction::IsWasmExportedFunction(*function));
auto exported_function = Handle<WasmExportedFunction>::cast(function);
- Handle<WasmInstanceObject> other_instance(exported_function->instance(),
- isolate);
+ Handle<WasmInstanceObject> target_instance(exported_function->instance(),
+ isolate);
int func_index = exported_function->function_index();
- auto* wasm_function = &other_instance->module()->functions[func_index];
+ auto* wasm_function = &target_instance->module()->functions[func_index];
DCHECK_NOT_NULL(wasm_function);
DCHECK_NOT_NULL(wasm_function->sig);
- Address call_target = exported_function->GetWasmCallTarget();
UpdateDispatchTables(isolate, table, table_index, wasm_function->sig,
handle(exported_function->instance(), isolate),
- call_target);
+ func_index);
array->set(table_index, *function);
}
void WasmTableObject::UpdateDispatchTables(
Isolate* isolate, Handle<WasmTableObject> table, int table_index,
- wasm::FunctionSig* sig, Handle<WasmInstanceObject> from_instance,
- Address call_target) {
+ wasm::FunctionSig* sig, Handle<WasmInstanceObject> target_instance,
+ int target_func_index) {
// We simply need to update the IFTs for each instance that imports
// this table.
Handle<FixedArray> dispatch_tables(table->dispatch_tables(), isolate);
@@ -852,15 +876,15 @@ void WasmTableObject::UpdateDispatchTables(
for (int i = 0; i < dispatch_tables->length();
i += kDispatchTableNumElements) {
- Handle<WasmInstanceObject> to_instance(
+ Handle<WasmInstanceObject> instance(
WasmInstanceObject::cast(
dispatch_tables->get(i + kDispatchTableInstanceOffset)),
isolate);
// Note that {SignatureMap::Find} may return {-1} if the signature is
// not found; it will simply never match any check.
- auto sig_id = to_instance->module()->signature_map.Find(*sig);
- IndirectFunctionTableEntry(to_instance, table_index)
- .set(sig_id, *from_instance, call_target);
+ auto sig_id = instance->module()->signature_map.Find(*sig);
+ IndirectFunctionTableEntry(instance, table_index)
+ .Set(sig_id, target_instance, target_func_index);
}
}
@@ -881,25 +905,12 @@ void WasmTableObject::ClearDispatchTables(Isolate* isolate,
}
namespace {
-MaybeHandle<JSArrayBuffer> GrowMemoryBuffer(Isolate* isolate,
+MaybeHandle<JSArrayBuffer> MemoryGrowBuffer(Isolate* isolate,
Handle<JSArrayBuffer> old_buffer,
- uint32_t pages,
- uint32_t maximum_pages) {
- if (!old_buffer->is_growable()) return {};
- void* old_mem_start = old_buffer->backing_store();
+ size_t new_size) {
+ CHECK_EQ(0, new_size % wasm::kWasmPageSize);
size_t old_size = old_buffer->byte_length();
- CHECK_GE(wasm::kV8MaxWasmMemoryBytes, old_size);
- CHECK_EQ(0, old_size % wasm::kWasmPageSize);
- size_t old_pages = old_size / wasm::kWasmPageSize;
- if (old_pages > maximum_pages || // already reached maximum
- (pages > maximum_pages - old_pages) || // exceeds remaining
- (pages > FLAG_wasm_max_mem_pages - old_pages)) { // exceeds limit
- return {};
- }
- size_t new_size =
- static_cast<size_t>(old_pages + pages) * wasm::kWasmPageSize;
- CHECK_GE(wasm::kV8MaxWasmMemoryBytes, new_size);
-
+ void* old_mem_start = old_buffer->backing_store();
// Reusing the backing store from externalized buffers causes problems with
// Blink's array buffers. The connection between the two is lost, which can
// lead to Blink not knowing about the other reference to the buffer and
@@ -914,8 +925,9 @@ MaybeHandle<JSArrayBuffer> GrowMemoryBuffer(Isolate* isolate,
new_size, PageAllocator::kReadWrite)) {
return {};
}
+ DCHECK_GE(new_size, old_size);
reinterpret_cast<v8::Isolate*>(isolate)
- ->AdjustAmountOfExternalAllocatedMemory(pages * wasm::kWasmPageSize);
+ ->AdjustAmountOfExternalAllocatedMemory(new_size - old_size);
}
// NOTE: We must allocate a new array buffer here because the spec
// assumes that ArrayBuffers do not change size.
@@ -976,7 +988,7 @@ void SetInstanceMemory(Handle<WasmInstanceObject> instance,
Handle<WasmMemoryObject> WasmMemoryObject::New(
Isolate* isolate, MaybeHandle<JSArrayBuffer> maybe_buffer,
- int32_t maximum) {
+ uint32_t maximum) {
// TODO(kschimpf): Do we need to add an argument that defines the
// style of memory the user prefers (with/without trap handling), so
// that the memory will match the style of the compiled wasm module.
@@ -997,11 +1009,6 @@ Handle<WasmMemoryObject> WasmMemoryObject::New(
return memory_obj;
}
-uint32_t WasmMemoryObject::current_pages() {
- return static_cast<uint32_t>(array_buffer()->byte_length() /
- wasm::kWasmPageSize);
-}
-
bool WasmMemoryObject::has_full_guard_region(Isolate* isolate) {
const wasm::WasmMemoryTracker::AllocationData* allocation =
isolate->wasm_engine()->memory_tracker()->FindAllocationData(
@@ -1041,38 +1048,44 @@ void WasmMemoryObject::AddInstance(Isolate* isolate,
SetInstanceMemory(instance, buffer);
}
-void WasmMemoryObject::RemoveInstance(Handle<WasmMemoryObject> memory,
- Handle<WasmInstanceObject> instance) {
- if (memory->has_instances()) {
- memory->instances()->RemoveOne(MaybeObjectHandle::Weak(instance));
- }
-}
-
// static
int32_t WasmMemoryObject::Grow(Isolate* isolate,
Handle<WasmMemoryObject> memory_object,
uint32_t pages) {
+ TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("v8.wasm"), "GrowMemory");
Handle<JSArrayBuffer> old_buffer(memory_object->array_buffer(), isolate);
if (!old_buffer->is_growable()) return -1;
- size_t old_size = old_buffer->byte_length();
- DCHECK_EQ(0, old_size % wasm::kWasmPageSize);
- Handle<JSArrayBuffer> new_buffer;
- uint32_t maximum_pages = FLAG_wasm_max_mem_pages;
+ // Checks for maximum memory size, compute new size.
+ uint32_t maximum_pages = wasm::max_mem_pages();
if (memory_object->has_maximum_pages()) {
- maximum_pages = Min(FLAG_wasm_max_mem_pages,
- static_cast<uint32_t>(memory_object->maximum_pages()));
+ maximum_pages = std::min(
+ maximum_pages, static_cast<uint32_t>(memory_object->maximum_pages()));
+ }
+ CHECK_GE(wasm::max_mem_pages(), maximum_pages);
+ size_t old_size = old_buffer->byte_length();
+ CHECK_EQ(0, old_size % wasm::kWasmPageSize);
+ size_t old_pages = old_size / wasm::kWasmPageSize;
+ CHECK_GE(wasm::max_mem_pages(), old_pages);
+ if ((pages > maximum_pages - old_pages) || // exceeds remaining
+ (pages > wasm::max_mem_pages() - old_pages)) { // exceeds limit
+ return -1;
}
- if (!GrowMemoryBuffer(isolate, old_buffer, pages, maximum_pages)
- .ToHandle(&new_buffer)) {
+ size_t new_size =
+ static_cast<size_t>(old_pages + pages) * wasm::kWasmPageSize;
+
+ // Grow the buffer.
+ Handle<JSArrayBuffer> new_buffer;
+ if (!MemoryGrowBuffer(isolate, old_buffer, new_size).ToHandle(&new_buffer)) {
return -1;
}
+ // Update instances if any.
if (memory_object->has_instances()) {
Handle<WeakArrayList> instances(memory_object->instances(), isolate);
for (int i = 0; i < instances->length(); i++) {
- MaybeObject* elem = instances->Get(i);
- HeapObject* heap_object;
+ MaybeObject elem = instances->Get(i);
+ HeapObject heap_object;
if (elem->GetHeapObjectIfWeak(&heap_object)) {
Handle<WasmInstanceObject> instance(
WasmInstanceObject::cast(heap_object), isolate);
@@ -1088,32 +1101,44 @@ int32_t WasmMemoryObject::Grow(Isolate* isolate,
// static
MaybeHandle<WasmGlobalObject> WasmGlobalObject::New(
- Isolate* isolate, MaybeHandle<JSArrayBuffer> maybe_buffer,
- wasm::ValueType type, int32_t offset, bool is_mutable) {
+ Isolate* isolate, MaybeHandle<JSArrayBuffer> maybe_untagged_buffer,
+ MaybeHandle<FixedArray> maybe_tagged_buffer, wasm::ValueType type,
+ int32_t offset, bool is_mutable) {
Handle<JSFunction> global_ctor(
isolate->native_context()->wasm_global_constructor(), isolate);
auto global_obj = Handle<WasmGlobalObject>::cast(
isolate->factory()->NewJSObject(global_ctor));
- uint32_t type_size = wasm::ValueTypes::ElementSizeInBytes(type);
-
- Handle<JSArrayBuffer> buffer;
- if (!maybe_buffer.ToHandle(&buffer)) {
- // If no buffer was provided, create one long enough for the given type.
- buffer =
- isolate->factory()->NewJSArrayBuffer(SharedFlag::kNotShared, TENURED);
-
- const bool initialize = true;
- if (!JSArrayBuffer::SetupAllocatingData(buffer, isolate, type_size,
- initialize)) {
- return {};
+ if (type == wasm::kWasmAnyRef) {
+ DCHECK(maybe_untagged_buffer.is_null());
+ Handle<FixedArray> tagged_buffer;
+ if (!maybe_tagged_buffer.ToHandle(&tagged_buffer)) {
+ // If no buffer was provided, create one.
+ tagged_buffer = isolate->factory()->NewFixedArray(1, TENURED);
+ CHECK_EQ(offset, 0);
+ }
+ global_obj->set_tagged_buffer(*tagged_buffer);
+ } else {
+ DCHECK(maybe_tagged_buffer.is_null());
+ Handle<JSArrayBuffer> untagged_buffer;
+ uint32_t type_size = wasm::ValueTypes::ElementSizeInBytes(type);
+ if (!maybe_untagged_buffer.ToHandle(&untagged_buffer)) {
+ // If no buffer was provided, create one long enough for the given type.
+ untagged_buffer =
+ isolate->factory()->NewJSArrayBuffer(SharedFlag::kNotShared, TENURED);
+
+ const bool initialize = true;
+ if (!JSArrayBuffer::SetupAllocatingData(untagged_buffer, isolate,
+ type_size, initialize)) {
+ return {};
+ }
}
- }
- // Check that the offset is in bounds.
- CHECK_LE(offset + type_size, buffer->byte_length());
+ // Check that the offset is in bounds.
+ CHECK_LE(offset + type_size, untagged_buffer->byte_length());
- global_obj->set_array_buffer(*buffer);
+ global_obj->set_untagged_buffer(*untagged_buffer);
+ }
global_obj->set_flags(0);
global_obj->set_type(type);
global_obj->set_offset(offset);
@@ -1125,23 +1150,42 @@ MaybeHandle<WasmGlobalObject> WasmGlobalObject::New(
void IndirectFunctionTableEntry::clear() {
instance_->indirect_function_table_sig_ids()[index_] = -1;
instance_->indirect_function_table_targets()[index_] = 0;
- instance_->indirect_function_table_instances()->set(
+ instance_->indirect_function_table_refs()->set(
index_, ReadOnlyRoots(instance_->GetIsolate()).undefined_value());
}
-void IndirectFunctionTableEntry::set(int sig_id, WasmInstanceObject* instance,
- Address call_target) {
- TRACE_IFT("IFT entry %p[%d] = {sig_id=%d, instance=%p, target=%" PRIuPTR
- "}\n",
- *instance_, index_, sig_id, instance, call_target);
+void IndirectFunctionTableEntry::Set(int sig_id,
+ Handle<WasmInstanceObject> target_instance,
+ int target_func_index) {
+ TRACE_IFT(
+ "IFT entry %p[%d] = {sig_id=%d, target_instance=%p, "
+ "target_func_index=%d}\n",
+ reinterpret_cast<void*>(instance_->ptr()), index_, sig_id,
+ reinterpret_cast<void*>(target_instance->ptr()), target_func_index);
+
+ Object ref;
+ Address call_target = 0;
+ if (target_func_index <
+ static_cast<int>(target_instance->module()->num_imported_functions)) {
+ // The function in the target instance was imported. Use its imports table,
+ // which contains a tuple needed by the import wrapper.
+ ImportedFunctionEntry entry(target_instance, target_func_index);
+ ref = entry.object_ref();
+ call_target = entry.target();
+ } else {
+ // The function in the target instance was not imported.
+ ref = *target_instance;
+ call_target = target_instance->GetCallTarget(target_func_index);
+ }
+
+ // Set the signature id, the target, and the receiver ref.
instance_->indirect_function_table_sig_ids()[index_] = sig_id;
instance_->indirect_function_table_targets()[index_] = call_target;
- instance_->indirect_function_table_instances()->set(index_, instance);
+ instance_->indirect_function_table_refs()->set(index_, ref);
}
-WasmInstanceObject* IndirectFunctionTableEntry::instance() {
- return WasmInstanceObject::cast(
- instance_->indirect_function_table_instances()->get(index_));
+Object IndirectFunctionTableEntry::object_ref() {
+ return instance_->indirect_function_table_refs()->get(index_);
}
int IndirectFunctionTableEntry::sig_id() {
@@ -1152,43 +1196,61 @@ Address IndirectFunctionTableEntry::target() {
return instance_->indirect_function_table_targets()[index_];
}
-void ImportedFunctionEntry::set_wasm_to_js(
- JSReceiver* callable, const wasm::WasmCode* wasm_to_js_wrapper) {
- TRACE_IFT("Import callable %p[%d] = {callable=%p, target=%p}\n", *instance_,
- index_, callable, wasm_to_js_wrapper->instructions().start());
+void IndirectFunctionTableEntry::CopyFrom(
+ const IndirectFunctionTableEntry& that) {
+ instance_->indirect_function_table_sig_ids()[index_] =
+ that.instance_->indirect_function_table_sig_ids()[that.index_];
+ instance_->indirect_function_table_targets()[index_] =
+ that.instance_->indirect_function_table_targets()[that.index_];
+ instance_->indirect_function_table_refs()->set(
+ index_, that.instance_->indirect_function_table_refs()->get(that.index_));
+}
+
+void ImportedFunctionEntry::SetWasmToJs(
+ Isolate* isolate, Handle<JSReceiver> callable,
+ const wasm::WasmCode* wasm_to_js_wrapper) {
+ TRACE_IFT("Import callable %p[%d] = {callable=%p, target=%p}\n",
+ reinterpret_cast<void*>(instance_->ptr()), index_,
+ reinterpret_cast<void*>(callable->ptr()),
+ wasm_to_js_wrapper->instructions().start());
DCHECK_EQ(wasm::WasmCode::kWasmToJsWrapper, wasm_to_js_wrapper->kind());
- instance_->imported_function_instances()->set(index_, *instance_);
- instance_->imported_function_callables()->set(index_, callable);
+ Handle<Tuple2> tuple =
+ isolate->factory()->NewTuple2(instance_, callable, TENURED);
+ instance_->imported_function_refs()->set(index_, *tuple);
instance_->imported_function_targets()[index_] =
wasm_to_js_wrapper->instruction_start();
}
-void ImportedFunctionEntry::set_wasm_to_wasm(WasmInstanceObject* instance,
- Address call_target) {
+void ImportedFunctionEntry::SetWasmToWasm(WasmInstanceObject instance,
+ Address call_target) {
TRACE_IFT("Import WASM %p[%d] = {instance=%p, target=%" PRIuPTR "}\n",
- *instance_, index_, instance, call_target);
- instance_->imported_function_instances()->set(index_, instance);
- instance_->imported_function_callables()->set(
- index_, instance_->GetReadOnlyRoots().undefined_value());
+ reinterpret_cast<void*>(instance_->ptr()), index_,
+ reinterpret_cast<void*>(instance->ptr()), call_target);
+ instance_->imported_function_refs()->set(index_, instance);
instance_->imported_function_targets()[index_] = call_target;
}
-WasmInstanceObject* ImportedFunctionEntry::instance() {
- return WasmInstanceObject::cast(
- instance_->imported_function_instances()->get(index_));
+WasmInstanceObject ImportedFunctionEntry::instance() {
+ // The imported reference entry is either a target instance or a tuple
+ // of this instance and the target callable.
+ Object value = instance_->imported_function_refs()->get(index_);
+ if (value->IsWasmInstanceObject()) {
+ return WasmInstanceObject::cast(value);
+ }
+ Tuple2 tuple = Tuple2::cast(value);
+ return WasmInstanceObject::cast(tuple->value1());
}
-JSReceiver* ImportedFunctionEntry::callable() {
- return JSReceiver::cast(
- instance_->imported_function_callables()->get(index_));
+JSReceiver ImportedFunctionEntry::callable() {
+ return JSReceiver::cast(Tuple2::cast(object_ref())->value2());
}
-Address ImportedFunctionEntry::target() {
- return instance_->imported_function_targets()[index_];
+Object ImportedFunctionEntry::object_ref() {
+ return instance_->imported_function_refs()->get(index_);
}
-bool ImportedFunctionEntry::is_js_receiver_entry() {
- return instance_->imported_function_callables()->get(index_)->IsJSReceiver();
+Address ImportedFunctionEntry::target() {
+ return instance_->imported_function_targets()[index_];
}
bool WasmInstanceObject::EnsureIndirectFunctionTableWithMinimumSize(
@@ -1205,7 +1267,7 @@ bool WasmInstanceObject::EnsureIndirectFunctionTableWithMinimumSize(
}
void WasmInstanceObject::SetRawMemory(byte* mem_start, size_t mem_size) {
- CHECK_LE(mem_size, wasm::kV8MaxWasmMemoryBytes);
+ CHECK_LE(mem_size, wasm::max_mem_bytes());
#if V8_HOST_ARCH_64_BIT
uint64_t mem_mask64 = base::bits::RoundUpToPowerOfTwo64(mem_size) - 1;
set_memory_start(mem_start);
@@ -1247,32 +1309,30 @@ Handle<WasmInstanceObject> WasmInstanceObject::New(
isolate->factory()->NewJSObject(instance_cons, TENURED);
Handle<WasmInstanceObject> instance(
- reinterpret_cast<WasmInstanceObject*>(*instance_object), isolate);
+ WasmInstanceObject::cast(*instance_object), isolate);
+ instance->clear_padding();
// Initialize the imported function arrays.
auto module = module_object->module();
auto num_imported_functions = module->num_imported_functions;
auto num_imported_mutable_globals = module->num_imported_mutable_globals;
+ auto num_data_segments = module->num_declared_data_segments;
size_t native_allocations_size = EstimateNativeAllocationsSize(module);
auto native_allocations = Managed<WasmInstanceNativeAllocations>::Allocate(
isolate, native_allocations_size, instance, num_imported_functions,
- num_imported_mutable_globals);
+ num_imported_mutable_globals, num_data_segments,
+ module->elem_segments.size());
instance->set_managed_native_allocations(*native_allocations);
- Handle<FixedArray> imported_function_instances =
- isolate->factory()->NewFixedArray(num_imported_functions);
- instance->set_imported_function_instances(*imported_function_instances);
-
- Handle<FixedArray> imported_function_callables =
+ Handle<FixedArray> imported_function_refs =
isolate->factory()->NewFixedArray(num_imported_functions);
- instance->set_imported_function_callables(*imported_function_callables);
+ instance->set_imported_function_refs(*imported_function_refs);
Handle<Code> centry_stub = CodeFactory::CEntry(isolate);
instance->set_centry_stub(*centry_stub);
instance->SetRawMemory(nullptr, 0);
- instance->set_roots_array_address(
- reinterpret_cast<Address>(isolate->heap()->roots_array_start()));
+ instance->set_isolate_root(isolate->isolate_root());
instance->set_stack_limit_address(
isolate->stack_guard()->address_of_jslimit());
instance->set_real_stack_limit_address(
@@ -1296,9 +1356,54 @@ Handle<WasmInstanceObject> WasmInstanceObject::New(
isolate, weak_instance_list, MaybeObjectHandle::Weak(instance));
module_object->set_weak_instance_list(*weak_instance_list);
+ InitDataSegmentArrays(instance, module_object);
+ InitElemSegmentArrays(instance, module_object);
+
return instance;
}
+// static
+void WasmInstanceObject::InitDataSegmentArrays(
+ Handle<WasmInstanceObject> instance,
+ Handle<WasmModuleObject> module_object) {
+ auto module = module_object->module();
+ auto wire_bytes = module_object->native_module()->wire_bytes();
+ auto num_data_segments = module->num_declared_data_segments;
+ // The number of declared data segments will be zero if there is no DataCount
+ // section. These arrays will not be allocated nor initialized in that case,
+ // since they cannot be used (since the validator checks that number of
+ // declared data segments when validating the memory.init and memory.drop
+ // instructions).
+ DCHECK(num_data_segments == 0 ||
+ num_data_segments == module->data_segments.size());
+ for (size_t i = 0; i < num_data_segments; ++i) {
+ const wasm::WasmDataSegment& segment = module->data_segments[i];
+ // Set the active segments to being already dropped, since memory.init on
+ // a dropped passive segment and an active segment have the same
+ // behavior.
+ instance->dropped_data_segments()[i] = segment.active ? 1 : 0;
+
+ // Initialize the pointer and size of passive segments.
+ instance->data_segment_starts()[i] =
+ reinterpret_cast<Address>(&wire_bytes[segment.source.offset()]);
+ instance->data_segment_sizes()[i] = segment.source.length();
+ }
+}
+
+void WasmInstanceObject::InitElemSegmentArrays(
+ Handle<WasmInstanceObject> instance,
+ Handle<WasmModuleObject> module_object) {
+ auto module = module_object->module();
+ auto num_elem_segments = module->elem_segments.size();
+ for (size_t i = 0; i < num_elem_segments; ++i) {
+ const wasm::WasmElemSegment& segment = module->elem_segments[i];
+ // Set the active segments to being already dropped, since table.init on
+ // a dropped passive segment and an active segment have the same
+ // behavior.
+ instance->dropped_elem_segments()[i] = segment.active ? 1 : 0;
+ }
+}
+
Address WasmInstanceObject::GetCallTarget(uint32_t func_index) {
wasm::NativeModule* native_module = module_object()->native_module();
if (func_index < native_module->num_imported_functions()) {
@@ -1307,6 +1412,71 @@ Address WasmInstanceObject::GetCallTarget(uint32_t func_index) {
return native_module->GetCallTargetForFunction(func_index);
}
+namespace {
+void CopyTableEntriesImpl(Handle<WasmInstanceObject> instance, uint32_t dst,
+ uint32_t src, uint32_t count) {
+ DCHECK(IsInBounds(dst, count, instance->indirect_function_table_size()));
+ if (src < dst) {
+ for (uint32_t i = count; i > 0; i--) {
+ auto to_entry = IndirectFunctionTableEntry(instance, dst + i - 1);
+ auto from_entry = IndirectFunctionTableEntry(instance, src + i - 1);
+ to_entry.CopyFrom(from_entry);
+ }
+ } else {
+ for (uint32_t i = 0; i < count; i++) {
+ auto to_entry = IndirectFunctionTableEntry(instance, dst + i);
+ auto from_entry = IndirectFunctionTableEntry(instance, src + i);
+ to_entry.CopyFrom(from_entry);
+ }
+ }
+}
+} // namespace
+
+// static
+bool WasmInstanceObject::CopyTableEntries(Isolate* isolate,
+ Handle<WasmInstanceObject> instance,
+ uint32_t table_index, uint32_t dst,
+ uint32_t src, uint32_t count) {
+ CHECK_EQ(0, table_index); // TODO(titzer): multiple tables in TableCopy
+ if (count == 0) return true; // no-op
+ auto max = instance->indirect_function_table_size();
+ if (!IsInBounds(dst, count, max)) return false;
+ if (!IsInBounds(src, count, max)) return false;
+ if (dst == src) return true; // no-op
+
+ if (!instance->has_table_object()) {
+ // No table object, only need to update this instance.
+ CopyTableEntriesImpl(instance, dst, src, count);
+ return true;
+ }
+
+ Handle<WasmTableObject> table =
+ Handle<WasmTableObject>(instance->table_object(), isolate);
+ // Broadcast table copy operation to all instances that import this table.
+ Handle<FixedArray> dispatch_tables(table->dispatch_tables(), isolate);
+ for (int i = 0; i < dispatch_tables->length();
+ i += kDispatchTableNumElements) {
+ Handle<WasmInstanceObject> target_instance(
+ WasmInstanceObject::cast(
+ dispatch_tables->get(i + kDispatchTableInstanceOffset)),
+ isolate);
+ CopyTableEntriesImpl(target_instance, dst, src, count);
+ }
+
+ // Copy the function entries.
+ Handle<FixedArray> functions(table->functions(), isolate);
+ if (src < dst) {
+ for (uint32_t i = count; i > 0; i--) {
+ functions->set(dst + i - 1, functions->get(src + i - 1));
+ }
+ } else {
+ for (uint32_t i = 0; i < count; i++) {
+ functions->set(dst + i, functions->get(src + i));
+ }
+ }
+ return true;
+}
+
// static
Handle<WasmExceptionObject> WasmExceptionObject::New(
Isolate* isolate, const wasm::FunctionSig* sig,
@@ -1347,20 +1517,15 @@ bool WasmExceptionObject::IsSignatureEqual(const wasm::FunctionSig* sig) {
return true;
}
-bool WasmExportedFunction::IsWasmExportedFunction(Object* object) {
+bool WasmExportedFunction::IsWasmExportedFunction(Object object) {
if (!object->IsJSFunction()) return false;
- JSFunction* js_function = JSFunction::cast(object);
+ JSFunction js_function = JSFunction::cast(object);
if (Code::JS_TO_WASM_FUNCTION != js_function->code()->kind()) return false;
DCHECK(js_function->shared()->HasWasmExportedFunctionData());
return true;
}
-WasmExportedFunction* WasmExportedFunction::cast(Object* object) {
- DCHECK(IsWasmExportedFunction(object));
- return reinterpret_cast<WasmExportedFunction*>(object);
-}
-
-WasmInstanceObject* WasmExportedFunction::instance() {
+WasmInstanceObject WasmExportedFunction::instance() {
return shared()->wasm_exported_function_data()->instance();
}
@@ -1413,6 +1578,37 @@ Address WasmExportedFunction::GetWasmCallTarget() {
return instance()->GetCallTarget(function_index());
}
+wasm::FunctionSig* WasmExportedFunction::sig() {
+ return instance()->module()->functions[function_index()].sig;
+}
+
+Handle<WasmExceptionTag> WasmExceptionTag::New(Isolate* isolate, int index) {
+ Handle<WasmExceptionTag> result = Handle<WasmExceptionTag>::cast(
+ isolate->factory()->NewStruct(WASM_EXCEPTION_TAG_TYPE, TENURED));
+ result->set_index(index);
+ return result;
+}
+
+Handle<AsmWasmData> AsmWasmData::New(
+ Isolate* isolate, std::shared_ptr<wasm::NativeModule> native_module,
+ Handle<FixedArray> export_wrappers, Handle<ByteArray> asm_js_offset_table,
+ Handle<HeapNumber> uses_bitset) {
+ const WasmModule* module = native_module->module();
+ size_t memory_estimate =
+ wasm::WasmCodeManager::EstimateNativeModuleCodeSize(module) +
+ wasm::WasmCodeManager::EstimateNativeModuleNonCodeSize(module);
+ Handle<Managed<wasm::NativeModule>> managed_native_module =
+ Managed<wasm::NativeModule>::FromSharedPtr(isolate, memory_estimate,
+ std::move(native_module));
+ Handle<AsmWasmData> result = Handle<AsmWasmData>::cast(
+ isolate->factory()->NewStruct(ASM_WASM_DATA_TYPE, TENURED));
+ result->set_managed_native_module(*managed_native_module);
+ result->set_export_wrappers(*export_wrappers);
+ result->set_asm_js_offset_table(*asm_js_offset_table);
+ result->set_uses_bitset(*uses_bitset);
+ return result;
+}
+
#undef TRACE
#undef TRACE_IFT
} // namespace internal