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 348 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
359 " is above the upper bound %d", | 359 " is above the upper bound %d", |
360 number, upper_bound); | 360 number, upper_bound); |
361 return false; | 361 return false; |
362 } | 362 } |
363 *result = static_cast<int>(number); | 363 *result = static_cast<int>(number); |
364 return true; | 364 return true; |
365 } | 365 } |
366 return false; | 366 return false; |
367 } | 367 } |
368 | 368 |
| 369 const int max_table_size = 1 << 26; |
| 370 |
369 void WebAssemblyTable(const v8::FunctionCallbackInfo<v8::Value>& args) { | 371 void WebAssemblyTable(const v8::FunctionCallbackInfo<v8::Value>& args) { |
370 v8::Isolate* isolate = args.GetIsolate(); | 372 v8::Isolate* isolate = args.GetIsolate(); |
371 HandleScope scope(isolate); | 373 HandleScope scope(isolate); |
372 ErrorThrower thrower(reinterpret_cast<i::Isolate*>(isolate), | 374 ErrorThrower thrower(reinterpret_cast<i::Isolate*>(isolate), |
373 "WebAssembly.Module()"); | 375 "WebAssembly.Module()"); |
374 if (args.Length() < 1 || !args[0]->IsObject()) { | 376 if (args.Length() < 1 || !args[0]->IsObject()) { |
375 thrower.TypeError("Argument 0 must be a table descriptor"); | 377 thrower.TypeError("Argument 0 must be a table descriptor"); |
376 return; | 378 return; |
377 } | 379 } |
378 Local<Context> context = isolate->GetCurrentContext(); | 380 Local<Context> context = isolate->GetCurrentContext(); |
379 Local<v8::Object> descriptor = args[0]->ToObject(context).ToLocalChecked(); | 381 Local<v8::Object> descriptor = args[0]->ToObject(context).ToLocalChecked(); |
380 // The descriptor's 'element'. | 382 // The descriptor's 'element'. |
381 { | 383 { |
382 v8::MaybeLocal<v8::Value> maybe = | 384 v8::MaybeLocal<v8::Value> maybe = |
383 descriptor->Get(context, v8_str(isolate, "element")); | 385 descriptor->Get(context, v8_str(isolate, "element")); |
384 v8::Local<v8::Value> value; | 386 v8::Local<v8::Value> value; |
385 if (!maybe.ToLocal(&value)) return; | 387 if (!maybe.ToLocal(&value)) return; |
386 v8::Local<v8::String> string; | 388 v8::Local<v8::String> string; |
387 if (!value->ToString(context).ToLocal(&string)) return; | 389 if (!value->ToString(context).ToLocal(&string)) return; |
388 bool equal; | 390 bool equal; |
389 if (!string->Equals(context, v8_str(isolate, "anyfunc")).To(&equal)) return; | 391 if (!string->Equals(context, v8_str(isolate, "anyfunc")).To(&equal)) return; |
390 if (!equal) { | 392 if (!equal) { |
391 thrower.TypeError("Descriptor property 'element' must be 'anyfunc'"); | 393 thrower.TypeError("Descriptor property 'element' must be 'anyfunc'"); |
392 return; | 394 return; |
393 } | 395 } |
394 } | 396 } |
395 const int max_table_size = 1 << 26; | |
396 // The descriptor's 'initial'. | 397 // The descriptor's 'initial'. |
397 int initial; | 398 int initial; |
398 if (!GetIntegerProperty(isolate, &thrower, context, descriptor, | 399 if (!GetIntegerProperty(isolate, &thrower, context, descriptor, |
399 v8_str(isolate, "initial"), &initial, 0, | 400 v8_str(isolate, "initial"), &initial, 0, |
400 max_table_size)) { | 401 max_table_size)) { |
401 return; | 402 return; |
402 } | 403 } |
403 // The descriptor's 'maximum'. | 404 // The descriptor's 'maximum'. |
404 int maximum = 0; | 405 int maximum = 0; |
405 Local<String> maximum_key = v8_str(isolate, "maximum"); | 406 Local<String> maximum_key = v8_str(isolate, "maximum"); |
(...skipping 98 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
504 | 505 |
505 void WebAssemblyTableGrow(const v8::FunctionCallbackInfo<v8::Value>& args) { | 506 void WebAssemblyTableGrow(const v8::FunctionCallbackInfo<v8::Value>& args) { |
506 v8::Isolate* isolate = args.GetIsolate(); | 507 v8::Isolate* isolate = args.GetIsolate(); |
507 Local<Context> context = isolate->GetCurrentContext(); | 508 Local<Context> context = isolate->GetCurrentContext(); |
508 i::Handle<i::Context> i_context = Utils::OpenHandle(*context); | 509 i::Handle<i::Context> i_context = Utils::OpenHandle(*context); |
509 if (!BrandCheck(isolate, Utils::OpenHandle(*args.This()), | 510 if (!BrandCheck(isolate, Utils::OpenHandle(*args.This()), |
510 i::Handle<i::Symbol>(i_context->wasm_table_sym()), | 511 i::Handle<i::Symbol>(i_context->wasm_table_sym()), |
511 "Receiver is not a WebAssembly.Table")) { | 512 "Receiver is not a WebAssembly.Table")) { |
512 return; | 513 return; |
513 } | 514 } |
514 // TODO(rossberg): grow table and update relevant instances. | 515 |
515 v8::Local<v8::Value> e = | 516 i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate); |
516 v8::Exception::TypeError(v8_str(isolate, "Table#grow unimplemented")); | 517 i::Handle<i::JSObject> receiver = |
517 isolate->ThrowException(e); | 518 i::Handle<i::JSObject>::cast(Utils::OpenHandle(*args.This())); |
| 519 i::Handle<i::FixedArray> old_array( |
| 520 i::FixedArray::cast( |
| 521 receiver->GetInternalField(kWasmTableArrayFieldIndex)), |
| 522 i_isolate); |
| 523 int old_size = old_array->length(); |
| 524 int64_t new_size64 = 0; |
| 525 if (args.Length() > 0 && !args[0]->IntegerValue(context).To(&new_size64)) { |
| 526 return; |
| 527 } |
| 528 new_size64 += old_size; |
| 529 |
| 530 i::Handle<i::Object> max_val( |
| 531 receiver->GetInternalField(kWasmTableMaximumFieldIndex), i_isolate); |
| 532 int max_size = |
| 533 max_val->IsSmi() ? i::Smi::cast(*max_val)->value() : max_table_size; |
| 534 if (new_size64 < old_size || new_size64 > max_size) { |
| 535 v8::Local<v8::Value> e = v8::Exception::RangeError( |
| 536 v8_str(isolate, new_size64 < old_size ? "trying to shrink table" |
| 537 : "maximum table size exceeded")); |
| 538 isolate->ThrowException(e); |
| 539 return; |
| 540 } |
| 541 int new_size = static_cast<int>(new_size64); |
| 542 |
| 543 if (new_size != old_size) { |
| 544 i::Handle<i::FixedArray> new_array = |
| 545 i_isolate->factory()->NewFixedArray(new_size); |
| 546 for (int i = 0; i < old_size; ++i) new_array->set(i, old_array->get(i)); |
| 547 i::Object* null = i_isolate->heap()->null_value(); |
| 548 for (int i = old_size; i < new_size; ++i) new_array->set(i, null); |
| 549 receiver->SetInternalField(kWasmTableArrayFieldIndex, *new_array); |
| 550 } |
| 551 |
| 552 // TODO(titzer): update relevant instances. |
518 } | 553 } |
519 | 554 |
520 void WebAssemblyTableGet(const v8::FunctionCallbackInfo<v8::Value>& args) { | 555 void WebAssemblyTableGet(const v8::FunctionCallbackInfo<v8::Value>& args) { |
521 v8::Isolate* isolate = args.GetIsolate(); | 556 v8::Isolate* isolate = args.GetIsolate(); |
522 Local<Context> context = isolate->GetCurrentContext(); | 557 Local<Context> context = isolate->GetCurrentContext(); |
523 i::Handle<i::Context> i_context = Utils::OpenHandle(*context); | 558 i::Handle<i::Context> i_context = Utils::OpenHandle(*context); |
524 if (!BrandCheck(isolate, Utils::OpenHandle(*args.This()), | 559 if (!BrandCheck(isolate, Utils::OpenHandle(*args.This()), |
525 i::Handle<i::Symbol>(i_context->wasm_table_sym()), | 560 i::Handle<i::Symbol>(i_context->wasm_table_sym()), |
526 "Receiver is not a WebAssembly.Table")) { | 561 "Receiver is not a WebAssembly.Table")) { |
527 return; | 562 return; |
528 } | 563 } |
529 | 564 |
530 i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate); | 565 i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate); |
531 i::Handle<i::JSObject> receiver = | 566 i::Handle<i::JSObject> receiver = |
532 i::Handle<i::JSObject>::cast(Utils::OpenHandle(*args.This())); | 567 i::Handle<i::JSObject>::cast(Utils::OpenHandle(*args.This())); |
533 i::Handle<i::Object> array( | 568 i::Handle<i::Object> array( |
534 receiver->GetInternalField(kWasmTableArrayFieldIndex), i_isolate); | 569 receiver->GetInternalField(kWasmTableArrayFieldIndex), i_isolate); |
535 int i = 0; | 570 int i = 0; |
536 if (args.Length() > 0 && !args[0]->Int32Value(context).To(&i)) return; | 571 if (args.Length() > 0 && !args[0]->Int32Value(context).To(&i)) return; |
537 v8::ReturnValue<v8::Value> return_value = args.GetReturnValue(); | 572 v8::ReturnValue<v8::Value> return_value = args.GetReturnValue(); |
538 if (i >= 0 && i < i::Handle<i::FixedArray>::cast(array)->length()) { | 573 if (i < 0 || i >= i::Handle<i::FixedArray>::cast(array)->length()) { |
539 i::Handle<i::Object> value(i::Handle<i::FixedArray>::cast(array)->get(i), | 574 v8::Local<v8::Value> e = |
540 i_isolate); | 575 v8::Exception::RangeError(v8_str(isolate, "index out of bounds")); |
541 return_value.Set(Utils::ToLocal(value)); | 576 isolate->ThrowException(e); |
| 577 return; |
542 } | 578 } |
| 579 |
| 580 i::Handle<i::Object> value(i::Handle<i::FixedArray>::cast(array)->get(i), |
| 581 i_isolate); |
| 582 return_value.Set(Utils::ToLocal(value)); |
543 } | 583 } |
544 | 584 |
545 void WebAssemblyTableSet(const v8::FunctionCallbackInfo<v8::Value>& args) { | 585 void WebAssemblyTableSet(const v8::FunctionCallbackInfo<v8::Value>& args) { |
546 v8::Isolate* isolate = args.GetIsolate(); | 586 v8::Isolate* isolate = args.GetIsolate(); |
| 587 i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate); |
547 Local<Context> context = isolate->GetCurrentContext(); | 588 Local<Context> context = isolate->GetCurrentContext(); |
548 i::Handle<i::Context> i_context = Utils::OpenHandle(*context); | 589 i::Handle<i::Context> i_context = Utils::OpenHandle(*context); |
549 if (!BrandCheck(isolate, Utils::OpenHandle(*args.This()), | 590 if (!BrandCheck(isolate, Utils::OpenHandle(*args.This()), |
550 i::Handle<i::Symbol>(i_context->wasm_table_sym()), | 591 i::Handle<i::Symbol>(i_context->wasm_table_sym()), |
551 "Receiver is not a WebAssembly.Table")) { | 592 "Receiver is not a WebAssembly.Table")) { |
552 return; | 593 return; |
553 } | 594 } |
554 if (args.Length() < 2 || | 595 if (args.Length() < 2) { |
555 !(args[1]->IsNull() || | |
556 (args[1]->IsObject() && v8::Object::Cast(*args[1])->IsCallable()))) { | |
557 v8::Local<v8::Value> e = v8::Exception::TypeError( | 596 v8::Local<v8::Value> e = v8::Exception::TypeError( |
558 v8_str(isolate, "Argument 1 must be null or a function")); | 597 v8_str(isolate, "Argument 1 must be null or a function")); |
559 isolate->ThrowException(e); | 598 isolate->ThrowException(e); |
560 return; | 599 return; |
561 } | 600 } |
| 601 i::Handle<i::Object> value = Utils::OpenHandle(*args[1]); |
| 602 if (!value->IsNull(i_isolate) && |
| 603 (!value->IsJSFunction() || |
| 604 i::Handle<i::JSFunction>::cast(value)->code()->kind() != |
| 605 i::Code::JS_TO_WASM_FUNCTION)) { |
| 606 v8::Local<v8::Value> e = v8::Exception::TypeError( |
| 607 v8_str(isolate, "Argument 1 must be null or a WebAssembly function")); |
| 608 isolate->ThrowException(e); |
| 609 return; |
| 610 } |
562 | 611 |
563 // TODO(rossberg): set table element and update relevent instances. | 612 i::Handle<i::JSObject> receiver = |
564 v8::Local<v8::Value> e = | 613 i::Handle<i::JSObject>::cast(Utils::OpenHandle(*args.This())); |
565 v8::Exception::TypeError(v8_str(isolate, "Table#set unimplemented")); | 614 i::Handle<i::Object> array( |
566 isolate->ThrowException(e); | 615 receiver->GetInternalField(kWasmTableArrayFieldIndex), i_isolate); |
| 616 int i; |
| 617 if (!args[0]->Int32Value(context).To(&i)) return; |
| 618 if (i < 0 || i >= i::Handle<i::FixedArray>::cast(array)->length()) { |
| 619 v8::Local<v8::Value> e = |
| 620 v8::Exception::RangeError(v8_str(isolate, "index out of bounds")); |
| 621 isolate->ThrowException(e); |
| 622 return; |
| 623 } |
| 624 |
| 625 i::Handle<i::FixedArray>::cast(array)->set(i, *value); |
| 626 |
| 627 // TODO(titzer): update relevant instances. |
567 } | 628 } |
568 | 629 |
569 void WebAssemblyMemoryGrow(const v8::FunctionCallbackInfo<v8::Value>& args) { | 630 void WebAssemblyMemoryGrow(const v8::FunctionCallbackInfo<v8::Value>& args) { |
570 v8::Isolate* isolate = args.GetIsolate(); | 631 v8::Isolate* isolate = args.GetIsolate(); |
571 Local<Context> context = isolate->GetCurrentContext(); | 632 Local<Context> context = isolate->GetCurrentContext(); |
572 i::Handle<i::Context> i_context = Utils::OpenHandle(*context); | 633 i::Handle<i::Context> i_context = Utils::OpenHandle(*context); |
573 if (!BrandCheck(isolate, Utils::OpenHandle(*args.This()), | 634 if (!BrandCheck(isolate, Utils::OpenHandle(*args.This()), |
574 i::Handle<i::Symbol>(i_context->wasm_memory_sym()), | 635 i::Handle<i::Symbol>(i_context->wasm_memory_sym()), |
575 "Receiver is not a WebAssembly.Memory")) { | 636 "Receiver is not a WebAssembly.Memory")) { |
576 return; | 637 return; |
(...skipping 273 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
850 Handle<JSArrayBuffer> WasmJs::GetWasmMemoryArrayBuffer(Isolate* isolate, | 911 Handle<JSArrayBuffer> WasmJs::GetWasmMemoryArrayBuffer(Isolate* isolate, |
851 Handle<Object> value) { | 912 Handle<Object> value) { |
852 DCHECK(IsWasmMemoryObject(isolate, value)); | 913 DCHECK(IsWasmMemoryObject(isolate, value)); |
853 Handle<Object> buf( | 914 Handle<Object> buf( |
854 JSObject::cast(*value)->GetInternalField(kWasmMemoryBufferFieldIndex), | 915 JSObject::cast(*value)->GetInternalField(kWasmMemoryBufferFieldIndex), |
855 isolate); | 916 isolate); |
856 return Handle<JSArrayBuffer>::cast(buf); | 917 return Handle<JSArrayBuffer>::cast(buf); |
857 } | 918 } |
858 } // namespace internal | 919 } // namespace internal |
859 } // namespace v8 | 920 } // namespace v8 |
OLD | NEW |