Chromium Code Reviews| 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 |