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; | |
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 Loading... | |
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 Loading... | |
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 Loading... | |
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 |
OLD | NEW |