Commit 96ddbf5b authored by mtrofin's avatar mtrofin Committed by Commit bot

[wasm] add WebAssembly.instantiate

BUG=v8:5816

Review-Url: https://codereview.chromium.org/2626693002
Cr-Commit-Position: refs/heads/master@{#42206}
parent 040f7434
......@@ -177,6 +177,12 @@ void WebAssemblyModule(const v8::FunctionCallbackInfo<v8::Value>& args) {
thrower.TypeError("Argument 0 must be a buffer source");
return;
}
if (args.Length() > 2) {
thrower.LinkError(
"WebAssembly.instantiate accepts no more than 2 parameters");
return;
}
i::MaybeHandle<i::JSObject> module_obj =
CreateModuleObject(isolate, args[0], &thrower);
if (module_obj.is_null()) return;
......@@ -185,7 +191,48 @@ void WebAssemblyModule(const v8::FunctionCallbackInfo<v8::Value>& args) {
return_value.Set(Utils::ToLocal(module_obj.ToHandleChecked()));
}
void WebAssemblyInstance(const v8::FunctionCallbackInfo<v8::Value>& args) {
MaybeLocal<Value> InstantiateModuleImpl(
i::Isolate* i_isolate, i::Handle<i::JSObject> i_module_obj,
const v8::FunctionCallbackInfo<v8::Value>& args, ErrorThrower* thrower) {
// It so happens that in both the WebAssembly.instantiate, as well as
// WebAssembly.Instance ctor, the positions of the ffi object and memory
// are the same. If that changes later, we refactor the consts into
// parameters.
static const int kFfiOffset = 1;
static const int kMemOffset = 2;
MaybeLocal<Value> nothing;
i::Handle<i::JSReceiver> ffi = i::Handle<i::JSObject>::null();
if (args.Length() > kFfiOffset && args[kFfiOffset]->IsObject()) {
Local<Object> obj = Local<Object>::Cast(args[kFfiOffset]);
ffi = i::Handle<i::JSReceiver>::cast(v8::Utils::OpenHandle(*obj));
}
i::Handle<i::JSArrayBuffer> memory = i::Handle<i::JSArrayBuffer>::null();
if (args.Length() > kMemOffset && args[kMemOffset]->IsObject()) {
Local<Object> obj = Local<Object>::Cast(args[kMemOffset]);
i::Handle<i::Object> mem_obj = v8::Utils::OpenHandle(*obj);
if (i::WasmJs::IsWasmMemoryObject(i_isolate, mem_obj)) {
memory = i::Handle<i::JSArrayBuffer>(
i::Handle<i::WasmMemoryObject>::cast(mem_obj)->buffer(), i_isolate);
} else {
thrower->TypeError("Argument %d must be a WebAssembly.Memory",
kMemOffset);
return nothing;
}
}
i::MaybeHandle<i::JSObject> instance = i::wasm::WasmModule::Instantiate(
i_isolate, thrower, i_module_obj, ffi, memory);
if (instance.is_null()) {
if (!thrower->error())
thrower->RuntimeError("Could not instantiate module");
return nothing;
}
DCHECK(!i_isolate->has_pending_exception());
return Utils::ToLocal(instance.ToHandleChecked());
}
void WebAssemblyInstanceCtor(const v8::FunctionCallbackInfo<v8::Value>& args) {
HandleScope scope(args.GetIsolate());
v8::Isolate* isolate = args.GetIsolate();
i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate);
......@@ -205,37 +252,51 @@ void WebAssemblyInstance(const v8::FunctionCallbackInfo<v8::Value>& args) {
return;
}
Local<Object> obj = Local<Object>::Cast(args[0]);
i::Handle<i::JSObject> i_obj =
i::Handle<i::JSObject>::cast(v8::Utils::OpenHandle(*obj));
Local<Object> module_obj = Local<Object>::Cast(args[0]);
i::Handle<i::JSObject> i_module_obj =
i::Handle<i::JSObject>::cast(v8::Utils::OpenHandle(*module_obj));
i::Handle<i::JSReceiver> ffi = i::Handle<i::JSObject>::null();
if (args.Length() > 1 && args[1]->IsObject()) {
Local<Object> obj = Local<Object>::Cast(args[1]);
ffi = i::Handle<i::JSReceiver>::cast(v8::Utils::OpenHandle(*obj));
MaybeLocal<Value> instance =
InstantiateModuleImpl(i_isolate, i_module_obj, args, &thrower);
if (instance.IsEmpty()) return;
v8::ReturnValue<v8::Value> return_value = args.GetReturnValue();
return_value.Set(instance.ToLocalChecked());
}
void WebAssemblyInstantiate(const v8::FunctionCallbackInfo<v8::Value>& args) {
v8::Isolate* isolate = args.GetIsolate();
i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate);
HandleScope scope(isolate);
ErrorThrower thrower(i_isolate, "WebAssembly.compile()");
if (args.Length() < 1) {
thrower.TypeError("Argument 0 must be a buffer source");
return;
}
i::MaybeHandle<i::JSObject> module_obj =
CreateModuleObject(isolate, args[0], &thrower);
i::Handle<i::JSArrayBuffer> memory = i::Handle<i::JSArrayBuffer>::null();
if (args.Length() > 2 && args[2]->IsObject()) {
Local<Object> obj = Local<Object>::Cast(args[2]);
i::Handle<i::Object> mem_obj = v8::Utils::OpenHandle(*obj);
if (i::WasmJs::IsWasmMemoryObject(i_isolate, mem_obj)) {
memory = i::Handle<i::JSArrayBuffer>(
i::Handle<i::WasmMemoryObject>::cast(mem_obj)->buffer(), i_isolate);
Local<Context> context = isolate->GetCurrentContext();
v8::Local<v8::Promise::Resolver> resolver;
if (!v8::Promise::Resolver::New(context).ToLocal(&resolver)) return;
if (module_obj.is_null()) {
DCHECK(thrower.error());
resolver->Reject(context, Utils::ToLocal(thrower.Reify()));
} else {
MaybeLocal<Value> instance = InstantiateModuleImpl(
i_isolate, module_obj.ToHandleChecked(), args, &thrower);
if (instance.IsEmpty()) {
DCHECK(thrower.error());
resolver->Reject(context, Utils::ToLocal(thrower.Reify()));
} else {
thrower.TypeError("Argument 2 must be a WebAssembly.Memory");
return;
DCHECK(!thrower.error());
resolver->Resolve(context, instance.ToLocalChecked());
}
}
i::MaybeHandle<i::JSObject> instance =
i::wasm::WasmModule::Instantiate(i_isolate, &thrower, i_obj, ffi, memory);
if (instance.is_null()) {
if (!thrower.error()) thrower.RuntimeError("Could not instantiate module");
return;
}
DCHECK(!i_isolate->has_pending_exception());
v8::ReturnValue<v8::Value> return_value = args.GetReturnValue();
return_value.Set(Utils::ToLocal(instance.ToHandleChecked()));
return_value.Set(resolver->GetPromise());
}
bool GetIntegerProperty(v8::Isolate* isolate, ErrorThrower* thrower,
......@@ -642,9 +703,12 @@ void WasmJs::InstallWasmConstructors(Isolate* isolate,
// Setup compile
InstallFunc(isolate, webassembly, "compile", WebAssemblyCompile, 1);
// Setup compile
// Setup validate
InstallFunc(isolate, webassembly, "validate", WebAssemblyValidate, 1);
// Setup instantiate
InstallFunc(isolate, webassembly, "instantiate", WebAssemblyInstantiate, 1);
// Setup Module
Handle<JSFunction> module_constructor =
InstallFunc(isolate, webassembly, "Module", WebAssemblyModule, 1);
......@@ -660,7 +724,7 @@ void WasmJs::InstallWasmConstructors(Isolate* isolate,
// Setup Instance
Handle<JSFunction> instance_constructor =
InstallFunc(isolate, webassembly, "Instance", WebAssemblyInstance, 1);
InstallFunc(isolate, webassembly, "Instance", WebAssemblyInstanceCtor, 1);
context->set_wasm_instance_constructor(*instance_constructor);
// Setup Table
......
......@@ -57,11 +57,20 @@ function CheckInstance(instance) {
}
// Official API
let module = new WebAssembly.Module(buffer);
CheckInstance(new WebAssembly.Instance(module));
(function BasicJSAPITest() {
print("sync module compile...");
let module = new WebAssembly.Module(buffer);
print("sync module instantiate...");
CheckInstance(new WebAssembly.Instance(module));
let promise = WebAssembly.compile(buffer);
promise.then(module => CheckInstance(new WebAssembly.Instance(module)));
print("async module compile...");
let promise = WebAssembly.compile(buffer);
promise.then(module => CheckInstance(new WebAssembly.Instance(module)));
print("async instantiate...");
let instance_promise = WebAssembly.instantiate(buffer);
instance_promise.then(CheckInstance);
})();
// Check that validate works correctly for a module.
assertTrue(WebAssembly.validate(buffer));
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment