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 11 matching lines...) Expand all Loading... |
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; |
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 459 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
511 receiver->GetInternalField(kWasmTableArrayFieldIndex), i_isolate); | 512 receiver->GetInternalField(kWasmTableArrayFieldIndex), i_isolate); |
512 int i; | 513 int i; |
513 if (!args[0]->Int32Value(context).To(&i)) return; | 514 if (!args[0]->Int32Value(context).To(&i)) return; |
514 if (i < 0 || i >= i::Handle<i::FixedArray>::cast(array)->length()) { | 515 if (i < 0 || i >= i::Handle<i::FixedArray>::cast(array)->length()) { |
515 v8::Local<v8::Value> e = | 516 v8::Local<v8::Value> e = |
516 v8::Exception::RangeError(v8_str(isolate, "index out of bounds")); | 517 v8::Exception::RangeError(v8_str(isolate, "index out of bounds")); |
517 isolate->ThrowException(e); | 518 isolate->ThrowException(e); |
518 return; | 519 return; |
519 } | 520 } |
520 | 521 |
| 522 i::Handle<i::FixedArray> dispatch_tables( |
| 523 i::FixedArray::cast( |
| 524 receiver->GetInternalField(kWasmTableDispatchTablesFieldIndex)), |
| 525 i_isolate); |
| 526 if (value->IsNull(i_isolate)) { |
| 527 i::wasm::UpdateDispatchTables(i_isolate, dispatch_tables, i, |
| 528 i::Handle<i::JSFunction>::null()); |
| 529 } else { |
| 530 i::wasm::UpdateDispatchTables(i_isolate, dispatch_tables, i, |
| 531 i::Handle<i::JSFunction>::cast(value)); |
| 532 } |
| 533 |
521 i::Handle<i::FixedArray>::cast(array)->set(i, *value); | 534 i::Handle<i::FixedArray>::cast(array)->set(i, *value); |
522 | |
523 // TODO(titzer): update relevant instances. | |
524 } | 535 } |
525 | 536 |
526 void WebAssemblyMemoryGrow(const v8::FunctionCallbackInfo<v8::Value>& args) { | 537 void WebAssemblyMemoryGrow(const v8::FunctionCallbackInfo<v8::Value>& args) { |
527 v8::Isolate* isolate = args.GetIsolate(); | 538 v8::Isolate* isolate = args.GetIsolate(); |
528 Local<Context> context = isolate->GetCurrentContext(); | 539 Local<Context> context = isolate->GetCurrentContext(); |
529 i::Handle<i::Context> i_context = Utils::OpenHandle(*context); | 540 i::Handle<i::Context> i_context = Utils::OpenHandle(*context); |
530 if (!BrandCheck(isolate, Utils::OpenHandle(*args.This()), | 541 if (!BrandCheck(isolate, Utils::OpenHandle(*args.This()), |
531 i::Handle<i::Symbol>(i_context->wasm_memory_sym()), | 542 i::Handle<i::Symbol>(i_context->wasm_memory_sym()), |
532 "Receiver is not a WebAssembly.Memory")) { | 543 "Receiver is not a WebAssembly.Memory")) { |
533 return; | 544 return; |
(...skipping 71 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
605 ? static_cast<i::Object*>(i::Smi::FromInt(maximum)) | 616 ? static_cast<i::Object*>(i::Smi::FromInt(maximum)) |
606 : static_cast<i::Object*>(i_isolate->heap()->undefined_value())); | 617 : static_cast<i::Object*>(i_isolate->heap()->undefined_value())); |
607 i::Handle<i::Symbol> memory_sym( | 618 i::Handle<i::Symbol> memory_sym( |
608 i_isolate->native_context()->wasm_memory_sym()); | 619 i_isolate->native_context()->wasm_memory_sym()); |
609 i::Object::SetProperty(memory_obj, memory_sym, memory_obj, i::STRICT).Check(); | 620 i::Object::SetProperty(memory_obj, memory_sym, memory_obj, i::STRICT).Check(); |
610 return memory_obj; | 621 return memory_obj; |
611 } | 622 } |
612 | 623 |
613 i::Handle<i::JSObject> i::WasmJs::CreateWasmTableObject( | 624 i::Handle<i::JSObject> i::WasmJs::CreateWasmTableObject( |
614 i::Isolate* i_isolate, uint32_t initial, bool has_maximum, uint32_t maximum, | 625 i::Isolate* i_isolate, uint32_t initial, bool has_maximum, uint32_t maximum, |
615 i::Handle<i::FixedArray>* array) { | 626 i::Handle<i::FixedArray>* js_functions) { |
616 i::Handle<i::JSFunction> table_ctor( | 627 i::Handle<i::JSFunction> table_ctor( |
617 i_isolate->native_context()->wasm_table_constructor()); | 628 i_isolate->native_context()->wasm_table_constructor()); |
618 i::Handle<i::JSObject> table_obj = | 629 i::Handle<i::JSObject> table_obj = |
619 i_isolate->factory()->NewJSObject(table_ctor); | 630 i_isolate->factory()->NewJSObject(table_ctor); |
620 *array = i_isolate->factory()->NewFixedArray(initial); | 631 *js_functions = i_isolate->factory()->NewFixedArray(initial); |
621 i::Object* null = i_isolate->heap()->null_value(); | 632 i::Object* null = i_isolate->heap()->null_value(); |
622 // TODO(titzer): consider moving FixedArray to size_t. | 633 // TODO(titzer): consider moving FixedArray to size_t. |
623 for (int i = 0; i < static_cast<int>(initial); ++i) (*array)->set(i, null); | 634 for (int i = 0; i < static_cast<int>(initial); ++i) { |
624 table_obj->SetInternalField(kWasmTableArrayFieldIndex, *(*array)); | 635 (*js_functions)->set(i, null); |
| 636 } |
| 637 table_obj->SetInternalField(kWasmTableArrayFieldIndex, *(*js_functions)); |
625 table_obj->SetInternalField( | 638 table_obj->SetInternalField( |
626 kWasmTableMaximumFieldIndex, | 639 kWasmTableMaximumFieldIndex, |
627 has_maximum | 640 has_maximum |
628 ? static_cast<i::Object*>(i::Smi::FromInt(maximum)) | 641 ? static_cast<i::Object*>(i::Smi::FromInt(maximum)) |
629 : static_cast<i::Object*>(i_isolate->heap()->undefined_value())); | 642 : static_cast<i::Object*>(i_isolate->heap()->undefined_value())); |
| 643 Handle<FixedArray> dispatch_tables = i_isolate->factory()->NewFixedArray(0); |
| 644 table_obj->SetInternalField(kWasmTableDispatchTablesFieldIndex, |
| 645 *dispatch_tables); |
630 i::Handle<i::Symbol> table_sym(i_isolate->native_context()->wasm_table_sym()); | 646 i::Handle<i::Symbol> table_sym(i_isolate->native_context()->wasm_table_sym()); |
631 i::Object::SetProperty(table_obj, table_sym, table_obj, i::STRICT).Check(); | 647 i::Object::SetProperty(table_obj, table_sym, table_obj, i::STRICT).Check(); |
632 return table_obj; | 648 return table_obj; |
633 } | 649 } |
634 | 650 |
| 651 i::Handle<i::FixedArray> i::WasmJs::AddWasmTableDispatchTable( |
| 652 i::Isolate* i_isolate, i::Handle<i::JSObject> table_obj, |
| 653 i::Handle<i::JSObject> instance, int table_index, |
| 654 i::Handle<i::FixedArray> dispatch_table) { |
| 655 DCHECK(IsWasmTableObject(i_isolate, table_obj)); |
| 656 i::Handle<i::FixedArray> dispatch_tables( |
| 657 i::FixedArray::cast( |
| 658 table_obj->GetInternalField(kWasmTableDispatchTablesFieldIndex)), |
| 659 i_isolate); |
| 660 DCHECK_EQ(0, dispatch_tables->length() % 3); |
| 661 |
| 662 if (instance.is_null()) return dispatch_tables; |
| 663 // TODO(titzer): use weak cells here to avoid leaking instances. |
| 664 |
| 665 // Grow the dispatch table and add a new pair at the end. |
| 666 i::Handle<i::FixedArray> new_dispatch_tables = |
| 667 i_isolate->factory()->CopyFixedArrayAndGrow(dispatch_tables, 3); |
| 668 |
| 669 new_dispatch_tables->set(dispatch_tables->length() + 0, *instance); |
| 670 new_dispatch_tables->set(dispatch_tables->length() + 1, |
| 671 Smi::FromInt(table_index)); |
| 672 new_dispatch_tables->set(dispatch_tables->length() + 2, *dispatch_table); |
| 673 |
| 674 table_obj->SetInternalField(kWasmTableDispatchTablesFieldIndex, |
| 675 *new_dispatch_tables); |
| 676 |
| 677 return new_dispatch_tables; |
| 678 } |
| 679 |
635 // TODO(titzer): we use the API to create the function template because the | 680 // TODO(titzer): we use the API to create the function template because the |
636 // internal guts are too ugly to replicate here. | 681 // internal guts are too ugly to replicate here. |
637 static i::Handle<i::FunctionTemplateInfo> NewTemplate(i::Isolate* i_isolate, | 682 static i::Handle<i::FunctionTemplateInfo> NewTemplate(i::Isolate* i_isolate, |
638 FunctionCallback func) { | 683 FunctionCallback func) { |
639 Isolate* isolate = reinterpret_cast<Isolate*>(i_isolate); | 684 Isolate* isolate = reinterpret_cast<Isolate*>(i_isolate); |
640 Local<FunctionTemplate> local = FunctionTemplate::New(isolate, func); | 685 Local<FunctionTemplate> local = FunctionTemplate::New(isolate, func); |
641 return v8::Utils::OpenHandle(*local); | 686 return v8::Utils::OpenHandle(*local); |
642 } | 687 } |
643 | 688 |
644 namespace internal { | 689 namespace internal { |
(...skipping 165 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
810 &in_object_properties); | 855 &in_object_properties); |
811 | 856 |
812 int unused_property_fields = in_object_properties - pre_allocated; | 857 int unused_property_fields = in_object_properties - pre_allocated; |
813 Handle<Map> map = Map::CopyInitialMap( | 858 Handle<Map> map = Map::CopyInitialMap( |
814 prev_map, instance_size, in_object_properties, unused_property_fields); | 859 prev_map, instance_size, in_object_properties, unused_property_fields); |
815 | 860 |
816 context->set_wasm_function_map(*map); | 861 context->set_wasm_function_map(*map); |
817 } | 862 } |
818 } | 863 } |
819 | 864 |
820 bool WasmJs::IsWasmMemoryObject(Isolate* isolate, Handle<Object> value) { | 865 static bool HasBrand(i::Handle<i::Object> value, i::Handle<i::Symbol> symbol) { |
821 if (value->IsJSObject()) { | 866 if (value->IsJSObject()) { |
822 i::Handle<i::JSObject> object = i::Handle<i::JSObject>::cast(value); | 867 i::Handle<i::JSObject> object = i::Handle<i::JSObject>::cast(value); |
823 i::Handle<i::Symbol> sym(isolate->context()->wasm_memory_sym(), isolate); | 868 Maybe<bool> has_brand = i::JSObject::HasOwnProperty(object, symbol); |
824 Maybe<bool> has_brand = i::JSObject::HasOwnProperty(object, sym); | |
825 if (has_brand.IsNothing()) return false; | 869 if (has_brand.IsNothing()) return false; |
826 if (has_brand.ToChecked()) return true; | 870 if (has_brand.ToChecked()) return true; |
827 } | 871 } |
828 return false; | 872 return false; |
829 } | 873 } |
830 | 874 |
| 875 bool WasmJs::IsWasmMemoryObject(Isolate* isolate, Handle<Object> value) { |
| 876 i::Handle<i::Symbol> symbol(isolate->context()->wasm_memory_sym(), isolate); |
| 877 return HasBrand(value, symbol); |
| 878 } |
| 879 |
| 880 bool WasmJs::IsWasmTableObject(Isolate* isolate, Handle<Object> value) { |
| 881 i::Handle<i::Symbol> symbol(isolate->context()->wasm_table_sym(), isolate); |
| 882 return HasBrand(value, symbol); |
| 883 } |
| 884 |
| 885 Handle<FixedArray> WasmJs::GetWasmTableFunctions(Isolate* isolate, |
| 886 Handle<JSObject> value) { |
| 887 DCHECK(IsWasmTableObject(isolate, value)); |
| 888 Handle<Object> arr( |
| 889 JSObject::cast(*value)->GetInternalField(kWasmTableArrayFieldIndex), |
| 890 isolate); |
| 891 return Handle<FixedArray>::cast(arr); |
| 892 } |
| 893 |
831 Handle<JSArrayBuffer> WasmJs::GetWasmMemoryArrayBuffer(Isolate* isolate, | 894 Handle<JSArrayBuffer> WasmJs::GetWasmMemoryArrayBuffer(Isolate* isolate, |
832 Handle<Object> value) { | 895 Handle<Object> value) { |
833 DCHECK(IsWasmMemoryObject(isolate, value)); | 896 DCHECK(IsWasmMemoryObject(isolate, value)); |
834 Handle<Object> buf( | 897 Handle<Object> buf( |
835 JSObject::cast(*value)->GetInternalField(kWasmMemoryBuffer), isolate); | 898 JSObject::cast(*value)->GetInternalField(kWasmMemoryBuffer), isolate); |
836 return Handle<JSArrayBuffer>::cast(buf); | 899 return Handle<JSArrayBuffer>::cast(buf); |
837 } | 900 } |
838 | 901 |
839 void WasmJs::SetWasmMemoryArrayBuffer(Isolate* isolate, Handle<Object> value, | 902 void WasmJs::SetWasmMemoryArrayBuffer(Isolate* isolate, Handle<Object> value, |
840 Handle<JSArrayBuffer> buffer) { | 903 Handle<JSArrayBuffer> buffer) { |
841 DCHECK(IsWasmMemoryObject(isolate, value)); | 904 DCHECK(IsWasmMemoryObject(isolate, value)); |
842 JSObject::cast(*value)->SetInternalField(kWasmMemoryBuffer, *buffer); | 905 JSObject::cast(*value)->SetInternalField(kWasmMemoryBuffer, *buffer); |
843 } | 906 } |
844 | 907 |
845 uint32_t WasmJs::GetWasmMemoryMaximumSize(Isolate* isolate, | 908 uint32_t WasmJs::GetWasmMemoryMaximumSize(Isolate* isolate, |
846 Handle<Object> value) { | 909 Handle<Object> value) { |
847 DCHECK(IsWasmMemoryObject(isolate, value)); | 910 DCHECK(IsWasmMemoryObject(isolate, value)); |
848 Object* max_mem = | 911 Object* max_mem = |
849 JSObject::cast(*value)->GetInternalField(kWasmMemoryMaximum); | 912 JSObject::cast(*value)->GetInternalField(kWasmMemoryMaximum); |
850 if (max_mem->IsUndefined(isolate)) return wasm::WasmModule::kMaxMemPages; | 913 if (max_mem->IsUndefined(isolate)) return wasm::WasmModule::kV8MaxPages; |
851 uint32_t max_pages = Smi::cast(max_mem)->value(); | 914 uint32_t max_pages = Smi::cast(max_mem)->value(); |
852 return max_pages; | 915 return max_pages; |
853 } | 916 } |
854 | 917 |
855 void WasmJs::SetWasmMemoryInstance(Isolate* isolate, | 918 void WasmJs::SetWasmMemoryInstance(Isolate* isolate, |
856 Handle<Object> memory_object, | 919 Handle<Object> memory_object, |
857 Handle<JSObject> instance) { | 920 Handle<JSObject> instance) { |
858 if (!memory_object->IsUndefined(isolate)) { | 921 if (!memory_object->IsUndefined(isolate)) { |
859 DCHECK(IsWasmMemoryObject(isolate, memory_object)); | 922 DCHECK(IsWasmMemoryObject(isolate, memory_object)); |
860 // TODO(gdeepti): This should be a weak list of instance objects | 923 // TODO(gdeepti): This should be a weak list of instance objects |
861 // for instances that share memory. | 924 // for instances that share memory. |
862 JSObject::cast(*memory_object) | 925 JSObject::cast(*memory_object) |
863 ->SetInternalField(kWasmMemoryInstanceObject, *instance); | 926 ->SetInternalField(kWasmMemoryInstanceObject, *instance); |
864 } | 927 } |
865 } | 928 } |
866 } // namespace internal | 929 } // namespace internal |
867 } // namespace v8 | 930 } // namespace v8 |
OLD | NEW |