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 <memory> | 5 #include <memory> |
6 | 6 |
7 #include "src/assembler-inl.h" | 7 #include "src/assembler-inl.h" |
8 #include "src/base/adapters.h" | 8 #include "src/base/adapters.h" |
9 #include "src/base/atomic-utils.h" | 9 #include "src/base/atomic-utils.h" |
10 #include "src/code-stubs.h" | 10 #include "src/code-stubs.h" |
(...skipping 264 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
275 RecordStats(isolate, Code::cast(functions->get(i))); | 275 RecordStats(isolate, Code::cast(functions->get(i))); |
276 } | 276 } |
277 } | 277 } |
278 | 278 |
279 Address GetGlobalStartAddressFromCodeTemplate(Object* undefined, | 279 Address GetGlobalStartAddressFromCodeTemplate(Object* undefined, |
280 JSObject* object) { | 280 JSObject* object) { |
281 auto instance = WasmInstanceObject::cast(object); | 281 auto instance = WasmInstanceObject::cast(object); |
282 Address old_address = nullptr; | 282 Address old_address = nullptr; |
283 if (instance->has_globals_buffer()) { | 283 if (instance->has_globals_buffer()) { |
284 old_address = | 284 old_address = |
285 static_cast<Address>(instance->get_globals_buffer()->backing_store()); | 285 static_cast<Address>(instance->globals_buffer()->backing_store()); |
286 } | 286 } |
287 return old_address; | 287 return old_address; |
288 } | 288 } |
289 | 289 |
290 void InitializeParallelCompilation( | 290 void InitializeParallelCompilation( |
291 Isolate* isolate, const std::vector<WasmFunction>& functions, | 291 Isolate* isolate, const std::vector<WasmFunction>& functions, |
292 std::vector<compiler::WasmCompilationUnit*>& compilation_units, | 292 std::vector<compiler::WasmCompilationUnit*>& compilation_units, |
293 ModuleBytesEnv& module_env, ErrorThrower* thrower) { | 293 ModuleBytesEnv& module_env, ErrorThrower* thrower) { |
294 for (uint32_t i = FLAG_skip_compiling_wasm_funcs; i < functions.size(); ++i) { | 294 for (uint32_t i = FLAG_skip_compiling_wasm_funcs; i < functions.size(); ++i) { |
295 const WasmFunction* func = &functions[i]; | 295 const WasmFunction* func = &functions[i]; |
(...skipping 248 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
544 } | 544 } |
545 compiled_module->reset_memory(); | 545 compiled_module->reset_memory(); |
546 } | 546 } |
547 | 547 |
548 static void MemoryInstanceFinalizer(Isolate* isolate, | 548 static void MemoryInstanceFinalizer(Isolate* isolate, |
549 WasmInstanceObject* instance) { | 549 WasmInstanceObject* instance) { |
550 DisallowHeapAllocation no_gc; | 550 DisallowHeapAllocation no_gc; |
551 // If the memory object is destroyed, nothing needs to be done here. | 551 // If the memory object is destroyed, nothing needs to be done here. |
552 if (!instance->has_memory_object()) return; | 552 if (!instance->has_memory_object()) return; |
553 Handle<WasmInstanceWrapper> instance_wrapper = | 553 Handle<WasmInstanceWrapper> instance_wrapper = |
554 handle(instance->get_instance_wrapper()); | 554 handle(instance->instance_wrapper()); |
555 DCHECK(WasmInstanceWrapper::IsWasmInstanceWrapper(*instance_wrapper)); | 555 DCHECK(WasmInstanceWrapper::IsWasmInstanceWrapper(*instance_wrapper)); |
556 DCHECK(instance_wrapper->has_instance()); | 556 DCHECK(instance_wrapper->has_instance()); |
557 bool has_prev = instance_wrapper->has_previous(); | 557 bool has_prev = instance_wrapper->has_previous(); |
558 bool has_next = instance_wrapper->has_next(); | 558 bool has_next = instance_wrapper->has_next(); |
559 Handle<WasmMemoryObject> memory_object(instance->get_memory_object()); | 559 Handle<WasmMemoryObject> memory_object(instance->memory_object()); |
560 | 560 |
561 if (!has_prev && !has_next) { | 561 if (!has_prev && !has_next) { |
562 memory_object->ResetInstancesLink(isolate); | 562 memory_object->ResetInstancesLink(isolate); |
563 return; | 563 return; |
564 } else { | 564 } else { |
565 Handle<WasmInstanceWrapper> next_wrapper, prev_wrapper; | 565 Handle<WasmInstanceWrapper> next_wrapper, prev_wrapper; |
566 if (!has_prev) { | 566 if (!has_prev) { |
567 Handle<WasmInstanceWrapper> next_wrapper = | 567 Handle<WasmInstanceWrapper> next_wrapper = |
568 instance_wrapper->next_wrapper(); | 568 instance_wrapper->next_wrapper(); |
569 next_wrapper->reset_previous_wrapper(); | 569 next_wrapper->reset_previous_wrapper(); |
(...skipping 15 matching lines...) Expand all Loading... |
585 // Reset to avoid dangling pointers | 585 // Reset to avoid dangling pointers |
586 instance_wrapper->reset(); | 586 instance_wrapper->reset(); |
587 } | 587 } |
588 } | 588 } |
589 | 589 |
590 static void InstanceFinalizer(const v8::WeakCallbackInfo<void>& data) { | 590 static void InstanceFinalizer(const v8::WeakCallbackInfo<void>& data) { |
591 DisallowHeapAllocation no_gc; | 591 DisallowHeapAllocation no_gc; |
592 JSObject** p = reinterpret_cast<JSObject**>(data.GetParameter()); | 592 JSObject** p = reinterpret_cast<JSObject**>(data.GetParameter()); |
593 WasmInstanceObject* owner = reinterpret_cast<WasmInstanceObject*>(*p); | 593 WasmInstanceObject* owner = reinterpret_cast<WasmInstanceObject*>(*p); |
594 Isolate* isolate = reinterpret_cast<Isolate*>(data.GetIsolate()); | 594 Isolate* isolate = reinterpret_cast<Isolate*>(data.GetIsolate()); |
595 // Is a link to shared memory instances exists, update the list of memory | 595 // If a link to shared memory instances exists, update the list of memory |
596 // instances before the instance is destroyed. | 596 // instances before the instance is destroyed. |
597 if (owner->has_instance_wrapper()) MemoryInstanceFinalizer(isolate, owner); | 597 if (owner->has_instance_wrapper()) MemoryInstanceFinalizer(isolate, owner); |
598 WasmCompiledModule* compiled_module = owner->get_compiled_module(); | 598 WasmCompiledModule* compiled_module = owner->compiled_module(); |
599 TRACE("Finalizing %d {\n", compiled_module->instance_id()); | 599 TRACE("Finalizing %d {\n", compiled_module->instance_id()); |
600 DCHECK(compiled_module->has_weak_wasm_module()); | 600 DCHECK(compiled_module->has_weak_wasm_module()); |
601 WeakCell* weak_wasm_module = compiled_module->ptr_to_weak_wasm_module(); | 601 WeakCell* weak_wasm_module = compiled_module->ptr_to_weak_wasm_module(); |
602 | 602 |
603 // weak_wasm_module may have been cleared, meaning the module object | 603 // weak_wasm_module may have been cleared, meaning the module object |
604 // was GC-ed. In that case, there won't be any new instances created, | 604 // was GC-ed. In that case, there won't be any new instances created, |
605 // and we don't need to maintain the links between instances. | 605 // and we don't need to maintain the links between instances. |
606 if (!weak_wasm_module->cleared()) { | 606 if (!weak_wasm_module->cleared()) { |
607 JSObject* wasm_module = JSObject::cast(weak_wasm_module->value()); | 607 JSObject* wasm_module = JSObject::cast(weak_wasm_module->value()); |
608 WasmCompiledModule* current_template = | 608 WasmCompiledModule* current_template = |
(...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
663 WasmModule* module = compiled_module->module(); | 663 WasmModule* module = compiled_module->module(); |
664 if (func_index < 0 || | 664 if (func_index < 0 || |
665 static_cast<size_t>(func_index) > module->functions.size()) { | 665 static_cast<size_t>(func_index) > module->functions.size()) { |
666 return {0, 0}; | 666 return {0, 0}; |
667 } | 667 } |
668 WasmFunction& func = module->functions[func_index]; | 668 WasmFunction& func = module->functions[func_index]; |
669 return {static_cast<int>(func.code_start_offset), | 669 return {static_cast<int>(func.code_start_offset), |
670 static_cast<int>(func.code_end_offset - func.code_start_offset)}; | 670 static_cast<int>(func.code_end_offset - func.code_start_offset)}; |
671 } | 671 } |
672 | 672 |
| 673 Handle<Script> CreateWasmScript(Isolate* isolate, |
| 674 const ModuleWireBytes& wire_bytes) { |
| 675 Handle<Script> script = |
| 676 isolate->factory()->NewScript(isolate->factory()->empty_string()); |
| 677 script->set_type(Script::TYPE_WASM); |
| 678 |
| 679 int hash = StringHasher::HashSequentialString( |
| 680 reinterpret_cast<const char*>(wire_bytes.module_bytes.start()), |
| 681 wire_bytes.module_bytes.length(), kZeroHashSeed); |
| 682 |
| 683 const int kBufferSize = 50; |
| 684 char buffer[kBufferSize]; |
| 685 int url_chars = SNPrintF(ArrayVector(buffer), "wasm://wasm/%08x", hash); |
| 686 DCHECK(url_chars >= 0 && url_chars < kBufferSize); |
| 687 MaybeHandle<String> url_str = isolate->factory()->NewStringFromOneByte( |
| 688 Vector<const uint8_t>(reinterpret_cast<uint8_t*>(buffer), url_chars), |
| 689 TENURED); |
| 690 script->set_source_url(*url_str.ToHandleChecked()); |
| 691 |
| 692 int name_chars = SNPrintF(ArrayVector(buffer), "wasm-%08x", hash); |
| 693 DCHECK(name_chars >= 0 && name_chars < kBufferSize); |
| 694 MaybeHandle<String> name_str = isolate->factory()->NewStringFromOneByte( |
| 695 Vector<const uint8_t>(reinterpret_cast<uint8_t*>(buffer), name_chars), |
| 696 TENURED); |
| 697 script->set_name(*name_str.ToHandleChecked()); |
| 698 |
| 699 return script; |
| 700 } |
673 } // namespace | 701 } // namespace |
674 | 702 |
675 Handle<JSArrayBuffer> wasm::NewArrayBuffer(Isolate* isolate, size_t size, | 703 Handle<JSArrayBuffer> wasm::NewArrayBuffer(Isolate* isolate, size_t size, |
676 bool enable_guard_regions) { | 704 bool enable_guard_regions) { |
677 if (size > (kV8MaxWasmMemoryPages * WasmModule::kPageSize)) { | 705 if (size > (kV8MaxWasmMemoryPages * WasmModule::kPageSize)) { |
678 // TODO(titzer): lift restriction on maximum memory allocated here. | 706 // TODO(titzer): lift restriction on maximum memory allocated here. |
679 return Handle<JSArrayBuffer>::null(); | 707 return Handle<JSArrayBuffer>::null(); |
680 } | 708 } |
681 | 709 |
682 enable_guard_regions = enable_guard_regions && kGuardRegionsSupported; | 710 enable_guard_regions = enable_guard_regions && kGuardRegionsSupported; |
(...skipping 114 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
797 int wasm::GetFunctionCodeOffset(Handle<WasmCompiledModule> compiled_module, | 825 int wasm::GetFunctionCodeOffset(Handle<WasmCompiledModule> compiled_module, |
798 int func_index) { | 826 int func_index) { |
799 return GetFunctionOffsetAndLength(compiled_module, func_index).first; | 827 return GetFunctionOffsetAndLength(compiled_module, func_index).first; |
800 } | 828 } |
801 | 829 |
802 WasmModule::WasmModule(Zone* owned) | 830 WasmModule::WasmModule(Zone* owned) |
803 : owned_zone(owned), pending_tasks(new base::Semaphore(0)) {} | 831 : owned_zone(owned), pending_tasks(new base::Semaphore(0)) {} |
804 | 832 |
805 MaybeHandle<WasmCompiledModule> WasmModule::CompileFunctions( | 833 MaybeHandle<WasmCompiledModule> WasmModule::CompileFunctions( |
806 Isolate* isolate, Handle<WasmModuleWrapper> module_wrapper, | 834 Isolate* isolate, Handle<WasmModuleWrapper> module_wrapper, |
807 ErrorThrower* thrower, const ModuleWireBytes& wire_bytes) const { | 835 ErrorThrower* thrower, const ModuleWireBytes& wire_bytes, |
| 836 Handle<Script> asm_js_script, |
| 837 Vector<const byte> asm_js_offset_table_bytes) const { |
808 Factory* factory = isolate->factory(); | 838 Factory* factory = isolate->factory(); |
809 | 839 |
810 MaybeHandle<WasmCompiledModule> nothing; | 840 MaybeHandle<WasmCompiledModule> nothing; |
811 | 841 |
812 WasmInstance temp_instance(this); | 842 WasmInstance temp_instance(this); |
813 temp_instance.context = isolate->native_context(); | 843 temp_instance.context = isolate->native_context(); |
814 temp_instance.mem_size = WasmModule::kPageSize * min_mem_pages; | 844 temp_instance.mem_size = WasmModule::kPageSize * min_mem_pages; |
815 temp_instance.mem_start = nullptr; | 845 temp_instance.mem_start = nullptr; |
816 temp_instance.globals_start = nullptr; | 846 temp_instance.globals_start = nullptr; |
817 | 847 |
(...skipping 60 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
878 i < temp_instance.function_code.size(); ++i) { | 908 i < temp_instance.function_code.size(); ++i) { |
879 Handle<Code> code = temp_instance.function_code[i]; | 909 Handle<Code> code = temp_instance.function_code[i]; |
880 bool modified = LinkFunction(code, temp_instance.function_code); | 910 bool modified = LinkFunction(code, temp_instance.function_code); |
881 if (modified) { | 911 if (modified) { |
882 // TODO(mtrofin): do we need to flush the cache here? | 912 // TODO(mtrofin): do we need to flush the cache here? |
883 Assembler::FlushICache(isolate, code->instruction_start(), | 913 Assembler::FlushICache(isolate, code->instruction_start(), |
884 code->instruction_size()); | 914 code->instruction_size()); |
885 } | 915 } |
886 } | 916 } |
887 | 917 |
| 918 // Create heap objects for script, module bytes and asm.js offset table to be |
| 919 // stored in the shared module data. |
| 920 Handle<Script> script; |
| 921 Handle<ByteArray> asm_js_offset_table; |
| 922 if (asm_js_script.is_null()) { |
| 923 script = CreateWasmScript(isolate, wire_bytes); |
| 924 } else { |
| 925 script = asm_js_script; |
| 926 asm_js_offset_table = |
| 927 isolate->factory()->NewByteArray(asm_js_offset_table_bytes.length()); |
| 928 asm_js_offset_table->copy_in(0, asm_js_offset_table_bytes.start(), |
| 929 asm_js_offset_table_bytes.length()); |
| 930 } |
| 931 // TODO(wasm): only save the sections necessary to deserialize a |
| 932 // {WasmModule}. E.g. function bodies could be omitted. |
| 933 Handle<String> module_bytes = |
| 934 factory->NewStringFromOneByte(wire_bytes.module_bytes, TENURED) |
| 935 .ToHandleChecked(); |
| 936 DCHECK(module_bytes->IsSeqOneByteString()); |
| 937 |
| 938 // Create the shared module data. |
| 939 // TODO(clemensh): For the same module (same bytes / same hash), we should |
| 940 // only have one WasmSharedModuleData. Otherwise, we might only set |
| 941 // breakpoints on a (potentially empty) subset of the instances. |
| 942 |
| 943 Handle<WasmSharedModuleData> shared = WasmSharedModuleData::New( |
| 944 isolate, module_wrapper, Handle<SeqOneByteString>::cast(module_bytes), |
| 945 script, asm_js_offset_table); |
| 946 |
888 // Create the compiled module object, and populate with compiled functions | 947 // Create the compiled module object, and populate with compiled functions |
889 // and information needed at instantiation time. This object needs to be | 948 // and information needed at instantiation time. This object needs to be |
890 // serializable. Instantiation may occur off a deserialized version of this | 949 // serializable. Instantiation may occur off a deserialized version of this |
891 // object. | 950 // object. |
892 Handle<WasmCompiledModule> ret = | 951 Handle<WasmCompiledModule> ret = WasmCompiledModule::New(isolate, shared); |
893 WasmCompiledModule::New(isolate, module_wrapper); | |
894 ret->set_code_table(code_table); | 952 ret->set_code_table(code_table); |
895 ret->set_min_mem_pages(min_mem_pages); | 953 ret->set_min_mem_pages(min_mem_pages); |
896 ret->set_max_mem_pages(max_mem_pages); | 954 ret->set_max_mem_pages(max_mem_pages); |
897 if (function_table_count > 0) { | 955 if (function_table_count > 0) { |
898 ret->set_function_tables(function_tables); | 956 ret->set_function_tables(function_tables); |
899 ret->set_empty_function_tables(function_tables); | 957 ret->set_empty_function_tables(function_tables); |
900 } | 958 } |
901 | 959 |
| 960 // If we created a wasm script, finish it now and make it public to the |
| 961 // debugger. |
| 962 if (asm_js_script.is_null()) { |
| 963 script->set_wasm_compiled_module(*ret); |
| 964 isolate->debug()->OnAfterCompile(script); |
| 965 } |
| 966 |
902 // Compile JS->WASM wrappers for exported functions. | 967 // Compile JS->WASM wrappers for exported functions. |
903 int func_index = 0; | 968 int func_index = 0; |
904 for (auto exp : export_table) { | 969 for (auto exp : export_table) { |
905 if (exp.kind != kExternalFunction) continue; | 970 if (exp.kind != kExternalFunction) continue; |
906 Handle<Code> wasm_code = | 971 Handle<Code> wasm_code = |
907 code_table->GetValueChecked<Code>(isolate, exp.index); | 972 code_table->GetValueChecked<Code>(isolate, exp.index); |
908 Handle<Code> wrapper_code = | 973 Handle<Code> wrapper_code = |
909 compiler::CompileJSToWasmWrapper(isolate, this, wasm_code, exp.index); | 974 compiler::CompileJSToWasmWrapper(isolate, this, wasm_code, exp.index); |
910 int export_index = static_cast<int>(functions.size() + func_index); | 975 int export_index = static_cast<int>(functions.size() + func_index); |
911 code_table->set(export_index, *wrapper_code); | 976 code_table->set(export_index, *wrapper_code); |
912 RecordStats(isolate, *wrapper_code); | 977 RecordStats(isolate, *wrapper_code); |
913 func_index++; | 978 func_index++; |
914 } | 979 } |
915 | 980 |
916 { | |
917 // TODO(wasm): only save the sections necessary to deserialize a | |
918 // {WasmModule}. E.g. function bodies could be omitted. | |
919 Handle<String> module_bytes_string = | |
920 factory->NewStringFromOneByte(wire_bytes.module_bytes, TENURED) | |
921 .ToHandleChecked(); | |
922 DCHECK(module_bytes_string->IsSeqOneByteString()); | |
923 ret->set_module_bytes(Handle<SeqOneByteString>::cast(module_bytes_string)); | |
924 } | |
925 | |
926 return ret; | 981 return ret; |
927 } | 982 } |
928 | 983 |
929 static WasmFunction* GetWasmFunctionForImportWrapper(Isolate* isolate, | 984 static WasmFunction* GetWasmFunctionForImportWrapper(Isolate* isolate, |
930 Handle<Object> target) { | 985 Handle<Object> target) { |
931 if (target->IsJSFunction()) { | 986 if (target->IsJSFunction()) { |
932 Handle<JSFunction> func = Handle<JSFunction>::cast(target); | 987 Handle<JSFunction> func = Handle<JSFunction>::cast(target); |
933 if (func->code()->kind() == Code::JS_TO_WASM_FUNCTION) { | 988 if (func->code()->kind() == Code::JS_TO_WASM_FUNCTION) { |
934 auto exported = Handle<WasmExportedFunction>::cast(func); | 989 auto exported = Handle<WasmExportedFunction>::cast(func); |
935 Handle<WasmInstanceObject> other_instance(exported->instance(), isolate); | 990 Handle<WasmInstanceObject> other_instance(exported->instance(), isolate); |
(...skipping 171 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1107 } | 1162 } |
1108 RecordStats(isolate_, code_table); | 1163 RecordStats(isolate_, code_table); |
1109 } else { | 1164 } else { |
1110 // There was no owner, so we can reuse the original. | 1165 // There was no owner, so we can reuse the original. |
1111 compiled_module_ = original; | 1166 compiled_module_ = original; |
1112 TRACE("Reusing existing instance %d\n", | 1167 TRACE("Reusing existing instance %d\n", |
1113 compiled_module_->instance_id()); | 1168 compiled_module_->instance_id()); |
1114 } | 1169 } |
1115 compiled_module_->set_code_table(code_table); | 1170 compiled_module_->set_code_table(code_table); |
1116 } | 1171 } |
1117 module_ = reinterpret_cast<WasmModuleWrapper*>( | 1172 module_ = compiled_module_->module(); |
1118 *compiled_module_->module_wrapper()) | |
1119 ->get(); | |
1120 | 1173 |
1121 //-------------------------------------------------------------------------- | 1174 //-------------------------------------------------------------------------- |
1122 // Allocate the instance object. | 1175 // Allocate the instance object. |
1123 //-------------------------------------------------------------------------- | 1176 //-------------------------------------------------------------------------- |
1124 Handle<WasmInstanceObject> instance = | 1177 Handle<WasmInstanceObject> instance = |
1125 WasmInstanceObject::New(isolate_, compiled_module_); | 1178 WasmInstanceObject::New(isolate_, compiled_module_); |
1126 | 1179 |
1127 //-------------------------------------------------------------------------- | 1180 //-------------------------------------------------------------------------- |
1128 // Set up the globals for the new instance. | 1181 // Set up the globals for the new instance. |
1129 //-------------------------------------------------------------------------- | 1182 //-------------------------------------------------------------------------- |
(...skipping 99 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1229 //-------------------------------------------------------------------------- | 1282 //-------------------------------------------------------------------------- |
1230 // Set up the exports object for the new instance. | 1283 // Set up the exports object for the new instance. |
1231 //-------------------------------------------------------------------------- | 1284 //-------------------------------------------------------------------------- |
1232 ProcessExports(code_table, instance); | 1285 ProcessExports(code_table, instance); |
1233 | 1286 |
1234 //-------------------------------------------------------------------------- | 1287 //-------------------------------------------------------------------------- |
1235 // Add instance to Memory object | 1288 // Add instance to Memory object |
1236 //-------------------------------------------------------------------------- | 1289 //-------------------------------------------------------------------------- |
1237 DCHECK(wasm::IsWasmInstance(*instance)); | 1290 DCHECK(wasm::IsWasmInstance(*instance)); |
1238 if (instance->has_memory_object()) { | 1291 if (instance->has_memory_object()) { |
1239 instance->get_memory_object()->AddInstance(isolate_, instance); | 1292 instance->memory_object()->AddInstance(isolate_, instance); |
1240 } | 1293 } |
1241 | 1294 |
1242 //-------------------------------------------------------------------------- | 1295 //-------------------------------------------------------------------------- |
1243 // Set up the indirect function tables for the new instance. | 1296 // Set up the indirect function tables for the new instance. |
1244 //-------------------------------------------------------------------------- | 1297 //-------------------------------------------------------------------------- |
1245 if (function_table_count > 0) InitializeTables(code_table, instance); | 1298 if (function_table_count > 0) InitializeTables(code_table, instance); |
1246 | 1299 |
1247 if (num_imported_functions > 0 || !owner.is_null()) { | 1300 if (num_imported_functions > 0 || !owner.is_null()) { |
1248 // If the code was cloned, or new imports were compiled, patch. | 1301 // If the code was cloned, or new imports were compiled, patch. |
1249 PatchDirectCalls(old_code_table, code_table, num_imported_functions); | 1302 PatchDirectCalls(old_code_table, code_table, num_imported_functions); |
(...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1293 Handle<WeakCell> link_to_clone = factory->NewWeakCell(compiled_module_); | 1346 Handle<WeakCell> link_to_clone = factory->NewWeakCell(compiled_module_); |
1294 Handle<WeakCell> link_to_owning_instance = factory->NewWeakCell(instance); | 1347 Handle<WeakCell> link_to_owning_instance = factory->NewWeakCell(instance); |
1295 MaybeHandle<WeakCell> link_to_original; | 1348 MaybeHandle<WeakCell> link_to_original; |
1296 MaybeHandle<WasmCompiledModule> original; | 1349 MaybeHandle<WasmCompiledModule> original; |
1297 if (!owner.is_null()) { | 1350 if (!owner.is_null()) { |
1298 // prepare the data needed for publishing in a chain, but don't link | 1351 // prepare the data needed for publishing in a chain, but don't link |
1299 // just yet, because | 1352 // just yet, because |
1300 // we want all the publishing to happen free from GC interruptions, and | 1353 // we want all the publishing to happen free from GC interruptions, and |
1301 // so we do it in | 1354 // so we do it in |
1302 // one GC-free scope afterwards. | 1355 // one GC-free scope afterwards. |
1303 original = handle(owner.ToHandleChecked()->get_compiled_module()); | 1356 original = handle(owner.ToHandleChecked()->compiled_module()); |
1304 link_to_original = factory->NewWeakCell(original.ToHandleChecked()); | 1357 link_to_original = factory->NewWeakCell(original.ToHandleChecked()); |
1305 } | 1358 } |
1306 // Publish the new instance to the instances chain. | 1359 // Publish the new instance to the instances chain. |
1307 { | 1360 { |
1308 DisallowHeapAllocation no_gc; | 1361 DisallowHeapAllocation no_gc; |
1309 if (!link_to_original.is_null()) { | 1362 if (!link_to_original.is_null()) { |
1310 compiled_module_->set_weak_next_instance( | 1363 compiled_module_->set_weak_next_instance( |
1311 link_to_original.ToHandleChecked()); | 1364 link_to_original.ToHandleChecked()); |
1312 original.ToHandleChecked()->set_weak_prev_instance(link_to_clone); | 1365 original.ToHandleChecked()->set_weak_prev_instance(link_to_clone); |
1313 compiled_module_->set_weak_wasm_module( | 1366 compiled_module_->set_weak_wasm_module( |
(...skipping 124 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1438 return *reinterpret_cast<uint32_t*>(raw_buffer_ptr(globals_, offset)); | 1491 return *reinterpret_cast<uint32_t*>(raw_buffer_ptr(globals_, offset)); |
1439 } | 1492 } |
1440 default: | 1493 default: |
1441 UNREACHABLE(); | 1494 UNREACHABLE(); |
1442 return 0; | 1495 return 0; |
1443 } | 1496 } |
1444 } | 1497 } |
1445 | 1498 |
1446 // Load data segments into the memory. | 1499 // Load data segments into the memory. |
1447 void LoadDataSegments(Address mem_addr, size_t mem_size) { | 1500 void LoadDataSegments(Address mem_addr, size_t mem_size) { |
1448 Handle<SeqOneByteString> module_bytes = compiled_module_->module_bytes(); | 1501 Handle<SeqOneByteString> module_bytes(compiled_module_->module_bytes(), |
| 1502 isolate_); |
1449 for (const WasmDataSegment& segment : module_->data_segments) { | 1503 for (const WasmDataSegment& segment : module_->data_segments) { |
1450 uint32_t source_size = segment.source_size; | 1504 uint32_t source_size = segment.source_size; |
1451 // Segments of size == 0 are just nops. | 1505 // Segments of size == 0 are just nops. |
1452 if (source_size == 0) continue; | 1506 if (source_size == 0) continue; |
1453 uint32_t dest_offset = EvalUint32InitExpr(segment.dest_addr); | 1507 uint32_t dest_offset = EvalUint32InitExpr(segment.dest_addr); |
1454 if (dest_offset >= mem_size || source_size >= mem_size || | 1508 if (dest_offset >= mem_size || source_size >= mem_size || |
1455 dest_offset > (mem_size - source_size)) { | 1509 dest_offset > (mem_size - source_size)) { |
1456 thrower_->LinkError("data segment (start = %" PRIu32 ", size = %" PRIu32 | 1510 thrower_->LinkError("data segment (start = %" PRIu32 ", size = %" PRIu32 |
1457 ") does not fit into memory (size = %" PRIuS ")", | 1511 ") does not fit into memory (size = %" PRIuS ")", |
1458 dest_offset, source_size, mem_size); | 1512 dest_offset, source_size, mem_size); |
(...skipping 94 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1553 if (!WasmJs::IsWasmTableObject(isolate_, value)) { | 1607 if (!WasmJs::IsWasmTableObject(isolate_, value)) { |
1554 ReportLinkError("table import requires a WebAssembly.Table", index, | 1608 ReportLinkError("table import requires a WebAssembly.Table", index, |
1555 module_name, import_name); | 1609 module_name, import_name); |
1556 return -1; | 1610 return -1; |
1557 } | 1611 } |
1558 WasmIndirectFunctionTable& table = | 1612 WasmIndirectFunctionTable& table = |
1559 module_->function_tables[num_imported_tables]; | 1613 module_->function_tables[num_imported_tables]; |
1560 TableInstance& table_instance = table_instances_[num_imported_tables]; | 1614 TableInstance& table_instance = table_instances_[num_imported_tables]; |
1561 table_instance.table_object = Handle<WasmTableObject>::cast(value); | 1615 table_instance.table_object = Handle<WasmTableObject>::cast(value); |
1562 table_instance.js_wrappers = Handle<FixedArray>( | 1616 table_instance.js_wrappers = Handle<FixedArray>( |
1563 table_instance.table_object->get_functions(), isolate_); | 1617 table_instance.table_object->functions(), isolate_); |
1564 | 1618 |
1565 // TODO(titzer): import table size must match exactly for now. | 1619 // TODO(titzer): import table size must match exactly for now. |
1566 int table_size = table_instance.js_wrappers->length(); | 1620 int table_size = table_instance.js_wrappers->length(); |
1567 if (table_size != static_cast<int>(table.min_size)) { | 1621 if (table_size != static_cast<int>(table.min_size)) { |
1568 thrower_->LinkError( | 1622 thrower_->LinkError( |
1569 "table import %d is wrong size (%d), expected %u", index, | 1623 "table import %d is wrong size (%d), expected %u", index, |
1570 table_size, table.min_size); | 1624 table_size, table.min_size); |
1571 return -1; | 1625 return -1; |
1572 } | 1626 } |
1573 | 1627 |
(...skipping 27 matching lines...) Expand all Loading... |
1601 } | 1655 } |
1602 case kExternalMemory: { | 1656 case kExternalMemory: { |
1603 if (!WasmJs::IsWasmMemoryObject(isolate_, value)) { | 1657 if (!WasmJs::IsWasmMemoryObject(isolate_, value)) { |
1604 ReportLinkError("memory import must be a WebAssembly.Memory object", | 1658 ReportLinkError("memory import must be a WebAssembly.Memory object", |
1605 index, module_name, import_name); | 1659 index, module_name, import_name); |
1606 return -1; | 1660 return -1; |
1607 } | 1661 } |
1608 auto memory = Handle<WasmMemoryObject>::cast(value); | 1662 auto memory = Handle<WasmMemoryObject>::cast(value); |
1609 DCHECK(WasmJs::IsWasmMemoryObject(isolate_, memory)); | 1663 DCHECK(WasmJs::IsWasmMemoryObject(isolate_, memory)); |
1610 instance->set_memory_object(*memory); | 1664 instance->set_memory_object(*memory); |
1611 memory_ = Handle<JSArrayBuffer>(memory->get_buffer(), isolate_); | 1665 memory_ = Handle<JSArrayBuffer>(memory->buffer(), isolate_); |
1612 break; | 1666 break; |
1613 } | 1667 } |
1614 case kExternalGlobal: { | 1668 case kExternalGlobal: { |
1615 // Global imports are converted to numbers and written into the | 1669 // Global imports are converted to numbers and written into the |
1616 // {globals_} array buffer. | 1670 // {globals_} array buffer. |
1617 if (!value->IsNumber()) { | 1671 if (!value->IsNumber()) { |
1618 ReportLinkError("global import must be a number", index, | 1672 ReportLinkError("global import must be a number", index, |
1619 module_name, import_name); | 1673 module_name, import_name); |
1620 return -1; | 1674 return -1; |
1621 } | 1675 } |
(...skipping 160 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1782 isolate_, table.min_size, maximum, &table_instance.js_wrappers); | 1836 isolate_, table.min_size, maximum, &table_instance.js_wrappers); |
1783 } | 1837 } |
1784 desc.set_value(table_instance.table_object); | 1838 desc.set_value(table_instance.table_object); |
1785 break; | 1839 break; |
1786 } | 1840 } |
1787 case kExternalMemory: { | 1841 case kExternalMemory: { |
1788 // Export the memory as a WebAssembly.Memory object. | 1842 // Export the memory as a WebAssembly.Memory object. |
1789 Handle<WasmMemoryObject> memory_object; | 1843 Handle<WasmMemoryObject> memory_object; |
1790 if (!instance->has_memory_object()) { | 1844 if (!instance->has_memory_object()) { |
1791 // If there was no imported WebAssembly.Memory object, create one. | 1845 // If there was no imported WebAssembly.Memory object, create one. |
1792 Handle<JSArrayBuffer> buffer(instance->get_memory_buffer(), | 1846 Handle<JSArrayBuffer> buffer(instance->memory_buffer(), isolate_); |
1793 isolate_); | |
1794 memory_object = WasmMemoryObject::New( | 1847 memory_object = WasmMemoryObject::New( |
1795 isolate_, buffer, | 1848 isolate_, buffer, |
1796 (module_->max_mem_pages != 0) ? module_->max_mem_pages : -1); | 1849 (module_->max_mem_pages != 0) ? module_->max_mem_pages : -1); |
1797 instance->set_memory_object(*memory_object); | 1850 instance->set_memory_object(*memory_object); |
1798 } else { | 1851 } else { |
1799 memory_object = Handle<WasmMemoryObject>( | 1852 memory_object = |
1800 instance->get_memory_object(), isolate_); | 1853 Handle<WasmMemoryObject>(instance->memory_object(), isolate_); |
1801 DCHECK(WasmJs::IsWasmMemoryObject(isolate_, memory_object)); | 1854 DCHECK(WasmJs::IsWasmMemoryObject(isolate_, memory_object)); |
1802 memory_object->ResetInstancesLink(isolate_); | 1855 memory_object->ResetInstancesLink(isolate_); |
1803 } | 1856 } |
1804 | 1857 |
1805 desc.set_value(memory_object); | 1858 desc.set_value(memory_object); |
1806 break; | 1859 break; |
1807 } | 1860 } |
1808 case kExternalGlobal: { | 1861 case kExternalGlobal: { |
1809 // Export the value of the global variable as a number. | 1862 // Export the value of the global variable as a number. |
1810 WasmGlobal& global = module_->globals[exp.index]; | 1863 WasmGlobal& global = module_->globals[exp.index]; |
(...skipping 167 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1978 WasmInstanceBuilder builder(isolate, thrower, wasm_module, ffi, memory); | 2031 WasmInstanceBuilder builder(isolate, thrower, wasm_module, ffi, memory); |
1979 return builder.Build(); | 2032 return builder.Build(); |
1980 } | 2033 } |
1981 | 2034 |
1982 bool wasm::IsWasmInstance(Object* object) { | 2035 bool wasm::IsWasmInstance(Object* object) { |
1983 return WasmInstanceObject::IsWasmInstanceObject(object); | 2036 return WasmInstanceObject::IsWasmInstanceObject(object); |
1984 } | 2037 } |
1985 | 2038 |
1986 Handle<Script> wasm::GetScript(Handle<JSObject> instance) { | 2039 Handle<Script> wasm::GetScript(Handle<JSObject> instance) { |
1987 WasmCompiledModule* compiled_module = | 2040 WasmCompiledModule* compiled_module = |
1988 WasmInstanceObject::cast(*instance)->get_compiled_module(); | 2041 WasmInstanceObject::cast(*instance)->compiled_module(); |
1989 DCHECK(compiled_module->has_script()); | 2042 return handle(compiled_module->script()); |
1990 return compiled_module->script(); | |
1991 } | |
1992 | |
1993 Handle<WasmDebugInfo> wasm::GetDebugInfo(Handle<JSObject> object) { | |
1994 auto instance = Handle<WasmInstanceObject>::cast(object); | |
1995 if (instance->has_debug_info()) { | |
1996 Handle<WasmDebugInfo> info(instance->get_debug_info(), | |
1997 instance->GetIsolate()); | |
1998 return info; | |
1999 } | |
2000 Handle<WasmDebugInfo> new_info = WasmDebugInfo::New(instance); | |
2001 instance->set_debug_info(*new_info); | |
2002 return new_info; | |
2003 } | 2043 } |
2004 | 2044 |
2005 // TODO(clemensh): origin can be inferred from asm_js_script; remove it. | 2045 // TODO(clemensh): origin can be inferred from asm_js_script; remove it. |
2006 MaybeHandle<WasmModuleObject> wasm::CreateModuleObjectFromBytes( | 2046 MaybeHandle<WasmModuleObject> wasm::CreateModuleObjectFromBytes( |
2007 Isolate* isolate, const byte* start, const byte* end, ErrorThrower* thrower, | 2047 Isolate* isolate, const byte* start, const byte* end, ErrorThrower* thrower, |
2008 ModuleOrigin origin, Handle<Script> asm_js_script, | 2048 ModuleOrigin origin, Handle<Script> asm_js_script, |
2009 const byte* asm_js_offset_tables_start, | 2049 Vector<const byte> asm_js_offset_table_bytes) { |
2010 const byte* asm_js_offset_tables_end) { | |
2011 MaybeHandle<WasmModuleObject> nothing; | 2050 MaybeHandle<WasmModuleObject> nothing; |
2012 ModuleResult result = DecodeWasmModule(isolate, start, end, false, origin); | 2051 ModuleResult result = DecodeWasmModule(isolate, start, end, false, origin); |
2013 if (result.failed()) { | 2052 if (result.failed()) { |
2014 if (result.val) delete result.val; | 2053 if (result.val) delete result.val; |
2015 thrower->CompileFailed("Wasm decoding failed", result); | 2054 thrower->CompileFailed("Wasm decoding failed", result); |
2016 return nothing; | 2055 return nothing; |
2017 } | 2056 } |
2018 | 2057 |
2019 // The {module_wrapper} will take ownership of the {WasmModule} object, | 2058 // The {module_wrapper} will take ownership of the {WasmModule} object, |
2020 // and it will be destroyed when the GC reclaims the wrapper object. | 2059 // and it will be destroyed when the GC reclaims the wrapper object. |
2021 Handle<WasmModuleWrapper> module_wrapper = | 2060 Handle<WasmModuleWrapper> module_wrapper = |
2022 WasmModuleWrapper::New(isolate, const_cast<WasmModule*>(result.val)); | 2061 WasmModuleWrapper::New(isolate, const_cast<WasmModule*>(result.val)); |
2023 | 2062 |
2024 // Compile the functions of the module, producing a compiled module. | 2063 // Compile the functions of the module, producing a compiled module. |
2025 MaybeHandle<WasmCompiledModule> maybe_compiled_module = | 2064 MaybeHandle<WasmCompiledModule> maybe_compiled_module = |
2026 result.val->CompileFunctions(isolate, module_wrapper, thrower, | 2065 result.val->CompileFunctions(isolate, module_wrapper, thrower, |
2027 ModuleWireBytes(start, end)); | 2066 ModuleWireBytes(start, end), asm_js_script, |
| 2067 asm_js_offset_table_bytes); |
2028 | 2068 |
2029 if (maybe_compiled_module.is_null()) return nothing; | 2069 if (maybe_compiled_module.is_null()) return nothing; |
2030 | 2070 |
2031 Handle<WasmCompiledModule> compiled_module = | 2071 Handle<WasmCompiledModule> compiled_module = |
2032 maybe_compiled_module.ToHandleChecked(); | 2072 maybe_compiled_module.ToHandleChecked(); |
2033 | 2073 |
2034 DCHECK_EQ(origin == kAsmJsOrigin, !asm_js_script.is_null()); | |
2035 DCHECK(!compiled_module->has_script()); | |
2036 DCHECK(!compiled_module->has_asm_js_offset_table()); | |
2037 if (origin == kAsmJsOrigin) { | |
2038 // Set script for the asm.js source, and the offset table mapping wasm byte | |
2039 // offsets to source positions. | |
2040 compiled_module->set_script(asm_js_script); | |
2041 size_t offset_table_len = | |
2042 asm_js_offset_tables_end - asm_js_offset_tables_start; | |
2043 DCHECK_GE(kMaxInt, offset_table_len); | |
2044 Handle<ByteArray> offset_table = | |
2045 isolate->factory()->NewByteArray(static_cast<int>(offset_table_len)); | |
2046 memcpy(offset_table->GetDataStartAddress(), asm_js_offset_tables_start, | |
2047 offset_table_len); | |
2048 compiled_module->set_asm_js_offset_table(offset_table); | |
2049 } else { | |
2050 // Create a new Script object representing this wasm module, store it in the | |
2051 // compiled wasm module, and register it at the debugger. | |
2052 Handle<Script> script = | |
2053 isolate->factory()->NewScript(isolate->factory()->empty_string()); | |
2054 script->set_type(Script::TYPE_WASM); | |
2055 | |
2056 DCHECK_GE(kMaxInt, end - start); | |
2057 int hash = StringHasher::HashSequentialString( | |
2058 reinterpret_cast<const char*>(start), static_cast<int>(end - start), | |
2059 kZeroHashSeed); | |
2060 | |
2061 const int kBufferSize = 50; | |
2062 char buffer[kBufferSize]; | |
2063 int url_chars = SNPrintF(ArrayVector(buffer), "wasm://wasm/%08x", hash); | |
2064 DCHECK(url_chars >= 0 && url_chars < kBufferSize); | |
2065 MaybeHandle<String> url_str = isolate->factory()->NewStringFromOneByte( | |
2066 Vector<const uint8_t>(reinterpret_cast<uint8_t*>(buffer), url_chars), | |
2067 TENURED); | |
2068 script->set_source_url(*url_str.ToHandleChecked()); | |
2069 | |
2070 int name_chars = SNPrintF(ArrayVector(buffer), "wasm-%08x", hash); | |
2071 DCHECK(name_chars >= 0 && name_chars < kBufferSize); | |
2072 MaybeHandle<String> name_str = isolate->factory()->NewStringFromOneByte( | |
2073 Vector<const uint8_t>(reinterpret_cast<uint8_t*>(buffer), name_chars), | |
2074 TENURED); | |
2075 script->set_name(*name_str.ToHandleChecked()); | |
2076 | |
2077 script->set_wasm_compiled_module(*compiled_module); | |
2078 compiled_module->set_script(script); | |
2079 isolate->debug()->OnAfterCompile(script); | |
2080 } | |
2081 | |
2082 return WasmModuleObject::New(isolate, compiled_module); | 2074 return WasmModuleObject::New(isolate, compiled_module); |
2083 } | 2075 } |
2084 | 2076 |
2085 bool wasm::ValidateModuleBytes(Isolate* isolate, const byte* start, | 2077 bool wasm::ValidateModuleBytes(Isolate* isolate, const byte* start, |
2086 const byte* end, ErrorThrower* thrower, | 2078 const byte* end, ErrorThrower* thrower, |
2087 ModuleOrigin origin) { | 2079 ModuleOrigin origin) { |
2088 ModuleResult result = DecodeWasmModule(isolate, start, end, true, origin); | 2080 ModuleResult result = DecodeWasmModule(isolate, start, end, true, origin); |
2089 if (result.val) { | 2081 if (result.val) { |
2090 delete result.val; | 2082 delete result.val; |
2091 } else { | 2083 } else { |
2092 DCHECK(!result.ok()); | 2084 DCHECK(!result.ok()); |
2093 } | 2085 } |
2094 return result.ok(); | 2086 return result.ok(); |
2095 } | 2087 } |
2096 | 2088 |
2097 MaybeHandle<JSArrayBuffer> wasm::GetInstanceMemory( | 2089 MaybeHandle<JSArrayBuffer> wasm::GetInstanceMemory( |
2098 Isolate* isolate, Handle<WasmInstanceObject> object) { | 2090 Isolate* isolate, Handle<WasmInstanceObject> object) { |
2099 auto instance = Handle<WasmInstanceObject>::cast(object); | 2091 auto instance = Handle<WasmInstanceObject>::cast(object); |
2100 if (instance->has_memory_buffer()) { | 2092 if (instance->has_memory_buffer()) { |
2101 return Handle<JSArrayBuffer>(instance->get_memory_buffer(), isolate); | 2093 return Handle<JSArrayBuffer>(instance->memory_buffer(), isolate); |
2102 } | 2094 } |
2103 return MaybeHandle<JSArrayBuffer>(); | 2095 return MaybeHandle<JSArrayBuffer>(); |
2104 } | 2096 } |
2105 | 2097 |
2106 void SetInstanceMemory(Handle<WasmInstanceObject> instance, | 2098 void SetInstanceMemory(Handle<WasmInstanceObject> instance, |
2107 JSArrayBuffer* buffer) { | 2099 JSArrayBuffer* buffer) { |
2108 DisallowHeapAllocation no_gc; | 2100 DisallowHeapAllocation no_gc; |
2109 instance->set_memory_buffer(buffer); | 2101 instance->set_memory_buffer(buffer); |
2110 instance->get_compiled_module()->set_ptr_to_memory(buffer); | 2102 instance->compiled_module()->set_ptr_to_memory(buffer); |
2111 } | 2103 } |
2112 | 2104 |
2113 int32_t wasm::GetInstanceMemorySize(Isolate* isolate, | 2105 int32_t wasm::GetInstanceMemorySize(Isolate* isolate, |
2114 Handle<WasmInstanceObject> instance) { | 2106 Handle<WasmInstanceObject> instance) { |
2115 DCHECK(IsWasmInstance(*instance)); | 2107 DCHECK(IsWasmInstance(*instance)); |
2116 MaybeHandle<JSArrayBuffer> maybe_mem_buffer = | 2108 MaybeHandle<JSArrayBuffer> maybe_mem_buffer = |
2117 GetInstanceMemory(isolate, instance); | 2109 GetInstanceMemory(isolate, instance); |
2118 Handle<JSArrayBuffer> buffer; | 2110 Handle<JSArrayBuffer> buffer; |
2119 if (!maybe_mem_buffer.ToHandle(&buffer)) { | 2111 if (!maybe_mem_buffer.ToHandle(&buffer)) { |
2120 return 0; | 2112 return 0; |
2121 } else { | 2113 } else { |
2122 return buffer->byte_length()->Number() / WasmModule::kPageSize; | 2114 return buffer->byte_length()->Number() / WasmModule::kPageSize; |
2123 } | 2115 } |
2124 } | 2116 } |
2125 | 2117 |
2126 uint32_t GetMaxInstanceMemorySize(Isolate* isolate, | 2118 uint32_t GetMaxInstanceMemorySize(Isolate* isolate, |
2127 Handle<WasmInstanceObject> instance) { | 2119 Handle<WasmInstanceObject> instance) { |
2128 if (instance->has_memory_object()) { | 2120 if (instance->has_memory_object()) { |
2129 Handle<WasmMemoryObject> memory_object(instance->get_memory_object(), | 2121 Handle<WasmMemoryObject> memory_object(instance->memory_object(), isolate); |
2130 isolate); | |
2131 | 2122 |
2132 int maximum = memory_object->maximum_pages(); | 2123 int maximum = memory_object->maximum_pages(); |
2133 if (maximum > 0) return static_cast<uint32_t>(maximum); | 2124 if (maximum > 0) return static_cast<uint32_t>(maximum); |
2134 } | 2125 } |
2135 uint32_t compiled_max_pages = | 2126 uint32_t compiled_max_pages = instance->compiled_module()->max_mem_pages(); |
2136 instance->get_compiled_module()->max_mem_pages(); | |
2137 isolate->counters()->wasm_max_mem_pages_count()->AddSample( | 2127 isolate->counters()->wasm_max_mem_pages_count()->AddSample( |
2138 compiled_max_pages); | 2128 compiled_max_pages); |
2139 if (compiled_max_pages != 0) return compiled_max_pages; | 2129 if (compiled_max_pages != 0) return compiled_max_pages; |
2140 return kV8MaxWasmMemoryPages; | 2130 return kV8MaxWasmMemoryPages; |
2141 } | 2131 } |
2142 | 2132 |
2143 Handle<JSArrayBuffer> GrowMemoryBuffer(Isolate* isolate, | 2133 Handle<JSArrayBuffer> GrowMemoryBuffer(Isolate* isolate, |
2144 MaybeHandle<JSArrayBuffer> buffer, | 2134 MaybeHandle<JSArrayBuffer> buffer, |
2145 uint32_t pages, uint32_t max_pages) { | 2135 uint32_t pages, uint32_t max_pages) { |
2146 Handle<JSArrayBuffer> old_buffer; | 2136 Handle<JSArrayBuffer> old_buffer; |
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2179 memcpy(new_mem_start, old_mem_start, old_size); | 2169 memcpy(new_mem_start, old_mem_start, old_size); |
2180 } | 2170 } |
2181 } | 2171 } |
2182 return new_buffer; | 2172 return new_buffer; |
2183 } | 2173 } |
2184 | 2174 |
2185 void UncheckedUpdateInstanceMemory(Isolate* isolate, | 2175 void UncheckedUpdateInstanceMemory(Isolate* isolate, |
2186 Handle<WasmInstanceObject> instance, | 2176 Handle<WasmInstanceObject> instance, |
2187 Address old_mem_start, uint32_t old_size) { | 2177 Address old_mem_start, uint32_t old_size) { |
2188 DCHECK(instance->has_memory_buffer()); | 2178 DCHECK(instance->has_memory_buffer()); |
2189 Handle<JSArrayBuffer> new_buffer(instance->get_memory_buffer()); | 2179 Handle<JSArrayBuffer> new_buffer(instance->memory_buffer()); |
2190 uint32_t new_size = new_buffer->byte_length()->Number(); | 2180 uint32_t new_size = new_buffer->byte_length()->Number(); |
2191 DCHECK(new_size <= std::numeric_limits<uint32_t>::max()); | 2181 DCHECK(new_size <= std::numeric_limits<uint32_t>::max()); |
2192 Address new_mem_start = static_cast<Address>(new_buffer->backing_store()); | 2182 Address new_mem_start = static_cast<Address>(new_buffer->backing_store()); |
2193 DCHECK_NOT_NULL(new_mem_start); | 2183 DCHECK_NOT_NULL(new_mem_start); |
2194 Handle<FixedArray> code_table = instance->get_compiled_module()->code_table(); | 2184 Handle<FixedArray> code_table = instance->compiled_module()->code_table(); |
2195 RelocateMemoryReferencesInCode(code_table, old_mem_start, new_mem_start, | 2185 RelocateMemoryReferencesInCode(code_table, old_mem_start, new_mem_start, |
2196 old_size, new_size); | 2186 old_size, new_size); |
2197 } | 2187 } |
2198 | 2188 |
2199 int32_t wasm::GrowWebAssemblyMemory(Isolate* isolate, Handle<Object> receiver, | 2189 int32_t wasm::GrowWebAssemblyMemory(Isolate* isolate, Handle<Object> receiver, |
2200 uint32_t pages) { | 2190 uint32_t pages) { |
2201 DCHECK(WasmJs::IsWasmMemoryObject(isolate, receiver)); | 2191 DCHECK(WasmJs::IsWasmMemoryObject(isolate, receiver)); |
2202 Handle<WasmMemoryObject> memory_object = | 2192 Handle<WasmMemoryObject> memory_object = |
2203 handle(WasmMemoryObject::cast(*receiver)); | 2193 handle(WasmMemoryObject::cast(*receiver)); |
2204 Handle<WasmInstanceWrapper> instance_wrapper( | 2194 Handle<WasmInstanceWrapper> instance_wrapper(memory_object->instances_link()); |
2205 memory_object->get_instances_link()); | |
2206 DCHECK(WasmInstanceWrapper::IsWasmInstanceWrapper(*instance_wrapper)); | 2195 DCHECK(WasmInstanceWrapper::IsWasmInstanceWrapper(*instance_wrapper)); |
2207 DCHECK(instance_wrapper->has_instance()); | 2196 DCHECK(instance_wrapper->has_instance()); |
2208 Handle<WasmInstanceObject> instance = instance_wrapper->instance_object(); | 2197 Handle<WasmInstanceObject> instance = instance_wrapper->instance_object(); |
2209 DCHECK(IsWasmInstance(*instance)); | 2198 DCHECK(IsWasmInstance(*instance)); |
2210 if (pages == 0) return GetInstanceMemorySize(isolate, instance); | 2199 if (pages == 0) return GetInstanceMemorySize(isolate, instance); |
2211 uint32_t max_pages = GetMaxInstanceMemorySize(isolate, instance); | 2200 uint32_t max_pages = GetMaxInstanceMemorySize(isolate, instance); |
2212 | 2201 |
2213 // Grow memory object buffer and update instances associated with it. | 2202 // Grow memory object buffer and update instances associated with it. |
2214 MaybeHandle<JSArrayBuffer> memory_buffer = | 2203 MaybeHandle<JSArrayBuffer> memory_buffer = handle(memory_object->buffer()); |
2215 handle(memory_object->get_buffer()); | |
2216 Handle<JSArrayBuffer> old_buffer; | 2204 Handle<JSArrayBuffer> old_buffer; |
2217 uint32_t old_size = 0; | 2205 uint32_t old_size = 0; |
2218 Address old_mem_start = nullptr; | 2206 Address old_mem_start = nullptr; |
2219 if (memory_buffer.ToHandle(&old_buffer) && | 2207 if (memory_buffer.ToHandle(&old_buffer) && |
2220 old_buffer->backing_store() != nullptr) { | 2208 old_buffer->backing_store() != nullptr) { |
2221 old_size = old_buffer->byte_length()->Number(); | 2209 old_size = old_buffer->byte_length()->Number(); |
2222 old_mem_start = static_cast<Address>(old_buffer->backing_store()); | 2210 old_mem_start = static_cast<Address>(old_buffer->backing_store()); |
2223 } | 2211 } |
2224 Handle<JSArrayBuffer> new_buffer = | 2212 Handle<JSArrayBuffer> new_buffer = |
2225 GrowMemoryBuffer(isolate, memory_buffer, pages, max_pages); | 2213 GrowMemoryBuffer(isolate, memory_buffer, pages, max_pages); |
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2259 } | 2247 } |
2260 uint32_t max_pages = GetMaxInstanceMemorySize(isolate, instance_obj); | 2248 uint32_t max_pages = GetMaxInstanceMemorySize(isolate, instance_obj); |
2261 Handle<JSArrayBuffer> buffer = | 2249 Handle<JSArrayBuffer> buffer = |
2262 GrowMemoryBuffer(isolate, instance_buffer, pages, max_pages); | 2250 GrowMemoryBuffer(isolate, instance_buffer, pages, max_pages); |
2263 if (buffer.is_null()) return -1; | 2251 if (buffer.is_null()) return -1; |
2264 SetInstanceMemory(instance, *buffer); | 2252 SetInstanceMemory(instance, *buffer); |
2265 UncheckedUpdateInstanceMemory(isolate, instance, old_mem_start, old_size); | 2253 UncheckedUpdateInstanceMemory(isolate, instance, old_mem_start, old_size); |
2266 DCHECK(old_size % WasmModule::kPageSize == 0); | 2254 DCHECK(old_size % WasmModule::kPageSize == 0); |
2267 return (old_size / WasmModule::kPageSize); | 2255 return (old_size / WasmModule::kPageSize); |
2268 } else { | 2256 } else { |
2269 return GrowWebAssemblyMemory( | 2257 return GrowWebAssemblyMemory(isolate, handle(instance_obj->memory_object()), |
2270 isolate, handle(instance_obj->get_memory_object()), pages); | 2258 pages); |
2271 } | 2259 } |
2272 } | 2260 } |
2273 | 2261 |
2274 void testing::ValidateInstancesChain(Isolate* isolate, | 2262 void testing::ValidateInstancesChain(Isolate* isolate, |
2275 Handle<WasmModuleObject> module_obj, | 2263 Handle<WasmModuleObject> module_obj, |
2276 int instance_count) { | 2264 int instance_count) { |
2277 CHECK_GE(instance_count, 0); | 2265 CHECK_GE(instance_count, 0); |
2278 DisallowHeapAllocation no_gc; | 2266 DisallowHeapAllocation no_gc; |
2279 WasmCompiledModule* compiled_module = module_obj->get_compiled_module(); | 2267 WasmCompiledModule* compiled_module = module_obj->compiled_module(); |
2280 CHECK_EQ(JSObject::cast(compiled_module->ptr_to_weak_wasm_module()->value()), | 2268 CHECK_EQ(JSObject::cast(compiled_module->ptr_to_weak_wasm_module()->value()), |
2281 *module_obj); | 2269 *module_obj); |
2282 Object* prev = nullptr; | 2270 Object* prev = nullptr; |
2283 int found_instances = compiled_module->has_weak_owning_instance() ? 1 : 0; | 2271 int found_instances = compiled_module->has_weak_owning_instance() ? 1 : 0; |
2284 WasmCompiledModule* current_instance = compiled_module; | 2272 WasmCompiledModule* current_instance = compiled_module; |
2285 while (current_instance->has_weak_next_instance()) { | 2273 while (current_instance->has_weak_next_instance()) { |
2286 CHECK((prev == nullptr && !current_instance->has_weak_prev_instance()) || | 2274 CHECK((prev == nullptr && !current_instance->has_weak_prev_instance()) || |
2287 current_instance->ptr_to_weak_prev_instance()->value() == prev); | 2275 current_instance->ptr_to_weak_prev_instance()->value() == prev); |
2288 CHECK_EQ(current_instance->ptr_to_weak_wasm_module()->value(), *module_obj); | 2276 CHECK_EQ(current_instance->ptr_to_weak_wasm_module()->value(), *module_obj); |
2289 CHECK(IsWasmInstance( | 2277 CHECK(IsWasmInstance( |
2290 current_instance->ptr_to_weak_owning_instance()->value())); | 2278 current_instance->ptr_to_weak_owning_instance()->value())); |
2291 prev = current_instance; | 2279 prev = current_instance; |
2292 current_instance = WasmCompiledModule::cast( | 2280 current_instance = WasmCompiledModule::cast( |
2293 current_instance->ptr_to_weak_next_instance()->value()); | 2281 current_instance->ptr_to_weak_next_instance()->value()); |
2294 ++found_instances; | 2282 ++found_instances; |
2295 CHECK_LE(found_instances, instance_count); | 2283 CHECK_LE(found_instances, instance_count); |
2296 } | 2284 } |
2297 CHECK_EQ(found_instances, instance_count); | 2285 CHECK_EQ(found_instances, instance_count); |
2298 } | 2286 } |
2299 | 2287 |
2300 void testing::ValidateModuleState(Isolate* isolate, | 2288 void testing::ValidateModuleState(Isolate* isolate, |
2301 Handle<WasmModuleObject> module_obj) { | 2289 Handle<WasmModuleObject> module_obj) { |
2302 DisallowHeapAllocation no_gc; | 2290 DisallowHeapAllocation no_gc; |
2303 WasmCompiledModule* compiled_module = module_obj->get_compiled_module(); | 2291 WasmCompiledModule* compiled_module = module_obj->compiled_module(); |
2304 CHECK(compiled_module->has_weak_wasm_module()); | 2292 CHECK(compiled_module->has_weak_wasm_module()); |
2305 CHECK_EQ(compiled_module->ptr_to_weak_wasm_module()->value(), *module_obj); | 2293 CHECK_EQ(compiled_module->ptr_to_weak_wasm_module()->value(), *module_obj); |
2306 CHECK(!compiled_module->has_weak_prev_instance()); | 2294 CHECK(!compiled_module->has_weak_prev_instance()); |
2307 CHECK(!compiled_module->has_weak_next_instance()); | 2295 CHECK(!compiled_module->has_weak_next_instance()); |
2308 CHECK(!compiled_module->has_weak_owning_instance()); | 2296 CHECK(!compiled_module->has_weak_owning_instance()); |
2309 } | 2297 } |
2310 | 2298 |
2311 void testing::ValidateOrphanedInstance(Isolate* isolate, | 2299 void testing::ValidateOrphanedInstance(Isolate* isolate, |
2312 Handle<WasmInstanceObject> instance) { | 2300 Handle<WasmInstanceObject> instance) { |
2313 DisallowHeapAllocation no_gc; | 2301 DisallowHeapAllocation no_gc; |
2314 WasmCompiledModule* compiled_module = instance->get_compiled_module(); | 2302 WasmCompiledModule* compiled_module = instance->compiled_module(); |
2315 CHECK(compiled_module->has_weak_wasm_module()); | 2303 CHECK(compiled_module->has_weak_wasm_module()); |
2316 CHECK(compiled_module->ptr_to_weak_wasm_module()->cleared()); | 2304 CHECK(compiled_module->ptr_to_weak_wasm_module()->cleared()); |
2317 } | 2305 } |
OLD | NEW |