summaryrefslogtreecommitdiff
path: root/chromium/v8/src/wasm/wasm-objects.cc
diff options
context:
space:
mode:
Diffstat (limited to 'chromium/v8/src/wasm/wasm-objects.cc')
-rw-r--r--chromium/v8/src/wasm/wasm-objects.cc341
1 files changed, 247 insertions, 94 deletions
diff --git a/chromium/v8/src/wasm/wasm-objects.cc b/chromium/v8/src/wasm/wasm-objects.cc
index 6a0be1d81d2..392ddd4ca83 100644
--- a/chromium/v8/src/wasm/wasm-objects.cc
+++ b/chromium/v8/src/wasm/wasm-objects.cc
@@ -14,6 +14,7 @@
#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"
@@ -65,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_);
@@ -82,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,
@@ -123,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();
}
@@ -278,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();
}
@@ -294,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 {
@@ -349,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);
}
@@ -521,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;
@@ -748,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);
@@ -756,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());
@@ -818,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.
@@ -826,8 +852,6 @@ 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> target_instance(exported_function->instance(),
isolate);
@@ -883,23 +907,10 @@ void WasmTableObject::ClearDispatchTables(Isolate* isolate,
namespace {
MaybeHandle<JSArrayBuffer> MemoryGrowBuffer(Isolate* isolate,
Handle<JSArrayBuffer> old_buffer,
- uint32_t pages,
- uint32_t maximum_pages) {
- CHECK_GE(wasm::max_mem_pages(), 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_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 {};
- }
- size_t new_size =
- static_cast<size_t>(old_pages + pages) * wasm::kWasmPageSize;
-
+ 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> MemoryGrowBuffer(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,13 +1048,6 @@ 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,
@@ -1055,25 +1055,37 @@ int32_t WasmMemoryObject::Grow(Isolate* isolate,
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;
+ // Checks for maximum memory size, compute new size.
uint32_t maximum_pages = wasm::max_mem_pages();
if (memory_object->has_maximum_pages()) {
maximum_pages = std::min(
maximum_pages, static_cast<uint32_t>(memory_object->maximum_pages()));
}
- if (!MemoryGrowBuffer(isolate, old_buffer, pages, maximum_pages)
- .ToHandle(&new_buffer)) {
+ 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;
+ }
+ 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;
+ HeapObject heap_object;
if (elem->GetHeapObjectIfWeak(&heap_object)) {
Handle<WasmInstanceObject> instance(
WasmInstanceObject::cast(heap_object), isolate);
@@ -1089,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);
@@ -1136,9 +1160,10 @@ void IndirectFunctionTableEntry::Set(int sig_id,
TRACE_IFT(
"IFT entry %p[%d] = {sig_id=%d, target_instance=%p, "
"target_func_index=%d}\n",
- *instance_, index_, sig_id, *target_instance, target_func_index);
+ reinterpret_cast<void*>(instance_->ptr()), index_, sig_id,
+ reinterpret_cast<void*>(target_instance->ptr()), target_func_index);
- Object* ref = nullptr;
+ Object ref;
Address call_target = 0;
if (target_func_index <
static_cast<int>(target_instance->module()->num_imported_functions)) {
@@ -1159,7 +1184,7 @@ void IndirectFunctionTableEntry::Set(int sig_id,
instance_->indirect_function_table_refs()->set(index_, ref);
}
-Object* IndirectFunctionTableEntry::object_ref() {
+Object IndirectFunctionTableEntry::object_ref() {
return instance_->indirect_function_table_refs()->get(index_);
}
@@ -1171,11 +1196,23 @@ Address IndirectFunctionTableEntry::target() {
return instance_->indirect_function_table_targets()[index_];
}
+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", *instance_,
- index_, *callable, wasm_to_js_wrapper->instructions().start());
+ 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());
Handle<Tuple2> tuple =
isolate->factory()->NewTuple2(instance_, callable, TENURED);
@@ -1184,30 +1221,31 @@ void ImportedFunctionEntry::SetWasmToJs(
wasm_to_js_wrapper->instruction_start();
}
-void ImportedFunctionEntry::SetWasmToWasm(WasmInstanceObject* instance,
+void ImportedFunctionEntry::SetWasmToWasm(WasmInstanceObject instance,
Address call_target) {
TRACE_IFT("Import WASM %p[%d] = {instance=%p, target=%" PRIuPTR "}\n",
- *instance_, index_, instance, call_target);
+ 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() {
+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_);
+ Object value = instance_->imported_function_refs()->get(index_);
if (value->IsWasmInstanceObject()) {
return WasmInstanceObject::cast(value);
}
- Tuple2* tuple = Tuple2::cast(value);
+ Tuple2 tuple = Tuple2::cast(value);
return WasmInstanceObject::cast(tuple->value1());
}
-JSReceiver* ImportedFunctionEntry::callable() {
+JSReceiver ImportedFunctionEntry::callable() {
return JSReceiver::cast(Tuple2::cast(object_ref())->value2());
}
-Object* ImportedFunctionEntry::object_ref() {
+Object ImportedFunctionEntry::object_ref() {
return instance_->imported_function_refs()->get(index_);
}
@@ -1271,16 +1309,19 @@ 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_refs =
@@ -1315,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()) {
@@ -1326,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,
@@ -1366,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();
}
@@ -1436,6 +1582,13 @@ 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,