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

Side by Side Diff: src/wasm/wasm-js.cc

Issue 2806073002: [wasm] instantiate expressed in terms of compile (Closed)
Patch Set: fix resetting 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 unified diff | Download patch
« no previous file with comments | « src/runtime/runtime-test.cc ('k') | src/wasm/wasm-module.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 2015 the V8 project authors. All rights reserved. 1 // Copyright 2015 the V8 project authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "src/api-natives.h" 5 #include "src/api-natives.h"
6 #include "src/api.h" 6 #include "src/api.h"
7 #include "src/asmjs/asm-js.h" 7 #include "src/asmjs/asm-js.h"
8 #include "src/asmjs/asm-typer.h" 8 #include "src/asmjs/asm-typer.h"
9 #include "src/asmjs/asm-wasm-builder.h" 9 #include "src/asmjs/asm-wasm-builder.h"
10 #include "src/assert-scope.h" 10 #include "src/assert-scope.h"
(...skipping 14 matching lines...) Expand all
25 #include "src/wasm/wasm-result.h" 25 #include "src/wasm/wasm-result.h"
26 26
27 typedef uint8_t byte; 27 typedef uint8_t byte;
28 28
29 using v8::internal::wasm::ErrorThrower; 29 using v8::internal::wasm::ErrorThrower;
30 30
31 namespace v8 { 31 namespace v8 {
32 32
33 namespace { 33 namespace {
34 34
35 #define ASSIGN(type, var, expr) \
adamk 2017/04/17 23:46:19 The name we use for this inside the API is ASSIGN_
Mircea Trofin 2017/04/18 01:03:54 Done.
36 Local<type> var; \
37 do { \
38 if (!expr.ToLocal(&var)) return; \
39 } while (false)
40
41 #define DO_BOOL(expr) \
42 do { \
43 bool ok; \
44 if (!expr.To(&ok) || !ok) return; \
45 } while (false)
46
35 // TODO(wasm): move brand check to the respective types, and don't throw 47 // TODO(wasm): move brand check to the respective types, and don't throw
36 // in it, rather, use a provided ErrorThrower, or let caller handle it. 48 // in it, rather, use a provided ErrorThrower, or let caller handle it.
37 static bool HasBrand(i::Handle<i::Object> value, i::Handle<i::Symbol> sym) { 49 static bool HasBrand(i::Handle<i::Object> value, i::Handle<i::Symbol> sym) {
38 if (!value->IsJSObject()) return false; 50 if (!value->IsJSObject()) return false;
39 i::Handle<i::JSObject> object = i::Handle<i::JSObject>::cast(value); 51 i::Handle<i::JSObject> object = i::Handle<i::JSObject>::cast(value);
40 Maybe<bool> has_brand = i::JSObject::HasOwnProperty(object, sym); 52 Maybe<bool> has_brand = i::JSObject::HasOwnProperty(object, sym);
41 return has_brand.FromMaybe(false); 53 return has_brand.FromMaybe(false);
42 } 54 }
43 55
44 static bool BrandCheck(i::Handle<i::Object> value, i::Handle<i::Symbol> sym, 56 static bool BrandCheck(i::Handle<i::Object> value, i::Handle<i::Symbol> sym,
(...skipping 65 matching lines...) Expand 10 before | Expand all | Expand 10 after
110 } 122 }
111 if (length > i::wasm::kV8MaxWasmModuleSize) { 123 if (length > i::wasm::kV8MaxWasmModuleSize) {
112 thrower->RangeError("buffer source exceeds maximum size of %zu (is %zu)", 124 thrower->RangeError("buffer source exceeds maximum size of %zu (is %zu)",
113 i::wasm::kV8MaxWasmModuleSize, length); 125 i::wasm::kV8MaxWasmModuleSize, length);
114 } 126 }
115 if (thrower->error()) return i::wasm::ModuleWireBytes(nullptr, nullptr); 127 if (thrower->error()) return i::wasm::ModuleWireBytes(nullptr, nullptr);
116 // TODO(titzer): use the handle as well? 128 // TODO(titzer): use the handle as well?
117 return i::wasm::ModuleWireBytes(start, start + length); 129 return i::wasm::ModuleWireBytes(start, start + length);
118 } 130 }
119 131
120 i::MaybeHandle<i::JSReceiver> GetSecondArgumentAsImports( 132 i::MaybeHandle<i::JSReceiver> GetValueAsImports(const Local<Value>& arg,
121 const v8::FunctionCallbackInfo<v8::Value>& args, ErrorThrower* thrower) { 133 ErrorThrower* thrower) {
122 if (args.Length() < 2) return {}; 134 if (arg->IsUndefined()) return {};
123 if (args[1]->IsUndefined()) return {};
124 135
125 if (!args[1]->IsObject()) { 136 if (!arg->IsObject()) {
126 thrower->TypeError("Argument 1 must be an object"); 137 thrower->TypeError("Argument 1 must be an object");
127 return {}; 138 return {};
128 } 139 }
129 Local<Object> obj = Local<Object>::Cast(args[1]); 140 Local<Object> obj = Local<Object>::Cast(arg);
130 return i::Handle<i::JSReceiver>::cast(v8::Utils::OpenHandle(*obj)); 141 return i::Handle<i::JSReceiver>::cast(v8::Utils::OpenHandle(*obj));
131 } 142 }
132 143
133 // WebAssembly.compile(bytes) -> Promise 144 // WebAssembly.compile(bytes) -> Promise
134 void WebAssemblyCompile(const v8::FunctionCallbackInfo<v8::Value>& args) { 145 void WebAssemblyCompile(const v8::FunctionCallbackInfo<v8::Value>& args) {
135 v8::Isolate* isolate = args.GetIsolate(); 146 v8::Isolate* isolate = args.GetIsolate();
136 i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate); 147 i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate);
148 MicrotasksScope runs_microtasks(isolate, MicrotasksScope::kRunMicrotasks);
137 if (i_isolate->wasm_compile_callback()(args)) return; 149 if (i_isolate->wasm_compile_callback()(args)) return;
138 150
139 HandleScope scope(isolate); 151 HandleScope scope(isolate);
140 ErrorThrower thrower(i_isolate, "WebAssembly.compile()"); 152 ErrorThrower thrower(i_isolate, "WebAssembly.compile()");
141 153
142 Local<Context> context = isolate->GetCurrentContext(); 154 Local<Context> context = isolate->GetCurrentContext();
143 v8::Local<v8::Promise::Resolver> resolver; 155 ASSIGN(Promise::Resolver, resolver, Promise::Resolver::New(context));
144 if (!v8::Promise::Resolver::New(context).ToLocal(&resolver)) return;
145 v8::ReturnValue<v8::Value> return_value = args.GetReturnValue(); 156 v8::ReturnValue<v8::Value> return_value = args.GetReturnValue();
146 return_value.Set(resolver->GetPromise()); 157 return_value.Set(resolver->GetPromise());
147 158
148 auto bytes = GetFirstArgumentAsBytes(args, &thrower); 159 auto bytes = GetFirstArgumentAsBytes(args, &thrower);
149 if (thrower.error()) { 160 if (thrower.error()) {
150 auto maybe = resolver->Reject(context, Utils::ToLocal(thrower.Reify())); 161 auto maybe = resolver->Reject(context, Utils::ToLocal(thrower.Reify()));
151 CHECK_IMPLIES(!maybe.FromMaybe(false), 162 CHECK_IMPLIES(!maybe.FromMaybe(false),
152 i_isolate->has_scheduled_exception()); 163 i_isolate->has_scheduled_exception());
153 return; 164 return;
154 } 165 }
(...skipping 91 matching lines...) Expand 10 before | Expand all | Expand 10 after
246 return; 257 return;
247 } 258 }
248 259
249 auto custom_sections = 260 auto custom_sections =
250 i::wasm::GetCustomSections(i_isolate, maybe_module.ToHandleChecked(), 261 i::wasm::GetCustomSections(i_isolate, maybe_module.ToHandleChecked(),
251 i::Handle<i::String>::cast(name), &thrower); 262 i::Handle<i::String>::cast(name), &thrower);
252 if (thrower.error()) return; 263 if (thrower.error()) return;
253 args.GetReturnValue().Set(Utils::ToLocal(custom_sections)); 264 args.GetReturnValue().Set(Utils::ToLocal(custom_sections));
254 } 265 }
255 266
267 // Entered as internal implementation detail of sync and async instantiate.
268 // args[0] *must* be a WebAssembly.Module.
269 void WebAssemblyInstantiateImpl(
270 const v8::FunctionCallbackInfo<v8::Value>& args) {
271 DCHECK_GE(args.Length(), 1);
272 v8::Isolate* isolate = args.GetIsolate();
273 i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate);
274 MicrotasksScope does_not_run_microtasks(isolate,
275 MicrotasksScope::kDoNotRunMicrotasks);
276
277 HandleScope scope(args.GetIsolate());
278 Local<Value> module = args[0];
279 Local<Value> ffi = args.Data();
280
281 ErrorThrower thrower(i_isolate, "WebAssembly Instantiation");
282 i::MaybeHandle<i::JSReceiver> maybe_imports =
283 GetValueAsImports(ffi, &thrower);
284 if (thrower.error()) return;
285
286 i::Handle<i::WasmModuleObject> module_obj =
287 i::Handle<i::WasmModuleObject>::cast(
288 Utils::OpenHandle(Object::Cast(*module)));
289 i::MaybeHandle<i::Object> instance_object =
290 i::wasm::SyncInstantiate(i_isolate, &thrower, module_obj, maybe_imports,
291 i::MaybeHandle<i::JSArrayBuffer>());
292
293 if (instance_object.is_null()) {
294 // TODO(wasm): this *should* mean there's an error to throw, but
295 // we exit sometimes the instantiation pipeline without throwing.
296 // v8:6232.
297 return;
298 }
299 args.GetReturnValue().Set(Utils::ToLocal(instance_object.ToHandleChecked()));
300 }
301
302 void WebAssemblyInstantiateToPair(
303 const v8::FunctionCallbackInfo<v8::Value>& args) {
304 DCHECK_GE(args.Length(), 1);
305 Isolate* isolate = args.GetIsolate();
306 MicrotasksScope does_not_run_microtasks(isolate,
307 MicrotasksScope::kDoNotRunMicrotasks);
308
309 HandleScope scope(args.GetIsolate());
310
311 Local<Context> context = isolate->GetCurrentContext();
312 Local<Value> module = args[0];
313
314 const uint8_t* instance_str = reinterpret_cast<const uint8_t*>("instance");
315 const uint8_t* module_str = reinterpret_cast<const uint8_t*>("module");
316 ASSIGN(Function, vanilla_instantiate,
317 Function::New(context, WebAssemblyInstantiateImpl, args.Data()));
318
319 ASSIGN(Value, instance,
320 vanilla_instantiate->Call(context, args.Holder(), 1, &module));
adamk 2017/04/17 23:46:19 I really feel like it's weird to create a v8::Func
Mircea Trofin 2017/04/18 01:03:53 Done.
321 Local<Object> ret = Object::New(isolate);
322 ASSIGN(String, instance_name,
323 String::NewFromOneByte(isolate, instance_str,
324 NewStringType::kInternalized));
325 ASSIGN(String, module_name,
adamk 2017/04/17 23:46:19 This and the above can't meaningfully fail (the AP
Mircea Trofin 2017/04/18 01:03:53 Done.
326 String::NewFromOneByte(isolate, module_str,
327 NewStringType::kInternalized));
328
329 DO_BOOL(ret->CreateDataProperty(context, instance_name, instance));
330 DO_BOOL(ret->CreateDataProperty(context, module_name, module));
adamk 2017/04/17 23:46:19 I don't believe that either of these could possibl
Mircea Trofin 2017/04/18 01:03:53 Done.
331 args.GetReturnValue().Set(ret);
332 }
333
256 // new WebAssembly.Instance(module, imports) -> WebAssembly.Instance 334 // new WebAssembly.Instance(module, imports) -> WebAssembly.Instance
257 void WebAssemblyInstance(const v8::FunctionCallbackInfo<v8::Value>& args) { 335 void WebAssemblyInstance(const v8::FunctionCallbackInfo<v8::Value>& args) {
336 Isolate* isolate = args.GetIsolate();
337 MicrotasksScope does_not_run_microtasks(isolate,
338 MicrotasksScope::kDoNotRunMicrotasks);
339
258 HandleScope scope(args.GetIsolate()); 340 HandleScope scope(args.GetIsolate());
259 v8::Isolate* isolate = args.GetIsolate(); 341 Local<Context> context = isolate->GetCurrentContext();
260 i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate); 342 i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate);
261 if (i_isolate->wasm_instance_callback()(args)) return; 343 if (i_isolate->wasm_instance_callback()(args)) return;
262 344
263 ErrorThrower thrower(i_isolate, "WebAssembly.Instance()"); 345 ErrorThrower thrower(i_isolate, "WebAssembly.Instance()");
264 346
265 auto maybe_module = GetFirstArgumentAsModule(args, &thrower); 347 auto maybe_module = GetFirstArgumentAsModule(args, &thrower);
266 if (thrower.error()) return; 348 if (thrower.error()) return;
267 349
268 auto maybe_imports = GetSecondArgumentAsImports(args, &thrower); 350 // If args.Length < 2, this will be undefined - see FunctionCallbackInfo.
269 if (thrower.error()) return; 351 // We'll check for that in WebAssemblyInstantiateImpl.
352 Local<Value> data = args[1];
270 353
271 i::MaybeHandle<i::Object> instance_object = i::wasm::SyncInstantiate( 354 ASSIGN(Function, impl,
272 i_isolate, &thrower, maybe_module.ToHandleChecked(), maybe_imports, 355 Function::New(context, WebAssemblyInstantiateImpl, data));
273 i::MaybeHandle<i::JSArrayBuffer>()); 356 Local<Value> first_param = args[0];
274 if (instance_object.is_null()) return; 357 ASSIGN(Value, ret, impl->Call(context, args.Holder(), 1, &first_param));
275 args.GetReturnValue().Set(Utils::ToLocal(instance_object.ToHandleChecked())); 358 args.GetReturnValue().Set(ret);
276 } 359 }
277 360
278 // WebAssembly.instantiate(module, imports) -> WebAssembly.Instance 361 // WebAssembly.instantiate(module, imports) -> WebAssembly.Instance
279 // WebAssembly.instantiate(bytes, imports) -> 362 // WebAssembly.instantiate(bytes, imports) ->
280 // {module: WebAssembly.Module, instance: WebAssembly.Instance} 363 // {module: WebAssembly.Module, instance: WebAssembly.Instance}
281 void WebAssemblyInstantiate(const v8::FunctionCallbackInfo<v8::Value>& args) { 364 void WebAssemblyInstantiate(const v8::FunctionCallbackInfo<v8::Value>& args) {
282 v8::Isolate* isolate = args.GetIsolate(); 365 v8::Isolate* isolate = args.GetIsolate();
283 i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate); 366 i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate);
367 MicrotasksScope runs_microtasks(isolate, MicrotasksScope::kRunMicrotasks);
284 if (i_isolate->wasm_instantiate_callback()(args)) return; 368 if (i_isolate->wasm_instantiate_callback()(args)) return;
285 369
286 ErrorThrower thrower(i_isolate, "WebAssembly.instantiate()"); 370 ErrorThrower thrower(i_isolate, "WebAssembly.instantiate()");
287 371
288 HandleScope scope(isolate); 372 HandleScope scope(isolate);
289 373
290 Local<Context> context = isolate->GetCurrentContext(); 374 Local<Context> context = isolate->GetCurrentContext();
291 i::Handle<i::Context> i_context = Utils::OpenHandle(*context); 375 i::Handle<i::Context> i_context = Utils::OpenHandle(*context);
292 376
293 v8::Local<v8::Promise::Resolver> resolver; 377 ASSIGN(Promise::Resolver, resolver, Promise::Resolver::New(context));
294 if (!v8::Promise::Resolver::New(context).ToLocal(&resolver)) return; 378 Local<Promise> module_promise = resolver->GetPromise();
295 v8::ReturnValue<v8::Value> return_value = args.GetReturnValue(); 379 args.GetReturnValue().Set(module_promise);
296 return_value.Set(resolver->GetPromise());
297 380
298 if (args.Length() < 1) { 381 if (args.Length() < 1) {
299 thrower.TypeError( 382 thrower.TypeError(
300 "Argument 0 must be provided and must be either a buffer source or a " 383 "Argument 0 must be provided and must be either a buffer source or a "
301 "WebAssembly.Module object"); 384 "WebAssembly.Module object");
302 auto maybe = resolver->Reject(context, Utils::ToLocal(thrower.Reify())); 385 auto maybe = resolver->Reject(context, Utils::ToLocal(thrower.Reify()));
303 CHECK_IMPLIES(!maybe.FromMaybe(false), 386 CHECK_IMPLIES(!maybe.FromMaybe(false),
304 i_isolate->has_scheduled_exception()); 387 i_isolate->has_scheduled_exception());
305 return; 388 return;
306 } 389 }
307 390
308 i::Handle<i::Object> first_arg = Utils::OpenHandle(*args[0]); 391 Local<Value> first_arg_value = args[0];
392 i::Handle<i::Object> first_arg = Utils::OpenHandle(*first_arg_value);
309 if (!first_arg->IsJSObject()) { 393 if (!first_arg->IsJSObject()) {
310 thrower.TypeError( 394 thrower.TypeError(
311 "Argument 0 must be a buffer source or a WebAssembly.Module object"); 395 "Argument 0 must be a buffer source or a WebAssembly.Module object");
312 auto maybe = resolver->Reject(context, Utils::ToLocal(thrower.Reify())); 396 auto maybe = resolver->Reject(context, Utils::ToLocal(thrower.Reify()));
313 CHECK_IMPLIES(!maybe.FromMaybe(false), 397 CHECK_IMPLIES(!maybe.FromMaybe(false),
314 i_isolate->has_scheduled_exception()); 398 i_isolate->has_scheduled_exception());
315 return; 399 return;
316 } 400 }
317 401
318 auto maybe_imports = GetSecondArgumentAsImports(args, &thrower); 402 FunctionCallback instantiator = nullptr;
319 if (thrower.error()) { 403 if (HasBrand(first_arg, i::Handle<i::Symbol>(i_context->wasm_module_sym()))) {
320 auto maybe = resolver->Reject(context, Utils::ToLocal(thrower.Reify())); 404 module_promise = resolver->GetPromise();
321 CHECK_IMPLIES(!maybe.FromMaybe(false), 405 DO_BOOL(resolver->Resolve(context, first_arg_value));
adamk 2017/04/17 23:46:19 This would be the last use of DO_BOOL; given that,
Mircea Trofin 2017/04/18 01:03:54 Done.
322 i_isolate->has_scheduled_exception()); 406 instantiator = WebAssemblyInstantiateImpl;
323 return; 407 } else {
408 ASSIGN(Function, async_compile, Function::New(context, WebAssemblyCompile));
409 ASSIGN(Value, async_compile_retval,
410 async_compile->Call(context, args.Holder(), 1, &first_arg_value));
411 module_promise = Local<Promise>::Cast(async_compile_retval);
412 instantiator = WebAssemblyInstantiateToPair;
324 } 413 }
325 i::Handle<i::JSPromise> promise = Utils::OpenHandle(*resolver->GetPromise()); 414 DCHECK(!module_promise.IsEmpty());
326 if (HasBrand(first_arg, i::Handle<i::Symbol>(i_context->wasm_module_sym()))) { 415 DCHECK_NOT_NULL(instantiator);
327 // WebAssembly.instantiate(module, imports) -> WebAssembly.Instance 416 // If args.Length < 2, this will be undefined - see FunctionCallbackInfo.
328 auto module_object = GetFirstArgumentAsModule(args, &thrower); 417 // We'll check for that in WebAssemblyInstantiateImpl.
329 i::wasm::AsyncInstantiate(i_isolate, promise, 418 Local<Value> data = args[1];
330 module_object.ToHandleChecked(), maybe_imports); 419 ASSIGN(Function, instantiate_impl,
331 } else { 420 Function::New(context, instantiator, data));
adamk 2017/04/17 23:46:19 It's a little wasteful to create a new function ea
Mircea Trofin 2017/04/18 01:03:53 That, but also, we need a closure to hold on to th
332 // WebAssembly.instantiate(bytes, imports) -> {module, instance} 421 ASSIGN(Promise, result, module_promise->Then(context, instantiate_impl));
333 auto bytes = GetFirstArgumentAsBytes(args, &thrower); 422 args.GetReturnValue().Set(result);
334 if (thrower.error()) {
335 auto maybe = resolver->Reject(context, Utils::ToLocal(thrower.Reify()));
336 CHECK_IMPLIES(!maybe.FromMaybe(false),
337 i_isolate->has_scheduled_exception());
338 return;
339 }
340 i::wasm::AsyncCompileAndInstantiate(i_isolate, promise, bytes,
341 maybe_imports);
342 }
343 } 423 }
344 424
345 bool GetIntegerProperty(v8::Isolate* isolate, ErrorThrower* thrower, 425 bool GetIntegerProperty(v8::Isolate* isolate, ErrorThrower* thrower,
346 Local<Context> context, Local<v8::Object> object, 426 Local<Context> context, Local<v8::Object> object,
347 Local<String> property, int* result, 427 Local<String> property, int* result,
348 int64_t lower_bound, uint64_t upper_bound) { 428 int64_t lower_bound, uint64_t upper_bound) {
349 v8::MaybeLocal<v8::Value> maybe = object->Get(context, property); 429 v8::MaybeLocal<v8::Value> maybe = object->Get(context, property);
350 v8::Local<v8::Value> value; 430 v8::Local<v8::Value> value;
351 if (maybe.ToLocal(&value)) { 431 if (maybe.ToLocal(&value)) {
352 int64_t number; 432 int64_t number;
(...skipping 531 matching lines...) Expand 10 before | Expand all | Expand 10 after
884 i::Handle<i::Symbol> symbol(isolate->context()->wasm_memory_sym(), isolate); 964 i::Handle<i::Symbol> symbol(isolate->context()->wasm_memory_sym(), isolate);
885 return HasBrand(value, symbol); 965 return HasBrand(value, symbol);
886 } 966 }
887 967
888 bool WasmJs::IsWasmTableObject(Isolate* isolate, Handle<Object> value) { 968 bool WasmJs::IsWasmTableObject(Isolate* isolate, Handle<Object> value) {
889 i::Handle<i::Symbol> symbol(isolate->context()->wasm_table_sym(), isolate); 969 i::Handle<i::Symbol> symbol(isolate->context()->wasm_table_sym(), isolate);
890 return HasBrand(value, symbol); 970 return HasBrand(value, symbol);
891 } 971 }
892 } // namespace internal 972 } // namespace internal
893 } // namespace v8 973 } // namespace v8
OLDNEW
« 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