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