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

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

Issue 2414053002: [wasm] Implement Table#set and Table#grow (Closed)
Patch Set: Avoid lossy int conversion Created 4 years, 2 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
« no previous file with comments | « no previous file | test/mjsunit/wasm/table.js » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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 348 matching lines...) Expand 10 before | Expand all | Expand 10 after
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
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
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
OLDNEW
« no previous file with comments | « no previous file | test/mjsunit/wasm/table.js » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698