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 336 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
347 DCHECK(thrower.error()); | 347 DCHECK(thrower.error()); |
348 resolver->Reject(context, Utils::ToLocal(thrower.Reify())); | 348 resolver->Reject(context, Utils::ToLocal(thrower.Reify())); |
349 } else { | 349 } else { |
350 DCHECK(!thrower.error()); | 350 DCHECK(!thrower.error()); |
351 resolver->Resolve(context, instance.ToLocalChecked()); | 351 resolver->Resolve(context, instance.ToLocalChecked()); |
352 } | 352 } |
353 } | 353 } |
354 | 354 |
355 bool GetIntegerProperty(v8::Isolate* isolate, ErrorThrower* thrower, | 355 bool GetIntegerProperty(v8::Isolate* isolate, ErrorThrower* thrower, |
356 Local<Context> context, Local<v8::Object> object, | 356 Local<Context> context, Local<v8::Object> object, |
357 Local<String> property, int* result, int lower_bound, | 357 Local<String> property, int* result, |
358 int upper_bound) { | 358 int64_t lower_bound, uint64_t upper_bound) { |
359 v8::MaybeLocal<v8::Value> maybe = object->Get(context, property); | 359 v8::MaybeLocal<v8::Value> maybe = object->Get(context, property); |
360 v8::Local<v8::Value> value; | 360 v8::Local<v8::Value> value; |
361 if (maybe.ToLocal(&value)) { | 361 if (maybe.ToLocal(&value)) { |
362 int64_t number; | 362 int64_t number; |
363 if (!value->IntegerValue(context).To(&number)) return false; | 363 if (!value->IntegerValue(context).To(&number)) return false; |
364 if (number < static_cast<int64_t>(lower_bound)) { | 364 if (number < lower_bound) { |
365 thrower->RangeError("Property value %" PRId64 | 365 thrower->RangeError("Property value %" PRId64 |
366 " is below the lower bound %d", | 366 " is below the lower bound %" PRIx64, |
367 number, lower_bound); | 367 number, lower_bound); |
368 return false; | 368 return false; |
369 } | 369 } |
370 if (number > static_cast<int64_t>(upper_bound)) { | 370 if (number > static_cast<int64_t>(upper_bound)) { |
371 thrower->RangeError("Property value %" PRId64 | 371 thrower->RangeError("Property value %" PRId64 |
372 " is above the upper bound %d", | 372 " is above the upper bound %" PRIu64, |
373 number, upper_bound); | 373 number, upper_bound); |
374 return false; | 374 return false; |
375 } | 375 } |
376 *result = static_cast<int>(number); | 376 *result = static_cast<int>(number); |
377 return true; | 377 return true; |
378 } | 378 } |
379 return false; | 379 return false; |
380 } | 380 } |
381 | 381 |
382 const int max_table_size = 1 << 26; | |
383 | |
384 void WebAssemblyTable(const v8::FunctionCallbackInfo<v8::Value>& args) { | 382 void WebAssemblyTable(const v8::FunctionCallbackInfo<v8::Value>& args) { |
385 v8::Isolate* isolate = args.GetIsolate(); | 383 v8::Isolate* isolate = args.GetIsolate(); |
386 HandleScope scope(isolate); | 384 HandleScope scope(isolate); |
387 ErrorThrower thrower(reinterpret_cast<i::Isolate*>(isolate), | 385 ErrorThrower thrower(reinterpret_cast<i::Isolate*>(isolate), |
388 "WebAssembly.Module()"); | 386 "WebAssembly.Module()"); |
389 if (args.Length() < 1 || !args[0]->IsObject()) { | 387 if (args.Length() < 1 || !args[0]->IsObject()) { |
390 thrower.TypeError("Argument 0 must be a table descriptor"); | 388 thrower.TypeError("Argument 0 must be a table descriptor"); |
391 return; | 389 return; |
392 } | 390 } |
393 Local<Context> context = isolate->GetCurrentContext(); | 391 Local<Context> context = isolate->GetCurrentContext(); |
394 Local<v8::Object> descriptor = args[0]->ToObject(context).ToLocalChecked(); | 392 Local<v8::Object> descriptor = args[0]->ToObject(context).ToLocalChecked(); |
395 // The descriptor's 'element'. | 393 // The descriptor's 'element'. |
396 { | 394 { |
397 v8::MaybeLocal<v8::Value> maybe = | 395 v8::MaybeLocal<v8::Value> maybe = |
398 descriptor->Get(context, v8_str(isolate, "element")); | 396 descriptor->Get(context, v8_str(isolate, "element")); |
399 v8::Local<v8::Value> value; | 397 v8::Local<v8::Value> value; |
400 if (!maybe.ToLocal(&value)) return; | 398 if (!maybe.ToLocal(&value)) return; |
401 v8::Local<v8::String> string; | 399 v8::Local<v8::String> string; |
402 if (!value->ToString(context).ToLocal(&string)) return; | 400 if (!value->ToString(context).ToLocal(&string)) return; |
403 bool equal; | 401 bool equal; |
404 if (!string->Equals(context, v8_str(isolate, "anyfunc")).To(&equal)) return; | 402 if (!string->Equals(context, v8_str(isolate, "anyfunc")).To(&equal)) return; |
405 if (!equal) { | 403 if (!equal) { |
406 thrower.TypeError("Descriptor property 'element' must be 'anyfunc'"); | 404 thrower.TypeError("Descriptor property 'element' must be 'anyfunc'"); |
407 return; | 405 return; |
408 } | 406 } |
409 } | 407 } |
410 // The descriptor's 'initial'. | 408 // The descriptor's 'initial'. |
411 int initial; | 409 int initial = 0; |
412 if (!GetIntegerProperty(isolate, &thrower, context, descriptor, | 410 if (!GetIntegerProperty(isolate, &thrower, context, descriptor, |
413 v8_str(isolate, "initial"), &initial, 0, | 411 v8_str(isolate, "initial"), &initial, 0, |
414 max_table_size)) { | 412 i::wasm::kV8MaxWasmTableSize)) { |
415 return; | 413 return; |
416 } | 414 } |
417 // The descriptor's 'maximum'. | 415 // The descriptor's 'maximum'. |
418 int maximum = 0; | 416 int maximum = -1; |
419 Local<String> maximum_key = v8_str(isolate, "maximum"); | 417 Local<String> maximum_key = v8_str(isolate, "maximum"); |
420 Maybe<bool> has_maximum = descriptor->Has(context, maximum_key); | 418 Maybe<bool> has_maximum = descriptor->Has(context, maximum_key); |
421 | 419 |
422 if (has_maximum.IsNothing()) { | 420 if (!has_maximum.IsNothing() && has_maximum.FromJust()) { |
423 // There has been an exception, just return. | |
424 return; | |
425 } | |
426 if (has_maximum.FromJust()) { | |
427 if (!GetIntegerProperty(isolate, &thrower, context, descriptor, maximum_key, | 421 if (!GetIntegerProperty(isolate, &thrower, context, descriptor, maximum_key, |
428 &maximum, initial, max_table_size)) { | 422 &maximum, initial, |
| 423 i::wasm::kSpecMaxWasmTableSize)) { |
429 return; | 424 return; |
430 } | 425 } |
431 } else { | |
432 maximum = static_cast<int>(i::wasm::kV8MaxWasmTableSize); | |
433 } | 426 } |
434 | 427 |
435 i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate); | 428 i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate); |
436 i::Handle<i::FixedArray> fixed_array; | 429 i::Handle<i::FixedArray> fixed_array; |
437 i::Handle<i::JSObject> table_obj = | 430 i::Handle<i::JSObject> table_obj = |
438 i::WasmTableObject::New(i_isolate, initial, maximum, &fixed_array); | 431 i::WasmTableObject::New(i_isolate, initial, maximum, &fixed_array); |
439 v8::ReturnValue<v8::Value> return_value = args.GetReturnValue(); | 432 v8::ReturnValue<v8::Value> return_value = args.GetReturnValue(); |
440 return_value.Set(Utils::ToLocal(table_obj)); | 433 return_value.Set(Utils::ToLocal(table_obj)); |
441 } | 434 } |
442 | 435 |
443 void WebAssemblyMemory(const v8::FunctionCallbackInfo<v8::Value>& args) { | 436 void WebAssemblyMemory(const v8::FunctionCallbackInfo<v8::Value>& args) { |
444 v8::Isolate* isolate = args.GetIsolate(); | 437 v8::Isolate* isolate = args.GetIsolate(); |
445 HandleScope scope(isolate); | 438 HandleScope scope(isolate); |
446 ErrorThrower thrower(reinterpret_cast<i::Isolate*>(isolate), | 439 ErrorThrower thrower(reinterpret_cast<i::Isolate*>(isolate), |
447 "WebAssembly.Memory()"); | 440 "WebAssembly.Memory()"); |
448 if (args.Length() < 1 || !args[0]->IsObject()) { | 441 if (args.Length() < 1 || !args[0]->IsObject()) { |
449 thrower.TypeError("Argument 0 must be a memory descriptor"); | 442 thrower.TypeError("Argument 0 must be a memory descriptor"); |
450 return; | 443 return; |
451 } | 444 } |
452 Local<Context> context = isolate->GetCurrentContext(); | 445 Local<Context> context = isolate->GetCurrentContext(); |
453 Local<v8::Object> descriptor = args[0]->ToObject(context).ToLocalChecked(); | 446 Local<v8::Object> descriptor = args[0]->ToObject(context).ToLocalChecked(); |
454 // The descriptor's 'initial'. | 447 // The descriptor's 'initial'. |
455 int initial; | 448 int initial = 0; |
456 if (!GetIntegerProperty(isolate, &thrower, context, descriptor, | 449 if (!GetIntegerProperty(isolate, &thrower, context, descriptor, |
457 v8_str(isolate, "initial"), &initial, 0, 65536)) { | 450 v8_str(isolate, "initial"), &initial, 0, |
| 451 i::wasm::kV8MaxWasmMemoryPages)) { |
458 return; | 452 return; |
459 } | 453 } |
460 // The descriptor's 'maximum'. | 454 // The descriptor's 'maximum'. |
461 int maximum = 0; | 455 int maximum = -1; |
462 Local<String> maximum_key = v8_str(isolate, "maximum"); | 456 Local<String> maximum_key = v8_str(isolate, "maximum"); |
463 Maybe<bool> has_maximum = descriptor->Has(context, maximum_key); | 457 Maybe<bool> has_maximum = descriptor->Has(context, maximum_key); |
464 | 458 |
465 if (has_maximum.IsNothing()) { | 459 if (!has_maximum.IsNothing() && has_maximum.FromJust()) { |
466 // There has been an exception, just return. | |
467 return; | |
468 } | |
469 if (has_maximum.FromJust()) { | |
470 if (!GetIntegerProperty(isolate, &thrower, context, descriptor, maximum_key, | 460 if (!GetIntegerProperty(isolate, &thrower, context, descriptor, maximum_key, |
471 &maximum, initial, 65536)) { | 461 &maximum, initial, |
| 462 i::wasm::kSpecMaxWasmMemoryPages)) { |
472 return; | 463 return; |
473 } | 464 } |
474 } | 465 } |
475 i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate); | 466 i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate); |
476 size_t size = static_cast<size_t>(i::wasm::WasmModule::kPageSize) * | 467 size_t size = static_cast<size_t>(i::wasm::WasmModule::kPageSize) * |
477 static_cast<size_t>(initial); | 468 static_cast<size_t>(initial); |
478 i::Handle<i::JSArrayBuffer> buffer = | 469 i::Handle<i::JSArrayBuffer> buffer = |
479 i::wasm::NewArrayBuffer(i_isolate, size, i::FLAG_wasm_guard_pages); | 470 i::wasm::NewArrayBuffer(i_isolate, size, i::FLAG_wasm_guard_pages); |
480 if (buffer.is_null()) { | 471 if (buffer.is_null()) { |
481 thrower.RangeError("could not allocate memory"); | 472 thrower.RangeError("could not allocate memory"); |
482 return; | 473 return; |
483 } | 474 } |
484 i::Handle<i::JSObject> memory_obj = i::WasmMemoryObject::New( | 475 i::Handle<i::JSObject> memory_obj = |
485 i_isolate, buffer, has_maximum.FromJust() ? maximum : -1); | 476 i::WasmMemoryObject::New(i_isolate, buffer, maximum); |
486 args.GetReturnValue().Set(Utils::ToLocal(memory_obj)); | 477 args.GetReturnValue().Set(Utils::ToLocal(memory_obj)); |
487 } | 478 } |
488 | 479 |
489 void WebAssemblyTableGetLength( | 480 void WebAssemblyTableGetLength( |
490 const v8::FunctionCallbackInfo<v8::Value>& args) { | 481 const v8::FunctionCallbackInfo<v8::Value>& args) { |
491 v8::Isolate* isolate = args.GetIsolate(); | 482 v8::Isolate* isolate = args.GetIsolate(); |
492 Local<Context> context = isolate->GetCurrentContext(); | 483 Local<Context> context = isolate->GetCurrentContext(); |
493 i::Handle<i::Context> i_context = Utils::OpenHandle(*context); | 484 i::Handle<i::Context> i_context = Utils::OpenHandle(*context); |
494 if (!BrandCheck(isolate, Utils::OpenHandle(*args.This()), | 485 if (!BrandCheck(isolate, Utils::OpenHandle(*args.This()), |
495 i::Handle<i::Symbol>(i_context->wasm_table_sym()), | 486 i::Handle<i::Symbol>(i_context->wasm_table_sym()), |
(...skipping 20 matching lines...) Expand all Loading... |
516 auto receiver = | 507 auto receiver = |
517 i::Handle<i::WasmTableObject>::cast(Utils::OpenHandle(*args.This())); | 508 i::Handle<i::WasmTableObject>::cast(Utils::OpenHandle(*args.This())); |
518 i::Handle<i::FixedArray> old_array(receiver->functions(), i_isolate); | 509 i::Handle<i::FixedArray> old_array(receiver->functions(), i_isolate); |
519 int old_size = old_array->length(); | 510 int old_size = old_array->length(); |
520 int64_t new_size64 = 0; | 511 int64_t new_size64 = 0; |
521 if (args.Length() > 0 && !args[0]->IntegerValue(context).To(&new_size64)) { | 512 if (args.Length() > 0 && !args[0]->IntegerValue(context).To(&new_size64)) { |
522 return; | 513 return; |
523 } | 514 } |
524 new_size64 += old_size; | 515 new_size64 += old_size; |
525 | 516 |
526 if (new_size64 < old_size || new_size64 > receiver->maximum_length()) { | 517 int64_t max_size64 = receiver->maximum_length(); |
| 518 if (max_size64 < 0 || |
| 519 max_size64 > static_cast<int64_t>(i::wasm::kV8MaxWasmTableSize)) { |
| 520 max_size64 = i::wasm::kV8MaxWasmTableSize; |
| 521 } |
| 522 |
| 523 if (new_size64 < old_size || new_size64 > max_size64) { |
527 v8::Local<v8::Value> e = v8::Exception::RangeError( | 524 v8::Local<v8::Value> e = v8::Exception::RangeError( |
528 v8_str(isolate, new_size64 < old_size ? "trying to shrink table" | 525 v8_str(isolate, new_size64 < old_size ? "trying to shrink table" |
529 : "maximum table size exceeded")); | 526 : "maximum table size exceeded")); |
530 isolate->ThrowException(e); | 527 isolate->ThrowException(e); |
531 return; | 528 return; |
532 } | 529 } |
533 | 530 |
534 int new_size = static_cast<int>(new_size64); | 531 int new_size = static_cast<int>(new_size64); |
535 i::WasmTableObject::Grow(i_isolate, receiver, | 532 i::WasmTableObject::Grow(i_isolate, receiver, |
536 static_cast<uint32_t>(new_size - old_size)); | 533 static_cast<uint32_t>(new_size - old_size)); |
(...skipping 350 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
887 i::Handle<i::Symbol> symbol(isolate->context()->wasm_memory_sym(), isolate); | 884 i::Handle<i::Symbol> symbol(isolate->context()->wasm_memory_sym(), isolate); |
888 return HasBrand(value, symbol); | 885 return HasBrand(value, symbol); |
889 } | 886 } |
890 | 887 |
891 bool WasmJs::IsWasmTableObject(Isolate* isolate, Handle<Object> value) { | 888 bool WasmJs::IsWasmTableObject(Isolate* isolate, Handle<Object> value) { |
892 i::Handle<i::Symbol> symbol(isolate->context()->wasm_table_sym(), isolate); | 889 i::Handle<i::Symbol> symbol(isolate->context()->wasm_table_sym(), isolate); |
893 return HasBrand(value, symbol); | 890 return HasBrand(value, symbol); |
894 } | 891 } |
895 } // namespace internal | 892 } // namespace internal |
896 } // namespace v8 | 893 } // namespace v8 |
OLD | NEW |