Index: src/wasm/wasm-objects.cc |
diff --git a/src/wasm/wasm-objects.cc b/src/wasm/wasm-objects.cc |
index 8e67d10290844e4b62352f20813341a927cc357e..33502704debe975b6d28ae6f6402ace5abdf98bf 100644 |
--- a/src/wasm/wasm-objects.cc |
+++ b/src/wasm/wasm-objects.cc |
@@ -772,6 +772,102 @@ Handle<WasmCompiledModule> WasmCompiledModule::New( |
return compiled_module; |
} |
+Handle<WasmCompiledModule> WasmCompiledModule::Clone( |
+ Isolate* isolate, Handle<WasmCompiledModule> module) { |
+ Handle<WasmCompiledModule> ret = Handle<WasmCompiledModule>::cast( |
+ isolate->factory()->CopyFixedArray(module)); |
+ ret->InitId(); |
+ ret->reset_weak_owning_instance(); |
+ ret->reset_weak_next_instance(); |
+ ret->reset_weak_prev_instance(); |
+ ret->reset_weak_exported_functions(); |
+ if (ret->has_embedded_mem_start()) { |
+ WasmCompiledModule::recreate_embedded_mem_start(ret, isolate->factory(), |
+ ret->embedded_mem_start()); |
+ } |
+ if (ret->has_globals_start()) { |
+ WasmCompiledModule::recreate_globals_start(ret, isolate->factory(), |
+ ret->globals_start()); |
+ } |
+ if (ret->has_embedded_mem_size()) { |
+ WasmCompiledModule::recreate_embedded_mem_size(ret, isolate->factory(), |
+ ret->embedded_mem_size()); |
+ } |
+ return ret; |
+} |
+ |
+void WasmCompiledModule::Reset(Isolate* isolate, |
+ WasmCompiledModule* compiled_module) { |
+ DisallowHeapAllocation no_gc; |
+ TRACE("Resetting %d\n", compiled_module->instance_id()); |
+ Object* undefined = *isolate->factory()->undefined_value(); |
+ Object* fct_obj = compiled_module->ptr_to_code_table(); |
+ if (fct_obj != nullptr && fct_obj != undefined) { |
+ uint32_t old_mem_size = compiled_module->mem_size(); |
+ uint32_t default_mem_size = compiled_module->default_mem_size(); |
+ Address old_mem_start = compiled_module->GetEmbeddedMemStartOrNull(); |
+ |
+ // Patch code to update memory references, global references, and function |
+ // table references. |
+ Zone specialization_zone(isolate->allocator(), ZONE_NAME); |
+ CodeSpecialization code_specialization(isolate, &specialization_zone); |
+ |
+ if (old_mem_size > 0 && old_mem_start != nullptr) { |
+ code_specialization.RelocateMemoryReferences(old_mem_start, old_mem_size, |
+ nullptr, default_mem_size); |
+ } |
+ |
+ 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(); |
+ FixedArray* empty_function_tables = |
+ compiled_module->ptr_to_empty_function_tables(); |
+ if (function_tables != empty_function_tables) { |
+ DCHECK_EQ(function_tables->length(), empty_function_tables->length()); |
+ for (int i = 0, e = function_tables->length(); i < e; ++i) { |
+ code_specialization.RelocateObject( |
+ handle(function_tables->get(i), isolate), |
+ handle(empty_function_tables->get(i), isolate)); |
+ } |
+ compiled_module->set_ptr_to_function_tables(empty_function_tables); |
+ } |
+ } |
+ |
+ FixedArray* functions = FixedArray::cast(fct_obj); |
+ for (int i = compiled_module->num_imported_functions(), |
+ end = functions->length(); |
+ i < end; ++i) { |
+ Code* code = Code::cast(functions->get(i)); |
+ // Skip lazy compile stubs. |
+ if (code->builtin_index() == Builtins::kWasmCompileLazy) continue; |
+ if (code->kind() != Code::WASM_FUNCTION) { |
+ // From here on, there should only be wrappers for exported functions. |
+ for (; i < end; ++i) { |
+ DCHECK_EQ(Code::JS_TO_WASM_FUNCTION, |
+ Code::cast(functions->get(i))->kind()); |
+ } |
+ break; |
+ } |
+ bool changed = |
+ code_specialization.ApplyToWasmCode(code, SKIP_ICACHE_FLUSH); |
+ // TODO(wasm): Check if this is faster than passing FLUSH_ICACHE_IF_NEEDED |
+ // above. |
+ if (changed) { |
+ Assembler::FlushICache(isolate, code->instruction_start(), |
+ code->instruction_size()); |
+ } |
+ } |
+ } |
+ compiled_module->ResetSpecializationMemInfoIfNeeded(); |
+} |
+ |
void WasmCompiledModule::InitId() { |
#if DEBUG |
static uint32_t instance_id_counter = 0; |
@@ -780,6 +876,45 @@ void WasmCompiledModule::InitId() { |
#endif |
} |
+void WasmCompiledModule::ResetSpecializationMemInfoIfNeeded() { |
+ DisallowHeapAllocation no_gc; |
+ if (has_embedded_mem_start()) { |
+ set_embedded_mem_size(0); |
+ set_embedded_mem_start(0); |
+ } |
+} |
+ |
+void WasmCompiledModule::SetSpecializationMemInfoFrom( |
+ Factory* factory, Handle<WasmCompiledModule> compiled_module, |
+ Handle<JSArrayBuffer> buffer) { |
+ DCHECK(!buffer.is_null()); |
+ size_t start_address = reinterpret_cast<size_t>(buffer->backing_store()); |
+ uint32_t size = static_cast<uint32_t>(buffer->byte_length()->Number()); |
+ if (!compiled_module->has_embedded_mem_start()) { |
+ DCHECK(!compiled_module->has_embedded_mem_size()); |
+ WasmCompiledModule::recreate_embedded_mem_start(compiled_module, factory, |
+ start_address); |
+ WasmCompiledModule::recreate_embedded_mem_size(compiled_module, factory, |
+ size); |
+ } else { |
+ compiled_module->set_embedded_mem_start(start_address); |
+ compiled_module->set_embedded_mem_size(size); |
+ } |
+} |
+ |
+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); |
+ } |
+} |
+ |
MaybeHandle<String> WasmCompiledModule::ExtractUtf8StringFromModuleBytes( |
Isolate* isolate, Handle<WasmCompiledModule> compiled_module, |
uint32_t offset, uint32_t size) { |
@@ -807,13 +942,23 @@ bool WasmCompiledModule::IsWasmCompiledModule(Object* obj) { |
Object* obj = arr->get(kID_##NAME); \ |
if (!(TYPE_CHECK)) return false; \ |
} while (false); |
+// We're OK with undefined, generally, because maybe we don't |
+// have a value for that item. For example, we may not have a |
+// memory, or globals. |
+// We're not OK with the fixed numbers being undefined. We want |
+// to set once all of them. |
#define WCM_CHECK_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)) |
#define WCM_CHECK_WEAK_LINK(TYPE, NAME) WCM_CHECK_OBJECT(WeakCell, NAME) |
-#define WCM_CHECK_SMALL_NUMBER(TYPE, NAME) WCM_CHECK_TYPE(NAME, obj->IsSmi()) |
+#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_FIXED_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 |
@@ -845,11 +990,13 @@ void WasmCompiledModule::ReinitializeAfterDeserialization( |
isolate); |
DCHECK(!WasmSharedModuleData::IsWasmSharedModuleData(*shared)); |
WasmSharedModuleData::ReinitializeAfterDeserialization(isolate, shared); |
+ WasmCompiledModule::Reset(isolate, *compiled_module); |
DCHECK(WasmSharedModuleData::IsWasmSharedModuleData(*shared)); |
} |
uint32_t WasmCompiledModule::mem_size() const { |
- return has_memory() ? memory()->byte_length()->Number() : default_mem_size(); |
+ DCHECK(has_embedded_mem_size() == has_embedded_mem_start()); |
+ return has_embedded_mem_start() ? embedded_mem_size() : default_mem_size(); |
} |
uint32_t WasmCompiledModule::default_mem_size() const { |