summaryrefslogtreecommitdiff
path: root/deps/v8/src/wasm/wasm-objects.cc
diff options
context:
space:
mode:
authorMichaƫl Zasso <targos@protonmail.com>2018-01-24 20:16:06 +0100
committerMyles Borins <mylesborins@google.com>2018-01-24 15:02:20 -0800
commit4c4af643e5042d615a60c6bbc05aee9d81b903e5 (patch)
tree3fb0a97988fe4439ae3ae06f26915d1dcf8cab92 /deps/v8/src/wasm/wasm-objects.cc
parentfa9f31a4fda5a3782c652e56e394465805ebb50f (diff)
downloadnode-new-4c4af643e5042d615a60c6bbc05aee9d81b903e5.tar.gz
deps: update V8 to 6.4.388.40
PR-URL: https://github.com/nodejs/node/pull/17489 Reviewed-By: Colin Ihrig <cjihrig@gmail.com> Reviewed-By: Matteo Collina <matteo.collina@gmail.com> Reviewed-By: Myles Borins <myles.borins@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.cc612
1 files changed, 439 insertions, 173 deletions
diff --git a/deps/v8/src/wasm/wasm-objects.cc b/deps/v8/src/wasm/wasm-objects.cc
index 012aa6644b..565f38a9e7 100644
--- a/deps/v8/src/wasm/wasm-objects.cc
+++ b/deps/v8/src/wasm/wasm-objects.cc
@@ -11,6 +11,7 @@
#include "src/debug/debug-interface.h"
#include "src/objects-inl.h"
#include "src/objects/debug-objects-inl.h"
+#include "src/trap-handler/trap-handler.h"
#include "src/wasm/module-compiler.h"
#include "src/wasm/module-decoder.h"
#include "src/wasm/wasm-code-specialization.h"
@@ -62,25 +63,17 @@ class CompiledModulesIterator
void Advance() {
DCHECK(!current_.is_null());
if (!is_backwards_) {
- if (current_->has_weak_next_instance()) {
- WeakCell* weak_next = current_->ptr_to_weak_next_instance();
- if (!weak_next->cleared()) {
- current_ =
- handle(WasmCompiledModule::cast(weak_next->value()), isolate_);
- return;
- }
+ if (current_->has_next_instance()) {
+ current_ = current_->next_instance();
+ return;
}
// No more modules in next-links, now try the previous-links.
is_backwards_ = true;
current_ = start_module_;
}
- if (current_->has_weak_prev_instance()) {
- WeakCell* weak_prev = current_->ptr_to_weak_prev_instance();
- if (!weak_prev->cleared()) {
- current_ =
- handle(WasmCompiledModule::cast(weak_prev->value()), isolate_);
- return;
- }
+ if (current_->has_prev_instance()) {
+ current_ = current_->prev_instance();
+ return;
}
current_ = Handle<WasmCompiledModule>::null();
}
@@ -158,6 +151,14 @@ bool IsBreakablePosition(Handle<WasmCompiledModule> compiled_module,
}
#endif // DEBUG
+void CompiledModuleFinalizer(const v8::WeakCallbackInfo<void>& data) {
+ DisallowHeapAllocation no_gc;
+ JSObject** p = reinterpret_cast<JSObject**>(data.GetParameter());
+ WasmCompiledModule* compiled_module = WasmCompiledModule::cast(*p);
+ compiled_module->reset_native_module();
+ GlobalHandles::Destroy(reinterpret_cast<Object**>(p));
+}
+
} // namespace
Handle<WasmModuleObject> WasmModuleObject::New(
@@ -179,8 +180,8 @@ void WasmModuleObject::ValidateStateForTesting(
WasmCompiledModule* compiled_module = module_obj->compiled_module();
CHECK(compiled_module->has_weak_wasm_module());
CHECK_EQ(compiled_module->ptr_to_weak_wasm_module()->value(), *module_obj);
- CHECK(!compiled_module->has_weak_prev_instance());
- CHECK(!compiled_module->has_weak_next_instance());
+ CHECK(!compiled_module->has_prev_instance());
+ CHECK(!compiled_module->has_next_instance());
CHECK(!compiled_module->has_weak_owning_instance());
}
@@ -233,6 +234,8 @@ Handle<FixedArray> WasmTableObject::AddDispatchTable(
}
void WasmTableObject::Grow(Isolate* isolate, uint32_t count) {
+ // TODO(6792): No longer needed once WebAssembly code is off heap.
+ CodeSpaceMemoryModificationScope modification_scope(isolate->heap());
Handle<FixedArray> dispatch_tables(this->dispatch_tables());
DCHECK_EQ(0, dispatch_tables->length() % 4);
uint32_t old_size = functions()->length();
@@ -258,7 +261,27 @@ void WasmTableObject::Grow(Isolate* isolate, uint32_t count) {
dispatch_tables->set(i + 3, *new_signature_table);
// Patch the code of the respective instance.
- {
+ if (FLAG_wasm_jit_to_native) {
+ DisallowHeapAllocation no_gc;
+ wasm::CodeSpecialization code_specialization(isolate,
+ &specialization_zone);
+ WasmInstanceObject* instance =
+ WasmInstanceObject::cast(dispatch_tables->get(i));
+ WasmCompiledModule* compiled_module = instance->compiled_module();
+ wasm::NativeModule* native_module = compiled_module->GetNativeModule();
+ GlobalHandleAddress old_function_table_addr =
+ native_module->function_tables()[table_index];
+ GlobalHandleAddress old_signature_table_addr =
+ native_module->signature_tables()[table_index];
+ code_specialization.PatchTableSize(old_size, old_size + count);
+ code_specialization.RelocatePointer(old_function_table_addr,
+ new_function_table_addr);
+ code_specialization.RelocatePointer(old_signature_table_addr,
+ new_signature_table_addr);
+ code_specialization.ApplyToWholeInstance(instance);
+ native_module->function_tables()[table_index] = new_function_table_addr;
+ native_module->signature_tables()[table_index] = new_signature_table_addr;
+ } else {
DisallowHeapAllocation no_gc;
wasm::CodeSpecialization code_specialization(isolate,
&specialization_zone);
@@ -294,18 +317,24 @@ void WasmTableObject::Set(Isolate* isolate, Handle<WasmTableObject> table,
Handle<FixedArray> dispatch_tables(table->dispatch_tables(), isolate);
WasmFunction* wasm_function = nullptr;
- Handle<Code> code = Handle<Code>::null();
+ Handle<Object> code = Handle<Object>::null();
Handle<Object> value = isolate->factory()->null_value();
if (!function.is_null()) {
+ auto exported_function = Handle<WasmExportedFunction>::cast(function);
wasm_function = wasm::GetWasmFunctionForExport(isolate, function);
// The verification that {function} is an export was done
// by the caller.
DCHECK_NOT_NULL(wasm_function);
- code = wasm::UnwrapExportWrapper(function);
- value = Handle<Object>::cast(function);
+ value = function;
+ // TODO(titzer): Make JSToWasm wrappers just call the WASM to WASM wrapper,
+ // and then we can just reuse the WASM to WASM wrapper.
+ WasmCodeWrapper wasm_code = exported_function->GetWasmCode();
+ CodeSpaceMemoryModificationScope gc_modification_scope(isolate->heap());
+ code = wasm::GetOrCreateIndirectCallWrapper(
+ isolate, handle(exported_function->instance()), wasm_code,
+ exported_function->function_index(), wasm_function->sig);
}
-
UpdateDispatchTables(isolate, dispatch_tables, index, wasm_function, code);
array->set(index, *value);
}
@@ -361,45 +390,44 @@ Handle<JSArrayBuffer> GrowMemoryBuffer(Isolate* isolate,
// May GC, because SetSpecializationMemInfoFrom may GC
void SetInstanceMemory(Isolate* isolate, Handle<WasmInstanceObject> instance,
Handle<JSArrayBuffer> buffer) {
- instance->set_memory_buffer(*buffer);
- if (instance->has_debug_info()) {
- instance->debug_info()->UpdateMemory(*buffer);
+ auto wasm_context = instance->wasm_context()->get();
+ wasm_context->SetRawMemory(reinterpret_cast<byte*>(buffer->backing_store()),
+ buffer->byte_length()->Number());
+#if DEBUG
+ // To flush out bugs earlier, in DEBUG mode, check that all pages of the
+ // memory are accessible by reading and writing one byte on each page.
+ for (uint32_t offset = 0; offset < wasm_context->mem_size;
+ offset += WasmModule::kPageSize) {
+ byte val = wasm_context->mem_start[offset];
+ wasm_context->mem_start[offset] = val;
}
-}
-
-void UpdateWasmContext(WasmContext* wasm_context,
- Handle<JSArrayBuffer> buffer) {
- uint32_t new_mem_size = buffer->byte_length()->Number();
- Address new_mem_start = static_cast<Address>(buffer->backing_store());
- DCHECK_NOT_NULL(new_mem_start);
- wasm_context->mem_start = new_mem_start;
- wasm_context->mem_size = new_mem_size;
+#endif
}
} // namespace
-Handle<WasmMemoryObject> WasmMemoryObject::New(Isolate* isolate,
- Handle<JSArrayBuffer> buffer,
- int32_t maximum) {
+Handle<WasmMemoryObject> WasmMemoryObject::New(
+ Isolate* isolate, MaybeHandle<JSArrayBuffer> maybe_buffer,
+ int32_t maximum) {
Handle<JSFunction> memory_ctor(
isolate->native_context()->wasm_memory_constructor());
auto memory_obj = Handle<WasmMemoryObject>::cast(
isolate->factory()->NewJSObject(memory_ctor, TENURED));
- auto wasm_context = Managed<WasmContext>::Allocate(isolate);
- if (buffer.is_null()) {
- const bool enable_guard_regions = trap_handler::UseTrapHandler();
+
+ Handle<JSArrayBuffer> buffer;
+ if (maybe_buffer.is_null()) {
+ // If no buffer was provided, create a 0-length one.
buffer = wasm::SetupArrayBuffer(isolate, nullptr, 0, nullptr, 0, false,
- enable_guard_regions);
- wasm_context->get()->mem_size = 0;
- wasm_context->get()->mem_start = nullptr;
+ trap_handler::UseTrapHandler());
} else {
- CHECK(buffer->byte_length()->ToUint32(&wasm_context->get()->mem_size));
- wasm_context->get()->mem_start =
- static_cast<Address>(buffer->backing_store());
+ buffer = maybe_buffer.ToHandleChecked();
+ // Paranoid check that the buffer size makes sense.
+ uint32_t mem_size = 0;
+ CHECK(buffer->byte_length()->ToUint32(&mem_size));
}
memory_obj->set_array_buffer(*buffer);
memory_obj->set_maximum_pages(maximum);
- memory_obj->set_wasm_context(*wasm_context);
+
return memory_obj;
}
@@ -419,6 +447,8 @@ void WasmMemoryObject::AddInstance(Isolate* isolate,
Handle<WeakFixedArray> new_instances =
WeakFixedArray::Add(old_instances, instance);
memory->set_instances(*new_instances);
+ Handle<JSArrayBuffer> buffer(memory->array_buffer(), isolate);
+ SetInstanceMemory(isolate, instance, buffer);
}
void WasmMemoryObject::RemoveInstance(Isolate* isolate,
@@ -463,29 +493,19 @@ int32_t WasmMemoryObject::Grow(Isolate* isolate,
if (!old_buffer->is_growable()) return -1;
uint32_t old_size = 0;
CHECK(old_buffer->byte_length()->ToUint32(&old_size));
+ DCHECK_EQ(0, old_size % WasmModule::kPageSize);
Handle<JSArrayBuffer> new_buffer;
// Return current size if grow by 0.
- if (pages == 0) {
- DCHECK_EQ(0, old_size % WasmModule::kPageSize);
- return old_size / WasmModule::kPageSize;
- }
+ if (pages == 0) return old_size / WasmModule::kPageSize;
- uint32_t maximum_pages;
+ uint32_t maximum_pages = FLAG_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()));
- } else {
- maximum_pages = FLAG_wasm_max_mem_pages;
}
new_buffer = GrowMemoryBuffer(isolate, old_buffer, pages, maximum_pages);
if (new_buffer.is_null()) return -1;
- // Verify that the values we will change are actually the ones we expect.
- DCHECK_EQ(memory_object->wasm_context()->get()->mem_size, old_size);
- DCHECK_EQ(memory_object->wasm_context()->get()->mem_start,
- static_cast<Address>(old_buffer->backing_store()));
- UpdateWasmContext(memory_object->wasm_context()->get(), new_buffer);
-
if (memory_object->has_instances()) {
Handle<WeakFixedArray> instances(memory_object->instances(), isolate);
for (int i = 0; i < instances->Length(); i++) {
@@ -497,7 +517,6 @@ int32_t WasmMemoryObject::Grow(Isolate* isolate,
}
}
memory_object->set_array_buffer(*new_buffer);
- DCHECK_EQ(0, old_size % WasmModule::kPageSize);
return old_size / WasmModule::kPageSize;
}
@@ -505,11 +524,6 @@ WasmModuleObject* WasmInstanceObject::module_object() {
return *compiled_module()->wasm_module();
}
-WasmContext* WasmInstanceObject::wasm_context() {
- DCHECK(has_memory_object());
- return memory_object()->wasm_context()->get();
-}
-
WasmModule* WasmInstanceObject::module() { return compiled_module()->module(); }
Handle<WasmDebugInfo> WasmInstanceObject::GetOrCreateDebugInfo(
@@ -530,13 +544,18 @@ Handle<WasmInstanceObject> WasmInstanceObject::New(
Handle<WasmInstanceObject> instance(
reinterpret_cast<WasmInstanceObject*>(*instance_object), isolate);
+ auto wasm_context = Managed<WasmContext>::Allocate(isolate);
+ wasm_context->get()->SetRawMemory(nullptr, 0);
+ wasm_context->get()->globals_start = nullptr;
+ instance->set_wasm_context(*wasm_context);
+
instance->set_compiled_module(*compiled_module);
return instance;
}
int32_t WasmInstanceObject::GetMemorySize() {
- if (!has_memory_buffer()) return 0;
- uint32_t bytes = memory_buffer()->byte_length()->Number();
+ if (!has_memory_object()) return 0;
+ uint32_t bytes = memory_object()->array_buffer()->byte_length()->Number();
DCHECK_EQ(0, bytes % WasmModule::kPageSize);
return bytes / WasmModule::kPageSize;
}
@@ -567,7 +586,20 @@ uint32_t WasmInstanceObject::GetMaxMemoryPages() {
return FLAG_wasm_max_mem_pages;
}
-WasmInstanceObject* WasmInstanceObject::GetOwningInstance(Code* code) {
+WasmInstanceObject* WasmInstanceObject::GetOwningInstance(
+ const wasm::WasmCode* code) {
+ DisallowHeapAllocation no_gc;
+ Object* weak_link = nullptr;
+ DCHECK(code->kind() == wasm::WasmCode::Function ||
+ code->kind() == wasm::WasmCode::InterpreterStub);
+ weak_link = code->owner()->compiled_module()->ptr_to_weak_owning_instance();
+ DCHECK(weak_link->IsWeakCell());
+ WeakCell* cell = WeakCell::cast(weak_link);
+ if (cell->cleared()) return nullptr;
+ return WasmInstanceObject::cast(cell->value());
+}
+
+WasmInstanceObject* WasmInstanceObject::GetOwningInstanceGC(Code* code) {
DisallowHeapAllocation no_gc;
DCHECK(code->kind() == Code::WASM_FUNCTION ||
code->kind() == Code::WASM_INTERPRETER_ENTRY);
@@ -591,16 +623,16 @@ void WasmInstanceObject::ValidateInstancesChainForTesting(
Object* prev = nullptr;
int found_instances = compiled_module->has_weak_owning_instance() ? 1 : 0;
WasmCompiledModule* current_instance = compiled_module;
- while (current_instance->has_weak_next_instance()) {
- CHECK((prev == nullptr && !current_instance->has_weak_prev_instance()) ||
- current_instance->ptr_to_weak_prev_instance()->value() == prev);
+ while (current_instance->has_next_instance()) {
+ CHECK((prev == nullptr && !current_instance->has_prev_instance()) ||
+ current_instance->ptr_to_prev_instance() == prev);
CHECK_EQ(current_instance->ptr_to_weak_wasm_module()->value(), *module_obj);
CHECK(current_instance->ptr_to_weak_owning_instance()
->value()
->IsWasmInstanceObject());
prev = current_instance;
- current_instance = WasmCompiledModule::cast(
- current_instance->ptr_to_weak_next_instance()->value());
+ current_instance =
+ WasmCompiledModule::cast(current_instance->ptr_to_next_instance());
++found_instances;
CHECK_LE(found_instances, instance_count);
}
@@ -668,8 +700,9 @@ Handle<WasmExportedFunction> WasmExportedFunction::New(
isolate->factory()->NewSharedFunctionInfo(name, export_wrapper, false);
shared->set_length(arity);
shared->set_internal_formal_parameter_count(arity);
- Handle<JSFunction> js_function = isolate->factory()->NewFunction(
- isolate->sloppy_function_map(), name, export_wrapper);
+ NewFunctionArgs args = NewFunctionArgs::ForWasm(
+ name, export_wrapper, isolate->sloppy_function_map());
+ Handle<JSFunction> js_function = isolate->factory()->NewFunction(args);
js_function->set_shared(*shared);
Handle<Symbol> instance_symbol(isolate->factory()->wasm_instance_symbol());
@@ -683,6 +716,49 @@ Handle<WasmExportedFunction> WasmExportedFunction::New(
return Handle<WasmExportedFunction>::cast(js_function);
}
+WasmCodeWrapper WasmExportedFunction::GetWasmCode() {
+ DisallowHeapAllocation no_gc;
+ Handle<Code> export_wrapper_code = handle(this->code());
+ DCHECK_EQ(export_wrapper_code->kind(), Code::JS_TO_WASM_FUNCTION);
+ int mask =
+ RelocInfo::ModeMask(FLAG_wasm_jit_to_native ? RelocInfo::JS_TO_WASM_CALL
+ : RelocInfo::CODE_TARGET);
+ auto IsWasmFunctionCode = [](Code* code) {
+ return code->kind() == Code::WASM_FUNCTION ||
+ code->kind() == Code::WASM_TO_JS_FUNCTION ||
+ code->kind() == Code::WASM_TO_WASM_FUNCTION ||
+ code->kind() == Code::WASM_INTERPRETER_ENTRY ||
+ code->builtin_index() == Builtins::kWasmCompileLazy;
+ };
+
+ for (RelocIterator it(*export_wrapper_code, mask);; it.next()) {
+ DCHECK(!it.done());
+ WasmCodeWrapper target;
+ if (FLAG_wasm_jit_to_native) {
+ target = WasmCodeWrapper(GetIsolate()->wasm_code_manager()->LookupCode(
+ it.rinfo()->js_to_wasm_address()));
+ } else {
+ Code* code = Code::GetCodeFromTargetAddress(it.rinfo()->target_address());
+ if (!IsWasmFunctionCode(code)) continue;
+ target = WasmCodeWrapper(handle(code));
+ }
+// There should only be this one call to wasm code.
+#ifdef DEBUG
+ for (it.next(); !it.done(); it.next()) {
+ if (FLAG_wasm_jit_to_native) {
+ UNREACHABLE();
+ } else {
+ Code* code =
+ Code::GetCodeFromTargetAddress(it.rinfo()->target_address());
+ DCHECK(!IsWasmFunctionCode(code));
+ }
+ }
+#endif
+ return target;
+ }
+ UNREACHABLE();
+}
+
bool WasmSharedModuleData::IsWasmSharedModuleData(Object* object) {
if (!object->IsFixedArray()) return false;
FixedArray* arr = FixedArray::cast(object);
@@ -916,8 +992,8 @@ void WasmSharedModuleData::PrepareForLazyCompilation(
}
Handle<WasmCompiledModule> WasmCompiledModule::New(
- Isolate* isolate, Handle<WasmSharedModuleData> shared,
- Handle<FixedArray> code_table, Handle<FixedArray> export_wrappers,
+ Isolate* isolate, WasmModule* module, Handle<FixedArray> code_table,
+ Handle<FixedArray> export_wrappers,
const std::vector<GlobalHandleAddress>& function_tables,
const std::vector<GlobalHandleAddress>& signature_tables) {
DCHECK_EQ(function_tables.size(), signature_tables.size());
@@ -926,40 +1002,75 @@ Handle<WasmCompiledModule> WasmCompiledModule::New(
// WasmCompiledModule::cast would fail since fields are not set yet.
Handle<WasmCompiledModule> compiled_module(
reinterpret_cast<WasmCompiledModule*>(*ret), isolate);
- compiled_module->InitId();
- compiled_module->set_shared(shared);
compiled_module->set_native_context(isolate->native_context());
- compiled_module->set_code_table(code_table);
- compiled_module->set_export_wrappers(export_wrappers);
- // TODO(mtrofin): we copy these because the order of finalization isn't
- // reliable, and we need these at Reset (which is called at
- // finalization). If the order were reliable, and top-down, we could instead
- // just get them from shared().
- compiled_module->set_initial_pages(shared->module()->initial_pages);
- compiled_module->set_num_imported_functions(
- shared->module()->num_imported_functions);
-
- int num_function_tables = static_cast<int>(function_tables.size());
- if (num_function_tables > 0) {
- Handle<FixedArray> st =
- isolate->factory()->NewFixedArray(num_function_tables, TENURED);
- Handle<FixedArray> ft =
- isolate->factory()->NewFixedArray(num_function_tables, TENURED);
- for (int i = 0; i < num_function_tables; ++i) {
- size_t index = static_cast<size_t>(i);
- SetTableValue(isolate, ft, i, function_tables[index]);
- SetTableValue(isolate, st, i, signature_tables[index]);
+ if (!FLAG_wasm_jit_to_native) {
+ compiled_module->InitId();
+ compiled_module->set_native_context(isolate->native_context());
+ compiled_module->set_code_table(code_table);
+ compiled_module->set_export_wrappers(export_wrappers);
+ // TODO(mtrofin): we copy these because the order of finalization isn't
+ // reliable, and we need these at Reset (which is called at
+ // finalization). If the order were reliable, and top-down, we could instead
+ // just get them from shared().
+ compiled_module->set_initial_pages(module->initial_pages);
+ compiled_module->set_num_imported_functions(module->num_imported_functions);
+
+ int num_function_tables = static_cast<int>(function_tables.size());
+ if (num_function_tables > 0) {
+ Handle<FixedArray> st =
+ isolate->factory()->NewFixedArray(num_function_tables, TENURED);
+ Handle<FixedArray> ft =
+ isolate->factory()->NewFixedArray(num_function_tables, TENURED);
+ for (int i = 0; i < num_function_tables; ++i) {
+ size_t index = static_cast<size_t>(i);
+ SetTableValue(isolate, ft, i, function_tables[index]);
+ SetTableValue(isolate, st, i, signature_tables[index]);
+ }
+ // TODO(wasm): setting the empty tables here this way is OK under the
+ // assumption that we compile and then instantiate. It needs rework if we
+ // do direct instantiation. The empty tables are used as a default when
+ // resetting the compiled module.
+ compiled_module->set_signature_tables(st);
+ compiled_module->set_empty_signature_tables(st);
+ compiled_module->set_function_tables(ft);
+ compiled_module->set_empty_function_tables(ft);
}
- // TODO(wasm): setting the empty tables here this way is OK under the
- // assumption that we compile and then instantiate. It needs rework if we do
- // direct instantiation. The empty tables are used as a default when
- // resetting the compiled module.
- compiled_module->set_signature_tables(st);
- compiled_module->set_empty_signature_tables(st);
- compiled_module->set_function_tables(ft);
- compiled_module->set_empty_function_tables(ft);
+ } else {
+ if (!export_wrappers.is_null()) {
+ compiled_module->set_export_wrappers(export_wrappers);
+ }
+ wasm::NativeModule* native_module = nullptr;
+ {
+ std::unique_ptr<wasm::NativeModule> native_module_ptr =
+ isolate->wasm_code_manager()->NewNativeModule(*module);
+ native_module = native_module_ptr.release();
+ Handle<Foreign> native_module_wrapper =
+ Managed<wasm::NativeModule>::From(isolate, native_module);
+ compiled_module->set_native_module(native_module_wrapper);
+ Handle<WasmCompiledModule> weak_link =
+ isolate->global_handles()->Create(*compiled_module);
+ GlobalHandles::MakeWeak(Handle<Object>::cast(weak_link).location(),
+ Handle<Object>::cast(weak_link).location(),
+ &CompiledModuleFinalizer,
+ v8::WeakCallbackType::kFinalizer);
+ compiled_module->GetNativeModule()->SetCompiledModule(weak_link);
+ }
+ // This is here just because it's easier for APIs that need to work with
+ // either code_table or native_module. Otherwise we need to check if
+ // has_code_table and pass undefined.
+ compiled_module->set_code_table(code_table);
+
+ native_module->function_tables() = function_tables;
+ native_module->signature_tables() = signature_tables;
+ native_module->empty_function_tables() = function_tables;
+ native_module->empty_signature_tables() = signature_tables;
+
+ int function_count = static_cast<int>(module->functions.size());
+ compiled_module->set_handler_table(
+ isolate->factory()->NewFixedArray(function_count, TENURED));
+ compiled_module->set_source_positions(
+ isolate->factory()->NewFixedArray(function_count, TENURED));
}
-
// TODO(mtrofin): copy the rest of the specialization parameters over.
// We're currently OK because we're only using defaults.
return compiled_module;
@@ -967,19 +1078,41 @@ Handle<WasmCompiledModule> WasmCompiledModule::New(
Handle<WasmCompiledModule> WasmCompiledModule::Clone(
Isolate* isolate, Handle<WasmCompiledModule> module) {
- Handle<FixedArray> code_copy =
- isolate->factory()->CopyFixedArray(module->code_table());
+ Handle<FixedArray> code_copy;
+ if (!FLAG_wasm_jit_to_native) {
+ code_copy = isolate->factory()->CopyFixedArray(module->code_table());
+ }
Handle<WasmCompiledModule> ret = Handle<WasmCompiledModule>::cast(
isolate->factory()->CopyFixedArray(module));
- ret->InitId();
- ret->set_code_table(code_copy);
ret->reset_weak_owning_instance();
- ret->reset_weak_next_instance();
- ret->reset_weak_prev_instance();
+ ret->reset_next_instance();
+ ret->reset_prev_instance();
ret->reset_weak_exported_functions();
- if (ret->has_globals_start()) {
- WasmCompiledModule::recreate_globals_start(ret, isolate->factory(),
- ret->globals_start());
+ if (!FLAG_wasm_jit_to_native) {
+ ret->InitId();
+ ret->set_code_table(code_copy);
+ return ret;
+ }
+
+ std::unique_ptr<wasm::NativeModule> native_module =
+ module->GetNativeModule()->Clone();
+ // construct the wrapper in 2 steps, because its construction may trigger GC,
+ // which would shift the this pointer in set_native_module.
+ Handle<Foreign> native_module_wrapper =
+ Managed<wasm::NativeModule>::From(isolate, native_module.release());
+ ret->set_native_module(native_module_wrapper);
+ Handle<WasmCompiledModule> weak_link =
+ isolate->global_handles()->Create(*ret);
+ GlobalHandles::MakeWeak(Handle<Object>::cast(weak_link).location(),
+ Handle<Object>::cast(weak_link).location(),
+ &CompiledModuleFinalizer,
+ v8::WeakCallbackType::kFinalizer);
+ ret->GetNativeModule()->SetCompiledModule(weak_link);
+
+ if (module->has_lazy_compile_data()) {
+ Handle<FixedArray> lazy_comp_data = isolate->factory()->NewFixedArray(
+ module->lazy_compile_data()->length(), TENURED);
+ ret->set_lazy_compile_data(lazy_comp_data);
}
return ret;
}
@@ -1005,8 +1138,13 @@ Address WasmCompiledModule::GetTableValue(FixedArray* table, int index) {
return reinterpret_cast<Address>(static_cast<size_t>(value));
}
-void WasmCompiledModule::Reset(Isolate* isolate,
- WasmCompiledModule* compiled_module) {
+wasm::NativeModule* WasmCompiledModule::GetNativeModule() const {
+ if (!has_native_module()) return nullptr;
+ return Managed<wasm::NativeModule>::cast(ptr_to_native_module())->get();
+}
+
+void WasmCompiledModule::ResetGCModel(Isolate* isolate,
+ WasmCompiledModule* compiled_module) {
DisallowHeapAllocation no_gc;
TRACE("Resetting %d\n", compiled_module->instance_id());
Object* undefined = *isolate->factory()->undefined_value();
@@ -1017,13 +1155,6 @@ void WasmCompiledModule::Reset(Isolate* isolate,
Zone specialization_zone(isolate->allocator(), ZONE_NAME);
wasm::CodeSpecialization code_specialization(isolate, &specialization_zone);
- if (compiled_module->has_globals_start()) {
- Address globals_start =
- reinterpret_cast<Address>(compiled_module->globals_start());
- code_specialization.RelocateGlobals(globals_start, nullptr);
- compiled_module->set_globals_start(0);
- }
-
// Reset function tables.
if (compiled_module->has_function_tables()) {
FixedArray* function_tables = compiled_module->ptr_to_function_tables();
@@ -1051,6 +1182,8 @@ void WasmCompiledModule::Reset(Isolate* isolate,
}
}
+ // TODO(6792): No longer needed once WebAssembly code is off heap.
+ CodeSpaceMemoryModificationScope modification_scope(isolate->heap());
FixedArray* functions = FixedArray::cast(fct_obj);
for (int i = compiled_module->num_imported_functions(),
end = functions->length();
@@ -1066,8 +1199,8 @@ void WasmCompiledModule::Reset(Isolate* isolate,
}
break;
}
- bool changed =
- code_specialization.ApplyToWasmCode(code, SKIP_ICACHE_FLUSH);
+ bool changed = code_specialization.ApplyToWasmCode(
+ WasmCodeWrapper(handle(code)), SKIP_ICACHE_FLUSH);
// TODO(wasm): Check if this is faster than passing FLUSH_ICACHE_IF_NEEDED
// above.
if (changed) {
@@ -1086,16 +1219,79 @@ void WasmCompiledModule::InitId() {
#endif
}
-void WasmCompiledModule::SetGlobalsStartAddressFrom(
- Factory* factory, Handle<WasmCompiledModule> compiled_module,
- Handle<JSArrayBuffer> buffer) {
- DCHECK(!buffer.is_null());
- size_t start_address = reinterpret_cast<size_t>(buffer->backing_store());
- if (!compiled_module->has_globals_start()) {
- WasmCompiledModule::recreate_globals_start(compiled_module, factory,
- start_address);
- } else {
- compiled_module->set_globals_start(start_address);
+void WasmCompiledModule::Reset(Isolate* isolate,
+ WasmCompiledModule* compiled_module) {
+ DisallowHeapAllocation no_gc;
+ compiled_module->reset_prev_instance();
+ compiled_module->reset_next_instance();
+ wasm::NativeModule* native_module = compiled_module->GetNativeModule();
+ if (native_module == nullptr) return;
+ TRACE("Resetting %zu\n", native_module->instance_id);
+ if (trap_handler::UseTrapHandler()) {
+ for (uint32_t i = native_module->num_imported_functions(),
+ e = native_module->FunctionCount();
+ i < e; ++i) {
+ wasm::WasmCode* wasm_code = native_module->GetCode(i);
+ if (wasm_code->HasTrapHandlerIndex()) {
+ CHECK_LT(wasm_code->trap_handler_index(),
+ static_cast<size_t>(std::numeric_limits<int>::max()));
+ trap_handler::ReleaseHandlerData(
+ static_cast<int>(wasm_code->trap_handler_index()));
+ wasm_code->ResetTrapHandlerIndex();
+ }
+ }
+ }
+
+ // Patch code to update memory references, global references, and function
+ // table references.
+ Zone specialization_zone(isolate->allocator(), ZONE_NAME);
+ wasm::CodeSpecialization code_specialization(isolate, &specialization_zone);
+
+ if (compiled_module->has_lazy_compile_data()) {
+ for (int i = 0, e = compiled_module->lazy_compile_data()->length(); i < e;
+ ++i) {
+ compiled_module->lazy_compile_data()->set(
+ i, isolate->heap()->undefined_value());
+ }
+ }
+ // Reset function tables.
+ if (native_module->function_tables().size() > 0) {
+ std::vector<GlobalHandleAddress>& function_tables =
+ native_module->function_tables();
+ std::vector<GlobalHandleAddress>& signature_tables =
+ native_module->signature_tables();
+ std::vector<GlobalHandleAddress>& empty_function_tables =
+ native_module->empty_function_tables();
+ std::vector<GlobalHandleAddress>& empty_signature_tables =
+ native_module->empty_signature_tables();
+
+ if (function_tables != empty_function_tables) {
+ DCHECK_EQ(function_tables.size(), empty_function_tables.size());
+ for (size_t i = 0, e = function_tables.size(); i < e; ++i) {
+ code_specialization.RelocatePointer(function_tables[i],
+ empty_function_tables[i]);
+ code_specialization.RelocatePointer(signature_tables[i],
+ empty_signature_tables[i]);
+ }
+ native_module->function_tables() = empty_function_tables;
+ native_module->signature_tables() = empty_signature_tables;
+ }
+ }
+
+ for (uint32_t i = native_module->num_imported_functions(),
+ end = native_module->FunctionCount();
+ i < end; ++i) {
+ wasm::WasmCode* code = native_module->GetCode(i);
+ // Skip lazy compile stubs.
+ if (code == nullptr || code->kind() != wasm::WasmCode::Function) continue;
+ bool changed = code_specialization.ApplyToWasmCode(WasmCodeWrapper(code),
+ SKIP_ICACHE_FLUSH);
+ // TODO(wasm): Check if this is faster than passing FLUSH_ICACHE_IF_NEEDED
+ // above.
+ if (changed) {
+ Assembler::FlushICache(isolate, code->instructions().start(),
+ code->instructions().size());
+ }
}
}
@@ -1129,7 +1325,6 @@ bool WasmCompiledModule::IsWasmCompiledModule(Object* obj) {
if (!obj->IsFixedArray()) return false;
FixedArray* arr = FixedArray::cast(obj);
if (arr->length() != PropertyIndices::Count) return false;
- Isolate* isolate = arr->GetIsolate();
#define WCM_CHECK_TYPE(NAME, TYPE_CHECK) \
do { \
Object* obj = arr->get(kID_##NAME); \
@@ -1145,16 +1340,13 @@ bool WasmCompiledModule::IsWasmCompiledModule(Object* obj) {
#define WCM_CHECK_CONST_OBJECT(TYPE, NAME) \
WCM_CHECK_TYPE(NAME, obj->IsUndefined(isolate) || obj->Is##TYPE())
#define WCM_CHECK_WASM_OBJECT(TYPE, NAME) \
- WCM_CHECK_TYPE(NAME, TYPE::Is##TYPE(obj))
+ WCM_CHECK_TYPE(NAME, obj->IsFixedArray() || obj->IsUndefined(isolate))
#define WCM_CHECK_WEAK_LINK(TYPE, NAME) WCM_CHECK_OBJECT(WeakCell, NAME)
#define WCM_CHECK_SMALL_NUMBER(TYPE, NAME) \
WCM_CHECK_TYPE(NAME, obj->IsUndefined(isolate) || obj->IsSmi())
#define WCM_CHECK(KIND, TYPE, NAME) WCM_CHECK_##KIND(TYPE, NAME)
#define WCM_CHECK_SMALL_CONST_NUMBER(TYPE, NAME) \
WCM_CHECK_TYPE(NAME, obj->IsSmi())
-#define WCM_CHECK_LARGE_NUMBER(TYPE, NAME) \
- WCM_CHECK_TYPE(NAME, obj->IsUndefined(isolate) || obj->IsMutableHeapNumber())
- WCM_PROPERTY_TABLE(WCM_CHECK)
#undef WCM_CHECK_TYPE
#undef WCM_CHECK_OBJECT
#undef WCM_CHECK_CONST_OBJECT
@@ -1163,7 +1355,6 @@ bool WasmCompiledModule::IsWasmCompiledModule(Object* obj) {
#undef WCM_CHECK_SMALL_NUMBER
#undef WCM_CHECK
#undef WCM_CHECK_SMALL_CONST_NUMBER
-#undef WCM_CHECK_LARGE_NUMBER
// All checks passed.
return true;
@@ -1173,16 +1364,46 @@ void WasmCompiledModule::PrintInstancesChain() {
#if DEBUG
if (!FLAG_trace_wasm_instances) return;
for (WasmCompiledModule* current = this; current != nullptr;) {
- PrintF("->%d", current->instance_id());
- if (!current->has_weak_next_instance()) break;
- DCHECK(!current->ptr_to_weak_next_instance()->cleared());
- current =
- WasmCompiledModule::cast(current->ptr_to_weak_next_instance()->value());
+ if (FLAG_wasm_jit_to_native) {
+ PrintF("->%zu", current->GetNativeModule()->instance_id);
+ } else {
+ PrintF("->%d", current->instance_id());
+ }
+ if (!current->has_next_instance()) break;
+ current = current->ptr_to_next_instance();
}
PrintF("\n");
#endif
}
+void WasmCompiledModule::InsertInChain(WasmModuleObject* module) {
+ DisallowHeapAllocation no_gc;
+ WasmCompiledModule* original = module->compiled_module();
+ set_ptr_to_next_instance(original);
+ original->set_ptr_to_prev_instance(this);
+ set_weak_wasm_module(original->weak_wasm_module());
+}
+
+void WasmCompiledModule::RemoveFromChain() {
+ DisallowHeapAllocation no_gc;
+ Isolate* isolate = GetIsolate();
+
+ Object* next = get(kID_next_instance);
+ Object* prev = get(kID_prev_instance);
+
+ if (!prev->IsUndefined(isolate)) {
+ WasmCompiledModule::cast(prev)->set(kID_next_instance, next);
+ }
+ if (!next->IsUndefined(isolate)) {
+ WasmCompiledModule::cast(next)->set(kID_prev_instance, prev);
+ }
+}
+
+void WasmCompiledModule::OnWasmModuleDecodingComplete(
+ Handle<WasmSharedModuleData> shared) {
+ set_shared(shared);
+}
+
void WasmCompiledModule::ReinitializeAfterDeserialization(
Isolate* isolate, Handle<WasmCompiledModule> compiled_module) {
// This method must only be called immediately after deserialization.
@@ -1191,31 +1412,48 @@ void WasmCompiledModule::ReinitializeAfterDeserialization(
Handle<WasmSharedModuleData> shared(
static_cast<WasmSharedModuleData*>(compiled_module->get(kID_shared)),
isolate);
- DCHECK(!WasmSharedModuleData::IsWasmSharedModuleData(*shared));
- WasmSharedModuleData::ReinitializeAfterDeserialization(isolate, shared);
- int function_table_count =
- static_cast<int>(compiled_module->module()->function_tables.size());
+ if (!FLAG_wasm_jit_to_native) {
+ DCHECK(!WasmSharedModuleData::IsWasmSharedModuleData(*shared));
+ WasmSharedModuleData::ReinitializeAfterDeserialization(isolate, shared);
+ }
+ size_t function_table_count =
+ compiled_module->module()->function_tables.size();
+ wasm::NativeModule* native_module = compiled_module->GetNativeModule();
+
if (function_table_count > 0) {
// The tables are of the right size, but contain bogus global handle
// addresses. Produce new global handles for the empty tables, then reset,
// which will relocate the code. We end up with a WasmCompiledModule as-if
// it were just compiled.
- DCHECK(compiled_module->has_function_tables());
- DCHECK(compiled_module->has_signature_tables());
- DCHECK(compiled_module->has_empty_signature_tables());
- DCHECK(compiled_module->has_empty_function_tables());
-
- for (int i = 0; i < function_table_count; ++i) {
+ if (!FLAG_wasm_jit_to_native) {
+ DCHECK(compiled_module->has_function_tables());
+ DCHECK(compiled_module->has_signature_tables());
+ DCHECK(compiled_module->has_empty_signature_tables());
+ DCHECK(compiled_module->has_empty_function_tables());
+ } else {
+ DCHECK_GT(native_module->function_tables().size(), 0);
+ DCHECK_GT(native_module->signature_tables().size(), 0);
+ DCHECK_EQ(native_module->empty_signature_tables().size(),
+ native_module->function_tables().size());
+ DCHECK_EQ(native_module->empty_function_tables().size(),
+ native_module->function_tables().size());
+ }
+ for (size_t i = 0; i < function_table_count; ++i) {
Handle<Object> global_func_table_handle =
isolate->global_handles()->Create(isolate->heap()->undefined_value());
Handle<Object> global_sig_table_handle =
isolate->global_handles()->Create(isolate->heap()->undefined_value());
GlobalHandleAddress new_func_table = global_func_table_handle.address();
GlobalHandleAddress new_sig_table = global_sig_table_handle.address();
- SetTableValue(isolate, compiled_module->empty_function_tables(), i,
- new_func_table);
- SetTableValue(isolate, compiled_module->empty_signature_tables(), i,
- new_sig_table);
+ if (!FLAG_wasm_jit_to_native) {
+ SetTableValue(isolate, compiled_module->empty_function_tables(),
+ static_cast<int>(i), new_func_table);
+ SetTableValue(isolate, compiled_module->empty_signature_tables(),
+ static_cast<int>(i), new_sig_table);
+ } else {
+ native_module->empty_function_tables()[i] = new_func_table;
+ native_module->empty_signature_tables()[i] = new_sig_table;
+ }
}
}
@@ -1575,16 +1813,44 @@ MaybeHandle<FixedArray> WasmCompiledModule::CheckBreakPoints(int position) {
return isolate->debug()->GetHitBreakPointObjects(breakpoint_objects);
}
-Handle<Code> WasmCompiledModule::CompileLazy(
- Isolate* isolate, Handle<WasmInstanceObject> instance, Handle<Code> caller,
- int offset, int func_index, bool patch_caller) {
- isolate->set_context(*instance->compiled_module()->native_context());
- Object* orch_obj =
- instance->compiled_module()->shared()->lazy_compilation_orchestrator();
- auto* orch =
- Managed<wasm::LazyCompilationOrchestrator>::cast(orch_obj)->get();
- return orch->CompileLazy(isolate, instance, caller, offset, func_index,
- patch_caller);
+void AttachWasmFunctionInfo(Isolate* isolate, Handle<Code> code,
+ MaybeHandle<WeakCell> weak_instance,
+ int func_index) {
+ DCHECK(weak_instance.is_null() ||
+ weak_instance.ToHandleChecked()->value()->IsWasmInstanceObject());
+ Handle<FixedArray> deopt_data = isolate->factory()->NewFixedArray(2, TENURED);
+ if (!weak_instance.is_null()) {
+ // TODO(wasm): Introduce constants for the indexes in wasm deopt data.
+ deopt_data->set(0, *weak_instance.ToHandleChecked());
+ }
+ deopt_data->set(1, Smi::FromInt(func_index));
+
+ code->set_deoptimization_data(*deopt_data);
+}
+
+void AttachWasmFunctionInfo(Isolate* isolate, Handle<Code> code,
+ MaybeHandle<WasmInstanceObject> instance,
+ int func_index) {
+ MaybeHandle<WeakCell> weak_instance;
+ if (!instance.is_null()) {
+ weak_instance = isolate->factory()->NewWeakCell(instance.ToHandleChecked());
+ }
+ AttachWasmFunctionInfo(isolate, code, weak_instance, func_index);
+}
+
+WasmFunctionInfo GetWasmFunctionInfo(Isolate* isolate, Handle<Code> code) {
+ FixedArray* deopt_data = code->deoptimization_data();
+ DCHECK_LE(2, deopt_data->length());
+ MaybeHandle<WasmInstanceObject> instance;
+ Object* maybe_weak_instance = deopt_data->get(0);
+ if (maybe_weak_instance->IsWeakCell()) {
+ Object* maybe_instance = WeakCell::cast(maybe_weak_instance)->value();
+ if (maybe_instance) {
+ instance = handle(WasmInstanceObject::cast(maybe_instance), isolate);
+ }
+ }
+ int func_index = Smi::ToInt(deopt_data->get(1));
+ return {instance, func_index};
}
#undef TRACE