| OLD | NEW |
| 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 90 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 101 if (buffer.start == nullptr) return false; | 101 if (buffer.start == nullptr) return false; |
| 102 | 102 |
| 103 DCHECK(source->IsArrayBuffer() || source->IsTypedArray()); | 103 DCHECK(source->IsArrayBuffer() || source->IsTypedArray()); |
| 104 return i::wasm::ValidateModuleBytes(i_isolate, buffer.start, buffer.end, | 104 return i::wasm::ValidateModuleBytes(i_isolate, buffer.start, buffer.end, |
| 105 thrower, | 105 thrower, |
| 106 i::wasm::ModuleOrigin::kWasmOrigin); | 106 i::wasm::ModuleOrigin::kWasmOrigin); |
| 107 } | 107 } |
| 108 | 108 |
| 109 // TODO(wasm): move brand check to the respective types, and don't throw | 109 // TODO(wasm): move brand check to the respective types, and don't throw |
| 110 // in it, rather, use a provided ErrorThrower, or let caller handle it. | 110 // in it, rather, use a provided ErrorThrower, or let caller handle it. |
| 111 static bool BrandCheck(Isolate* isolate, i::Handle<i::Object> value, | 111 static bool HasBrand(i::Handle<i::Object> value, i::Handle<i::Symbol> sym) { |
| 112 i::Handle<i::Symbol> sym) { | |
| 113 if (!value->IsJSObject()) return false; | 112 if (!value->IsJSObject()) return false; |
| 114 i::Handle<i::JSObject> object = i::Handle<i::JSObject>::cast(value); | 113 i::Handle<i::JSObject> object = i::Handle<i::JSObject>::cast(value); |
| 115 Maybe<bool> has_brand = i::JSObject::HasOwnProperty(object, sym); | 114 Maybe<bool> has_brand = i::JSObject::HasOwnProperty(object, sym); |
| 116 if (has_brand.IsNothing()) return false; | 115 return !has_brand.IsNothing() && has_brand.ToChecked(); |
| 117 return has_brand.ToChecked(); | |
| 118 } | 116 } |
| 119 | 117 |
| 120 static bool BrandCheck(Isolate* isolate, i::Handle<i::Object> value, | 118 static bool BrandCheck(ErrorThrower* thrower, i::Handle<i::Object> value, |
| 121 i::Handle<i::Symbol> sym, const char* msg) { | 119 i::Handle<i::Symbol> sym, const char* msg) { |
| 122 if (value->IsJSObject()) { | 120 return HasBrand(value, sym) ? true : (thrower->TypeError("%s", msg), false); |
| 123 i::Handle<i::JSObject> object = i::Handle<i::JSObject>::cast(value); | |
| 124 Maybe<bool> has_brand = i::JSObject::HasOwnProperty(object, sym); | |
| 125 if (has_brand.IsNothing()) return false; | |
| 126 if (has_brand.ToChecked()) return true; | |
| 127 } | |
| 128 v8::Local<v8::Value> e = v8::Exception::TypeError(v8_str(isolate, msg)); | |
| 129 isolate->ThrowException(e); | |
| 130 return false; | |
| 131 } | 121 } |
| 132 | 122 |
| 133 void WebAssemblyCompile(const v8::FunctionCallbackInfo<v8::Value>& args) { | 123 void WebAssemblyCompile(const v8::FunctionCallbackInfo<v8::Value>& args) { |
| 134 v8::Isolate* isolate = args.GetIsolate(); | 124 v8::Isolate* isolate = args.GetIsolate(); |
| 135 HandleScope scope(isolate); | 125 HandleScope scope(isolate); |
| 136 ErrorThrower thrower(reinterpret_cast<i::Isolate*>(isolate), | 126 ErrorThrower thrower(reinterpret_cast<i::Isolate*>(isolate), |
| 137 "WebAssembly.compile()"); | 127 "WebAssembly.compile()"); |
| 138 | 128 |
| 139 Local<Context> context = isolate->GetCurrentContext(); | 129 Local<Context> context = isolate->GetCurrentContext(); |
| 140 v8::Local<v8::Promise::Resolver> resolver; | 130 v8::Local<v8::Promise::Resolver> resolver; |
| (...skipping 85 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 226 if (!thrower->error()) | 216 if (!thrower->error()) |
| 227 thrower->RuntimeError("Could not instantiate module"); | 217 thrower->RuntimeError("Could not instantiate module"); |
| 228 return nothing; | 218 return nothing; |
| 229 } | 219 } |
| 230 DCHECK(!i_isolate->has_pending_exception()); | 220 DCHECK(!i_isolate->has_pending_exception()); |
| 231 return Utils::ToLocal(instance.ToHandleChecked()); | 221 return Utils::ToLocal(instance.ToHandleChecked()); |
| 232 } | 222 } |
| 233 | 223 |
| 234 namespace { | 224 namespace { |
| 235 i::MaybeHandle<i::WasmModuleObject> GetFirstArgumentAsModule( | 225 i::MaybeHandle<i::WasmModuleObject> GetFirstArgumentAsModule( |
| 236 const v8::FunctionCallbackInfo<v8::Value>& args, ErrorThrower& thrower) { | 226 const v8::FunctionCallbackInfo<v8::Value>& args, ErrorThrower* thrower) { |
| 237 v8::Isolate* isolate = args.GetIsolate(); | 227 v8::Isolate* isolate = args.GetIsolate(); |
| 238 i::MaybeHandle<i::WasmModuleObject> nothing; | 228 i::MaybeHandle<i::WasmModuleObject> nothing; |
| 239 if (args.Length() < 1) { | 229 if (args.Length() < 1) { |
| 240 thrower.TypeError("Argument 0 must be a WebAssembly.Module"); | 230 thrower->TypeError("Argument 0 must be a WebAssembly.Module"); |
| 241 return nothing; | 231 return nothing; |
| 242 } | 232 } |
| 243 | 233 |
| 244 Local<Context> context = isolate->GetCurrentContext(); | 234 Local<Context> context = isolate->GetCurrentContext(); |
| 245 i::Handle<i::Context> i_context = Utils::OpenHandle(*context); | 235 i::Handle<i::Context> i_context = Utils::OpenHandle(*context); |
| 246 if (!BrandCheck(isolate, Utils::OpenHandle(*args[0]), | 236 if (!BrandCheck(thrower, Utils::OpenHandle(*args[0]), |
| 247 i::Handle<i::Symbol>(i_context->wasm_module_sym()), | 237 i::Handle<i::Symbol>(i_context->wasm_module_sym()), |
| 248 "Argument 0 must be a WebAssembly.Module")) { | 238 "Argument 0 must be a WebAssembly.Module")) { |
| 249 return nothing; | 239 return nothing; |
| 250 } | 240 } |
| 251 | 241 |
| 252 Local<Object> module_obj = Local<Object>::Cast(args[0]); | 242 Local<Object> module_obj = Local<Object>::Cast(args[0]); |
| 253 return i::Handle<i::WasmModuleObject>::cast( | 243 return i::Handle<i::WasmModuleObject>::cast( |
| 254 v8::Utils::OpenHandle(*module_obj)); | 244 v8::Utils::OpenHandle(*module_obj)); |
| 255 } | 245 } |
| 256 } // namespace | 246 } // namespace |
| 257 | 247 |
| 258 void WebAssemblyModuleImports(const v8::FunctionCallbackInfo<v8::Value>& args) { | 248 void WebAssemblyModuleImports(const v8::FunctionCallbackInfo<v8::Value>& args) { |
| 259 HandleScope scope(args.GetIsolate()); | 249 HandleScope scope(args.GetIsolate()); |
| 260 v8::Isolate* isolate = args.GetIsolate(); | 250 v8::Isolate* isolate = args.GetIsolate(); |
| 261 i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate); | 251 i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate); |
| 262 ErrorThrower thrower(i_isolate, "WebAssembly.Module.imports()"); | 252 ErrorThrower thrower(i_isolate, "WebAssembly.Module.imports()"); |
| 263 | 253 |
| 264 auto maybe_module = GetFirstArgumentAsModule(args, thrower); | 254 auto maybe_module = GetFirstArgumentAsModule(args, &thrower); |
| 265 | 255 |
| 266 if (!maybe_module.is_null()) { | 256 if (!maybe_module.is_null()) { |
| 267 auto imports = | 257 auto imports = |
| 268 i::wasm::GetImports(i_isolate, maybe_module.ToHandleChecked()); | 258 i::wasm::GetImports(i_isolate, maybe_module.ToHandleChecked()); |
| 269 args.GetReturnValue().Set(Utils::ToLocal(imports)); | 259 args.GetReturnValue().Set(Utils::ToLocal(imports)); |
| 270 } | 260 } |
| 271 } | 261 } |
| 272 | 262 |
| 273 void WebAssemblyModuleExports(const v8::FunctionCallbackInfo<v8::Value>& args) { | 263 void WebAssemblyModuleExports(const v8::FunctionCallbackInfo<v8::Value>& args) { |
| 274 HandleScope scope(args.GetIsolate()); | 264 HandleScope scope(args.GetIsolate()); |
| 275 v8::Isolate* isolate = args.GetIsolate(); | 265 v8::Isolate* isolate = args.GetIsolate(); |
| 276 i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate); | 266 i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate); |
| 277 | |
| 278 ErrorThrower thrower(i_isolate, "WebAssembly.Module.exports()"); | 267 ErrorThrower thrower(i_isolate, "WebAssembly.Module.exports()"); |
| 279 | 268 |
| 280 auto maybe_module = GetFirstArgumentAsModule(args, thrower); | 269 auto maybe_module = GetFirstArgumentAsModule(args, &thrower); |
| 281 | 270 |
| 282 if (!maybe_module.is_null()) { | 271 if (!maybe_module.is_null()) { |
| 283 auto exports = | 272 auto exports = |
| 284 i::wasm::GetExports(i_isolate, maybe_module.ToHandleChecked()); | 273 i::wasm::GetExports(i_isolate, maybe_module.ToHandleChecked()); |
| 285 args.GetReturnValue().Set(Utils::ToLocal(exports)); | 274 args.GetReturnValue().Set(Utils::ToLocal(exports)); |
| 286 } | 275 } |
| 287 } | 276 } |
| 288 | 277 |
| 289 void WebAssemblyModuleCustomSections( | 278 void WebAssemblyModuleCustomSections( |
| 290 const v8::FunctionCallbackInfo<v8::Value>& args) { | 279 const v8::FunctionCallbackInfo<v8::Value>& args) { |
| 291 HandleScope scope(args.GetIsolate()); | 280 HandleScope scope(args.GetIsolate()); |
| 292 v8::Isolate* isolate = args.GetIsolate(); | 281 v8::Isolate* isolate = args.GetIsolate(); |
| 293 i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate); | 282 i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate); |
| 294 | |
| 295 ErrorThrower thrower(i_isolate, "WebAssembly.Module.customSections()"); | 283 ErrorThrower thrower(i_isolate, "WebAssembly.Module.customSections()"); |
| 296 | 284 |
| 297 auto maybe_module = GetFirstArgumentAsModule(args, thrower); | 285 auto maybe_module = GetFirstArgumentAsModule(args, &thrower); |
| 298 | 286 |
| 299 if (args.Length() < 2) { | 287 if (args.Length() < 2) { |
| 300 thrower.TypeError("Argument 1 must be a string"); | 288 thrower.TypeError("Argument 1 must be a string"); |
| 301 return; | 289 return; |
| 302 } | 290 } |
| 303 | 291 |
| 304 i::Handle<i::Object> name = Utils::OpenHandle(*args[1]); | 292 i::Handle<i::Object> name = Utils::OpenHandle(*args[1]); |
| 305 if (!name->IsString()) { | 293 if (!name->IsString()) { |
| 306 thrower.TypeError("Argument 1 must be a string"); | 294 thrower.TypeError("Argument 1 must be a string"); |
| 307 return; | 295 return; |
| 308 } | 296 } |
| 309 | 297 |
| 310 if (!maybe_module.is_null()) { | 298 if (!maybe_module.is_null()) { |
| 311 auto custom_sections = | 299 auto custom_sections = |
| 312 i::wasm::GetCustomSections(i_isolate, maybe_module.ToHandleChecked(), | 300 i::wasm::GetCustomSections(i_isolate, maybe_module.ToHandleChecked(), |
| 313 i::Handle<i::String>::cast(name), &thrower); | 301 i::Handle<i::String>::cast(name), &thrower); |
| 314 if (!thrower.error()) { | 302 if (!thrower.error()) { |
| 315 args.GetReturnValue().Set(Utils::ToLocal(custom_sections)); | 303 args.GetReturnValue().Set(Utils::ToLocal(custom_sections)); |
| 316 } | 304 } |
| 317 } | 305 } |
| 318 } | 306 } |
| 319 | 307 |
| 320 void WebAssemblyInstance(const v8::FunctionCallbackInfo<v8::Value>& args) { | 308 void WebAssemblyInstance(const v8::FunctionCallbackInfo<v8::Value>& args) { |
| 321 HandleScope scope(args.GetIsolate()); | 309 HandleScope scope(args.GetIsolate()); |
| 322 v8::Isolate* isolate = args.GetIsolate(); | 310 v8::Isolate* isolate = args.GetIsolate(); |
| 323 i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate); | 311 i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate); |
| 324 | |
| 325 ErrorThrower thrower(i_isolate, "WebAssembly.Instance()"); | 312 ErrorThrower thrower(i_isolate, "WebAssembly.Instance()"); |
| 326 | 313 |
| 327 auto maybe_module = GetFirstArgumentAsModule(args, thrower); | 314 auto maybe_module = GetFirstArgumentAsModule(args, &thrower); |
| 328 | 315 |
| 329 if (!maybe_module.is_null()) { | 316 if (!maybe_module.is_null()) { |
| 330 MaybeLocal<Value> instance = InstantiateModuleImpl( | 317 MaybeLocal<Value> instance = InstantiateModuleImpl( |
| 331 i_isolate, maybe_module.ToHandleChecked(), args, &thrower); | 318 i_isolate, maybe_module.ToHandleChecked(), args, &thrower); |
| 332 | 319 |
| 333 if (instance.IsEmpty()) { | 320 if (instance.IsEmpty()) { |
| 334 DCHECK(thrower.error()); | 321 DCHECK(thrower.error()); |
| 335 return; | 322 return; |
| 336 } | 323 } |
| 337 args.GetReturnValue().Set(instance.ToLocalChecked()); | 324 args.GetReturnValue().Set(instance.ToLocalChecked()); |
| 338 } | 325 } |
| 339 } | 326 } |
| 340 | 327 |
| 341 void WebAssemblyInstantiate(const v8::FunctionCallbackInfo<v8::Value>& args) { | 328 void WebAssemblyInstantiate(const v8::FunctionCallbackInfo<v8::Value>& args) { |
| 342 v8::Isolate* isolate = args.GetIsolate(); | 329 v8::Isolate* isolate = args.GetIsolate(); |
| 343 i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate); | 330 i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate); |
| 331 ErrorThrower thrower(i_isolate, "WebAssembly.instantiate()"); |
| 344 | 332 |
| 345 HandleScope scope(isolate); | 333 HandleScope scope(isolate); |
| 346 ErrorThrower thrower(i_isolate, "WebAssembly.instantiate()"); | |
| 347 | 334 |
| 348 Local<Context> context = isolate->GetCurrentContext(); | 335 Local<Context> context = isolate->GetCurrentContext(); |
| 349 i::Handle<i::Context> i_context = Utils::OpenHandle(*context); | 336 i::Handle<i::Context> i_context = Utils::OpenHandle(*context); |
| 350 | 337 |
| 351 v8::Local<v8::Promise::Resolver> resolver; | 338 v8::Local<v8::Promise::Resolver> resolver; |
| 352 if (!v8::Promise::Resolver::New(context).ToLocal(&resolver)) return; | 339 if (!v8::Promise::Resolver::New(context).ToLocal(&resolver)) return; |
| 353 v8::ReturnValue<v8::Value> return_value = args.GetReturnValue(); | 340 v8::ReturnValue<v8::Value> return_value = args.GetReturnValue(); |
| 354 return_value.Set(resolver->GetPromise()); | 341 return_value.Set(resolver->GetPromise()); |
| 355 | 342 |
| 356 if (args.Length() < 1) { | 343 if (args.Length() < 1) { |
| 357 thrower.TypeError( | 344 thrower.TypeError( |
| 358 "Argument 0 must be provided and must be either a buffer source or a " | 345 "Argument 0 must be provided and must be either a buffer source or a " |
| 359 "WebAssembly.Module object"); | 346 "WebAssembly.Module object"); |
| 360 resolver->Reject(context, Utils::ToLocal(thrower.Reify())); | 347 resolver->Reject(context, Utils::ToLocal(thrower.Reify())); |
| 361 return; | 348 return; |
| 362 } | 349 } |
| 363 | 350 |
| 364 i::Handle<i::Object> first_arg = Utils::OpenHandle(*args[0]); | 351 i::Handle<i::Object> first_arg = Utils::OpenHandle(*args[0]); |
| 365 if (!first_arg->IsJSObject()) { | 352 if (!first_arg->IsJSObject()) { |
| 366 thrower.TypeError( | 353 thrower.TypeError( |
| 367 "Argument 0 must be a buffer source or a WebAssembly.Module object"); | 354 "Argument 0 must be a buffer source or a WebAssembly.Module object"); |
| 368 resolver->Reject(context, Utils::ToLocal(thrower.Reify())); | 355 resolver->Reject(context, Utils::ToLocal(thrower.Reify())); |
| 369 return; | 356 return; |
| 370 } | 357 } |
| 371 bool want_pair = !BrandCheck( | 358 bool want_pair = |
| 372 isolate, first_arg, i::Handle<i::Symbol>(i_context->wasm_module_sym())); | 359 !HasBrand(first_arg, i::Handle<i::Symbol>(i_context->wasm_module_sym())); |
| 373 i::Handle<i::WasmModuleObject> module_obj; | 360 i::Handle<i::WasmModuleObject> module_obj; |
| 374 if (want_pair) { | 361 if (want_pair) { |
| 375 i::MaybeHandle<i::WasmModuleObject> maybe_module_obj = | 362 i::MaybeHandle<i::WasmModuleObject> maybe_module_obj = |
| 376 CreateModuleObject(isolate, args[0], &thrower); | 363 CreateModuleObject(isolate, args[0], &thrower); |
| 377 if (!maybe_module_obj.ToHandle(&module_obj)) { | 364 if (!maybe_module_obj.ToHandle(&module_obj)) { |
| 378 DCHECK(thrower.error()); | 365 DCHECK(thrower.error()); |
| 379 resolver->Reject(context, Utils::ToLocal(thrower.Reify())); | 366 resolver->Reject(context, Utils::ToLocal(thrower.Reify())); |
| 380 return; | 367 return; |
| 381 } | 368 } |
| 382 } else { | 369 } else { |
| (...skipping 153 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 536 return; | 523 return; |
| 537 } | 524 } |
| 538 i::Handle<i::JSObject> memory_obj = | 525 i::Handle<i::JSObject> memory_obj = |
| 539 i::WasmMemoryObject::New(i_isolate, buffer, maximum); | 526 i::WasmMemoryObject::New(i_isolate, buffer, maximum); |
| 540 args.GetReturnValue().Set(Utils::ToLocal(memory_obj)); | 527 args.GetReturnValue().Set(Utils::ToLocal(memory_obj)); |
| 541 } | 528 } |
| 542 | 529 |
| 543 void WebAssemblyTableGetLength( | 530 void WebAssemblyTableGetLength( |
| 544 const v8::FunctionCallbackInfo<v8::Value>& args) { | 531 const v8::FunctionCallbackInfo<v8::Value>& args) { |
| 545 v8::Isolate* isolate = args.GetIsolate(); | 532 v8::Isolate* isolate = args.GetIsolate(); |
| 533 ErrorThrower thrower(reinterpret_cast<i::Isolate*>(isolate), |
| 534 "WebAssembly.Table.length()"); |
| 546 Local<Context> context = isolate->GetCurrentContext(); | 535 Local<Context> context = isolate->GetCurrentContext(); |
| 547 i::Handle<i::Context> i_context = Utils::OpenHandle(*context); | 536 i::Handle<i::Context> i_context = Utils::OpenHandle(*context); |
| 548 if (!BrandCheck(isolate, Utils::OpenHandle(*args.This()), | 537 if (!BrandCheck(&thrower, Utils::OpenHandle(*args.This()), |
| 549 i::Handle<i::Symbol>(i_context->wasm_table_sym()), | 538 i::Handle<i::Symbol>(i_context->wasm_table_sym()), |
| 550 "Receiver is not a WebAssembly.Table")) { | 539 "Receiver is not a WebAssembly.Table")) { |
| 551 return; | 540 return; |
| 552 } | 541 } |
| 553 auto receiver = | 542 auto receiver = |
| 554 i::Handle<i::WasmTableObject>::cast(Utils::OpenHandle(*args.This())); | 543 i::Handle<i::WasmTableObject>::cast(Utils::OpenHandle(*args.This())); |
| 555 args.GetReturnValue().Set( | 544 args.GetReturnValue().Set( |
| 556 v8::Number::New(isolate, receiver->current_length())); | 545 v8::Number::New(isolate, receiver->current_length())); |
| 557 } | 546 } |
| 558 | 547 |
| 559 void WebAssemblyTableGrow(const v8::FunctionCallbackInfo<v8::Value>& args) { | 548 void WebAssemblyTableGrow(const v8::FunctionCallbackInfo<v8::Value>& args) { |
| 560 v8::Isolate* isolate = args.GetIsolate(); | 549 v8::Isolate* isolate = args.GetIsolate(); |
| 550 ErrorThrower thrower(reinterpret_cast<i::Isolate*>(isolate), |
| 551 "WebAssembly.Table.grow()"); |
| 561 Local<Context> context = isolate->GetCurrentContext(); | 552 Local<Context> context = isolate->GetCurrentContext(); |
| 562 i::Handle<i::Context> i_context = Utils::OpenHandle(*context); | 553 i::Handle<i::Context> i_context = Utils::OpenHandle(*context); |
| 563 if (!BrandCheck(isolate, Utils::OpenHandle(*args.This()), | 554 if (!BrandCheck(&thrower, Utils::OpenHandle(*args.This()), |
| 564 i::Handle<i::Symbol>(i_context->wasm_table_sym()), | 555 i::Handle<i::Symbol>(i_context->wasm_table_sym()), |
| 565 "Receiver is not a WebAssembly.Table")) { | 556 "Receiver is not a WebAssembly.Table")) { |
| 566 return; | 557 return; |
| 567 } | 558 } |
| 568 | 559 |
| 569 i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate); | 560 i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate); |
| 570 auto receiver = | 561 auto receiver = |
| 571 i::Handle<i::WasmTableObject>::cast(Utils::OpenHandle(*args.This())); | 562 i::Handle<i::WasmTableObject>::cast(Utils::OpenHandle(*args.This())); |
| 572 i::Handle<i::FixedArray> old_array(receiver->functions(), i_isolate); | 563 i::Handle<i::FixedArray> old_array(receiver->functions(), i_isolate); |
| 573 int old_size = old_array->length(); | 564 int old_size = old_array->length(); |
| 574 int64_t new_size64 = 0; | 565 int64_t new_size64 = 0; |
| 575 if (args.Length() > 0 && !args[0]->IntegerValue(context).To(&new_size64)) { | 566 if (args.Length() > 0 && !args[0]->IntegerValue(context).To(&new_size64)) { |
| 576 return; | 567 return; |
| 577 } | 568 } |
| 578 new_size64 += old_size; | 569 new_size64 += old_size; |
| 579 | 570 |
| 580 int64_t max_size64 = receiver->maximum_length(); | 571 int64_t max_size64 = receiver->maximum_length(); |
| 581 if (max_size64 < 0 || | 572 if (max_size64 < 0 || |
| 582 max_size64 > static_cast<int64_t>(i::FLAG_wasm_max_table_size)) { | 573 max_size64 > static_cast<int64_t>(i::FLAG_wasm_max_table_size)) { |
| 583 max_size64 = i::FLAG_wasm_max_table_size; | 574 max_size64 = i::FLAG_wasm_max_table_size; |
| 584 } | 575 } |
| 585 | 576 |
| 586 if (new_size64 < old_size || new_size64 > max_size64) { | 577 if (new_size64 < old_size || new_size64 > max_size64) { |
| 587 v8::Local<v8::Value> e = v8::Exception::RangeError( | 578 thrower.RangeError(new_size64 < old_size ? "trying to shrink table" |
| 588 v8_str(isolate, new_size64 < old_size ? "trying to shrink table" | 579 : "maximum table size exceeded"); |
| 589 : "maximum table size exceeded")); | |
| 590 isolate->ThrowException(e); | |
| 591 return; | 580 return; |
| 592 } | 581 } |
| 593 | 582 |
| 594 int new_size = static_cast<int>(new_size64); | 583 int new_size = static_cast<int>(new_size64); |
| 595 i::WasmTableObject::Grow(i_isolate, receiver, | 584 i::WasmTableObject::Grow(i_isolate, receiver, |
| 596 static_cast<uint32_t>(new_size - old_size)); | 585 static_cast<uint32_t>(new_size - old_size)); |
| 597 | 586 |
| 598 if (new_size != old_size) { | 587 if (new_size != old_size) { |
| 599 i::Handle<i::FixedArray> new_array = | 588 i::Handle<i::FixedArray> new_array = |
| 600 i_isolate->factory()->NewFixedArray(new_size); | 589 i_isolate->factory()->NewFixedArray(new_size); |
| 601 for (int i = 0; i < old_size; ++i) new_array->set(i, old_array->get(i)); | 590 for (int i = 0; i < old_size; ++i) new_array->set(i, old_array->get(i)); |
| 602 i::Object* null = i_isolate->heap()->null_value(); | 591 i::Object* null = i_isolate->heap()->null_value(); |
| 603 for (int i = old_size; i < new_size; ++i) new_array->set(i, null); | 592 for (int i = old_size; i < new_size; ++i) new_array->set(i, null); |
| 604 receiver->set_functions(*new_array); | 593 receiver->set_functions(*new_array); |
| 605 } | 594 } |
| 606 | 595 |
| 607 // TODO(gdeepti): use weak links for instances | 596 // TODO(gdeepti): use weak links for instances |
| 608 v8::ReturnValue<v8::Value> return_value = args.GetReturnValue(); | 597 v8::ReturnValue<v8::Value> return_value = args.GetReturnValue(); |
| 609 return_value.Set(old_size); | 598 return_value.Set(old_size); |
| 610 } | 599 } |
| 611 | 600 |
| 612 void WebAssemblyTableGet(const v8::FunctionCallbackInfo<v8::Value>& args) { | 601 void WebAssemblyTableGet(const v8::FunctionCallbackInfo<v8::Value>& args) { |
| 613 v8::Isolate* isolate = args.GetIsolate(); | 602 v8::Isolate* isolate = args.GetIsolate(); |
| 603 i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate); |
| 604 ErrorThrower thrower(i_isolate, "WebAssembly.Table.get()"); |
| 614 Local<Context> context = isolate->GetCurrentContext(); | 605 Local<Context> context = isolate->GetCurrentContext(); |
| 615 i::Handle<i::Context> i_context = Utils::OpenHandle(*context); | 606 i::Handle<i::Context> i_context = Utils::OpenHandle(*context); |
| 616 if (!BrandCheck(isolate, Utils::OpenHandle(*args.This()), | 607 if (!BrandCheck(&thrower, Utils::OpenHandle(*args.This()), |
| 617 i::Handle<i::Symbol>(i_context->wasm_table_sym()), | 608 i::Handle<i::Symbol>(i_context->wasm_table_sym()), |
| 618 "Receiver is not a WebAssembly.Table")) { | 609 "Receiver is not a WebAssembly.Table")) { |
| 619 return; | 610 return; |
| 620 } | 611 } |
| 621 | 612 |
| 622 i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate); | |
| 623 auto receiver = | 613 auto receiver = |
| 624 i::Handle<i::WasmTableObject>::cast(Utils::OpenHandle(*args.This())); | 614 i::Handle<i::WasmTableObject>::cast(Utils::OpenHandle(*args.This())); |
| 625 i::Handle<i::FixedArray> array(receiver->functions(), i_isolate); | 615 i::Handle<i::FixedArray> array(receiver->functions(), i_isolate); |
| 626 int i = 0; | 616 int i = 0; |
| 627 if (args.Length() > 0 && !args[0]->Int32Value(context).To(&i)) return; | 617 if (args.Length() > 0 && !args[0]->Int32Value(context).To(&i)) return; |
| 628 v8::ReturnValue<v8::Value> return_value = args.GetReturnValue(); | 618 v8::ReturnValue<v8::Value> return_value = args.GetReturnValue(); |
| 629 if (i < 0 || i >= array->length()) { | 619 if (i < 0 || i >= array->length()) { |
| 630 v8::Local<v8::Value> e = | 620 thrower.RangeError("index out of bounds"); |
| 631 v8::Exception::RangeError(v8_str(isolate, "index out of bounds")); | |
| 632 isolate->ThrowException(e); | |
| 633 return; | 621 return; |
| 634 } | 622 } |
| 635 | 623 |
| 636 i::Handle<i::Object> value(array->get(i), i_isolate); | 624 i::Handle<i::Object> value(array->get(i), i_isolate); |
| 637 return_value.Set(Utils::ToLocal(value)); | 625 return_value.Set(Utils::ToLocal(value)); |
| 638 } | 626 } |
| 639 | 627 |
| 640 void WebAssemblyTableSet(const v8::FunctionCallbackInfo<v8::Value>& args) { | 628 void WebAssemblyTableSet(const v8::FunctionCallbackInfo<v8::Value>& args) { |
| 641 v8::Isolate* isolate = args.GetIsolate(); | 629 v8::Isolate* isolate = args.GetIsolate(); |
| 642 i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate); | 630 i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate); |
| 631 ErrorThrower thrower(i_isolate, "WebAssembly.Table.set()"); |
| 643 Local<Context> context = isolate->GetCurrentContext(); | 632 Local<Context> context = isolate->GetCurrentContext(); |
| 644 i::Handle<i::Context> i_context = Utils::OpenHandle(*context); | 633 i::Handle<i::Context> i_context = Utils::OpenHandle(*context); |
| 645 if (!BrandCheck(isolate, Utils::OpenHandle(*args.This()), | 634 if (!BrandCheck(&thrower, Utils::OpenHandle(*args.This()), |
| 646 i::Handle<i::Symbol>(i_context->wasm_table_sym()), | 635 i::Handle<i::Symbol>(i_context->wasm_table_sym()), |
| 647 "Receiver is not a WebAssembly.Table")) { | 636 "Receiver is not a WebAssembly.Table")) { |
| 648 return; | 637 return; |
| 649 } | 638 } |
| 650 if (args.Length() < 2) { | 639 if (args.Length() < 2) { |
| 651 v8::Local<v8::Value> e = v8::Exception::TypeError( | 640 thrower.TypeError("Argument 1 must be null or a function"); |
| 652 v8_str(isolate, "Argument 1 must be null or a function")); | |
| 653 isolate->ThrowException(e); | |
| 654 return; | 641 return; |
| 655 } | 642 } |
| 656 i::Handle<i::Object> value = Utils::OpenHandle(*args[1]); | 643 i::Handle<i::Object> value = Utils::OpenHandle(*args[1]); |
| 657 if (!value->IsNull(i_isolate) && | 644 if (!value->IsNull(i_isolate) && |
| 658 (!value->IsJSFunction() || | 645 (!value->IsJSFunction() || |
| 659 i::Handle<i::JSFunction>::cast(value)->code()->kind() != | 646 i::Handle<i::JSFunction>::cast(value)->code()->kind() != |
| 660 i::Code::JS_TO_WASM_FUNCTION)) { | 647 i::Code::JS_TO_WASM_FUNCTION)) { |
| 661 v8::Local<v8::Value> e = v8::Exception::TypeError( | 648 thrower.TypeError("Argument 1 must be null or a WebAssembly function"); |
| 662 v8_str(isolate, "Argument 1 must be null or a WebAssembly function")); | |
| 663 isolate->ThrowException(e); | |
| 664 return; | 649 return; |
| 665 } | 650 } |
| 666 | 651 |
| 667 auto receiver = | 652 auto receiver = |
| 668 i::Handle<i::WasmTableObject>::cast(Utils::OpenHandle(*args.This())); | 653 i::Handle<i::WasmTableObject>::cast(Utils::OpenHandle(*args.This())); |
| 669 i::Handle<i::FixedArray> array(receiver->functions(), i_isolate); | 654 i::Handle<i::FixedArray> array(receiver->functions(), i_isolate); |
| 670 int i; | 655 int i; |
| 671 if (!args[0]->Int32Value(context).To(&i)) return; | 656 if (!args[0]->Int32Value(context).To(&i)) return; |
| 672 if (i < 0 || i >= array->length()) { | 657 if (i < 0 || i >= array->length()) { |
| 673 v8::Local<v8::Value> e = | 658 thrower.RangeError("index out of bounds"); |
| 674 v8::Exception::RangeError(v8_str(isolate, "index out of bounds")); | |
| 675 isolate->ThrowException(e); | |
| 676 return; | 659 return; |
| 677 } | 660 } |
| 678 | 661 |
| 679 i::Handle<i::FixedArray> dispatch_tables(receiver->dispatch_tables(), | 662 i::Handle<i::FixedArray> dispatch_tables(receiver->dispatch_tables(), |
| 680 i_isolate); | 663 i_isolate); |
| 681 if (value->IsNull(i_isolate)) { | 664 if (value->IsNull(i_isolate)) { |
| 682 i::wasm::UpdateDispatchTables(i_isolate, dispatch_tables, i, | 665 i::wasm::UpdateDispatchTables(i_isolate, dispatch_tables, i, |
| 683 i::Handle<i::JSFunction>::null()); | 666 i::Handle<i::JSFunction>::null()); |
| 684 } else { | 667 } else { |
| 685 i::wasm::UpdateDispatchTables(i_isolate, dispatch_tables, i, | 668 i::wasm::UpdateDispatchTables(i_isolate, dispatch_tables, i, |
| 686 i::Handle<i::JSFunction>::cast(value)); | 669 i::Handle<i::JSFunction>::cast(value)); |
| 687 } | 670 } |
| 688 | 671 |
| 689 i::Handle<i::FixedArray>::cast(array)->set(i, *value); | 672 i::Handle<i::FixedArray>::cast(array)->set(i, *value); |
| 690 } | 673 } |
| 691 | 674 |
| 692 void WebAssemblyMemoryGrow(const v8::FunctionCallbackInfo<v8::Value>& args) { | 675 void WebAssemblyMemoryGrow(const v8::FunctionCallbackInfo<v8::Value>& args) { |
| 693 v8::Isolate* isolate = args.GetIsolate(); | 676 v8::Isolate* isolate = args.GetIsolate(); |
| 677 i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate); |
| 678 ErrorThrower thrower(i_isolate, "WebAssembly.Memory.grow()"); |
| 694 Local<Context> context = isolate->GetCurrentContext(); | 679 Local<Context> context = isolate->GetCurrentContext(); |
| 695 i::Handle<i::Context> i_context = Utils::OpenHandle(*context); | 680 i::Handle<i::Context> i_context = Utils::OpenHandle(*context); |
| 696 if (!BrandCheck(isolate, Utils::OpenHandle(*args.This()), | 681 if (!BrandCheck(&thrower, Utils::OpenHandle(*args.This()), |
| 697 i::Handle<i::Symbol>(i_context->wasm_memory_sym()), | 682 i::Handle<i::Symbol>(i_context->wasm_memory_sym()), |
| 698 "Receiver is not a WebAssembly.Memory")) { | 683 "Receiver is not a WebAssembly.Memory")) { |
| 699 return; | 684 return; |
| 700 } | 685 } |
| 701 int64_t delta_size = 0; | 686 int64_t delta_size = 0; |
| 702 if (args.Length() < 1 || !args[0]->IntegerValue(context).To(&delta_size)) { | 687 if (args.Length() < 1 || !args[0]->IntegerValue(context).To(&delta_size)) { |
| 703 v8::Local<v8::Value> e = v8::Exception::TypeError( | 688 thrower.TypeError("Argument 0 required, must be numeric value of pages"); |
| 704 v8_str(isolate, "Argument 0 required, must be numeric value of pages")); | |
| 705 isolate->ThrowException(e); | |
| 706 return; | 689 return; |
| 707 } | 690 } |
| 708 i::Handle<i::WasmMemoryObject> receiver = | 691 i::Handle<i::WasmMemoryObject> receiver = |
| 709 i::Handle<i::WasmMemoryObject>::cast(Utils::OpenHandle(*args.This())); | 692 i::Handle<i::WasmMemoryObject>::cast(Utils::OpenHandle(*args.This())); |
| 710 int64_t max_size64 = receiver->maximum_pages(); | 693 int64_t max_size64 = receiver->maximum_pages(); |
| 711 if (max_size64 < 0 || | 694 if (max_size64 < 0 || |
| 712 max_size64 > static_cast<int64_t>(i::FLAG_wasm_max_mem_pages)) { | 695 max_size64 > static_cast<int64_t>(i::FLAG_wasm_max_mem_pages)) { |
| 713 max_size64 = i::FLAG_wasm_max_mem_pages; | 696 max_size64 = i::FLAG_wasm_max_mem_pages; |
| 714 } | 697 } |
| 715 i::Handle<i::JSArrayBuffer> old_buffer(receiver->buffer()); | 698 i::Handle<i::JSArrayBuffer> old_buffer(receiver->buffer()); |
| 716 uint32_t old_size = | 699 uint32_t old_size = |
| 717 old_buffer->byte_length()->Number() / i::wasm::kSpecMaxWasmMemoryPages; | 700 old_buffer->byte_length()->Number() / i::wasm::kSpecMaxWasmMemoryPages; |
| 718 int64_t new_size64 = old_size + delta_size; | 701 int64_t new_size64 = old_size + delta_size; |
| 719 if (delta_size < 0 || max_size64 < new_size64 || new_size64 < old_size) { | 702 if (delta_size < 0 || max_size64 < new_size64 || new_size64 < old_size) { |
| 720 v8::Local<v8::Value> e = v8::Exception::RangeError(v8_str( | 703 thrower.RangeError(new_size64 < old_size ? "trying to shrink memory" |
| 721 isolate, new_size64 < old_size ? "trying to shrink memory" | 704 : "maximum memory size exceeded"); |
| 722 : "maximum memory size exceeded")); | |
| 723 isolate->ThrowException(e); | |
| 724 return; | 705 return; |
| 725 } | 706 } |
| 726 i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate); | |
| 727 int32_t ret = i::wasm::GrowWebAssemblyMemory( | 707 int32_t ret = i::wasm::GrowWebAssemblyMemory( |
| 728 i_isolate, receiver, static_cast<uint32_t>(delta_size)); | 708 i_isolate, receiver, static_cast<uint32_t>(delta_size)); |
| 729 if (ret == -1) { | 709 if (ret == -1) { |
| 730 v8::Local<v8::Value> e = v8::Exception::RangeError( | 710 thrower.RangeError("Unable to grow instance memory."); |
| 731 v8_str(isolate, "Unable to grow instance memory.")); | |
| 732 isolate->ThrowException(e); | |
| 733 return; | 711 return; |
| 734 } | 712 } |
| 735 v8::ReturnValue<v8::Value> return_value = args.GetReturnValue(); | 713 v8::ReturnValue<v8::Value> return_value = args.GetReturnValue(); |
| 736 return_value.Set(ret); | 714 return_value.Set(ret); |
| 737 } | 715 } |
| 738 | 716 |
| 739 void WebAssemblyMemoryGetBuffer( | 717 void WebAssemblyMemoryGetBuffer( |
| 740 const v8::FunctionCallbackInfo<v8::Value>& args) { | 718 const v8::FunctionCallbackInfo<v8::Value>& args) { |
| 741 v8::Isolate* isolate = args.GetIsolate(); | 719 v8::Isolate* isolate = args.GetIsolate(); |
| 720 i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate); |
| 721 ErrorThrower thrower(i_isolate, "WebAssembly.Memory.buffer"); |
| 742 Local<Context> context = isolate->GetCurrentContext(); | 722 Local<Context> context = isolate->GetCurrentContext(); |
| 743 i::Handle<i::Context> i_context = Utils::OpenHandle(*context); | 723 i::Handle<i::Context> i_context = Utils::OpenHandle(*context); |
| 744 if (!BrandCheck(isolate, Utils::OpenHandle(*args.This()), | 724 if (!BrandCheck(&thrower, Utils::OpenHandle(*args.This()), |
| 745 i::Handle<i::Symbol>(i_context->wasm_memory_sym()), | 725 i::Handle<i::Symbol>(i_context->wasm_memory_sym()), |
| 746 "Receiver is not a WebAssembly.Memory")) { | 726 "Receiver is not a WebAssembly.Memory")) { |
| 747 return; | 727 return; |
| 748 } | 728 } |
| 749 i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate); | |
| 750 i::Handle<i::WasmMemoryObject> receiver = | 729 i::Handle<i::WasmMemoryObject> receiver = |
| 751 i::Handle<i::WasmMemoryObject>::cast(Utils::OpenHandle(*args.This())); | 730 i::Handle<i::WasmMemoryObject>::cast(Utils::OpenHandle(*args.This())); |
| 752 i::Handle<i::Object> buffer(receiver->buffer(), i_isolate); | 731 i::Handle<i::Object> buffer(receiver->buffer(), i_isolate); |
| 753 DCHECK(buffer->IsJSArrayBuffer()); | 732 DCHECK(buffer->IsJSArrayBuffer()); |
| 754 v8::ReturnValue<v8::Value> return_value = args.GetReturnValue(); | 733 v8::ReturnValue<v8::Value> return_value = args.GetReturnValue(); |
| 755 return_value.Set(Utils::ToLocal(buffer)); | 734 return_value.Set(Utils::ToLocal(buffer)); |
| 756 } | 735 } |
| 757 } // namespace | 736 } // namespace |
| 758 | 737 |
| 759 // TODO(titzer): we use the API to create the function template because the | 738 // TODO(titzer): we use the API to create the function template because the |
| (...skipping 184 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 944 Handle<JSFunction> link_error( | 923 Handle<JSFunction> link_error( |
| 945 isolate->native_context()->wasm_link_error_function()); | 924 isolate->native_context()->wasm_link_error_function()); |
| 946 JSObject::AddProperty(webassembly, isolate->factory()->LinkError_string(), | 925 JSObject::AddProperty(webassembly, isolate->factory()->LinkError_string(), |
| 947 link_error, attributes); | 926 link_error, attributes); |
| 948 Handle<JSFunction> runtime_error( | 927 Handle<JSFunction> runtime_error( |
| 949 isolate->native_context()->wasm_runtime_error_function()); | 928 isolate->native_context()->wasm_runtime_error_function()); |
| 950 JSObject::AddProperty(webassembly, isolate->factory()->RuntimeError_string(), | 929 JSObject::AddProperty(webassembly, isolate->factory()->RuntimeError_string(), |
| 951 runtime_error, attributes); | 930 runtime_error, attributes); |
| 952 } | 931 } |
| 953 | 932 |
| 954 static bool HasBrand(i::Handle<i::Object> value, i::Handle<i::Symbol> symbol) { | |
| 955 if (value->IsJSObject()) { | |
| 956 i::Handle<i::JSObject> object = i::Handle<i::JSObject>::cast(value); | |
| 957 Maybe<bool> has_brand = i::JSObject::HasOwnProperty(object, symbol); | |
| 958 if (has_brand.IsNothing()) return false; | |
| 959 if (has_brand.ToChecked()) return true; | |
| 960 } | |
| 961 return false; | |
| 962 } | |
| 963 | |
| 964 bool WasmJs::IsWasmMemoryObject(Isolate* isolate, Handle<Object> value) { | 933 bool WasmJs::IsWasmMemoryObject(Isolate* isolate, Handle<Object> value) { |
| 965 i::Handle<i::Symbol> symbol(isolate->context()->wasm_memory_sym(), isolate); | 934 i::Handle<i::Symbol> symbol(isolate->context()->wasm_memory_sym(), isolate); |
| 966 return HasBrand(value, symbol); | 935 return HasBrand(value, symbol); |
| 967 } | 936 } |
| 968 | 937 |
| 969 bool WasmJs::IsWasmTableObject(Isolate* isolate, Handle<Object> value) { | 938 bool WasmJs::IsWasmTableObject(Isolate* isolate, Handle<Object> value) { |
| 970 i::Handle<i::Symbol> symbol(isolate->context()->wasm_table_sym(), isolate); | 939 i::Handle<i::Symbol> symbol(isolate->context()->wasm_table_sym(), isolate); |
| 971 return HasBrand(value, symbol); | 940 return HasBrand(value, symbol); |
| 972 } | 941 } |
| 973 } // namespace internal | 942 } // namespace internal |
| 974 } // namespace v8 | 943 } // namespace v8 |
| OLD | NEW |