Index: src/wasm/wasm-module.cc |
diff --git a/src/wasm/wasm-module.cc b/src/wasm/wasm-module.cc |
index 3021fb55b9b67d917ae25093b62f298302c93779..cee393b4cf6f12eb9c5c2b21cebd9c6abe922a6a 100644 |
--- a/src/wasm/wasm-module.cc |
+++ b/src/wasm/wasm-module.cc |
@@ -898,23 +898,23 @@ int wasm::GetFunctionCodeOffset(Handle<WasmCompiledModule> compiled_module, |
WasmModule::WasmModule(Zone* owned) |
: owned_zone(owned), pending_tasks(new base::Semaphore(0)) {} |
-MaybeHandle<WasmCompiledModule> WasmModule::CompileFunctions( |
- Isolate* isolate, Handle<WasmModuleWrapper> module_wrapper, |
- ErrorThrower* thrower, const ModuleWireBytes& wire_bytes, |
- Handle<Script> asm_js_script, |
- Vector<const byte> asm_js_offset_table_bytes) const { |
+MaybeHandle<WasmModuleObject> CompileToModuleObject( |
+ Isolate* isolate, WasmModule* m, ErrorThrower* thrower, |
+ const ModuleWireBytes& wire_bytes, Handle<Script> asm_js_script, |
+ Vector<const byte> asm_js_offset_table_bytes) { |
Factory* factory = isolate->factory(); |
- |
- MaybeHandle<WasmCompiledModule> nothing; |
- |
- WasmInstance temp_instance(this); |
+ MaybeHandle<WasmModuleObject> nothing; |
+ // The {module_wrapper} will take ownership of the {WasmModule} object, |
+ // and it will be destroyed when the GC reclaims the wrapper object. |
+ Handle<WasmModuleWrapper> module_wrapper = WasmModuleWrapper::New(isolate, m); |
+ WasmInstance temp_instance(m); |
temp_instance.context = isolate->native_context(); |
- temp_instance.mem_size = WasmModule::kPageSize * min_mem_pages; |
+ temp_instance.mem_size = WasmModule::kPageSize * m->min_mem_pages; |
temp_instance.mem_start = nullptr; |
temp_instance.globals_start = nullptr; |
// Initialize the indirect tables with placeholders. |
- int function_table_count = static_cast<int>(function_tables.size()); |
+ int function_table_count = static_cast<int>(m->function_tables.size()); |
Handle<FixedArray> function_tables = |
factory->NewFixedArray(function_table_count, TENURED); |
Handle<FixedArray> signature_tables = |
@@ -929,25 +929,25 @@ MaybeHandle<WasmCompiledModule> WasmModule::CompileFunctions( |
HistogramTimerScope wasm_compile_module_time_scope( |
isolate->counters()->wasm_compile_module_time()); |
- ModuleBytesEnv module_env(this, &temp_instance, wire_bytes); |
+ ModuleBytesEnv module_env(m, &temp_instance, wire_bytes); |
// The {code_table} array contains import wrappers and functions (which |
// are both included in {functions.size()}, and export wrappers. |
int code_table_size = |
- static_cast<int>(functions.size() + num_exported_functions); |
+ static_cast<int>(m->functions.size() + m->num_exported_functions); |
Handle<FixedArray> code_table = |
factory->NewFixedArray(static_cast<int>(code_table_size), TENURED); |
// Initialize the code table with the illegal builtin. All call sites will be |
// patched at instantiation. |
Handle<Code> illegal_builtin = isolate->builtins()->Illegal(); |
- for (uint32_t i = 0; i < functions.size(); ++i) { |
+ for (uint32_t i = 0; i < m->functions.size(); ++i) { |
code_table->set(static_cast<int>(i), *illegal_builtin); |
temp_instance.function_code[i] = illegal_builtin; |
} |
isolate->counters()->wasm_functions_per_module()->AddSample( |
- static_cast<int>(functions.size())); |
+ static_cast<int>(m->functions.size())); |
if (!FLAG_trace_wasm_decoder && FLAG_wasm_num_compilation_tasks != 0) { |
// Avoid a race condition by collecting results into a second vector. |
std::vector<Handle<Code>> results(temp_instance.function_code); |
@@ -1002,39 +1002,40 @@ MaybeHandle<WasmCompiledModule> WasmModule::CompileFunctions( |
// and information needed at instantiation time. This object needs to be |
// serializable. Instantiation may occur off a deserialized version of this |
// object. |
- Handle<WasmCompiledModule> ret = WasmCompiledModule::New(isolate, shared); |
- ret->set_num_imported_functions(num_imported_functions); |
- ret->set_code_table(code_table); |
- ret->set_min_mem_pages(min_mem_pages); |
- ret->set_max_mem_pages(max_mem_pages); |
+ Handle<WasmCompiledModule> compiled_module = |
+ WasmCompiledModule::New(isolate, shared); |
+ compiled_module->set_num_imported_functions(m->num_imported_functions); |
+ compiled_module->set_code_table(code_table); |
+ compiled_module->set_min_mem_pages(m->min_mem_pages); |
+ compiled_module->set_max_mem_pages(m->max_mem_pages); |
if (function_table_count > 0) { |
- ret->set_function_tables(function_tables); |
- ret->set_signature_tables(signature_tables); |
- ret->set_empty_function_tables(function_tables); |
+ compiled_module->set_function_tables(function_tables); |
+ compiled_module->set_signature_tables(signature_tables); |
+ compiled_module->set_empty_function_tables(function_tables); |
} |
// If we created a wasm script, finish it now and make it public to the |
// debugger. |
if (asm_js_script.is_null()) { |
- script->set_wasm_compiled_module(*ret); |
+ script->set_wasm_compiled_module(*compiled_module); |
isolate->debug()->OnAfterCompile(script); |
} |
// Compile JS->WASM wrappers for exported functions. |
int func_index = 0; |
- for (auto exp : export_table) { |
+ for (auto exp : m->export_table) { |
if (exp.kind != kExternalFunction) continue; |
Handle<Code> wasm_code = |
code_table->GetValueChecked<Code>(isolate, exp.index); |
Handle<Code> wrapper_code = |
- compiler::CompileJSToWasmWrapper(isolate, this, wasm_code, exp.index); |
- int export_index = static_cast<int>(functions.size() + func_index); |
+ compiler::CompileJSToWasmWrapper(isolate, m, wasm_code, exp.index); |
+ int export_index = static_cast<int>(m->functions.size() + func_index); |
code_table->set(export_index, *wrapper_code); |
RecordStats(isolate, *wrapper_code); |
func_index++; |
} |
- return ret; |
+ return WasmModuleObject::New(isolate, compiled_module); |
} |
static WasmFunction* GetWasmFunctionForImportWrapper(Isolate* isolate, |
@@ -1139,17 +1140,20 @@ void wasm::UpdateDispatchTables(Isolate* isolate, |
// A helper class to simplify instantiating a module from a compiled module. |
// It closes over the {Isolate}, the {ErrorThrower}, the {WasmCompiledModule}, |
// etc. |
-class WasmInstanceBuilder { |
+class InstantiationHelper { |
public: |
- WasmInstanceBuilder(Isolate* isolate, ErrorThrower* thrower, |
+ InstantiationHelper(Isolate* isolate, ErrorThrower* thrower, |
Handle<WasmModuleObject> module_object, |
- Handle<JSReceiver> ffi, Handle<JSArrayBuffer> memory) |
+ MaybeHandle<JSReceiver> ffi, |
+ MaybeHandle<JSArrayBuffer> memory) |
: isolate_(isolate), |
module_(module_object->compiled_module()->module()), |
thrower_(thrower), |
module_object_(module_object), |
- ffi_(ffi), |
- memory_(memory) {} |
+ ffi_(ffi.is_null() ? Handle<JSReceiver>::null() |
+ : ffi.ToHandleChecked()), |
+ memory_(memory.is_null() ? Handle<JSArrayBuffer>::null() |
+ : memory.ToHandleChecked()) {} |
// Build an instance, in all of its glory. |
MaybeHandle<WasmInstanceObject> Build() { |
@@ -1526,8 +1530,8 @@ class WasmInstanceBuilder { |
WasmModule* const module_; |
ErrorThrower* thrower_; |
Handle<WasmModuleObject> module_object_; |
- Handle<JSReceiver> ffi_; |
- Handle<JSArrayBuffer> memory_; |
+ Handle<JSReceiver> ffi_; // TODO(titzer): Use MaybeHandle |
+ Handle<JSArrayBuffer> memory_; // TODO(titzer): Use MaybeHandle |
Handle<JSArrayBuffer> globals_; |
Handle<WasmCompiledModule> compiled_module_; |
std::vector<TableInstance> table_instances_; |
@@ -2243,16 +2247,6 @@ class WasmInstanceBuilder { |
} |
}; |
-// Instantiates a WASM module, creating a WebAssembly.Instance from a |
-// WebAssembly.Module. |
-MaybeHandle<WasmInstanceObject> WasmModule::Instantiate( |
- Isolate* isolate, ErrorThrower* thrower, |
- Handle<WasmModuleObject> wasm_module, Handle<JSReceiver> ffi, |
- Handle<JSArrayBuffer> memory) { |
- WasmInstanceBuilder builder(isolate, thrower, wasm_module, ffi, memory); |
- return builder.Build(); |
-} |
- |
bool wasm::IsWasmInstance(Object* object) { |
return WasmInstanceObject::IsWasmInstanceObject(object); |
} |
@@ -2268,57 +2262,6 @@ bool wasm::IsWasmCodegenAllowed(Isolate* isolate, Handle<Context> context) { |
isolate->allow_code_gen_callback()(v8::Utils::ToLocal(context)); |
} |
-// TODO(clemensh): origin can be inferred from asm_js_script; remove it. |
-MaybeHandle<WasmModuleObject> wasm::CreateModuleObjectFromBytes( |
- Isolate* isolate, const byte* start, const byte* end, ErrorThrower* thrower, |
- ModuleOrigin origin, Handle<Script> asm_js_script, |
- Vector<const byte> asm_js_offset_table_bytes) { |
- MaybeHandle<WasmModuleObject> nothing; |
- |
- if (origin != kAsmJsOrigin && |
- !IsWasmCodegenAllowed(isolate, isolate->native_context())) { |
- thrower->CompileError("Wasm code generation disallowed in this context"); |
- return nothing; |
- } |
- |
- ModuleResult result = DecodeWasmModule(isolate, start, end, false, origin); |
- if (result.failed()) { |
- if (result.val) delete result.val; |
- thrower->CompileFailed("Wasm decoding failed", result); |
- return nothing; |
- } |
- |
- // The {module_wrapper} will take ownership of the {WasmModule} object, |
- // and it will be destroyed when the GC reclaims the wrapper object. |
- Handle<WasmModuleWrapper> module_wrapper = |
- WasmModuleWrapper::New(isolate, const_cast<WasmModule*>(result.val)); |
- |
- // Compile the functions of the module, producing a compiled module. |
- MaybeHandle<WasmCompiledModule> maybe_compiled_module = |
- result.val->CompileFunctions(isolate, module_wrapper, thrower, |
- ModuleWireBytes(start, end), asm_js_script, |
- asm_js_offset_table_bytes); |
- |
- if (maybe_compiled_module.is_null()) return nothing; |
- |
- Handle<WasmCompiledModule> compiled_module = |
- maybe_compiled_module.ToHandleChecked(); |
- |
- return WasmModuleObject::New(isolate, compiled_module); |
-} |
- |
-bool wasm::ValidateModuleBytes(Isolate* isolate, const byte* start, |
- const byte* end, ErrorThrower* thrower, |
- ModuleOrigin origin) { |
- ModuleResult result = DecodeWasmModule(isolate, start, end, true, origin); |
- if (result.val) { |
- delete result.val; |
- } else { |
- DCHECK(!result.ok()); |
- } |
- return result.ok(); |
-} |
- |
MaybeHandle<JSArrayBuffer> wasm::GetInstanceMemory( |
Isolate* isolate, Handle<WasmInstanceObject> object) { |
auto instance = Handle<WasmInstanceObject>::cast(object); |
@@ -2825,3 +2768,143 @@ Handle<JSArray> wasm::GetCustomSections(Isolate* isolate, |
return array_object; |
} |
+ |
+bool wasm::SyncValidate(Isolate* isolate, ErrorThrower* thrower, |
+ const ModuleWireBytes& bytes) { |
+ if (bytes.start() == nullptr || bytes.length() == 0) return false; |
+ ModuleResult result = |
+ DecodeWasmModule(isolate, bytes.start(), bytes.end(), true, kWasmOrigin); |
+ if (result.val) delete result.val; |
+ return result.ok(); |
+} |
+ |
+MaybeHandle<WasmModuleObject> wasm::SyncCompileTranslatedAsmJs( |
+ Isolate* isolate, ErrorThrower* thrower, const ModuleWireBytes& bytes, |
+ Handle<Script> asm_js_script, |
+ Vector<const byte> asm_js_offset_table_bytes) { |
+ MaybeHandle<WasmModuleObject> nothing; |
+ |
+ ModuleResult result = DecodeWasmModule(isolate, bytes.start(), bytes.end(), |
+ false, kAsmJsOrigin); |
+ if (result.failed()) { |
+ // TODO(titzer): use Result<std::unique_ptr<const WasmModule*>>? |
+ if (result.val) delete result.val; |
+ thrower->CompileFailed("Wasm decoding failed", result); |
+ return nothing; |
+ } |
+ |
+ return CompileToModuleObject(isolate, const_cast<WasmModule*>(result.val), |
+ thrower, bytes, asm_js_script, |
+ asm_js_offset_table_bytes); |
+} |
+ |
+MaybeHandle<WasmModuleObject> wasm::SyncCompile(Isolate* isolate, |
+ ErrorThrower* thrower, |
+ const ModuleWireBytes& bytes) { |
+ MaybeHandle<WasmModuleObject> nothing; |
+ |
+ if (!IsWasmCodegenAllowed(isolate, isolate->native_context())) { |
+ thrower->CompileError("Wasm code generation disallowed in this context"); |
+ return nothing; |
+ } |
+ |
+ ModuleResult result = |
+ DecodeWasmModule(isolate, bytes.start(), bytes.end(), false, kWasmOrigin); |
+ if (result.failed()) { |
+ if (result.val) delete result.val; |
+ thrower->CompileFailed("Wasm decoding failed", result); |
+ return nothing; |
+ } |
+ |
+ return CompileToModuleObject(isolate, const_cast<WasmModule*>(result.val), |
+ thrower, bytes, Handle<Script>(), |
+ Vector<const byte>()); |
+} |
+ |
+MaybeHandle<WasmInstanceObject> wasm::SyncInstantiate( |
+ Isolate* isolate, ErrorThrower* thrower, |
+ Handle<WasmModuleObject> module_object, MaybeHandle<JSReceiver> imports, |
+ MaybeHandle<JSArrayBuffer> memory) { |
+ InstantiationHelper helper(isolate, thrower, module_object, imports, memory); |
+ return helper.Build(); |
+} |
+ |
+void RejectPromise(Isolate* isolate, ErrorThrower* thrower, |
+ Handle<JSPromise> promise) { |
+ v8::Local<v8::Promise::Resolver> resolver = |
+ v8::Utils::PromiseToLocal(promise).As<v8::Promise::Resolver>(); |
+ Handle<Context> context(isolate->context(), isolate); |
+ resolver->Reject(v8::Utils::ToLocal(context), |
+ v8::Utils::ToLocal(thrower->Reify())); |
+} |
+ |
+void ResolvePromise(Isolate* isolate, Handle<JSPromise> promise, |
+ Handle<Object> result) { |
+ v8::Local<v8::Promise::Resolver> resolver = |
+ v8::Utils::PromiseToLocal(promise).As<v8::Promise::Resolver>(); |
+ Handle<Context> context(isolate->context(), isolate); |
+ resolver->Resolve(v8::Utils::ToLocal(context), v8::Utils::ToLocal(result)); |
+} |
+ |
+void wasm::AsyncCompile(Isolate* isolate, Handle<JSPromise> promise, |
+ const ModuleWireBytes& bytes) { |
+ ErrorThrower thrower(isolate, nullptr); |
+ MaybeHandle<WasmModuleObject> module_object = |
+ SyncCompile(isolate, &thrower, bytes); |
+ if (thrower.error()) { |
+ RejectPromise(isolate, &thrower, promise); |
+ return; |
+ } |
+ ResolvePromise(isolate, promise, module_object.ToHandleChecked()); |
+} |
+ |
+void wasm::AsyncInstantiate(Isolate* isolate, Handle<JSPromise> promise, |
+ Handle<WasmModuleObject> module_object, |
+ MaybeHandle<JSReceiver> imports) { |
+ ErrorThrower thrower(isolate, nullptr); |
+ MaybeHandle<WasmInstanceObject> instance_object = SyncInstantiate( |
+ isolate, &thrower, module_object, imports, Handle<JSArrayBuffer>::null()); |
+ if (thrower.error()) { |
+ RejectPromise(isolate, &thrower, promise); |
+ return; |
+ } |
+ ResolvePromise(isolate, promise, instance_object.ToHandleChecked()); |
+} |
+ |
+void wasm::AsyncCompileAndInstantiate(Isolate* isolate, |
+ Handle<JSPromise> promise, |
+ const ModuleWireBytes& bytes, |
+ MaybeHandle<JSReceiver> imports) { |
+ ErrorThrower thrower(isolate, nullptr); |
+ |
+ // Compile the module. |
+ MaybeHandle<WasmModuleObject> module_object = |
+ SyncCompile(isolate, &thrower, bytes); |
+ if (thrower.error()) { |
+ RejectPromise(isolate, &thrower, promise); |
+ return; |
+ } |
+ Handle<WasmModuleObject> module = module_object.ToHandleChecked(); |
+ |
+ // Instantiate the module. |
+ MaybeHandle<WasmInstanceObject> instance_object = SyncInstantiate( |
+ isolate, &thrower, module, imports, Handle<JSArrayBuffer>::null()); |
+ if (thrower.error()) { |
+ RejectPromise(isolate, &thrower, promise); |
+ return; |
+ } |
+ |
+ Handle<JSFunction> object_function = |
+ Handle<JSFunction>(isolate->native_context()->object_function(), isolate); |
+ Handle<JSObject> ret = |
+ isolate->factory()->NewJSObject(object_function, TENURED); |
+ Handle<String> module_property_name = |
+ isolate->factory()->InternalizeUtf8String("module"); |
+ Handle<String> instance_property_name = |
+ isolate->factory()->InternalizeUtf8String("instance"); |
+ JSObject::AddProperty(ret, module_property_name, module, NONE); |
+ JSObject::AddProperty(ret, instance_property_name, |
+ instance_object.ToHandleChecked(), NONE); |
+ |
+ ResolvePromise(isolate, promise, ret); |
+} |