| 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 |