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

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

Issue 2454503005: [wasm] Support for restricted table imports. (Closed)
Patch Set: Implemented .Set() Created 4 years, 1 month 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
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 11 matching lines...) Expand all
22 #include "src/wasm/wasm-result.h" 22 #include "src/wasm/wasm-result.h"
23 23
24 typedef uint8_t byte; 24 typedef uint8_t byte;
25 25
26 using v8::internal::wasm::ErrorThrower; 26 using v8::internal::wasm::ErrorThrower;
27 27
28 namespace v8 { 28 namespace v8 {
29 29
30 static const int kWasmTableArrayFieldIndex = 0; 30 static const int kWasmTableArrayFieldIndex = 0;
31 static const int kWasmTableMaximumFieldIndex = 1; 31 static const int kWasmTableMaximumFieldIndex = 1;
32 static const int kWasmTableDispatchTablesFieldIndex = 2;
bradnelson 2016/10/28 16:59:01 Any reason not to move these into the enum?
titzer 2016/10/28 17:29:08 Yeah, would be OK. I'm planning on moving this al
32 33
33 enum WasmMemoryObjectData { 34 enum WasmMemoryObjectData {
34 kWasmMemoryBuffer, 35 kWasmMemoryBuffer,
35 kWasmMemoryMaximum, 36 kWasmMemoryMaximum,
36 kWasmMemoryInstanceObject 37 kWasmMemoryInstanceObject
37 }; 38 };
38 39
39 enum WasmInternalFieldCountData { 40 enum WasmInternalFieldCountData {
40 kWasmTableInternalFieldCount = 2, 41 kWasmTableInternalFieldCount = 3,
41 kWasmMemoryInternalFieldCount 42 kWasmMemoryInternalFieldCount = 3
42 }; 43 };
43 44
44 namespace { 45 namespace {
45 i::Handle<i::String> v8_str(i::Isolate* isolate, const char* str) { 46 i::Handle<i::String> v8_str(i::Isolate* isolate, const char* str) {
46 return isolate->factory()->NewStringFromAsciiChecked(str); 47 return isolate->factory()->NewStringFromAsciiChecked(str);
47 } 48 }
48 Local<String> v8_str(Isolate* isolate, const char* str) { 49 Local<String> v8_str(Isolate* isolate, const char* str) {
49 return Utils::ToLocal(v8_str(reinterpret_cast<i::Isolate*>(isolate), str)); 50 return Utils::ToLocal(v8_str(reinterpret_cast<i::Isolate*>(isolate), str));
50 } 51 }
51 52
(...skipping 455 matching lines...) Expand 10 before | Expand all | Expand 10 after
507 receiver->GetInternalField(kWasmTableArrayFieldIndex), i_isolate); 508 receiver->GetInternalField(kWasmTableArrayFieldIndex), i_isolate);
508 int i; 509 int i;
509 if (!args[0]->Int32Value(context).To(&i)) return; 510 if (!args[0]->Int32Value(context).To(&i)) return;
510 if (i < 0 || i >= i::Handle<i::FixedArray>::cast(array)->length()) { 511 if (i < 0 || i >= i::Handle<i::FixedArray>::cast(array)->length()) {
511 v8::Local<v8::Value> e = 512 v8::Local<v8::Value> e =
512 v8::Exception::RangeError(v8_str(isolate, "index out of bounds")); 513 v8::Exception::RangeError(v8_str(isolate, "index out of bounds"));
513 isolate->ThrowException(e); 514 isolate->ThrowException(e);
514 return; 515 return;
515 } 516 }
516 517
518 i::Handle<i::FixedArray> dispatch_tables(
519 i::FixedArray::cast(
520 receiver->GetInternalField(kWasmTableDispatchTablesFieldIndex)),
521 i_isolate);
522 if (value->IsNull(i_isolate)) {
523 i::wasm::UpdateDispatchTables(i_isolate, dispatch_tables, i,
524 i::Handle<i::JSFunction>::null());
525 } else {
526 i::wasm::UpdateDispatchTables(i_isolate, dispatch_tables, i,
527 i::Handle<i::JSFunction>::cast(value));
528 }
529
517 i::Handle<i::FixedArray>::cast(array)->set(i, *value); 530 i::Handle<i::FixedArray>::cast(array)->set(i, *value);
518
519 // TODO(titzer): update relevant instances.
520 } 531 }
521 532
522 void WebAssemblyMemoryGrow(const v8::FunctionCallbackInfo<v8::Value>& args) { 533 void WebAssemblyMemoryGrow(const v8::FunctionCallbackInfo<v8::Value>& args) {
523 v8::Isolate* isolate = args.GetIsolate(); 534 v8::Isolate* isolate = args.GetIsolate();
524 Local<Context> context = isolate->GetCurrentContext(); 535 Local<Context> context = isolate->GetCurrentContext();
525 i::Handle<i::Context> i_context = Utils::OpenHandle(*context); 536 i::Handle<i::Context> i_context = Utils::OpenHandle(*context);
526 if (!BrandCheck(isolate, Utils::OpenHandle(*args.This()), 537 if (!BrandCheck(isolate, Utils::OpenHandle(*args.This()),
527 i::Handle<i::Symbol>(i_context->wasm_memory_sym()), 538 i::Handle<i::Symbol>(i_context->wasm_memory_sym()),
528 "Receiver is not a WebAssembly.Memory")) { 539 "Receiver is not a WebAssembly.Memory")) {
529 return; 540 return;
(...skipping 71 matching lines...) Expand 10 before | Expand all | Expand 10 after
601 ? static_cast<i::Object*>(i::Smi::FromInt(maximum)) 612 ? static_cast<i::Object*>(i::Smi::FromInt(maximum))
602 : static_cast<i::Object*>(i_isolate->heap()->undefined_value())); 613 : static_cast<i::Object*>(i_isolate->heap()->undefined_value()));
603 i::Handle<i::Symbol> memory_sym( 614 i::Handle<i::Symbol> memory_sym(
604 i_isolate->native_context()->wasm_memory_sym()); 615 i_isolate->native_context()->wasm_memory_sym());
605 i::Object::SetProperty(memory_obj, memory_sym, memory_obj, i::STRICT).Check(); 616 i::Object::SetProperty(memory_obj, memory_sym, memory_obj, i::STRICT).Check();
606 return memory_obj; 617 return memory_obj;
607 } 618 }
608 619
609 i::Handle<i::JSObject> i::WasmJs::CreateWasmTableObject( 620 i::Handle<i::JSObject> i::WasmJs::CreateWasmTableObject(
610 i::Isolate* i_isolate, uint32_t initial, bool has_maximum, uint32_t maximum, 621 i::Isolate* i_isolate, uint32_t initial, bool has_maximum, uint32_t maximum,
611 i::Handle<i::FixedArray>* array) { 622 i::Handle<i::FixedArray>* js_functions) {
612 i::Handle<i::JSFunction> table_ctor( 623 i::Handle<i::JSFunction> table_ctor(
613 i_isolate->native_context()->wasm_table_constructor()); 624 i_isolate->native_context()->wasm_table_constructor());
614 i::Handle<i::JSObject> table_obj = 625 i::Handle<i::JSObject> table_obj =
615 i_isolate->factory()->NewJSObject(table_ctor); 626 i_isolate->factory()->NewJSObject(table_ctor);
616 *array = i_isolate->factory()->NewFixedArray(initial); 627 *js_functions = i_isolate->factory()->NewFixedArray(initial);
617 i::Object* null = i_isolate->heap()->null_value(); 628 i::Object* null = i_isolate->heap()->null_value();
618 // TODO(titzer): consider moving FixedArray to size_t. 629 // TODO(titzer): consider moving FixedArray to size_t.
619 for (int i = 0; i < static_cast<int>(initial); ++i) (*array)->set(i, null); 630 for (int i = 0; i < static_cast<int>(initial); ++i) {
620 table_obj->SetInternalField(kWasmTableArrayFieldIndex, *(*array)); 631 (*js_functions)->set(i, null);
632 }
633 table_obj->SetInternalField(kWasmTableArrayFieldIndex, *(*js_functions));
621 table_obj->SetInternalField( 634 table_obj->SetInternalField(
622 kWasmTableMaximumFieldIndex, 635 kWasmTableMaximumFieldIndex,
623 has_maximum 636 has_maximum
624 ? static_cast<i::Object*>(i::Smi::FromInt(maximum)) 637 ? static_cast<i::Object*>(i::Smi::FromInt(maximum))
625 : static_cast<i::Object*>(i_isolate->heap()->undefined_value())); 638 : static_cast<i::Object*>(i_isolate->heap()->undefined_value()));
639 Handle<FixedArray> dispatch_tables = i_isolate->factory()->NewFixedArray(0);
640 table_obj->SetInternalField(kWasmTableDispatchTablesFieldIndex,
641 *dispatch_tables);
626 i::Handle<i::Symbol> table_sym(i_isolate->native_context()->wasm_table_sym()); 642 i::Handle<i::Symbol> table_sym(i_isolate->native_context()->wasm_table_sym());
627 i::Object::SetProperty(table_obj, table_sym, table_obj, i::STRICT).Check(); 643 i::Object::SetProperty(table_obj, table_sym, table_obj, i::STRICT).Check();
628 return table_obj; 644 return table_obj;
629 } 645 }
630 646
647 i::Handle<i::FixedArray> i::WasmJs::AddWasmTableDispatchTable(
648 i::Isolate* i_isolate, i::Handle<i::JSObject> table_obj,
649 i::Handle<i::JSObject> instance, int table_index,
650 i::Handle<i::FixedArray> dispatch_table) {
651 DCHECK(IsWasmTableObject(i_isolate, table_obj));
652 i::Handle<i::FixedArray> dispatch_tables(
653 i::FixedArray::cast(
654 table_obj->GetInternalField(kWasmTableDispatchTablesFieldIndex)),
655 i_isolate);
656 DCHECK_EQ(0, dispatch_tables->length() % 3);
657
658 if (instance.is_null()) return dispatch_tables;
659 // TODO(titzer): use weak cells here to avoid leaking instances.
660
661 // Grow the dispatch table and add a new pair at the end.
662 i::Handle<i::FixedArray> new_dispatch_tables =
663 i_isolate->factory()->CopyFixedArrayAndGrow(dispatch_tables, 3);
664
665 new_dispatch_tables->set(dispatch_tables->length() + 0, *instance);
666 new_dispatch_tables->set(dispatch_tables->length() + 1,
667 Smi::FromInt(table_index));
668 new_dispatch_tables->set(dispatch_tables->length() + 2, *dispatch_table);
669
670 table_obj->SetInternalField(kWasmTableDispatchTablesFieldIndex,
671 *new_dispatch_tables);
672
673 return new_dispatch_tables;
674 }
675
631 // TODO(titzer): we use the API to create the function template because the 676 // TODO(titzer): we use the API to create the function template because the
632 // internal guts are too ugly to replicate here. 677 // internal guts are too ugly to replicate here.
633 static i::Handle<i::FunctionTemplateInfo> NewTemplate(i::Isolate* i_isolate, 678 static i::Handle<i::FunctionTemplateInfo> NewTemplate(i::Isolate* i_isolate,
634 FunctionCallback func) { 679 FunctionCallback func) {
635 Isolate* isolate = reinterpret_cast<Isolate*>(i_isolate); 680 Isolate* isolate = reinterpret_cast<Isolate*>(i_isolate);
636 Local<FunctionTemplate> local = FunctionTemplate::New(isolate, func); 681 Local<FunctionTemplate> local = FunctionTemplate::New(isolate, func);
637 return v8::Utils::OpenHandle(*local); 682 return v8::Utils::OpenHandle(*local);
638 } 683 }
639 684
640 namespace internal { 685 namespace internal {
(...skipping 165 matching lines...) Expand 10 before | Expand all | Expand 10 after
806 &in_object_properties); 851 &in_object_properties);
807 852
808 int unused_property_fields = in_object_properties - pre_allocated; 853 int unused_property_fields = in_object_properties - pre_allocated;
809 Handle<Map> map = Map::CopyInitialMap( 854 Handle<Map> map = Map::CopyInitialMap(
810 prev_map, instance_size, in_object_properties, unused_property_fields); 855 prev_map, instance_size, in_object_properties, unused_property_fields);
811 856
812 context->set_wasm_function_map(*map); 857 context->set_wasm_function_map(*map);
813 } 858 }
814 } 859 }
815 860
816 bool WasmJs::IsWasmMemoryObject(Isolate* isolate, Handle<Object> value) { 861 static bool IsBrand(i::Handle<i::Object> value, i::Handle<i::Symbol> symbol) {
bradnelson 2016/10/28 16:59:01 HasBrand is a little better.
titzer 2016/10/28 17:29:08 Done.
817 if (value->IsJSObject()) { 862 if (value->IsJSObject()) {
818 i::Handle<i::JSObject> object = i::Handle<i::JSObject>::cast(value); 863 i::Handle<i::JSObject> object = i::Handle<i::JSObject>::cast(value);
819 i::Handle<i::Symbol> sym(isolate->context()->wasm_memory_sym(), isolate); 864 Maybe<bool> has_brand = i::JSObject::HasOwnProperty(object, symbol);
820 Maybe<bool> has_brand = i::JSObject::HasOwnProperty(object, sym);
821 if (has_brand.IsNothing()) return false; 865 if (has_brand.IsNothing()) return false;
822 if (has_brand.ToChecked()) return true; 866 if (has_brand.ToChecked()) return true;
823 } 867 }
824 return false; 868 return false;
825 } 869 }
826 870
871 bool WasmJs::IsWasmMemoryObject(Isolate* isolate, Handle<Object> value) {
872 i::Handle<i::Symbol> symbol(isolate->context()->wasm_memory_sym(), isolate);
873 return IsBrand(value, symbol);
874 }
875
876 bool WasmJs::IsWasmTableObject(Isolate* isolate, Handle<Object> value) {
877 i::Handle<i::Symbol> symbol(isolate->context()->wasm_table_sym(), isolate);
878 return IsBrand(value, symbol);
879 }
880
881 Handle<FixedArray> WasmJs::GetWasmTableFunctions(Isolate* isolate,
882 Handle<JSObject> value) {
883 DCHECK(IsWasmTableObject(isolate, value));
884 Handle<Object> arr(
885 JSObject::cast(*value)->GetInternalField(kWasmTableArrayFieldIndex),
886 isolate);
887 return Handle<FixedArray>::cast(arr);
888 }
889
827 Handle<JSArrayBuffer> WasmJs::GetWasmMemoryArrayBuffer(Isolate* isolate, 890 Handle<JSArrayBuffer> WasmJs::GetWasmMemoryArrayBuffer(Isolate* isolate,
828 Handle<Object> value) { 891 Handle<Object> value) {
829 DCHECK(IsWasmMemoryObject(isolate, value)); 892 DCHECK(IsWasmMemoryObject(isolate, value));
830 Handle<Object> buf( 893 Handle<Object> buf(
831 JSObject::cast(*value)->GetInternalField(kWasmMemoryBuffer), isolate); 894 JSObject::cast(*value)->GetInternalField(kWasmMemoryBuffer), isolate);
832 return Handle<JSArrayBuffer>::cast(buf); 895 return Handle<JSArrayBuffer>::cast(buf);
833 } 896 }
834 897
835 void WasmJs::SetWasmMemoryArrayBuffer(Isolate* isolate, Handle<Object> value, 898 void WasmJs::SetWasmMemoryArrayBuffer(Isolate* isolate, Handle<Object> value,
836 Handle<JSArrayBuffer> buffer) { 899 Handle<JSArrayBuffer> buffer) {
837 DCHECK(IsWasmMemoryObject(isolate, value)); 900 DCHECK(IsWasmMemoryObject(isolate, value));
838 JSObject::cast(*value)->SetInternalField(kWasmMemoryBuffer, *buffer); 901 JSObject::cast(*value)->SetInternalField(kWasmMemoryBuffer, *buffer);
839 } 902 }
840 903
841 uint32_t WasmJs::GetWasmMemoryMaximumSize(Isolate* isolate, 904 uint32_t WasmJs::GetWasmMemoryMaximumSize(Isolate* isolate,
842 Handle<Object> value) { 905 Handle<Object> value) {
843 DCHECK(IsWasmMemoryObject(isolate, value)); 906 DCHECK(IsWasmMemoryObject(isolate, value));
844 Object* max_mem = 907 Object* max_mem =
845 JSObject::cast(*value)->GetInternalField(kWasmMemoryMaximum); 908 JSObject::cast(*value)->GetInternalField(kWasmMemoryMaximum);
846 if (max_mem->IsUndefined(isolate)) return wasm::WasmModule::kMaxMemPages; 909 if (max_mem->IsUndefined(isolate)) return wasm::WasmModule::kV8MaxPages;
847 uint32_t max_pages = Smi::cast(max_mem)->value(); 910 uint32_t max_pages = Smi::cast(max_mem)->value();
848 return max_pages; 911 return max_pages;
849 } 912 }
850 913
851 void WasmJs::SetWasmMemoryInstance(Isolate* isolate, 914 void WasmJs::SetWasmMemoryInstance(Isolate* isolate,
852 Handle<Object> memory_object, 915 Handle<Object> memory_object,
853 Handle<JSObject> instance) { 916 Handle<JSObject> instance) {
854 if (!memory_object->IsUndefined(isolate)) { 917 if (!memory_object->IsUndefined(isolate)) {
855 DCHECK(IsWasmMemoryObject(isolate, memory_object)); 918 DCHECK(IsWasmMemoryObject(isolate, memory_object));
856 // TODO(gdeepti): This should be a weak list of instance objects 919 // TODO(gdeepti): This should be a weak list of instance objects
857 // for instances that share memory. 920 // for instances that share memory.
858 JSObject::cast(*memory_object) 921 JSObject::cast(*memory_object)
859 ->SetInternalField(kWasmMemoryInstanceObject, *instance); 922 ->SetInternalField(kWasmMemoryInstanceObject, *instance);
860 } 923 }
861 } 924 }
862 } // namespace internal 925 } // namespace internal
863 } // namespace v8 926 } // namespace v8
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698