Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(352)

Unified Diff: src/wasm/wasm-module.cc

Issue 2695813005: [wasm] Split the compilation and instantiation API into sync and async methods. (Closed)
Patch Set: [wasm] Split the compilation and instantiation API into sync and async methods. Created 3 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « src/wasm/wasm-module.h ('k') | test/cctest/wasm/test-run-wasm-module.cc » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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);
+}
« no previous file with comments | « src/wasm/wasm-module.h ('k') | test/cctest/wasm/test-run-wasm-module.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698