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

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

Issue 2806073002: [wasm] instantiate expressed in terms of compile (Closed)
Patch Set: feedback Created 3 years, 8 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/runtime/runtime-test.cc ('k') | src/wasm/wasm-module.h » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: src/wasm/wasm-js.cc
diff --git a/src/wasm/wasm-js.cc b/src/wasm/wasm-js.cc
index 3b275d19ecccc1444274f0fe60f93fe177d40dbb..93b396ba9a0365c8e9b803d26581cbbd7b2b1729 100644
--- a/src/wasm/wasm-js.cc
+++ b/src/wasm/wasm-js.cc
@@ -32,6 +32,14 @@ namespace v8 {
namespace {
+#define ASSIGN(type, var, expr) \
+ Local<type> var; \
+ do { \
+ if (!expr.ToLocal(&var)) { \
+ DCHECK(i_isolate->has_pending_exception()); \
adamk 2017/04/18 17:17:22 You still need to return here, otherwise we'll cra
+ } \
+ } while (false)
+
// TODO(wasm): move brand check to the respective types, and don't throw
// in it, rather, use a provided ErrorThrower, or let caller handle it.
static bool HasBrand(i::Handle<i::Object> value, i::Handle<i::Symbol> sym) {
@@ -117,16 +125,15 @@ i::wasm::ModuleWireBytes GetFirstArgumentAsBytes(
return i::wasm::ModuleWireBytes(start, start + length);
}
-i::MaybeHandle<i::JSReceiver> GetSecondArgumentAsImports(
- const v8::FunctionCallbackInfo<v8::Value>& args, ErrorThrower* thrower) {
- if (args.Length() < 2) return {};
- if (args[1]->IsUndefined()) return {};
+i::MaybeHandle<i::JSReceiver> GetValueAsImports(const Local<Value>& arg,
adamk 2017/04/18 17:17:22 Style nit: we pass Locals and Handles by value (th
+ ErrorThrower* thrower) {
+ if (arg->IsUndefined()) return {};
- if (!args[1]->IsObject()) {
+ if (!arg->IsObject()) {
thrower->TypeError("Argument 1 must be an object");
return {};
}
- Local<Object> obj = Local<Object>::Cast(args[1]);
+ Local<Object> obj = Local<Object>::Cast(arg);
return i::Handle<i::JSReceiver>::cast(v8::Utils::OpenHandle(*obj));
}
@@ -134,14 +141,14 @@ i::MaybeHandle<i::JSReceiver> GetSecondArgumentAsImports(
void WebAssemblyCompile(const v8::FunctionCallbackInfo<v8::Value>& args) {
v8::Isolate* isolate = args.GetIsolate();
i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate);
+ MicrotasksScope runs_microtasks(isolate, MicrotasksScope::kRunMicrotasks);
if (i_isolate->wasm_compile_callback()(args)) return;
HandleScope scope(isolate);
ErrorThrower thrower(i_isolate, "WebAssembly.compile()");
Local<Context> context = isolate->GetCurrentContext();
- v8::Local<v8::Promise::Resolver> resolver;
- if (!v8::Promise::Resolver::New(context).ToLocal(&resolver)) return;
+ ASSIGN(Promise::Resolver, resolver, Promise::Resolver::New(context));
v8::ReturnValue<v8::Value> return_value = args.GetReturnValue();
return_value.Set(resolver->GetPromise());
@@ -253,10 +260,90 @@ void WebAssemblyModuleCustomSections(
args.GetReturnValue().Set(Utils::ToLocal(custom_sections));
}
+MaybeLocal<Value> WebAssemblyInstantiateImpl(Isolate* isolate,
+ Local<Value> module,
+ Local<Value> ffi) {
+ i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate);
+
+ ErrorThrower thrower(i_isolate, "WebAssembly Instantiation");
+ i::MaybeHandle<i::JSReceiver> maybe_imports =
+ GetValueAsImports(ffi, &thrower);
+ if (thrower.error()) return {};
+
+ i::Handle<i::WasmModuleObject> module_obj =
+ i::Handle<i::WasmModuleObject>::cast(
+ Utils::OpenHandle(Object::Cast(*module)));
+ i::MaybeHandle<i::Object> instance_object =
+ i::wasm::SyncInstantiate(i_isolate, &thrower, module_obj, maybe_imports,
+ i::MaybeHandle<i::JSArrayBuffer>());
+
+ if (instance_object.is_null()) {
+ // TODO(wasm): this *should* mean there's an error to throw, but
+ // we exit sometimes the instantiation pipeline without throwing.
+ // v8:6232.
+ return {};
+ }
+ return Utils::ToLocal(instance_object.ToHandleChecked());
+}
+
+// Entered as internal implementation detail of sync and async instantiate.
+// args[0] *must* be a WebAssembly.Module.
+void WebAssemblyInstantiateImplCallback(
+ const v8::FunctionCallbackInfo<v8::Value>& args) {
+ DCHECK_GE(args.Length(), 1);
+ v8::Isolate* isolate = args.GetIsolate();
+ MicrotasksScope does_not_run_microtasks(isolate,
+ MicrotasksScope::kDoNotRunMicrotasks);
+
+ HandleScope scope(args.GetIsolate());
+ Local<Value> module = args[0];
+ Local<Value> ffi = args.Data();
+ Local<Value> instance;
+ if (WebAssemblyInstantiateImpl(isolate, module, ffi).ToLocal(&instance)) {
+ args.GetReturnValue().Set(instance);
+ }
+}
+
+void WebAssemblyInstantiateToPairCallback(
+ const v8::FunctionCallbackInfo<v8::Value>& args) {
+ DCHECK_GE(args.Length(), 1);
+ Isolate* isolate = args.GetIsolate();
+ MicrotasksScope does_not_run_microtasks(isolate,
+ MicrotasksScope::kDoNotRunMicrotasks);
+
+ HandleScope scope(args.GetIsolate());
+
+ Local<Context> context = isolate->GetCurrentContext();
+ Local<Value> module = args[0];
+
+ const uint8_t* instance_str = reinterpret_cast<const uint8_t*>("instance");
+ const uint8_t* module_str = reinterpret_cast<const uint8_t*>("module");
+ Local<Value> instance;
+ if (!WebAssemblyInstantiateImpl(isolate, module, args.Data())
+ .ToLocal(&instance))
adamk 2017/04/18 17:17:22 Style nit: please add { } around if-statement body
+ return;
+
+ Local<Object> ret = Object::New(isolate);
+ Local<String> instance_name =
+ String::NewFromOneByte(isolate, instance_str,
+ NewStringType::kInternalized)
+ .ToLocalChecked();
+ Local<String> module_name =
+ String::NewFromOneByte(isolate, module_str, NewStringType::kInternalized)
+ .ToLocalChecked();
+
+ CHECK(ret->CreateDataProperty(context, instance_name, instance).IsJust());
+ CHECK(ret->CreateDataProperty(context, module_name, module).IsJust());
+ args.GetReturnValue().Set(ret);
+}
+
// new WebAssembly.Instance(module, imports) -> WebAssembly.Instance
void WebAssemblyInstance(const v8::FunctionCallbackInfo<v8::Value>& args) {
+ Isolate* isolate = args.GetIsolate();
+ MicrotasksScope does_not_run_microtasks(isolate,
+ MicrotasksScope::kDoNotRunMicrotasks);
+
HandleScope scope(args.GetIsolate());
- v8::Isolate* isolate = args.GetIsolate();
i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate);
if (i_isolate->wasm_instance_callback()(args)) return;
@@ -265,14 +352,14 @@ void WebAssemblyInstance(const v8::FunctionCallbackInfo<v8::Value>& args) {
auto maybe_module = GetFirstArgumentAsModule(args, &thrower);
if (thrower.error()) return;
- auto maybe_imports = GetSecondArgumentAsImports(args, &thrower);
- if (thrower.error()) return;
+ // If args.Length < 2, this will be undefined - see FunctionCallbackInfo.
+ // We'll check for that in WebAssemblyInstantiateImpl.
+ Local<Value> data = args[1];
- i::MaybeHandle<i::Object> instance_object = i::wasm::SyncInstantiate(
- i_isolate, &thrower, maybe_module.ToHandleChecked(), maybe_imports,
- i::MaybeHandle<i::JSArrayBuffer>());
- if (instance_object.is_null()) return;
- args.GetReturnValue().Set(Utils::ToLocal(instance_object.ToHandleChecked()));
+ Local<Value> instance;
+ if (WebAssemblyInstantiateImpl(isolate, args[0], data).ToLocal(&instance)) {
+ args.GetReturnValue().Set(instance);
+ }
}
// WebAssembly.instantiate(module, imports) -> WebAssembly.Instance
@@ -281,6 +368,7 @@ void WebAssemblyInstance(const v8::FunctionCallbackInfo<v8::Value>& args) {
void WebAssemblyInstantiate(const v8::FunctionCallbackInfo<v8::Value>& args) {
v8::Isolate* isolate = args.GetIsolate();
i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate);
+ MicrotasksScope runs_microtasks(isolate, MicrotasksScope::kRunMicrotasks);
if (i_isolate->wasm_instantiate_callback()(args)) return;
ErrorThrower thrower(i_isolate, "WebAssembly.instantiate()");
@@ -290,10 +378,9 @@ void WebAssemblyInstantiate(const v8::FunctionCallbackInfo<v8::Value>& args) {
Local<Context> context = isolate->GetCurrentContext();
i::Handle<i::Context> i_context = Utils::OpenHandle(*context);
- v8::Local<v8::Promise::Resolver> resolver;
- if (!v8::Promise::Resolver::New(context).ToLocal(&resolver)) return;
- v8::ReturnValue<v8::Value> return_value = args.GetReturnValue();
- return_value.Set(resolver->GetPromise());
+ ASSIGN(Promise::Resolver, resolver, Promise::Resolver::New(context));
+ Local<Promise> module_promise = resolver->GetPromise();
+ args.GetReturnValue().Set(module_promise);
if (args.Length() < 1) {
thrower.TypeError(
@@ -305,7 +392,8 @@ void WebAssemblyInstantiate(const v8::FunctionCallbackInfo<v8::Value>& args) {
return;
}
- i::Handle<i::Object> first_arg = Utils::OpenHandle(*args[0]);
+ Local<Value> first_arg_value = args[0];
+ i::Handle<i::Object> first_arg = Utils::OpenHandle(*first_arg_value);
if (!first_arg->IsJSObject()) {
thrower.TypeError(
"Argument 0 must be a buffer source or a WebAssembly.Module object");
@@ -315,31 +403,27 @@ void WebAssemblyInstantiate(const v8::FunctionCallbackInfo<v8::Value>& args) {
return;
}
- auto maybe_imports = GetSecondArgumentAsImports(args, &thrower);
- if (thrower.error()) {
- auto maybe = resolver->Reject(context, Utils::ToLocal(thrower.Reify()));
- CHECK_IMPLIES(!maybe.FromMaybe(false),
- i_isolate->has_scheduled_exception());
- return;
- }
- i::Handle<i::JSPromise> promise = Utils::OpenHandle(*resolver->GetPromise());
+ FunctionCallback instantiator = nullptr;
if (HasBrand(first_arg, i::Handle<i::Symbol>(i_context->wasm_module_sym()))) {
- // WebAssembly.instantiate(module, imports) -> WebAssembly.Instance
- auto module_object = GetFirstArgumentAsModule(args, &thrower);
- i::wasm::AsyncInstantiate(i_isolate, promise,
- module_object.ToHandleChecked(), maybe_imports);
+ module_promise = resolver->GetPromise();
+ if (!resolver->Resolve(context, first_arg_value).IsJust()) return;
+ instantiator = WebAssemblyInstantiateImplCallback;
} else {
- // WebAssembly.instantiate(bytes, imports) -> {module, instance}
- auto bytes = GetFirstArgumentAsBytes(args, &thrower);
- if (thrower.error()) {
- auto maybe = resolver->Reject(context, Utils::ToLocal(thrower.Reify()));
- CHECK_IMPLIES(!maybe.FromMaybe(false),
- i_isolate->has_scheduled_exception());
- return;
- }
- i::wasm::AsyncCompileAndInstantiate(i_isolate, promise, bytes,
- maybe_imports);
- }
+ ASSIGN(Function, async_compile, Function::New(context, WebAssemblyCompile));
+ ASSIGN(Value, async_compile_retval,
+ async_compile->Call(context, args.Holder(), 1, &first_arg_value));
+ module_promise = Local<Promise>::Cast(async_compile_retval);
+ instantiator = WebAssemblyInstantiateToPairCallback;
+ }
+ DCHECK(!module_promise.IsEmpty());
+ DCHECK_NOT_NULL(instantiator);
+ // If args.Length < 2, this will be undefined - see FunctionCallbackInfo.
+ // We'll check for that in WebAssemblyInstantiateImpl.
+ Local<Value> data = args[1];
+ ASSIGN(Function, instantiate_impl,
+ Function::New(context, instantiator, data));
+ ASSIGN(Promise, result, module_promise->Then(context, instantiate_impl));
+ args.GetReturnValue().Set(result);
}
bool GetIntegerProperty(v8::Isolate* isolate, ErrorThrower* thrower,
« no previous file with comments | « src/runtime/runtime-test.cc ('k') | src/wasm/wasm-module.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698