Index: src/wasm/wasm-module.cc |
diff --git a/src/wasm/wasm-module.cc b/src/wasm/wasm-module.cc |
index c0d517b005e362c993362b7a5384e781c342af96..dde1571194105b8b1c89960b8b081611e22ee789 100644 |
--- a/src/wasm/wasm-module.cc |
+++ b/src/wasm/wasm-module.cc |
@@ -28,38 +28,9 @@ namespace v8 { |
namespace internal { |
namespace wasm { |
-const char* SectionName(WasmSectionCode code) { |
- switch (code) { |
- case kUnknownSectionCode: |
- return "Unknown"; |
- case kTypeSectionCode: |
- return "Type"; |
- case kImportSectionCode: |
- return "Import"; |
- case kFunctionSectionCode: |
- return "Function"; |
- case kTableSectionCode: |
- return "Table"; |
- case kMemorySectionCode: |
- return "Memory"; |
- case kGlobalSectionCode: |
- return "Global"; |
- case kExportSectionCode: |
- return "Export"; |
- case kStartSectionCode: |
- return "Start"; |
- case kCodeSectionCode: |
- return "Code"; |
- case kElementSectionCode: |
- return "Element"; |
- case kDataSectionCode: |
- return "Data"; |
- case kNameSectionCode: |
- return "Name"; |
- default: |
- return "<unknown>"; |
- } |
-} |
+namespace { |
+ |
+static const int kPlaceholderMarker = 1000000000; |
enum JSFunctionExportInternalField { |
kInternalModuleInstance, |
@@ -67,77 +38,6 @@ enum JSFunctionExportInternalField { |
kInternalSignature |
}; |
-static const int kPlaceholderMarker = 1000000000; |
- |
-std::ostream& operator<<(std::ostream& os, const WasmModule& module) { |
- os << "WASM module with "; |
- os << (module.min_mem_pages * module.kPageSize) << " min mem"; |
- os << (module.max_mem_pages * module.kPageSize) << " max mem"; |
- os << module.functions.size() << " functions"; |
- os << module.functions.size() << " globals"; |
- os << module.functions.size() << " data segments"; |
- return os; |
-} |
- |
-std::ostream& operator<<(std::ostream& os, const WasmFunction& function) { |
- os << "WASM function with signature " << *function.sig; |
- |
- os << " code bytes: " |
- << (function.code_end_offset - function.code_start_offset); |
- return os; |
-} |
- |
-std::ostream& operator<<(std::ostream& os, const WasmFunctionName& pair) { |
- os << "#" << pair.function_->func_index << ":"; |
- if (pair.function_->name_offset > 0) { |
- if (pair.module_) { |
- WasmName name = pair.module_->GetName(pair.function_->name_offset, |
- pair.function_->name_length); |
- os.write(name.start(), name.length()); |
- } else { |
- os << "+" << pair.function_->func_index; |
- } |
- } else { |
- os << "?"; |
- } |
- return os; |
-} |
- |
-Handle<JSFunction> WrapExportCodeAsJSFunction( |
- Isolate* isolate, Handle<Code> export_code, Handle<String> name, int arity, |
- MaybeHandle<ByteArray> maybe_signature, 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(kInternalModuleInstance, *module_instance); |
- // add another Internal Field as the function arity |
- function->SetInternalField(kInternalArity, Smi::FromInt(arity)); |
- // add another Internal Field as the signature of the foreign function |
- Handle<ByteArray> signature; |
- if (maybe_signature.ToHandle(&signature)) { |
- function->SetInternalField(kInternalSignature, *signature); |
- } |
- return function; |
-} |
- |
-Object* GetOwningWasmInstance(Object* undefined, Code* code) { |
- DCHECK(code->kind() == Code::WASM_FUNCTION); |
- DisallowHeapAllocation no_gc; |
- FixedArray* deopt_data = code->deoptimization_data(); |
- DCHECK_NOT_NULL(deopt_data); |
- DCHECK(deopt_data->length() == 2); |
- Object* weak_link = deopt_data->get(0); |
- if (weak_link == undefined) return undefined; |
- WeakCell* cell = WeakCell::cast(weak_link); |
- return cell->value(); |
-} |
- |
-namespace { |
// Internal constants for the layout of the module object. |
enum WasmInstanceObjectFields { |
kWasmCompiledModule = 0, |
@@ -381,93 +281,7 @@ void FlushICache(Isolate* isolate, Handle<FixedArray> functions) { |
code->instruction_size()); |
} |
} |
-} // namespace |
- |
-uint32_t GetNumImportedFunctions(Handle<JSObject> wasm_object) { |
- return static_cast<uint32_t>( |
- Smi::cast(wasm_object->GetInternalField(kWasmNumImportedFunctions)) |
- ->value()); |
-} |
-WasmModule::WasmModule(byte* module_start) |
- : module_start(module_start), |
- module_end(nullptr), |
- min_mem_pages(0), |
- max_mem_pages(0), |
- mem_export(false), |
- start_function_index(-1), |
- origin(kWasmOrigin), |
- globals_size(0), |
- num_imported_functions(0), |
- num_declared_functions(0), |
- num_exported_functions(0), |
- pending_tasks(new base::Semaphore(0)) {} |
- |
-static MaybeHandle<JSFunction> ReportFFIError( |
- ErrorThrower* thrower, const char* error, uint32_t index, |
- Handle<String> module_name, MaybeHandle<String> function_name) { |
- 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(), |
- function_name_handle->ToCString().get(), error); |
- } else { |
- thrower->Error("Import #%d module=\"%.*s\" error: %s", index, |
- module_name->length(), module_name->ToCString().get(), |
- error); |
- } |
- thrower->Error("Import "); |
- return MaybeHandle<JSFunction>(); |
-} |
- |
-static MaybeHandle<JSReceiver> LookupFunction( |
- ErrorThrower* thrower, Factory* factory, Handle<JSReceiver> ffi, |
- uint32_t index, Handle<String> module_name, |
- MaybeHandle<String> function_name) { |
- if (ffi.is_null()) { |
- return ReportFFIError(thrower, "FFI is not an object", index, module_name, |
- function_name); |
- } |
- |
- // Look up the module first. |
- MaybeHandle<Object> result = Object::GetProperty(ffi, module_name); |
- if (result.is_null()) { |
- return ReportFFIError(thrower, "module not found", index, module_name, |
- function_name); |
- } |
- |
- Handle<Object> module = result.ToHandleChecked(); |
- |
- if (!module->IsJSReceiver()) { |
- return ReportFFIError(thrower, "module is not an object or function", index, |
- module_name, function_name); |
- } |
- |
- Handle<Object> function; |
- if (!function_name.is_null()) { |
- // Look up the function in the module. |
- MaybeHandle<Object> result = |
- Object::GetProperty(module, function_name.ToHandleChecked()); |
- if (result.is_null()) { |
- return ReportFFIError(thrower, "function not found", index, module_name, |
- function_name); |
- } |
- function = result.ToHandleChecked(); |
- } else { |
- // No function specified. Use the "default export". |
- function = module; |
- } |
- |
- if (!function->IsCallable()) { |
- return ReportFFIError(thrower, "not a callable", index, module_name, |
- function_name); |
- } |
- |
- return Handle<JSReceiver>::cast(function); |
-} |
- |
-namespace { |
// Fetches the compilation unit of a wasm function and executes its parallel |
// phase. |
bool FetchAndExecuteCompilationUnit( |
@@ -588,6 +402,70 @@ Handle<FixedArray> GetImportsData(Factory* factory, const WasmModule* module) { |
return ret; |
} |
+static MaybeHandle<JSFunction> ReportFFIError( |
+ ErrorThrower* thrower, const char* error, uint32_t index, |
+ Handle<String> module_name, MaybeHandle<String> function_name) { |
+ 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(), |
+ function_name_handle->ToCString().get(), error); |
+ } else { |
+ thrower->Error("Import #%d module=\"%.*s\" error: %s", index, |
+ module_name->length(), module_name->ToCString().get(), |
+ error); |
+ } |
+ thrower->Error("Import "); |
+ return MaybeHandle<JSFunction>(); |
+} |
+ |
+static MaybeHandle<JSReceiver> LookupFunction( |
+ ErrorThrower* thrower, Factory* factory, Handle<JSReceiver> ffi, |
+ uint32_t index, Handle<String> module_name, |
+ MaybeHandle<String> function_name) { |
+ if (ffi.is_null()) { |
+ return ReportFFIError(thrower, "FFI is not an object", index, module_name, |
+ function_name); |
+ } |
+ |
+ // Look up the module first. |
+ MaybeHandle<Object> result = Object::GetProperty(ffi, module_name); |
+ if (result.is_null()) { |
+ return ReportFFIError(thrower, "module not found", index, module_name, |
+ function_name); |
+ } |
+ |
+ Handle<Object> module = result.ToHandleChecked(); |
+ |
+ if (!module->IsJSReceiver()) { |
+ return ReportFFIError(thrower, "module is not an object or function", index, |
+ module_name, function_name); |
+ } |
+ |
+ Handle<Object> function; |
+ if (!function_name.is_null()) { |
+ // Look up the function in the module. |
+ MaybeHandle<Object> result = |
+ Object::GetProperty(module, function_name.ToHandleChecked()); |
+ if (result.is_null()) { |
+ return ReportFFIError(thrower, "function not found", index, module_name, |
+ function_name); |
+ } |
+ function = result.ToHandleChecked(); |
+ } else { |
+ // No function specified. Use the "default export". |
+ function = module; |
+ } |
+ |
+ if (!function->IsCallable()) { |
+ return ReportFFIError(thrower, "not a callable", index, module_name, |
+ function_name); |
+ } |
+ |
+ return Handle<JSReceiver>::cast(function); |
+} |
+ |
Handle<Code> CompileImportWrapper(Isolate* isolate, |
const Handle<JSReceiver> ffi, int index, |
Handle<FixedArray> import_data, |
@@ -956,8 +834,159 @@ static void InstanceFinalizer(const v8::WeakCallbackInfo<void>& data) { |
GlobalHandles::Destroy(reinterpret_cast<Object**>(p)); |
} |
+Handle<FixedArray> SetupIndirectFunctionTable( |
+ Isolate* isolate, Handle<FixedArray> wasm_functions, |
+ Handle<FixedArray> indirect_table_template, |
+ Handle<FixedArray> tables_to_replace) { |
+ Factory* factory = isolate->factory(); |
+ Handle<FixedArray> cloned_indirect_tables = |
+ factory->CopyFixedArray(indirect_table_template); |
+ for (int i = 0; i < cloned_indirect_tables->length(); ++i) { |
+ Handle<FixedArray> orig_metadata = |
+ cloned_indirect_tables->GetValueChecked<FixedArray>(isolate, i); |
+ Handle<FixedArray> cloned_metadata = factory->CopyFixedArray(orig_metadata); |
+ cloned_indirect_tables->set(i, *cloned_metadata); |
+ |
+ Handle<FixedArray> orig_table = |
+ cloned_metadata->GetValueChecked<FixedArray>(isolate, kTable); |
+ Handle<FixedArray> cloned_table = factory->CopyFixedArray(orig_table); |
+ cloned_metadata->set(kTable, *cloned_table); |
+ // Patch the cloned code to refer to the cloned kTable. |
+ Handle<FixedArray> table_to_replace = |
+ tables_to_replace->GetValueChecked<FixedArray>(isolate, i) |
+ ->GetValueChecked<FixedArray>(isolate, kTable); |
+ for (int fct_index = 0; fct_index < wasm_functions->length(); ++fct_index) { |
+ Handle<Code> wasm_function = |
+ wasm_functions->GetValueChecked<Code>(isolate, fct_index); |
+ PatchFunctionTable(wasm_function, table_to_replace, cloned_table); |
+ } |
+ } |
+ return cloned_indirect_tables; |
+} |
+ |
} // namespace |
+const char* SectionName(WasmSectionCode code) { |
+ switch (code) { |
+ case kUnknownSectionCode: |
+ return "Unknown"; |
+ case kTypeSectionCode: |
+ return "Type"; |
+ case kImportSectionCode: |
+ return "Import"; |
+ case kFunctionSectionCode: |
+ return "Function"; |
+ case kTableSectionCode: |
+ return "Table"; |
+ case kMemorySectionCode: |
+ return "Memory"; |
+ case kGlobalSectionCode: |
+ return "Global"; |
+ case kExportSectionCode: |
+ return "Export"; |
+ case kStartSectionCode: |
+ return "Start"; |
+ case kCodeSectionCode: |
+ return "Code"; |
+ case kElementSectionCode: |
+ return "Element"; |
+ case kDataSectionCode: |
+ return "Data"; |
+ case kNameSectionCode: |
+ return "Name"; |
+ default: |
+ return "<unknown>"; |
+ } |
+} |
+ |
+std::ostream& operator<<(std::ostream& os, const WasmModule& module) { |
+ os << "WASM module with "; |
+ os << (module.min_mem_pages * module.kPageSize) << " min mem"; |
+ os << (module.max_mem_pages * module.kPageSize) << " max mem"; |
+ os << module.functions.size() << " functions"; |
+ os << module.functions.size() << " globals"; |
+ os << module.functions.size() << " data segments"; |
+ return os; |
+} |
+ |
+std::ostream& operator<<(std::ostream& os, const WasmFunction& function) { |
+ os << "WASM function with signature " << *function.sig; |
+ |
+ os << " code bytes: " |
+ << (function.code_end_offset - function.code_start_offset); |
+ return os; |
+} |
+ |
+std::ostream& operator<<(std::ostream& os, const WasmFunctionName& pair) { |
+ os << "#" << pair.function_->func_index << ":"; |
+ if (pair.function_->name_offset > 0) { |
+ if (pair.module_) { |
+ WasmName name = pair.module_->GetName(pair.function_->name_offset, |
+ pair.function_->name_length); |
+ os.write(name.start(), name.length()); |
+ } else { |
+ os << "+" << pair.function_->func_index; |
+ } |
+ } else { |
+ os << "?"; |
+ } |
+ return os; |
+} |
+ |
+Handle<JSFunction> WrapExportCodeAsJSFunction( |
+ Isolate* isolate, Handle<Code> export_code, Handle<String> name, int arity, |
+ MaybeHandle<ByteArray> maybe_signature, 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(kInternalModuleInstance, *module_instance); |
+ // add another Internal Field as the function arity |
+ function->SetInternalField(kInternalArity, Smi::FromInt(arity)); |
+ // add another Internal Field as the signature of the foreign function |
+ Handle<ByteArray> signature; |
+ if (maybe_signature.ToHandle(&signature)) { |
+ function->SetInternalField(kInternalSignature, *signature); |
+ } |
+ return function; |
+} |
+ |
+Object* GetOwningWasmInstance(Code* code) { |
+ DCHECK(code->kind() == Code::WASM_FUNCTION); |
+ DisallowHeapAllocation no_gc; |
+ FixedArray* deopt_data = code->deoptimization_data(); |
+ DCHECK_NOT_NULL(deopt_data); |
+ DCHECK(deopt_data->length() == 2); |
+ Object* weak_link = deopt_data->get(0); |
+ if (!weak_link->IsWeakCell()) return nullptr; |
+ WeakCell* cell = WeakCell::cast(weak_link); |
+ return cell->value(); |
+} |
+ |
+uint32_t GetNumImportedFunctions(Handle<JSObject> wasm_object) { |
+ return static_cast<uint32_t>( |
+ Smi::cast(wasm_object->GetInternalField(kWasmNumImportedFunctions)) |
+ ->value()); |
+} |
+ |
+WasmModule::WasmModule(byte* module_start) |
+ : module_start(module_start), |
+ module_end(nullptr), |
+ min_mem_pages(0), |
+ max_mem_pages(0), |
+ mem_export(false), |
+ start_function_index(-1), |
+ origin(kWasmOrigin), |
+ globals_size(0), |
+ num_imported_functions(0), |
+ num_declared_functions(0), |
+ num_exported_functions(0), |
+ pending_tasks(new base::Semaphore(0)) {} |
+ |
MaybeHandle<WasmCompiledModule> WasmModule::CompileFunctions( |
Isolate* isolate, ErrorThrower* thrower) const { |
Factory* factory = isolate->factory(); |
@@ -1133,55 +1162,6 @@ MaybeHandle<WasmCompiledModule> WasmModule::CompileFunctions( |
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> SetupIndirectFunctionTable( |
- Isolate* isolate, Handle<FixedArray> wasm_functions, |
- Handle<FixedArray> indirect_table_template, |
- Handle<FixedArray> tables_to_replace) { |
- Factory* factory = isolate->factory(); |
- Handle<FixedArray> cloned_indirect_tables = |
- factory->CopyFixedArray(indirect_table_template); |
- for (int i = 0; i < cloned_indirect_tables->length(); ++i) { |
- Handle<FixedArray> orig_metadata = |
- cloned_indirect_tables->GetValueChecked<FixedArray>(isolate, i); |
- Handle<FixedArray> cloned_metadata = factory->CopyFixedArray(orig_metadata); |
- cloned_indirect_tables->set(i, *cloned_metadata); |
- |
- Handle<FixedArray> orig_table = |
- cloned_metadata->GetValueChecked<FixedArray>(isolate, kTable); |
- Handle<FixedArray> cloned_table = factory->CopyFixedArray(orig_table); |
- cloned_metadata->set(kTable, *cloned_table); |
- // Patch the cloned code to refer to the cloned kTable. |
- Handle<FixedArray> table_to_replace = |
- tables_to_replace->GetValueChecked<FixedArray>(isolate, i) |
- ->GetValueChecked<FixedArray>(isolate, kTable); |
- for (int fct_index = 0; fct_index < wasm_functions->length(); ++fct_index) { |
- Handle<Code> wasm_function = |
- wasm_functions->GetValueChecked<Code>(isolate, fct_index); |
- PatchFunctionTable(wasm_function, table_to_replace, cloned_table); |
- } |
- } |
- return cloned_indirect_tables; |
-} |
- |
// Instantiates a WASM module, creating a WebAssembly.Instance from a |
// WebAssembly.Module. |
MaybeHandle<JSObject> WasmModule::Instantiate(Isolate* isolate, |
@@ -1556,15 +1536,6 @@ Handle<WasmCompiledModule> WasmCompiledModule::New(Isolate* isolate, |
return handle(WasmCompiledModule::cast(*ret)); |
} |
-compiler::CallDescriptor* ModuleEnv::GetCallDescriptor(Zone* zone, |
- uint32_t index) { |
- DCHECK(IsValidFunction(index)); |
- // Always make a direct call to whatever is in the table at that location. |
- // A wrapper will be generated for FFI calls. |
- const WasmFunction* function = &module->functions[index]; |
- return GetWasmCallDescriptor(zone, function->sig); |
-} |
- |
Handle<Object> GetWasmFunctionNameOrNull(Isolate* isolate, Handle<Object> wasm, |
uint32_t func_index) { |
if (!wasm->IsUndefined(isolate)) { |