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; | |
33 | 32 |
34 enum WasmMemoryObjectData { | 33 enum WasmMemoryObjectData { |
35 kWasmMemoryBuffer, | 34 kWasmMemoryBuffer, |
36 kWasmMemoryMaximum, | 35 kWasmMemoryMaximum, |
37 kWasmMemoryInstanceObject | 36 kWasmMemoryInstanceObject |
38 }; | 37 }; |
39 | 38 |
40 enum WasmInternalFieldCountData { | 39 enum WasmInternalFieldCountData { |
41 kWasmTableInternalFieldCount = 3, | 40 kWasmTableInternalFieldCount = 2, |
42 kWasmMemoryInternalFieldCount = 3 | 41 kWasmMemoryInternalFieldCount |
43 }; | 42 }; |
44 | 43 |
45 namespace { | 44 namespace { |
46 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) { |
47 return isolate->factory()->NewStringFromAsciiChecked(str); | 46 return isolate->factory()->NewStringFromAsciiChecked(str); |
48 } | 47 } |
49 Local<String> v8_str(Isolate* isolate, const char* str) { | 48 Local<String> v8_str(Isolate* isolate, const char* str) { |
50 return Utils::ToLocal(v8_str(reinterpret_cast<i::Isolate*>(isolate), str)); | 49 return Utils::ToLocal(v8_str(reinterpret_cast<i::Isolate*>(isolate), str)); |
51 } | 50 } |
52 | 51 |
(...skipping 455 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
508 receiver->GetInternalField(kWasmTableArrayFieldIndex), i_isolate); | 507 receiver->GetInternalField(kWasmTableArrayFieldIndex), i_isolate); |
509 int i; | 508 int i; |
510 if (!args[0]->Int32Value(context).To(&i)) return; | 509 if (!args[0]->Int32Value(context).To(&i)) return; |
511 if (i < 0 || i >= i::Handle<i::FixedArray>::cast(array)->length()) { | 510 if (i < 0 || i >= i::Handle<i::FixedArray>::cast(array)->length()) { |
512 v8::Local<v8::Value> e = | 511 v8::Local<v8::Value> e = |
513 v8::Exception::RangeError(v8_str(isolate, "index out of bounds")); | 512 v8::Exception::RangeError(v8_str(isolate, "index out of bounds")); |
514 isolate->ThrowException(e); | 513 isolate->ThrowException(e); |
515 return; | 514 return; |
516 } | 515 } |
517 | 516 |
518 i::Handle<i::FixedArray> dispatch_tables( | 517 i::Handle<i::FixedArray>::cast(array)->set(i, *value); |
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 | 518 |
530 i::Handle<i::FixedArray>::cast(array)->set(i, *value); | 519 // TODO(titzer): update relevant instances. |
531 } | 520 } |
532 | 521 |
533 void WebAssemblyMemoryGrow(const v8::FunctionCallbackInfo<v8::Value>& args) { | 522 void WebAssemblyMemoryGrow(const v8::FunctionCallbackInfo<v8::Value>& args) { |
534 v8::Isolate* isolate = args.GetIsolate(); | 523 v8::Isolate* isolate = args.GetIsolate(); |
535 Local<Context> context = isolate->GetCurrentContext(); | 524 Local<Context> context = isolate->GetCurrentContext(); |
536 i::Handle<i::Context> i_context = Utils::OpenHandle(*context); | 525 i::Handle<i::Context> i_context = Utils::OpenHandle(*context); |
537 if (!BrandCheck(isolate, Utils::OpenHandle(*args.This()), | 526 if (!BrandCheck(isolate, Utils::OpenHandle(*args.This()), |
538 i::Handle<i::Symbol>(i_context->wasm_memory_sym()), | 527 i::Handle<i::Symbol>(i_context->wasm_memory_sym()), |
539 "Receiver is not a WebAssembly.Memory")) { | 528 "Receiver is not a WebAssembly.Memory")) { |
540 return; | 529 return; |
(...skipping 71 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
612 ? static_cast<i::Object*>(i::Smi::FromInt(maximum)) | 601 ? static_cast<i::Object*>(i::Smi::FromInt(maximum)) |
613 : static_cast<i::Object*>(i_isolate->heap()->undefined_value())); | 602 : static_cast<i::Object*>(i_isolate->heap()->undefined_value())); |
614 i::Handle<i::Symbol> memory_sym( | 603 i::Handle<i::Symbol> memory_sym( |
615 i_isolate->native_context()->wasm_memory_sym()); | 604 i_isolate->native_context()->wasm_memory_sym()); |
616 i::Object::SetProperty(memory_obj, memory_sym, memory_obj, i::STRICT).Check(); | 605 i::Object::SetProperty(memory_obj, memory_sym, memory_obj, i::STRICT).Check(); |
617 return memory_obj; | 606 return memory_obj; |
618 } | 607 } |
619 | 608 |
620 i::Handle<i::JSObject> i::WasmJs::CreateWasmTableObject( | 609 i::Handle<i::JSObject> i::WasmJs::CreateWasmTableObject( |
621 i::Isolate* i_isolate, uint32_t initial, bool has_maximum, uint32_t maximum, | 610 i::Isolate* i_isolate, uint32_t initial, bool has_maximum, uint32_t maximum, |
622 i::Handle<i::FixedArray>* js_functions) { | 611 i::Handle<i::FixedArray>* array) { |
623 i::Handle<i::JSFunction> table_ctor( | 612 i::Handle<i::JSFunction> table_ctor( |
624 i_isolate->native_context()->wasm_table_constructor()); | 613 i_isolate->native_context()->wasm_table_constructor()); |
625 i::Handle<i::JSObject> table_obj = | 614 i::Handle<i::JSObject> table_obj = |
626 i_isolate->factory()->NewJSObject(table_ctor); | 615 i_isolate->factory()->NewJSObject(table_ctor); |
627 *js_functions = i_isolate->factory()->NewFixedArray(initial); | 616 *array = i_isolate->factory()->NewFixedArray(initial); |
628 i::Object* null = i_isolate->heap()->null_value(); | 617 i::Object* null = i_isolate->heap()->null_value(); |
629 // TODO(titzer): consider moving FixedArray to size_t. | 618 // TODO(titzer): consider moving FixedArray to size_t. |
630 for (int i = 0; i < static_cast<int>(initial); ++i) { | 619 for (int i = 0; i < static_cast<int>(initial); ++i) (*array)->set(i, null); |
631 (*js_functions)->set(i, null); | 620 table_obj->SetInternalField(kWasmTableArrayFieldIndex, *(*array)); |
632 } | |
633 table_obj->SetInternalField(kWasmTableArrayFieldIndex, *(*js_functions)); | |
634 table_obj->SetInternalField( | 621 table_obj->SetInternalField( |
635 kWasmTableMaximumFieldIndex, | 622 kWasmTableMaximumFieldIndex, |
636 has_maximum | 623 has_maximum |
637 ? static_cast<i::Object*>(i::Smi::FromInt(maximum)) | 624 ? static_cast<i::Object*>(i::Smi::FromInt(maximum)) |
638 : static_cast<i::Object*>(i_isolate->heap()->undefined_value())); | 625 : 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); | |
642 i::Handle<i::Symbol> table_sym(i_isolate->native_context()->wasm_table_sym()); | 626 i::Handle<i::Symbol> table_sym(i_isolate->native_context()->wasm_table_sym()); |
643 i::Object::SetProperty(table_obj, table_sym, table_obj, i::STRICT).Check(); | 627 i::Object::SetProperty(table_obj, table_sym, table_obj, i::STRICT).Check(); |
644 return table_obj; | 628 return table_obj; |
645 } | 629 } |
646 | 630 |
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 | |
676 // TODO(titzer): we use the API to create the function template because the | 631 // TODO(titzer): we use the API to create the function template because the |
677 // internal guts are too ugly to replicate here. | 632 // internal guts are too ugly to replicate here. |
678 static i::Handle<i::FunctionTemplateInfo> NewTemplate(i::Isolate* i_isolate, | 633 static i::Handle<i::FunctionTemplateInfo> NewTemplate(i::Isolate* i_isolate, |
679 FunctionCallback func) { | 634 FunctionCallback func) { |
680 Isolate* isolate = reinterpret_cast<Isolate*>(i_isolate); | 635 Isolate* isolate = reinterpret_cast<Isolate*>(i_isolate); |
681 Local<FunctionTemplate> local = FunctionTemplate::New(isolate, func); | 636 Local<FunctionTemplate> local = FunctionTemplate::New(isolate, func); |
682 return v8::Utils::OpenHandle(*local); | 637 return v8::Utils::OpenHandle(*local); |
683 } | 638 } |
684 | 639 |
685 namespace internal { | 640 namespace internal { |
(...skipping 165 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
851 &in_object_properties); | 806 &in_object_properties); |
852 | 807 |
853 int unused_property_fields = in_object_properties - pre_allocated; | 808 int unused_property_fields = in_object_properties - pre_allocated; |
854 Handle<Map> map = Map::CopyInitialMap( | 809 Handle<Map> map = Map::CopyInitialMap( |
855 prev_map, instance_size, in_object_properties, unused_property_fields); | 810 prev_map, instance_size, in_object_properties, unused_property_fields); |
856 | 811 |
857 context->set_wasm_function_map(*map); | 812 context->set_wasm_function_map(*map); |
858 } | 813 } |
859 } | 814 } |
860 | 815 |
861 static bool HasBrand(i::Handle<i::Object> value, i::Handle<i::Symbol> symbol) { | 816 bool WasmJs::IsWasmMemoryObject(Isolate* isolate, Handle<Object> value) { |
862 if (value->IsJSObject()) { | 817 if (value->IsJSObject()) { |
863 i::Handle<i::JSObject> object = i::Handle<i::JSObject>::cast(value); | 818 i::Handle<i::JSObject> object = i::Handle<i::JSObject>::cast(value); |
864 Maybe<bool> has_brand = i::JSObject::HasOwnProperty(object, symbol); | 819 i::Handle<i::Symbol> sym(isolate->context()->wasm_memory_sym(), isolate); |
| 820 Maybe<bool> has_brand = i::JSObject::HasOwnProperty(object, sym); |
865 if (has_brand.IsNothing()) return false; | 821 if (has_brand.IsNothing()) return false; |
866 if (has_brand.ToChecked()) return true; | 822 if (has_brand.ToChecked()) return true; |
867 } | 823 } |
868 return false; | 824 return false; |
869 } | 825 } |
870 | 826 |
871 bool WasmJs::IsWasmMemoryObject(Isolate* isolate, Handle<Object> value) { | |
872 i::Handle<i::Symbol> symbol(isolate->context()->wasm_memory_sym(), isolate); | |
873 return HasBrand(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 HasBrand(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 | |
890 Handle<JSArrayBuffer> WasmJs::GetWasmMemoryArrayBuffer(Isolate* isolate, | 827 Handle<JSArrayBuffer> WasmJs::GetWasmMemoryArrayBuffer(Isolate* isolate, |
891 Handle<Object> value) { | 828 Handle<Object> value) { |
892 DCHECK(IsWasmMemoryObject(isolate, value)); | 829 DCHECK(IsWasmMemoryObject(isolate, value)); |
893 Handle<Object> buf( | 830 Handle<Object> buf( |
894 JSObject::cast(*value)->GetInternalField(kWasmMemoryBuffer), isolate); | 831 JSObject::cast(*value)->GetInternalField(kWasmMemoryBuffer), isolate); |
895 return Handle<JSArrayBuffer>::cast(buf); | 832 return Handle<JSArrayBuffer>::cast(buf); |
896 } | 833 } |
897 | 834 |
898 void WasmJs::SetWasmMemoryArrayBuffer(Isolate* isolate, Handle<Object> value, | 835 void WasmJs::SetWasmMemoryArrayBuffer(Isolate* isolate, Handle<Object> value, |
899 Handle<JSArrayBuffer> buffer) { | 836 Handle<JSArrayBuffer> buffer) { |
900 DCHECK(IsWasmMemoryObject(isolate, value)); | 837 DCHECK(IsWasmMemoryObject(isolate, value)); |
901 JSObject::cast(*value)->SetInternalField(kWasmMemoryBuffer, *buffer); | 838 JSObject::cast(*value)->SetInternalField(kWasmMemoryBuffer, *buffer); |
902 } | 839 } |
903 | 840 |
904 uint32_t WasmJs::GetWasmMemoryMaximumSize(Isolate* isolate, | 841 uint32_t WasmJs::GetWasmMemoryMaximumSize(Isolate* isolate, |
905 Handle<Object> value) { | 842 Handle<Object> value) { |
906 DCHECK(IsWasmMemoryObject(isolate, value)); | 843 DCHECK(IsWasmMemoryObject(isolate, value)); |
907 Object* max_mem = | 844 Object* max_mem = |
908 JSObject::cast(*value)->GetInternalField(kWasmMemoryMaximum); | 845 JSObject::cast(*value)->GetInternalField(kWasmMemoryMaximum); |
909 if (max_mem->IsUndefined(isolate)) return wasm::WasmModule::kV8MaxPages; | 846 if (max_mem->IsUndefined(isolate)) return wasm::WasmModule::kMaxMemPages; |
910 uint32_t max_pages = Smi::cast(max_mem)->value(); | 847 uint32_t max_pages = Smi::cast(max_mem)->value(); |
911 return max_pages; | 848 return max_pages; |
912 } | 849 } |
913 | 850 |
914 void WasmJs::SetWasmMemoryInstance(Isolate* isolate, | 851 void WasmJs::SetWasmMemoryInstance(Isolate* isolate, |
915 Handle<Object> memory_object, | 852 Handle<Object> memory_object, |
916 Handle<JSObject> instance) { | 853 Handle<JSObject> instance) { |
917 if (!memory_object->IsUndefined(isolate)) { | 854 if (!memory_object->IsUndefined(isolate)) { |
918 DCHECK(IsWasmMemoryObject(isolate, memory_object)); | 855 DCHECK(IsWasmMemoryObject(isolate, memory_object)); |
919 // TODO(gdeepti): This should be a weak list of instance objects | 856 // TODO(gdeepti): This should be a weak list of instance objects |
920 // for instances that share memory. | 857 // for instances that share memory. |
921 JSObject::cast(*memory_object) | 858 JSObject::cast(*memory_object) |
922 ->SetInternalField(kWasmMemoryInstanceObject, *instance); | 859 ->SetInternalField(kWasmMemoryInstanceObject, *instance); |
923 } | 860 } |
924 } | 861 } |
925 } // namespace internal | 862 } // namespace internal |
926 } // namespace v8 | 863 } // namespace v8 |
OLD | NEW |