| Index: src/wasm/wasm-module.cc
|
| diff --git a/src/wasm/wasm-module.cc b/src/wasm/wasm-module.cc
|
| index 27d9e63bc60cb00c4fbfea63c61680081f9dacfd..7123a127e648b3e58c3c03c0d6c1899a27e1e1b6 100644
|
| --- a/src/wasm/wasm-module.cc
|
| +++ b/src/wasm/wasm-module.cc
|
| @@ -112,6 +112,21 @@ std::ostream& operator<<(std::ostream& os, const WasmFunctionName& pair) {
|
| return os;
|
| }
|
|
|
| +Handle<JSFunction> WrapExportCodeAsJSFunction(
|
| + Isolate* isolate, Handle<Code> export_code, Handle<String> name, int arity,
|
| + Handle<JSObject> module_instance) {
|
| + Handle<SharedFunctionInfo> shared =
|
| + isolate->factory()->NewSharedFunctionInfo(name, export_code, false);
|
| + shared->set_length(arity);
|
| + shared->set_internal_formal_parameter_count(arity);
|
| + Handle<JSFunction> function = isolate->factory()->NewFunction(
|
| + isolate->wasm_function_map(), name, export_code);
|
| + function->set_shared(*shared);
|
| +
|
| + function->SetInternalField(0, *module_instance);
|
| + return function;
|
| +}
|
| +
|
| namespace {
|
| // Internal constants for the layout of the module object.
|
| const int kWasmModuleFunctionTable = 0;
|
| @@ -131,14 +146,17 @@ const int kWasmModuleInternalFieldCount = 7;
|
| // a snapshot produced by a compatible (==identical) v8 instance, we simply
|
| // fail at instantiation time, in the face of invalid data.
|
| enum CompiledWasmObjectFields {
|
| - kFunctions, // FixedArray of Code
|
| - kImportData, // maybe FixedArray of FixedArray respecting the
|
| - // WasmImportMetadata structure.
|
| - kExports, // maybe FixedArray of JSFunction
|
| - kStartupFunction, // maybe JSFunction
|
| - kModuleBytes, // maybe String
|
| - kFunctionNameTable, // maybe ByteArray
|
| - kMinRequiredMemory, // Smi. an uint32_t
|
| + kFunctions, // FixedArray of Code
|
| + kImportData, // maybe FixedArray of FixedArray respecting the
|
| + // WasmImportMetadata structure.
|
| + kExports, // maybe FixedArray of FixedArray of WasmExportMetadata
|
| + // structure
|
| + kStartupFunction, // maybe FixedArray of WasmExportMetadata structure
|
| + kIndirectFunctionTableSize, // Smi. Size of indirect function table.
|
| + kIndirectFunctionTablePrototype, // maybe FixedArray
|
| + kModuleBytes, // maybe String
|
| + kFunctionNameTable, // maybe ByteArray
|
| + kMinRequiredMemory, // Smi. an uint32_t
|
| // The following 2 are either together present or absent:
|
| kDataSegmentsInfo, // maybe FixedArray of FixedArray respecting the
|
| // WasmSegmentInfo structure
|
| @@ -158,6 +176,14 @@ enum WasmImportMetadata {
|
| kWasmImportDataTableSize // Sentinel value.
|
| };
|
|
|
| +enum WasmExportMetadata {
|
| + kExportCode, // Code
|
| + kExportName, // String
|
| + kExportArity, // Smi, an int
|
| + kExportedFunctionIndex, // Smi, an uint32_t
|
| + kWasmExportMetadataTableSize // Sentinel value.
|
| +};
|
| +
|
| enum WasmSegmentInfo {
|
| kDestAddr, // Smi. an uint32_t
|
| kSourceSize, // Smi. an uint32_t
|
| @@ -229,22 +255,26 @@ void SaveDataSegmentInfo(Factory* factory, const WasmModule* module,
|
| compiled_module->set(kDataSegments, *data);
|
| }
|
|
|
| -Handle<FixedArray> BuildFunctionTable(Isolate* isolate,
|
| - const WasmModule* module) {
|
| +MaybeHandle<FixedArray> BuildFunctionTable(Isolate* isolate,
|
| + const WasmModule* module) {
|
| // Compute the size of the indirect function table
|
| uint32_t table_size = module->FunctionTableSize();
|
| if (table_size == 0) {
|
| - return Handle<FixedArray>::null();
|
| + return MaybeHandle<FixedArray>();
|
| }
|
|
|
| + DCHECK_GE(table_size, module->function_table.size());
|
| +
|
| Handle<FixedArray> fixed = isolate->factory()->NewFixedArray(2 * table_size);
|
| - for (uint32_t i = 0;
|
| - i < static_cast<uint32_t>(module->function_table.size());
|
| - ++i) {
|
| + for (uint32_t i = 0; i < module->function_table.size(); ++i) {
|
| const WasmFunction* function =
|
| &module->functions[module->function_table[i]];
|
| - fixed->set(i, Smi::FromInt(function->sig_index));
|
| + int fixed_array_index = static_cast<int>(i);
|
| + fixed->set(fixed_array_index, Smi::FromInt(function->sig_index));
|
| + fixed->set(fixed_array_index + table_size,
|
| + Smi::FromInt(module->function_table[fixed_array_index]));
|
| }
|
| +
|
| // Set the remaining elements to -1 (instead of "undefined"). These
|
| // elements are accessed directly as SMIs (without a check). On 64-bit
|
| // platforms, it is possible to have the top bits of "undefined" take
|
| @@ -258,6 +288,17 @@ Handle<FixedArray> BuildFunctionTable(Isolate* isolate,
|
| return fixed;
|
| }
|
|
|
| +void PatchFunctionTable(Handle<Code> code,
|
| + Handle<FixedArray> old_indirect_table,
|
| + Handle<FixedArray> new_indirect_table) {
|
| + for (RelocIterator it(*code, 1 << RelocInfo::EMBEDDED_OBJECT); !it.done();
|
| + it.next()) {
|
| + if (it.rinfo()->target_object() == *old_indirect_table) {
|
| + it.rinfo()->set_target_object(*new_indirect_table);
|
| + }
|
| + }
|
| +}
|
| +
|
| Handle<JSArrayBuffer> NewArrayBuffer(Isolate* isolate, size_t size) {
|
| if (size > (WasmModule::kMaxMemPages * WasmModule::kPageSize)) {
|
| // TODO(titzer): lift restriction on maximum memory allocated here.
|
| @@ -386,11 +427,7 @@ void LinkModuleFunctions(Isolate* isolate,
|
| std::vector<Handle<Code>>& functions) {
|
| for (size_t i = 0; i < functions.size(); ++i) {
|
| Handle<Code> code = functions[i];
|
| - bool modified = LinkFunction(code, functions, Code::WASM_FUNCTION);
|
| - if (modified) {
|
| - Assembler::FlushICache(isolate, code->instruction_start(),
|
| - code->instruction_size());
|
| - }
|
| + LinkFunction(code, functions, Code::WASM_FUNCTION);
|
| }
|
| }
|
|
|
| @@ -398,11 +435,15 @@ void LinkImports(Isolate* isolate, std::vector<Handle<Code>>& functions,
|
| const std::vector<Handle<Code>>& imports) {
|
| for (uint32_t i = 0; i < functions.size(); ++i) {
|
| Handle<Code> code = functions[i];
|
| - bool modified = LinkFunction(code, imports, Code::WASM_TO_JS_FUNCTION);
|
| - if (modified) {
|
| - Assembler::FlushICache(isolate, code->instruction_start(),
|
| - code->instruction_size());
|
| - }
|
| + LinkFunction(code, imports, Code::WASM_TO_JS_FUNCTION);
|
| + }
|
| +}
|
| +
|
| +void FlushAssemblyCache(Isolate* isolate, Handle<FixedArray> functions) {
|
| + for (int i = 0; i < functions->length(); ++i) {
|
| + Handle<Code> code = functions->GetValueChecked<Code>(i);
|
| + Assembler::FlushICache(isolate, code->instruction_start(),
|
| + code->instruction_size());
|
| }
|
| }
|
|
|
| @@ -424,8 +465,8 @@ WasmModule::WasmModule()
|
| static MaybeHandle<JSFunction> ReportFFIError(
|
| ErrorThrower& thrower, const char* error, uint32_t index,
|
| Handle<String> module_name, MaybeHandle<String> function_name) {
|
| - if (!function_name.is_null()) {
|
| - Handle<String> function_name_handle = function_name.ToHandleChecked();
|
| + Handle<String> function_name_handle;
|
| + if (function_name.ToHandle(&function_name_handle)) {
|
| thrower.Error("Import #%d module=\"%.*s\" function=\"%.*s\" error: %s",
|
| index, module_name->length(), module_name->ToCString().get(),
|
| function_name_handle->length(),
|
| @@ -802,20 +843,6 @@ void CompileSequentially(Isolate* isolate, const WasmModule* module,
|
| }
|
| }
|
|
|
| -void PopulateFunctionTable(WasmModuleInstance* instance) {
|
| - if (!instance->function_table.is_null()) {
|
| - uint32_t table_size = instance->module->FunctionTableSize();
|
| - DCHECK_EQ(table_size * 2, instance->function_table->length());
|
| - uint32_t populated_table_size =
|
| - static_cast<uint32_t>(instance->module->function_table.size());
|
| - for (uint32_t i = 0; i < populated_table_size; ++i) {
|
| - instance->function_table->set(
|
| - i + table_size,
|
| - *instance->function_code[instance->module->function_table[i]]);
|
| - }
|
| - }
|
| -}
|
| -
|
| void SetDebugSupport(Factory* factory, Handle<FixedArray> compiled_module,
|
| Handle<JSObject> js_object) {
|
| MaybeHandle<String> module_bytes_string =
|
| @@ -901,8 +928,8 @@ bool SetupImports(Isolate* isolate, Handle<FixedArray> compiled_module,
|
| std::vector<Handle<Code>> import_code;
|
| MaybeHandle<FixedArray> maybe_import_data =
|
| compiled_module->GetValue<FixedArray>(kImportData);
|
| - if (!maybe_import_data.is_null()) {
|
| - Handle<FixedArray> import_data = maybe_import_data.ToHandleChecked();
|
| + Handle<FixedArray> import_data;
|
| + if (maybe_import_data.ToHandle(&import_data)) {
|
| if (!CompileWrappersToImportedFunctions(isolate, ffi, import_code,
|
| import_data, thrower)) {
|
| return false;
|
| @@ -921,7 +948,6 @@ bool SetupImports(Isolate* isolate, Handle<FixedArray> compiled_module,
|
| function_code[i] = code;
|
| }
|
|
|
| - instance->SetInternalField(kWasmModuleFunctionTable, Smi::FromInt(0));
|
| LinkImports(isolate, function_code, import_code);
|
| return true;
|
| }
|
| @@ -949,18 +975,21 @@ bool SetupExportsObject(Handle<FixedArray> compiled_module, Isolate* isolate,
|
| Handle<String> exports_name = factory->InternalizeUtf8String("exports");
|
| JSObject::AddProperty(instance, exports_name, exports_object, READ_ONLY);
|
| }
|
| - if (!maybe_exports.is_null()) {
|
| - Handle<FixedArray> exports = maybe_exports.ToHandleChecked();
|
| -
|
| + Handle<FixedArray> exports;
|
| + if (maybe_exports.ToHandle(&exports)) {
|
| int exports_size = exports->length();
|
| for (int i = 0; i < exports_size; ++i) {
|
| if (thrower->error()) return false;
|
| - Handle<JSFunction> function = exports->GetValueChecked<JSFunction>(i);
|
| - RecordStats(isolate, function->code());
|
| + Handle<FixedArray> export_metadata =
|
| + exports->GetValueChecked<FixedArray>(i);
|
| + Handle<Code> export_code =
|
| + export_metadata->GetValueChecked<Code>(kExportCode);
|
| + RecordStats(isolate, *export_code);
|
| Handle<String> name =
|
| - Handle<String>(String::cast(function->shared()->name()));
|
| - function->SetInternalField(0, *instance);
|
| -
|
| + export_metadata->GetValueChecked<String>(kExportName);
|
| + int arity = Smi::cast(export_metadata->get(kExportArity))->value();
|
| + Handle<JSFunction> function = WrapExportCodeAsJSFunction(
|
| + isolate, export_code, name, arity, instance);
|
| desc.set_value(function);
|
| Maybe<bool> status = JSReceiver::DefineOwnProperty(
|
| isolate, exports_object, name, &desc, Object::THROW_ON_ERROR);
|
| @@ -991,13 +1020,17 @@ MaybeHandle<FixedArray> WasmModule::CompileFunctions(Isolate* isolate) const {
|
| MaybeHandle<FixedArray> nothing;
|
|
|
| WasmModuleInstance temp_instance_for_compilation(this);
|
| - temp_instance_for_compilation.function_table =
|
| - BuildFunctionTable(isolate, this);
|
| temp_instance_for_compilation.context = isolate->native_context();
|
| temp_instance_for_compilation.mem_size = GetMinModuleMemSize(this);
|
| temp_instance_for_compilation.mem_start = nullptr;
|
| temp_instance_for_compilation.globals_start = nullptr;
|
|
|
| + MaybeHandle<FixedArray> indirect_table = BuildFunctionTable(isolate, this);
|
| + if (!indirect_table.is_null()) {
|
| + temp_instance_for_compilation.function_table =
|
| + indirect_table.ToHandleChecked();
|
| + }
|
| +
|
| HistogramTimerScope wasm_compile_module_time_scope(
|
| isolate->counters()->wasm_compile_module_time());
|
|
|
| @@ -1028,8 +1061,6 @@ MaybeHandle<FixedArray> WasmModule::CompileFunctions(Isolate* isolate) const {
|
| }
|
| if (thrower.error()) return nothing;
|
|
|
| - LinkModuleFunctions(isolate, temp_instance_for_compilation.function_code);
|
| -
|
| // At this point, compilation has completed. Update the code table.
|
| for (size_t i = FLAG_skip_compiling_wasm_funcs;
|
| i < temp_instance_for_compilation.function_code.size(); ++i) {
|
| @@ -1037,8 +1068,6 @@ MaybeHandle<FixedArray> WasmModule::CompileFunctions(Isolate* isolate) const {
|
| compiled_functions->set(static_cast<int>(i), code);
|
| }
|
|
|
| - PopulateFunctionTable(&temp_instance_for_compilation);
|
| -
|
| // Create the compiled module object, and populate with compiled functions
|
| // and information needed at instantiation time. This object needs to be
|
| // serializable. Instantiation may occur off a deserialized version of this
|
| @@ -1046,27 +1075,41 @@ MaybeHandle<FixedArray> WasmModule::CompileFunctions(Isolate* isolate) const {
|
| Handle<FixedArray> ret =
|
| factory->NewFixedArray(kCompiledWasmObjectTableSize, TENURED);
|
| ret->set(kFunctions, *compiled_functions);
|
| -
|
| + ret->set(kIndirectFunctionTableSize,
|
| + Smi::FromInt(static_cast<int>(function_table.size())));
|
| + if (!indirect_table.is_null()) {
|
| + ret->set(kIndirectFunctionTablePrototype,
|
| + *indirect_table.ToHandleChecked());
|
| + }
|
| Handle<FixedArray> import_data = GetImportsMetadata(factory, this);
|
| ret->set(kImportData, *import_data);
|
|
|
| // Compile export functions.
|
| int export_size = static_cast<int>(export_table.size());
|
| - Handle<JSFunction> startup_fct;
|
| + Handle<Code> startup_fct;
|
| if (export_size > 0) {
|
| Handle<FixedArray> exports = factory->NewFixedArray(export_size, TENURED);
|
| for (int i = 0; i < export_size; ++i) {
|
| + Handle<FixedArray> export_metadata =
|
| + factory->NewFixedArray(kWasmExportMetadataTableSize, TENURED);
|
| const WasmExport& exp = export_table[i];
|
| WasmName str = GetName(exp.name_offset, exp.name_length);
|
| Handle<String> name = factory->InternalizeUtf8String(str);
|
| Handle<Code> code =
|
| temp_instance_for_compilation.function_code[exp.func_index];
|
| - Handle<JSFunction> function = compiler::CompileJSToWasmWrapper(
|
| - isolate, &module_env, name, code, exp.func_index);
|
| + Handle<Code> export_code = compiler::CompileJSToWasmWrapper(
|
| + isolate, &module_env, code, exp.func_index);
|
| if (thrower.error()) return nothing;
|
| - exports->set(i, *function);
|
| + export_metadata->set(kExportCode, *export_code);
|
| + export_metadata->set(kExportName, *name);
|
| + export_metadata->set(
|
| + kExportArity, Smi::FromInt(static_cast<int>(
|
| + functions[exp.func_index].sig->parameter_count())));
|
| + export_metadata->set(kExportedFunctionIndex,
|
| + Smi::FromInt(static_cast<int>(exp.func_index)));
|
| + exports->set(i, *export_metadata);
|
| if (exp.func_index == start_function_index) {
|
| - startup_fct = function;
|
| + startup_fct = export_code;
|
| }
|
| }
|
| ret->set(kExports, *exports);
|
| @@ -1074,15 +1117,20 @@ MaybeHandle<FixedArray> WasmModule::CompileFunctions(Isolate* isolate) const {
|
|
|
| // Compile startup function, if we haven't already.
|
| if (start_function_index >= 0) {
|
| + uint32_t index = static_cast<uint32_t>(start_function_index);
|
| HandleScope scope(isolate);
|
| if (startup_fct.is_null()) {
|
| - uint32_t index = static_cast<uint32_t>(start_function_index);
|
| - Handle<String> name = factory->NewStringFromStaticChars("start");
|
| Handle<Code> code = temp_instance_for_compilation.function_code[index];
|
| - startup_fct = compiler::CompileJSToWasmWrapper(isolate, &module_env, name,
|
| - code, index);
|
| + DCHECK_EQ(0, functions[index].sig->parameter_count());
|
| + startup_fct =
|
| + compiler::CompileJSToWasmWrapper(isolate, &module_env, code, index);
|
| }
|
| - ret->set(kStartupFunction, *startup_fct);
|
| + Handle<FixedArray> metadata =
|
| + factory->NewFixedArray(kWasmExportMetadataTableSize, TENURED);
|
| + metadata->set(kExportCode, *startup_fct);
|
| + metadata->set(kExportArity, Smi::FromInt(0));
|
| + metadata->set(kExportedFunctionIndex, Smi::FromInt(start_function_index));
|
| + ret->set(kStartupFunction, *metadata);
|
| }
|
|
|
| // TODO(wasm): saving the module bytes for debugging is wasteful. We should
|
| @@ -1109,6 +1157,104 @@ MaybeHandle<FixedArray> WasmModule::CompileFunctions(Isolate* isolate) const {
|
| return ret;
|
| }
|
|
|
| +void PatchJSWrapper(Isolate* isolate, Handle<Code> wrapper,
|
| + Handle<Code> new_target) {
|
| + AllowDeferredHandleDereference embedding_raw_address;
|
| + bool seen = false;
|
| + for (RelocIterator it(*wrapper, 1 << RelocInfo::CODE_TARGET); !it.done();
|
| + it.next()) {
|
| + Code* target = Code::GetCodeFromTargetAddress(it.rinfo()->target_address());
|
| + if (target->kind() == Code::WASM_FUNCTION) {
|
| + DCHECK(!seen);
|
| + seen = true;
|
| + it.rinfo()->set_target_address(new_target->instruction_start(),
|
| + UPDATE_WRITE_BARRIER, SKIP_ICACHE_FLUSH);
|
| + }
|
| + }
|
| + CHECK(seen);
|
| + Assembler::FlushICache(isolate, wrapper->instruction_start(),
|
| + wrapper->instruction_size());
|
| +}
|
| +
|
| +Handle<FixedArray> CloneModuleForInstance(Isolate* isolate,
|
| + Handle<FixedArray> original) {
|
| + Factory* factory = isolate->factory();
|
| + Handle<FixedArray> clone = factory->CopyFixedArray(original);
|
| +
|
| + Handle<FixedArray> orig_wasm_functions =
|
| + original->GetValueChecked<FixedArray>(kFunctions);
|
| + Handle<FixedArray> clone_wasm_functions =
|
| + factory->CopyFixedArray(orig_wasm_functions);
|
| + clone->set(kFunctions, *clone_wasm_functions);
|
| +
|
| + MaybeHandle<FixedArray> maybe_indirect_table =
|
| + original->GetValue<FixedArray>(kIndirectFunctionTablePrototype);
|
| +
|
| + Handle<FixedArray> indirect_table;
|
| + Handle<FixedArray> old_table;
|
| + if (maybe_indirect_table.ToHandle(&old_table)) {
|
| + indirect_table = factory->CopyFixedArray(old_table);
|
| + clone->set(kIndirectFunctionTablePrototype, *indirect_table);
|
| + }
|
| +
|
| + for (int i = 0; i < orig_wasm_functions->length(); ++i) {
|
| + Handle<Code> orig_code = orig_wasm_functions->GetValueChecked<Code>(i);
|
| + Handle<Code> cloned_code = factory->CopyCode(orig_code);
|
| + clone_wasm_functions->set(i, *cloned_code);
|
| + if (!maybe_indirect_table.is_null()) {
|
| + PatchFunctionTable(cloned_code, old_table, indirect_table);
|
| + }
|
| + }
|
| +
|
| + MaybeHandle<FixedArray> maybe_orig_exports =
|
| + original->GetValue<FixedArray>(kExports);
|
| + Handle<FixedArray> orig_exports;
|
| + if (maybe_orig_exports.ToHandle(&orig_exports)) {
|
| + Handle<FixedArray> cloned_exports = factory->CopyFixedArray(orig_exports);
|
| + clone->set(kExports, *cloned_exports);
|
| + for (int i = 0; i < orig_exports->length(); ++i) {
|
| + Handle<FixedArray> export_metadata =
|
| + orig_exports->GetValueChecked<FixedArray>(i);
|
| + Handle<FixedArray> clone_metadata =
|
| + factory->CopyFixedArray(export_metadata);
|
| + cloned_exports->set(i, *clone_metadata);
|
| + Handle<Code> orig_code =
|
| + export_metadata->GetValueChecked<Code>(kExportCode);
|
| + Handle<Code> cloned_code = factory->CopyCode(orig_code);
|
| + clone_metadata->set(kExportCode, *cloned_code);
|
| + // TODO(wasm): This is actually a uint32_t, but since FixedArray indexes
|
| + // in int, we are taking the risk of invalid values.
|
| + int exported_fct_index =
|
| + Smi::cast(export_metadata->get(kExportedFunctionIndex))->value();
|
| + CHECK_GE(exported_fct_index, 0);
|
| + CHECK_LT(exported_fct_index, clone_wasm_functions->length());
|
| + Handle<Code> new_target =
|
| + clone_wasm_functions->GetValueChecked<Code>(exported_fct_index);
|
| + PatchJSWrapper(isolate, cloned_code, new_target);
|
| + }
|
| + }
|
| +
|
| + MaybeHandle<FixedArray> maybe_startup =
|
| + original->GetValue<FixedArray>(kStartupFunction);
|
| + if (!maybe_startup.is_null()) {
|
| + Handle<FixedArray> startup_metadata =
|
| + factory->CopyFixedArray(maybe_startup.ToHandleChecked());
|
| + Handle<Code> startup_fct_clone =
|
| + factory->CopyCode(startup_metadata->GetValueChecked<Code>(kExportCode));
|
| + startup_metadata->set(kExportCode, *startup_fct_clone);
|
| + clone->set(kStartupFunction, *startup_metadata);
|
| + // TODO(wasm): see todo above about int vs size_t indexing in FixedArray.
|
| + int startup_fct_index =
|
| + Smi::cast(startup_metadata->get(kExportedFunctionIndex))->value();
|
| + CHECK_GE(startup_fct_index, 0);
|
| + CHECK_LT(startup_fct_index, clone_wasm_functions->length());
|
| + Handle<Code> new_target =
|
| + clone_wasm_functions->GetValueChecked<Code>(startup_fct_index);
|
| + PatchJSWrapper(isolate, startup_fct_clone, new_target);
|
| + }
|
| + return clone;
|
| +}
|
| +
|
| // Instantiates a wasm module as a JSObject.
|
| // * allocates a backing store of {mem_size} bytes.
|
| // * installs a named property "memory" for that buffer if exported
|
| @@ -1122,10 +1268,21 @@ MaybeHandle<JSObject> WasmModule::Instantiate(
|
| ErrorThrower thrower(isolate, "WasmModule::Instantiate()");
|
| Factory* factory = isolate->factory();
|
|
|
| + compiled_module = CloneModuleForInstance(isolate, compiled_module);
|
| +
|
| // These fields are compulsory.
|
| Handle<FixedArray> code_table =
|
| compiled_module->GetValueChecked<FixedArray>(kFunctions);
|
|
|
| + {
|
| + std::vector<Handle<Code>> functions(
|
| + static_cast<size_t>(code_table->length()));
|
| + for (int i = 0; i < code_table->length(); ++i) {
|
| + functions[static_cast<size_t>(i)] = code_table->GetValueChecked<Code>(i);
|
| + }
|
| + LinkModuleFunctions(isolate, functions);
|
| + }
|
| +
|
| RecordStats(isolate, code_table);
|
|
|
| MaybeHandle<JSObject> nothing;
|
| @@ -1146,14 +1303,36 @@ MaybeHandle<JSObject> WasmModule::Instantiate(
|
|
|
| SetDebugSupport(factory, compiled_module, js_object);
|
|
|
| + FlushAssemblyCache(isolate, code_table);
|
| +
|
| + MaybeHandle<FixedArray> maybe_indirect_table =
|
| + compiled_module->GetValue<FixedArray>(kIndirectFunctionTablePrototype);
|
| + Handle<FixedArray> indirect_table;
|
| + if (maybe_indirect_table.ToHandle(&indirect_table)) {
|
| + int table_size =
|
| + Smi::cast(compiled_module->get(kIndirectFunctionTableSize))->value();
|
| + int half_point = indirect_table->length() / 2;
|
| + for (int i = half_point; i < half_point + table_size; ++i) {
|
| + int index = Smi::cast(indirect_table->get(i))->value();
|
| + DCHECK_GE(index, 0);
|
| + DCHECK_LT(index, code_table->length());
|
| + indirect_table->set(i, code_table->get(index));
|
| + }
|
| + js_object->SetInternalField(kWasmModuleFunctionTable, *indirect_table);
|
| + }
|
| +
|
| // Run the start function if one was specified.
|
| - MaybeHandle<JSFunction> maybe_startup_fct =
|
| - compiled_module->GetValue<JSFunction>(kStartupFunction);
|
| - if (!maybe_startup_fct.is_null()) {
|
| + MaybeHandle<FixedArray> maybe_startup_fct =
|
| + compiled_module->GetValue<FixedArray>(kStartupFunction);
|
| + Handle<FixedArray> metadata;
|
| + if (maybe_startup_fct.ToHandle(&metadata)) {
|
| HandleScope scope(isolate);
|
| - Handle<JSFunction> startup_fct = maybe_startup_fct.ToHandleChecked();
|
| - RecordStats(isolate, startup_fct->code());
|
| - startup_fct->SetInternalField(0, *js_object);
|
| + Handle<Code> startup_code = metadata->GetValueChecked<Code>(kExportCode);
|
| + int arity = Smi::cast(metadata->get(kExportArity))->value();
|
| + Handle<JSFunction> startup_fct = WrapExportCodeAsJSFunction(
|
| + isolate, startup_code, factory->InternalizeUtf8String("start"), arity,
|
| + js_object);
|
| + RecordStats(isolate, *startup_code);
|
| // Call the JS function.
|
| Handle<Object> undefined = isolate->factory()->undefined_value();
|
| MaybeHandle<Object> retval =
|
| @@ -1334,10 +1513,9 @@ int32_t CompileAndRunWasmModule(Isolate* isolate, const byte* module_start,
|
|
|
| if (compiled_module.is_null()) return -1;
|
| Handle<JSObject> instance =
|
| - module
|
| - ->Instantiate(isolate, compiled_module.ToHandleChecked(),
|
| - Handle<JSReceiver>::null(),
|
| - Handle<JSArrayBuffer>::null())
|
| + WasmModule::Instantiate(isolate, compiled_module.ToHandleChecked(),
|
| + Handle<JSReceiver>::null(),
|
| + Handle<JSArrayBuffer>::null())
|
| .ToHandleChecked();
|
|
|
| Handle<Name> exports = isolate->factory()->InternalizeUtf8String("exports");
|
|
|