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" |
11 #include "src/ast/ast.h" | 11 #include "src/ast/ast.h" |
12 #include "src/execution.h" | 12 #include "src/execution.h" |
13 #include "src/factory.h" | 13 #include "src/factory.h" |
14 #include "src/handles.h" | 14 #include "src/handles.h" |
15 #include "src/isolate.h" | 15 #include "src/isolate.h" |
16 #include "src/objects.h" | 16 #include "src/objects.h" |
17 #include "src/parsing/parse-info.h" | 17 #include "src/parsing/parse-info.h" |
18 | 18 |
19 #include "src/wasm/module-decoder.h" | 19 #include "src/wasm/module-decoder.h" |
20 #include "src/wasm/wasm-js.h" | 20 #include "src/wasm/wasm-js.h" |
21 #include "src/wasm/wasm-module.h" | 21 #include "src/wasm/wasm-module.h" |
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 kWasmMemoryBufferFieldIndex = 0; | |
31 static const int kWasmMemoryMaximumFieldIndex = 1; | |
32 static const int kWasmTableArrayFieldIndex = 0; | 30 static const int kWasmTableArrayFieldIndex = 0; |
33 static const int kWasmTableMaximumFieldIndex = 1; | 31 static const int kWasmTableMaximumFieldIndex = 1; |
34 | 32 |
| 33 enum WasmMemoryObjectData { |
| 34 kWasmMemoryBuffer, |
| 35 kWasmMemoryMaximum, |
| 36 kWasmMemoryInstanceObject |
| 37 }; |
| 38 |
| 39 enum WasmInternalFieldCountData { |
| 40 kWasmTableInternalFieldCount = 2, |
| 41 kWasmMemoryInternalFieldCount |
| 42 }; |
| 43 |
35 namespace { | 44 namespace { |
36 i::Handle<i::String> v8_str(i::Isolate* isolate, const char* str) { | 45 i::Handle<i::String> v8_str(i::Isolate* isolate, const char* str) { |
37 return isolate->factory()->NewStringFromAsciiChecked(str); | 46 return isolate->factory()->NewStringFromAsciiChecked(str); |
38 } | 47 } |
39 Local<String> v8_str(Isolate* isolate, const char* str) { | 48 Local<String> v8_str(Isolate* isolate, const char* str) { |
40 return Utils::ToLocal(v8_str(reinterpret_cast<i::Isolate*>(isolate), str)); | 49 return Utils::ToLocal(v8_str(reinterpret_cast<i::Isolate*>(isolate), str)); |
41 } | 50 } |
42 | 51 |
43 struct RawBuffer { | 52 struct RawBuffer { |
44 const byte* start; | 53 const byte* start; |
(...skipping 584 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
629 | 638 |
630 void WebAssemblyMemoryGrow(const v8::FunctionCallbackInfo<v8::Value>& args) { | 639 void WebAssemblyMemoryGrow(const v8::FunctionCallbackInfo<v8::Value>& args) { |
631 v8::Isolate* isolate = args.GetIsolate(); | 640 v8::Isolate* isolate = args.GetIsolate(); |
632 Local<Context> context = isolate->GetCurrentContext(); | 641 Local<Context> context = isolate->GetCurrentContext(); |
633 i::Handle<i::Context> i_context = Utils::OpenHandle(*context); | 642 i::Handle<i::Context> i_context = Utils::OpenHandle(*context); |
634 if (!BrandCheck(isolate, Utils::OpenHandle(*args.This()), | 643 if (!BrandCheck(isolate, Utils::OpenHandle(*args.This()), |
635 i::Handle<i::Symbol>(i_context->wasm_memory_sym()), | 644 i::Handle<i::Symbol>(i_context->wasm_memory_sym()), |
636 "Receiver is not a WebAssembly.Memory")) { | 645 "Receiver is not a WebAssembly.Memory")) { |
637 return; | 646 return; |
638 } | 647 } |
| 648 if (args.Length() < 1) { |
| 649 v8::Local<v8::Value> e = v8::Exception::TypeError( |
| 650 v8_str(isolate, "Argument 0 required, must be numeric value of pages")); |
| 651 isolate->ThrowException(e); |
| 652 return; |
| 653 } |
639 | 654 |
640 // TODO(rossberg): grow memory. | 655 uint32_t delta = args[0]->Uint32Value(context).FromJust(); |
641 v8::Local<v8::Value> e = | 656 i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate); |
642 v8::Exception::TypeError(v8_str(isolate, "Memory#grow unimplemented")); | 657 i::Handle<i::JSObject> receiver = |
643 isolate->ThrowException(e); | 658 i::Handle<i::JSObject>::cast(Utils::OpenHandle(*args.This())); |
| 659 i::Handle<i::Object> instance_object( |
| 660 receiver->GetInternalField(kWasmMemoryInstanceObject), i_isolate); |
| 661 i::Handle<i::JSObject> instance( |
| 662 i::Handle<i::JSObject>::cast(instance_object)); |
| 663 |
| 664 // TODO(gdeepti) Implement growing memory when shared by different |
| 665 // instances. |
| 666 int32_t ret = internal::wasm::GrowInstanceMemory(i_isolate, instance, delta); |
| 667 if (ret == -1) { |
| 668 v8::Local<v8::Value> e = v8::Exception::Error( |
| 669 v8_str(isolate, "Unable to grow instance memory.")); |
| 670 isolate->ThrowException(e); |
| 671 return; |
| 672 } |
| 673 i::MaybeHandle<i::JSArrayBuffer> buffer = |
| 674 internal::wasm::GetInstanceMemory(i_isolate, instance); |
| 675 if (buffer.is_null()) { |
| 676 v8::Local<v8::Value> e = v8::Exception::Error( |
| 677 v8_str(isolate, "WebAssembly.Memory buffer object not set.")); |
| 678 isolate->ThrowException(e); |
| 679 return; |
| 680 } |
| 681 receiver->SetInternalField(kWasmMemoryBuffer, *buffer.ToHandleChecked()); |
| 682 v8::ReturnValue<v8::Value> return_value = args.GetReturnValue(); |
| 683 return_value.Set(ret); |
644 } | 684 } |
645 | 685 |
646 void WebAssemblyMemoryGetBuffer( | 686 void WebAssemblyMemoryGetBuffer( |
647 const v8::FunctionCallbackInfo<v8::Value>& args) { | 687 const v8::FunctionCallbackInfo<v8::Value>& args) { |
648 v8::Isolate* isolate = args.GetIsolate(); | 688 v8::Isolate* isolate = args.GetIsolate(); |
649 Local<Context> context = isolate->GetCurrentContext(); | 689 Local<Context> context = isolate->GetCurrentContext(); |
650 i::Handle<i::Context> i_context = Utils::OpenHandle(*context); | 690 i::Handle<i::Context> i_context = Utils::OpenHandle(*context); |
651 if (!BrandCheck(isolate, Utils::OpenHandle(*args.This()), | 691 if (!BrandCheck(isolate, Utils::OpenHandle(*args.This()), |
652 i::Handle<i::Symbol>(i_context->wasm_memory_sym()), | 692 i::Handle<i::Symbol>(i_context->wasm_memory_sym()), |
653 "Receiver is not a WebAssembly.Memory")) { | 693 "Receiver is not a WebAssembly.Memory")) { |
654 return; | 694 return; |
655 } | 695 } |
656 i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate); | 696 i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate); |
657 i::Handle<i::JSObject> receiver = | 697 i::Handle<i::JSObject> receiver = |
658 i::Handle<i::JSObject>::cast(Utils::OpenHandle(*args.This())); | 698 i::Handle<i::JSObject>::cast(Utils::OpenHandle(*args.This())); |
659 i::Handle<i::Object> buffer( | 699 i::Handle<i::Object> buffer(receiver->GetInternalField(kWasmMemoryBuffer), |
660 receiver->GetInternalField(kWasmMemoryBufferFieldIndex), i_isolate); | 700 i_isolate); |
661 DCHECK(buffer->IsJSArrayBuffer()); | 701 DCHECK(buffer->IsJSArrayBuffer()); |
662 v8::ReturnValue<v8::Value> return_value = args.GetReturnValue(); | 702 v8::ReturnValue<v8::Value> return_value = args.GetReturnValue(); |
663 return_value.Set(Utils::ToLocal(buffer)); | 703 return_value.Set(Utils::ToLocal(buffer)); |
664 } | 704 } |
665 } // namespace | 705 } // namespace |
666 | 706 |
667 i::Handle<i::JSObject> i::WasmJs::CreateWasmMemoryObject( | 707 i::Handle<i::JSObject> i::WasmJs::CreateWasmMemoryObject( |
668 i::Isolate* i_isolate, i::Handle<i::JSArrayBuffer> buffer, bool has_maximum, | 708 i::Isolate* i_isolate, i::Handle<i::JSArrayBuffer> buffer, bool has_maximum, |
669 int maximum) { | 709 int maximum) { |
670 i::Handle<i::JSFunction> memory_ctor( | 710 i::Handle<i::JSFunction> memory_ctor( |
671 i_isolate->native_context()->wasm_memory_constructor()); | 711 i_isolate->native_context()->wasm_memory_constructor()); |
672 i::Handle<i::JSObject> memory_obj = | 712 i::Handle<i::JSObject> memory_obj = |
673 i_isolate->factory()->NewJSObject(memory_ctor); | 713 i_isolate->factory()->NewJSObject(memory_ctor); |
674 memory_obj->SetInternalField(kWasmMemoryBufferFieldIndex, *buffer); | 714 memory_obj->SetInternalField(kWasmMemoryBuffer, *buffer); |
675 memory_obj->SetInternalField( | 715 memory_obj->SetInternalField( |
676 kWasmMemoryMaximumFieldIndex, | 716 kWasmMemoryMaximum, |
677 has_maximum | 717 has_maximum |
678 ? static_cast<i::Object*>(i::Smi::FromInt(maximum)) | 718 ? static_cast<i::Object*>(i::Smi::FromInt(maximum)) |
679 : static_cast<i::Object*>(i_isolate->heap()->undefined_value())); | 719 : static_cast<i::Object*>(i_isolate->heap()->undefined_value())); |
680 i::Handle<i::Symbol> memory_sym( | 720 i::Handle<i::Symbol> memory_sym( |
681 i_isolate->native_context()->wasm_memory_sym()); | 721 i_isolate->native_context()->wasm_memory_sym()); |
682 i::Object::SetProperty(memory_obj, memory_sym, memory_obj, i::STRICT).Check(); | 722 i::Object::SetProperty(memory_obj, memory_sym, memory_obj, i::STRICT).Check(); |
683 return memory_obj; | 723 return memory_obj; |
684 } | 724 } |
685 | 725 |
686 // TODO(titzer): we use the API to create the function template because the | 726 // TODO(titzer): we use the API to create the function template because the |
(...skipping 94 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
781 InstallFunc(isolate, wasm_object, "Instance", WebAssemblyInstance); | 821 InstallFunc(isolate, wasm_object, "Instance", WebAssemblyInstance); |
782 context->set_wasm_instance_constructor(*instance_constructor); | 822 context->set_wasm_instance_constructor(*instance_constructor); |
783 | 823 |
784 // Setup Table | 824 // Setup Table |
785 Handle<JSFunction> table_constructor = | 825 Handle<JSFunction> table_constructor = |
786 InstallFunc(isolate, wasm_object, "Table", WebAssemblyTable); | 826 InstallFunc(isolate, wasm_object, "Table", WebAssemblyTable); |
787 context->set_wasm_table_constructor(*table_constructor); | 827 context->set_wasm_table_constructor(*table_constructor); |
788 Handle<JSObject> table_proto = | 828 Handle<JSObject> table_proto = |
789 factory->NewJSObject(table_constructor, TENURED); | 829 factory->NewJSObject(table_constructor, TENURED); |
790 map = isolate->factory()->NewMap( | 830 map = isolate->factory()->NewMap( |
791 i::JS_OBJECT_TYPE, i::JSObject::kHeaderSize + 2 * i::kPointerSize); | 831 i::JS_OBJECT_TYPE, i::JSObject::kHeaderSize + |
| 832 kWasmTableInternalFieldCount * i::kPointerSize); |
792 JSFunction::SetInitialMap(table_constructor, map, table_proto); | 833 JSFunction::SetInitialMap(table_constructor, map, table_proto); |
793 JSObject::AddProperty(table_proto, isolate->factory()->constructor_string(), | 834 JSObject::AddProperty(table_proto, isolate->factory()->constructor_string(), |
794 table_constructor, DONT_ENUM); | 835 table_constructor, DONT_ENUM); |
795 InstallGetter(isolate, table_proto, "length", WebAssemblyTableGetLength); | 836 InstallGetter(isolate, table_proto, "length", WebAssemblyTableGetLength); |
796 InstallFunc(isolate, table_proto, "grow", WebAssemblyTableGrow); | 837 InstallFunc(isolate, table_proto, "grow", WebAssemblyTableGrow); |
797 InstallFunc(isolate, table_proto, "get", WebAssemblyTableGet); | 838 InstallFunc(isolate, table_proto, "get", WebAssemblyTableGet); |
798 InstallFunc(isolate, table_proto, "set", WebAssemblyTableSet); | 839 InstallFunc(isolate, table_proto, "set", WebAssemblyTableSet); |
799 | 840 |
800 // Setup Memory | 841 // Setup Memory |
801 Handle<JSFunction> memory_constructor = | 842 Handle<JSFunction> memory_constructor = |
802 InstallFunc(isolate, wasm_object, "Memory", WebAssemblyMemory); | 843 InstallFunc(isolate, wasm_object, "Memory", WebAssemblyMemory); |
803 context->set_wasm_memory_constructor(*memory_constructor); | 844 context->set_wasm_memory_constructor(*memory_constructor); |
804 Handle<JSObject> memory_proto = | 845 Handle<JSObject> memory_proto = |
805 factory->NewJSObject(memory_constructor, TENURED); | 846 factory->NewJSObject(memory_constructor, TENURED); |
806 map = isolate->factory()->NewMap( | 847 map = isolate->factory()->NewMap( |
807 i::JS_OBJECT_TYPE, i::JSObject::kHeaderSize + 2 * i::kPointerSize); | 848 i::JS_OBJECT_TYPE, i::JSObject::kHeaderSize + |
| 849 kWasmMemoryInternalFieldCount * i::kPointerSize); |
808 JSFunction::SetInitialMap(memory_constructor, map, memory_proto); | 850 JSFunction::SetInitialMap(memory_constructor, map, memory_proto); |
809 JSObject::AddProperty(memory_proto, isolate->factory()->constructor_string(), | 851 JSObject::AddProperty(memory_proto, isolate->factory()->constructor_string(), |
810 memory_constructor, DONT_ENUM); | 852 memory_constructor, DONT_ENUM); |
811 InstallFunc(isolate, memory_proto, "grow", WebAssemblyMemoryGrow); | 853 InstallFunc(isolate, memory_proto, "grow", WebAssemblyMemoryGrow); |
812 InstallGetter(isolate, memory_proto, "buffer", WebAssemblyMemoryGetBuffer); | 854 InstallGetter(isolate, memory_proto, "buffer", WebAssemblyMemoryGetBuffer); |
813 | 855 |
814 // Setup errors | 856 // Setup errors |
815 attributes = static_cast<PropertyAttributes>(DONT_DELETE | READ_ONLY); | 857 attributes = static_cast<PropertyAttributes>(DONT_DELETE | READ_ONLY); |
816 Handle<JSFunction> compile_error( | 858 Handle<JSFunction> compile_error( |
817 isolate->native_context()->wasm_compile_error_function()); | 859 isolate->native_context()->wasm_compile_error_function()); |
(...skipping 87 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
905 if (has_brand.IsNothing()) return false; | 947 if (has_brand.IsNothing()) return false; |
906 if (has_brand.ToChecked()) return true; | 948 if (has_brand.ToChecked()) return true; |
907 } | 949 } |
908 return false; | 950 return false; |
909 } | 951 } |
910 | 952 |
911 Handle<JSArrayBuffer> WasmJs::GetWasmMemoryArrayBuffer(Isolate* isolate, | 953 Handle<JSArrayBuffer> WasmJs::GetWasmMemoryArrayBuffer(Isolate* isolate, |
912 Handle<Object> value) { | 954 Handle<Object> value) { |
913 DCHECK(IsWasmMemoryObject(isolate, value)); | 955 DCHECK(IsWasmMemoryObject(isolate, value)); |
914 Handle<Object> buf( | 956 Handle<Object> buf( |
915 JSObject::cast(*value)->GetInternalField(kWasmMemoryBufferFieldIndex), | 957 JSObject::cast(*value)->GetInternalField(kWasmMemoryBuffer), isolate); |
916 isolate); | |
917 return Handle<JSArrayBuffer>::cast(buf); | 958 return Handle<JSArrayBuffer>::cast(buf); |
918 } | 959 } |
| 960 |
| 961 uint32_t WasmJs::GetWasmMemoryMaximumSize(Isolate* isolate, |
| 962 Handle<Object> value) { |
| 963 DCHECK(IsWasmMemoryObject(isolate, value)); |
| 964 Object* max_mem = |
| 965 JSObject::cast(*value)->GetInternalField(kWasmMemoryMaximum); |
| 966 if (max_mem->IsUndefined(isolate)) return wasm::WasmModule::kMaxMemPages; |
| 967 uint32_t max_pages = Smi::cast(max_mem)->value(); |
| 968 return max_pages; |
| 969 } |
| 970 |
| 971 void WasmJs::SetWasmMemoryInstance(Isolate* isolate, |
| 972 Handle<Object> memory_object, |
| 973 Handle<JSObject> instance) { |
| 974 if (!memory_object->IsUndefined(isolate)) { |
| 975 DCHECK(IsWasmMemoryObject(isolate, memory_object)); |
| 976 // TODO(gdeepti): This should be a weak list of instance objects |
| 977 // for instances that share memory. |
| 978 JSObject::cast(*memory_object) |
| 979 ->SetInternalField(kWasmMemoryInstanceObject, *instance); |
| 980 } |
| 981 } |
919 } // namespace internal | 982 } // namespace internal |
920 } // namespace v8 | 983 } // namespace v8 |
OLD | NEW |