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

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

Issue 2806073002: [wasm] instantiate expressed in terms of compile (Closed)
Patch Set: intantiate 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
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) \
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);
137 if (i_isolate->wasm_compile_callback()(args)) return; 148 if (i_isolate->wasm_compile_callback()(args)) return;
138 149
139 HandleScope scope(isolate); 150 HandleScope scope(isolate);
140 ErrorThrower thrower(i_isolate, "WebAssembly.compile()"); 151 ErrorThrower thrower(i_isolate, "WebAssembly.compile()");
141 152
142 Local<Context> context = isolate->GetCurrentContext(); 153 Local<Context> context = isolate->GetCurrentContext();
143 v8::Local<v8::Promise::Resolver> resolver; 154 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(); 155 v8::ReturnValue<v8::Value> return_value = args.GetReturnValue();
146 return_value.Set(resolver->GetPromise()); 156 return_value.Set(resolver->GetPromise());
147 157
148 auto bytes = GetFirstArgumentAsBytes(args, &thrower); 158 auto bytes = GetFirstArgumentAsBytes(args, &thrower);
149 if (thrower.error()) { 159 if (thrower.error()) {
150 auto maybe = resolver->Reject(context, Utils::ToLocal(thrower.Reify())); 160 auto maybe = resolver->Reject(context, Utils::ToLocal(thrower.Reify()));
151 CHECK_IMPLIES(!maybe.FromMaybe(false), 161 CHECK_IMPLIES(!maybe.FromMaybe(false),
152 i_isolate->has_scheduled_exception()); 162 i_isolate->has_scheduled_exception());
153 return; 163 return;
154 } 164 }
(...skipping 91 matching lines...) Expand 10 before | Expand all | Expand 10 after
246 return; 256 return;
247 } 257 }
248 258
249 auto custom_sections = 259 auto custom_sections =
250 i::wasm::GetCustomSections(i_isolate, maybe_module.ToHandleChecked(), 260 i::wasm::GetCustomSections(i_isolate, maybe_module.ToHandleChecked(),
251 i::Handle<i::String>::cast(name), &thrower); 261 i::Handle<i::String>::cast(name), &thrower);
252 if (thrower.error()) return; 262 if (thrower.error()) return;
253 args.GetReturnValue().Set(Utils::ToLocal(custom_sections)); 263 args.GetReturnValue().Set(Utils::ToLocal(custom_sections));
254 } 264 }
255 265
266 // Entered as internal implementation detail of sync and async instantiate.
267 // args[0] *must* be a WebAssembly.Module.
268 void WebAssemblyInstantiateImpl(
269 const v8::FunctionCallbackInfo<v8::Value>& args) {
270 DCHECK_GE(args.Length(), 1);
271 Local<Value> module = args[0];
272 Local<Value> ffi = args.Data();
273
274 HandleScope scope(args.GetIsolate());
275 v8::Isolate* isolate = args.GetIsolate();
276 i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate);
277 ErrorThrower thrower(i_isolate, "WebAssembly Instantiation");
278 i::MaybeHandle<i::JSReceiver> maybe_imports =
279 GetValueAsImports(ffi, &thrower);
280 if (thrower.error()) return;
281
282 i::Handle<i::WasmModuleObject> module_obj =
283 i::Handle<i::WasmModuleObject>::cast(
284 Utils::OpenHandle(Object::Cast(*module)));
285 i::MaybeHandle<i::Object> instance_object =
286 i::wasm::SyncInstantiate(i_isolate, &thrower, module_obj, maybe_imports,
287 i::MaybeHandle<i::JSArrayBuffer>());
288
289 if (instance_object.is_null()) {
290 // TODO(wasm): this *should* mean there's an error to throw, but
291 // we exit sometimes the instantiation pipeline without throwing.
292 // v8:6232.
293 return;
294 }
295 args.GetReturnValue().Set(Utils::ToLocal(instance_object.ToHandleChecked()));
296 }
297
298 void WebAssemblyInstantiateToPair(
299 const v8::FunctionCallbackInfo<v8::Value>& args) {
300 DCHECK_GE(args.Length(), 1);
301 Local<Value> module = args[0];
302 Isolate* isolate = args.GetIsolate();
303 Local<Context> context = isolate->GetCurrentContext();
304
305 const uint8_t* instance_str = reinterpret_cast<const uint8_t*>("instance");
306 const uint8_t* module_str = reinterpret_cast<const uint8_t*>("module");
307 ASSIGN(Function, vanilla_instantiate,
308 Function::New(context, WebAssemblyInstantiateImpl, args.Data()));
309
310 ASSIGN(Value, instance,
311 vanilla_instantiate->Call(context, args.Holder(), 1, &module));
312 Local<Object> ret = Object::New(isolate);
313 ASSIGN(String, instance_name,
314 String::NewFromOneByte(isolate, instance_str,
315 NewStringType::kInternalized));
316 ASSIGN(String, module_name,
317 String::NewFromOneByte(isolate, module_str,
318 NewStringType::kInternalized));
319
320 DO_BOOL(ret->CreateDataProperty(context, instance_name, instance));
321 DO_BOOL(ret->CreateDataProperty(context, module_name, module));
322 args.GetReturnValue().Set(ret);
323 }
324
256 // new WebAssembly.Instance(module, imports) -> WebAssembly.Instance 325 // new WebAssembly.Instance(module, imports) -> WebAssembly.Instance
257 void WebAssemblyInstance(const v8::FunctionCallbackInfo<v8::Value>& args) { 326 void WebAssemblyInstance(const v8::FunctionCallbackInfo<v8::Value>& args) {
258 HandleScope scope(args.GetIsolate()); 327 HandleScope scope(args.GetIsolate());
259 v8::Isolate* isolate = args.GetIsolate(); 328 Isolate* isolate = args.GetIsolate();
329 Local<Context> context = isolate->GetCurrentContext();
260 i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate); 330 i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate);
261 if (i_isolate->wasm_instance_callback()(args)) return; 331 if (i_isolate->wasm_instance_callback()(args)) return;
262 332
263 ErrorThrower thrower(i_isolate, "WebAssembly.Instance()"); 333 ErrorThrower thrower(i_isolate, "WebAssembly.Instance()");
264 334
265 auto maybe_module = GetFirstArgumentAsModule(args, &thrower); 335 auto maybe_module = GetFirstArgumentAsModule(args, &thrower);
266 if (thrower.error()) return; 336 if (thrower.error()) return;
267 337
268 auto maybe_imports = GetSecondArgumentAsImports(args, &thrower); 338 // If args.Length < 2, this will be undefined - see FunctionCallbackInfo.
269 if (thrower.error()) return; 339 // We'll check for that in WebAssemblyInstantiateImpl.
340 Local<Value> data = args[1];
bradnelson 2017/04/11 23:18:41 You sure args does that automatically? Old code di
Mircea Trofin 2017/04/11 23:33:18 Yes: https://cs.chromium.org/chromium/src/v8/inclu
270 341
271 i::MaybeHandle<i::Object> instance_object = i::wasm::SyncInstantiate( 342 ASSIGN(Function, impl,
272 i_isolate, &thrower, maybe_module.ToHandleChecked(), maybe_imports, 343 Function::New(context, WebAssemblyInstantiateImpl, data));
273 i::MaybeHandle<i::JSArrayBuffer>()); 344 Local<Value> first_param = args[0];
274 if (instance_object.is_null()) return; 345 ASSIGN(Value, ret, impl->Call(context, args.Holder(), 1, &first_param));
275 args.GetReturnValue().Set(Utils::ToLocal(instance_object.ToHandleChecked())); 346 args.GetReturnValue().Set(ret);
276 } 347 }
277 348
278 // WebAssembly.instantiate(module, imports) -> WebAssembly.Instance 349 // WebAssembly.instantiate(module, imports) -> WebAssembly.Instance
279 // WebAssembly.instantiate(bytes, imports) -> 350 // WebAssembly.instantiate(bytes, imports) ->
280 // {module: WebAssembly.Module, instance: WebAssembly.Instance} 351 // {module: WebAssembly.Module, instance: WebAssembly.Instance}
281 void WebAssemblyInstantiate(const v8::FunctionCallbackInfo<v8::Value>& args) { 352 void WebAssemblyInstantiate(const v8::FunctionCallbackInfo<v8::Value>& args) {
282 v8::Isolate* isolate = args.GetIsolate(); 353 v8::Isolate* isolate = args.GetIsolate();
283 i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate); 354 i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate);
284 if (i_isolate->wasm_instantiate_callback()(args)) return; 355 if (i_isolate->wasm_instantiate_callback()(args)) return;
285 356
286 ErrorThrower thrower(i_isolate, "WebAssembly.instantiate()"); 357 ErrorThrower thrower(i_isolate, "WebAssembly.instantiate()");
287 358
288 HandleScope scope(isolate); 359 HandleScope scope(isolate);
289 360
290 Local<Context> context = isolate->GetCurrentContext(); 361 Local<Context> context = isolate->GetCurrentContext();
291 i::Handle<i::Context> i_context = Utils::OpenHandle(*context); 362 i::Handle<i::Context> i_context = Utils::OpenHandle(*context);
292 363
293 v8::Local<v8::Promise::Resolver> resolver; 364 ASSIGN(Promise::Resolver, resolver, Promise::Resolver::New(context));
294 if (!v8::Promise::Resolver::New(context).ToLocal(&resolver)) return; 365 Local<Promise> module_promise = resolver->GetPromise();
295 v8::ReturnValue<v8::Value> return_value = args.GetReturnValue(); 366 args.GetReturnValue().Set(module_promise);
296 return_value.Set(resolver->GetPromise());
297 367
298 if (args.Length() < 1) { 368 if (args.Length() < 1) {
299 thrower.TypeError( 369 thrower.TypeError(
300 "Argument 0 must be provided and must be either a buffer source or a " 370 "Argument 0 must be provided and must be either a buffer source or a "
301 "WebAssembly.Module object"); 371 "WebAssembly.Module object");
302 auto maybe = resolver->Reject(context, Utils::ToLocal(thrower.Reify())); 372 auto maybe = resolver->Reject(context, Utils::ToLocal(thrower.Reify()));
303 CHECK_IMPLIES(!maybe.FromMaybe(false), 373 CHECK_IMPLIES(!maybe.FromMaybe(false),
304 i_isolate->has_scheduled_exception()); 374 i_isolate->has_scheduled_exception());
305 return; 375 return;
306 } 376 }
307 377
308 i::Handle<i::Object> first_arg = Utils::OpenHandle(*args[0]); 378 Local<Value> first_arg_value = args[0];
379 i::Handle<i::Object> first_arg = Utils::OpenHandle(*first_arg_value);
309 if (!first_arg->IsJSObject()) { 380 if (!first_arg->IsJSObject()) {
310 thrower.TypeError( 381 thrower.TypeError(
311 "Argument 0 must be a buffer source or a WebAssembly.Module object"); 382 "Argument 0 must be a buffer source or a WebAssembly.Module object");
312 auto maybe = resolver->Reject(context, Utils::ToLocal(thrower.Reify())); 383 auto maybe = resolver->Reject(context, Utils::ToLocal(thrower.Reify()));
313 CHECK_IMPLIES(!maybe.FromMaybe(false), 384 CHECK_IMPLIES(!maybe.FromMaybe(false),
314 i_isolate->has_scheduled_exception()); 385 i_isolate->has_scheduled_exception());
315 return; 386 return;
316 } 387 }
317 388
318 auto maybe_imports = GetSecondArgumentAsImports(args, &thrower); 389 FunctionCallback instantiator = nullptr;
319 if (thrower.error()) { 390 if (HasBrand(first_arg, i::Handle<i::Symbol>(i_context->wasm_module_sym()))) {
320 auto maybe = resolver->Reject(context, Utils::ToLocal(thrower.Reify())); 391 module_promise = resolver->GetPromise();
321 CHECK_IMPLIES(!maybe.FromMaybe(false), 392 DO_BOOL(resolver->Resolve(context, first_arg_value));
322 i_isolate->has_scheduled_exception()); 393 instantiator = WebAssemblyInstantiateImpl;
323 return; 394 } else {
395 ASSIGN(Function, async_compile, Function::New(context, WebAssemblyCompile));
396 ASSIGN(Value, async_compile_retval,
397 async_compile->Call(context, args.Holder(), 1, &first_arg_value));
398 module_promise = Local<Promise>::Cast(async_compile_retval);
399 instantiator = WebAssemblyInstantiateToPair;
324 } 400 }
325 i::Handle<i::JSPromise> promise = Utils::OpenHandle(*resolver->GetPromise()); 401 DCHECK(!module_promise.IsEmpty());
326 if (HasBrand(first_arg, i::Handle<i::Symbol>(i_context->wasm_module_sym()))) { 402 DCHECK_NOT_NULL(instantiator);
327 // WebAssembly.instantiate(module, imports) -> WebAssembly.Instance 403 // If args.Length < 2, this will be undefined - see FunctionCallbackInfo.
328 auto module_object = GetFirstArgumentAsModule(args, &thrower); 404 // We'll check for that in WebAssemblyInstantiateImpl.
329 i::wasm::AsyncInstantiate(i_isolate, promise, 405 Local<Value> data = args[1];
bradnelson 2017/04/11 23:18:41 Same
Mircea Trofin 2017/04/11 23:33:18 See above.
330 module_object.ToHandleChecked(), maybe_imports); 406 ASSIGN(Function, instantiate_impl,
331 } else { 407 Function::New(context, instantiator, data));
332 // WebAssembly.instantiate(bytes, imports) -> {module, instance} 408 ASSIGN(Promise, result, module_promise->Then(context, instantiate_impl));
333 auto bytes = GetFirstArgumentAsBytes(args, &thrower); 409 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 } 410 }
344 411
345 bool GetIntegerProperty(v8::Isolate* isolate, ErrorThrower* thrower, 412 bool GetIntegerProperty(v8::Isolate* isolate, ErrorThrower* thrower,
346 Local<Context> context, Local<v8::Object> object, 413 Local<Context> context, Local<v8::Object> object,
347 Local<String> property, int* result, 414 Local<String> property, int* result,
348 int64_t lower_bound, uint64_t upper_bound) { 415 int64_t lower_bound, uint64_t upper_bound) {
349 v8::MaybeLocal<v8::Value> maybe = object->Get(context, property); 416 v8::MaybeLocal<v8::Value> maybe = object->Get(context, property);
350 v8::Local<v8::Value> value; 417 v8::Local<v8::Value> value;
351 if (maybe.ToLocal(&value)) { 418 if (maybe.ToLocal(&value)) {
352 int64_t number; 419 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); 951 i::Handle<i::Symbol> symbol(isolate->context()->wasm_memory_sym(), isolate);
885 return HasBrand(value, symbol); 952 return HasBrand(value, symbol);
886 } 953 }
887 954
888 bool WasmJs::IsWasmTableObject(Isolate* isolate, Handle<Object> value) { 955 bool WasmJs::IsWasmTableObject(Isolate* isolate, Handle<Object> value) {
889 i::Handle<i::Symbol> symbol(isolate->context()->wasm_table_sym(), isolate); 956 i::Handle<i::Symbol> symbol(isolate->context()->wasm_table_sym(), isolate);
890 return HasBrand(value, symbol); 957 return HasBrand(value, symbol);
891 } 958 }
892 } // namespace internal 959 } // namespace internal
893 } // namespace v8 960 } // namespace v8
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698