OLD | NEW |
1 // Copyright 2017 the V8 project authors. All rights reserved. | 1 // Copyright 2017 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/wasm/module-compiler.h> | 5 #include <src/wasm/module-compiler.h> |
6 | 6 |
7 #include <atomic> | 7 #include <atomic> |
8 | 8 |
9 #include "src/asmjs/asm-js.h" | 9 #include "src/asmjs/asm-js.h" |
10 #include "src/assembler-inl.h" | 10 #include "src/assembler-inl.h" |
(...skipping 67 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
78 size_t index = (size_t)(factor * schedule_.size()); | 78 size_t index = (size_t)(factor * schedule_.size()); |
79 DCHECK_GE(index, 0); | 79 DCHECK_GE(index, 0); |
80 DCHECK_LT(index, schedule_.size()); | 80 DCHECK_LT(index, schedule_.size()); |
81 return index; | 81 return index; |
82 } | 82 } |
83 | 83 |
84 ModuleCompiler::ModuleCompiler(Isolate* isolate, | 84 ModuleCompiler::ModuleCompiler(Isolate* isolate, |
85 std::unique_ptr<WasmModule> module, bool is_sync) | 85 std::unique_ptr<WasmModule> module, bool is_sync) |
86 : isolate_(isolate), | 86 : isolate_(isolate), |
87 module_(std::move(module)), | 87 module_(std::move(module)), |
88 counters_shared_(isolate->counters_shared()), | 88 async_counters_(isolate->async_counters()), |
89 is_sync_(is_sync), | 89 is_sync_(is_sync), |
90 executed_units_( | 90 executed_units_( |
91 isolate->random_number_generator(), | 91 isolate->random_number_generator(), |
92 (isolate->heap()->memory_allocator()->code_range()->valid() | 92 (isolate->heap()->memory_allocator()->code_range()->valid() |
93 ? isolate->heap()->memory_allocator()->code_range()->size() | 93 ? isolate->heap()->memory_allocator()->code_range()->size() |
94 : isolate->heap()->code_space()->Capacity()) / | 94 : isolate->heap()->code_space()->Capacity()) / |
95 2), | 95 2), |
96 num_background_tasks_( | 96 num_background_tasks_( |
97 Min(static_cast<size_t>(FLAG_wasm_num_compilation_tasks), | 97 Min(static_cast<size_t>(FLAG_wasm_num_compilation_tasks), |
98 V8::GetCurrentPlatform()->NumberOfAvailableBackgroundThreads())), | 98 V8::GetCurrentPlatform()->NumberOfAvailableBackgroundThreads())), |
99 stopped_compilation_tasks_(num_background_tasks_) { | 99 stopped_compilation_tasks_(num_background_tasks_) {} |
100 counters_ = counters_shared_.get(); | |
101 } | |
102 | 100 |
103 bool ModuleCompiler::GetNextUncompiledFunctionId(size_t* index) { | 101 bool ModuleCompiler::GetNextUncompiledFunctionId(size_t* index) { |
104 DCHECK_NOT_NULL(index); | 102 DCHECK_NOT_NULL(index); |
105 // - 1 because AtomicIncrement returns the value after the atomic increment. | 103 // - 1 because AtomicIncrement returns the value after the atomic increment. |
106 *index = next_unit_.Increment(1) - 1; | 104 *index = next_unit_.Increment(1) - 1; |
107 return *index < compilation_units_.size(); | 105 return *index < compilation_units_.size(); |
108 } | 106 } |
109 | 107 |
110 // The actual runnable task that performs compilations in the background. | 108 // The actual runnable task that performs compilations in the background. |
111 ModuleCompiler::CompilationTask::CompilationTask(ModuleCompiler* compiler) | 109 ModuleCompiler::CompilationTask::CompilationTask(ModuleCompiler* compiler) |
(...skipping 65 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
177 | 175 |
178 size_t ModuleCompiler::InitializeParallelCompilation( | 176 size_t ModuleCompiler::InitializeParallelCompilation( |
179 const std::vector<WasmFunction>& functions, ModuleBytesEnv& module_env) { | 177 const std::vector<WasmFunction>& functions, ModuleBytesEnv& module_env) { |
180 uint32_t start = module_env.module_env.module->num_imported_functions + | 178 uint32_t start = module_env.module_env.module->num_imported_functions + |
181 FLAG_skip_compiling_wasm_funcs; | 179 FLAG_skip_compiling_wasm_funcs; |
182 uint32_t num_funcs = static_cast<uint32_t>(functions.size()); | 180 uint32_t num_funcs = static_cast<uint32_t>(functions.size()); |
183 uint32_t funcs_to_compile = start > num_funcs ? 0 : num_funcs - start; | 181 uint32_t funcs_to_compile = start > num_funcs ? 0 : num_funcs - start; |
184 compilation_units_.reserve(funcs_to_compile); | 182 compilation_units_.reserve(funcs_to_compile); |
185 for (uint32_t i = start; i < num_funcs; ++i) { | 183 for (uint32_t i = start; i < num_funcs; ++i) { |
186 const WasmFunction* func = &functions[i]; | 184 const WasmFunction* func = &functions[i]; |
187 constexpr bool is_sync = true; | |
188 compilation_units_.push_back(std::unique_ptr<compiler::WasmCompilationUnit>( | 185 compilation_units_.push_back(std::unique_ptr<compiler::WasmCompilationUnit>( |
189 new compiler::WasmCompilationUnit(isolate_, &module_env, func, | 186 new compiler::WasmCompilationUnit(isolate_, &module_env, func))); |
190 !is_sync))); | |
191 } | 187 } |
192 return funcs_to_compile; | 188 return funcs_to_compile; |
193 } | 189 } |
194 | 190 |
195 void ModuleCompiler::RestartCompilationTasks() { | 191 void ModuleCompiler::RestartCompilationTasks() { |
196 base::LockGuard<base::Mutex> guard(&tasks_mutex_); | 192 base::LockGuard<base::Mutex> guard(&tasks_mutex_); |
197 for (; stopped_compilation_tasks_ > 0; --stopped_compilation_tasks_) { | 193 for (; stopped_compilation_tasks_ > 0; --stopped_compilation_tasks_) { |
198 V8::GetCurrentPlatform()->CallOnBackgroundThread( | 194 V8::GetCurrentPlatform()->CallOnBackgroundThread( |
199 new CompilationTask(this), | 195 new CompilationTask(this), |
200 v8::Platform::ExpectedRuntime::kShortRunningTask); | 196 v8::Platform::ExpectedRuntime::kShortRunningTask); |
(...skipping 157 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
358 Handle<FixedArray> function_tables = | 354 Handle<FixedArray> function_tables = |
359 factory->NewFixedArray(function_table_count, TENURED); | 355 factory->NewFixedArray(function_table_count, TENURED); |
360 Handle<FixedArray> signature_tables = | 356 Handle<FixedArray> signature_tables = |
361 factory->NewFixedArray(function_table_count, TENURED); | 357 factory->NewFixedArray(function_table_count, TENURED); |
362 for (int i = 0; i < function_table_count; ++i) { | 358 for (int i = 0; i < function_table_count; ++i) { |
363 temp_instance.function_tables[i] = factory->NewFixedArray(1, TENURED); | 359 temp_instance.function_tables[i] = factory->NewFixedArray(1, TENURED); |
364 temp_instance.signature_tables[i] = factory->NewFixedArray(1, TENURED); | 360 temp_instance.signature_tables[i] = factory->NewFixedArray(1, TENURED); |
365 function_tables->set(i, *temp_instance.function_tables[i]); | 361 function_tables->set(i, *temp_instance.function_tables[i]); |
366 signature_tables->set(i, *temp_instance.signature_tables[i]); | 362 signature_tables->set(i, *temp_instance.signature_tables[i]); |
367 } | 363 } |
368 | 364 TimedHistogramScope wasm_compile_module_time_scope( |
369 if (is_sync_) { | 365 module_->is_wasm() ? counters()->wasm_compile_wasm_module_time() |
370 // TODO(karlschimpf): Make this work when asynchronous. | 366 : counters()->wasm_compile_asm_module_time()); |
371 // https://bugs.chromium.org/p/v8/issues/detail?id=6361 | |
372 HistogramTimerScope wasm_compile_module_time_scope( | |
373 module_->is_wasm() | |
374 ? isolate_->counters()->wasm_compile_wasm_module_time() | |
375 : isolate_->counters()->wasm_compile_asm_module_time()); | |
376 return CompileToModuleObjectInternal( | |
377 thrower, wire_bytes, asm_js_script, asm_js_offset_table_bytes, factory, | |
378 &temp_instance, &function_tables, &signature_tables); | |
379 } | |
380 return CompileToModuleObjectInternal( | 367 return CompileToModuleObjectInternal( |
381 thrower, wire_bytes, asm_js_script, asm_js_offset_table_bytes, factory, | 368 thrower, wire_bytes, asm_js_script, asm_js_offset_table_bytes, factory, |
382 &temp_instance, &function_tables, &signature_tables); | 369 &temp_instance, &function_tables, &signature_tables); |
383 } | 370 } |
384 | 371 |
385 namespace { | 372 namespace { |
386 bool compile_lazy(const WasmModule* module) { | 373 bool compile_lazy(const WasmModule* module) { |
387 return FLAG_wasm_lazy_compilation || | 374 return FLAG_wasm_lazy_compilation || |
388 (FLAG_asm_wasm_lazy_compilation && module->is_asm_js()); | 375 (FLAG_asm_wasm_lazy_compilation && module->is_asm_js()); |
389 } | 376 } |
(...skipping 218 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
608 ? isolate_->builtins()->WasmCompileLazy() | 595 ? isolate_->builtins()->WasmCompileLazy() |
609 : isolate_->builtins()->Illegal(); | 596 : isolate_->builtins()->Illegal(); |
610 for (int i = 0, e = static_cast<int>(module_->functions.size()); i < e; ++i) { | 597 for (int i = 0, e = static_cast<int>(module_->functions.size()); i < e; ++i) { |
611 code_table->set(i, *init_builtin); | 598 code_table->set(i, *init_builtin); |
612 temp_instance->function_code[i] = init_builtin; | 599 temp_instance->function_code[i] = init_builtin; |
613 } | 600 } |
614 | 601 |
615 if (is_sync_) | 602 if (is_sync_) |
616 // TODO(karlschimpf): Make this work when asynchronous. | 603 // TODO(karlschimpf): Make this work when asynchronous. |
617 // https://bugs.chromium.org/p/v8/issues/detail?id=6361 | 604 // https://bugs.chromium.org/p/v8/issues/detail?id=6361 |
618 (module_->is_wasm() ? isolate_->counters()->wasm_functions_per_wasm_module() | 605 (module_->is_wasm() ? counters()->wasm_functions_per_wasm_module() |
619 : isolate_->counters()->wasm_functions_per_asm_module()) | 606 : counters()->wasm_functions_per_asm_module()) |
620 ->AddSample(static_cast<int>(module_->functions.size())); | 607 ->AddSample(static_cast<int>(module_->functions.size())); |
621 | 608 |
622 if (!lazy_compile) { | 609 if (!lazy_compile) { |
623 size_t funcs_to_compile = | 610 size_t funcs_to_compile = |
624 module_->functions.size() - module_->num_imported_functions; | 611 module_->functions.size() - module_->num_imported_functions; |
625 bool compile_parallel = | 612 bool compile_parallel = |
626 !FLAG_trace_wasm_decoder && FLAG_wasm_num_compilation_tasks > 0 && | 613 !FLAG_trace_wasm_decoder && FLAG_wasm_num_compilation_tasks > 0 && |
627 funcs_to_compile > 1 && | 614 funcs_to_compile > 1 && |
628 V8::GetCurrentPlatform()->NumberOfAvailableBackgroundThreads() > 0; | 615 V8::GetCurrentPlatform()->NumberOfAvailableBackgroundThreads() > 0; |
629 if (compile_parallel) { | 616 if (compile_parallel) { |
(...skipping 13 matching lines...) Expand all Loading... |
643 // (lazy) compilation time. | 630 // (lazy) compilation time. |
644 ValidateSequentially(&module_env, thrower); | 631 ValidateSequentially(&module_env, thrower); |
645 } | 632 } |
646 if (thrower->error()) return {}; | 633 if (thrower->error()) return {}; |
647 | 634 |
648 // At this point, compilation has completed. Update the code table. | 635 // At this point, compilation has completed. Update the code table. |
649 for (size_t i = FLAG_skip_compiling_wasm_funcs; | 636 for (size_t i = FLAG_skip_compiling_wasm_funcs; |
650 i < temp_instance->function_code.size(); ++i) { | 637 i < temp_instance->function_code.size(); ++i) { |
651 Code* code = *temp_instance->function_code[i]; | 638 Code* code = *temp_instance->function_code[i]; |
652 code_table->set(static_cast<int>(i), code); | 639 code_table->set(static_cast<int>(i), code); |
653 RecordStats(code, counters_); | 640 RecordStats(code, counters()); |
654 } | 641 } |
655 | 642 |
656 // Create heap objects for script, module bytes and asm.js offset table to | 643 // Create heap objects for script, module bytes and asm.js offset table to |
657 // be stored in the shared module data. | 644 // be stored in the shared module data. |
658 Handle<Script> script; | 645 Handle<Script> script; |
659 Handle<ByteArray> asm_js_offset_table; | 646 Handle<ByteArray> asm_js_offset_table; |
660 if (asm_js_script.is_null()) { | 647 if (asm_js_script.is_null()) { |
661 script = CreateWasmScript(isolate_, wire_bytes); | 648 script = CreateWasmScript(isolate_, wire_bytes); |
662 } else { | 649 } else { |
663 script = asm_js_script; | 650 script = asm_js_script; |
(...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
709 JSToWasmWrapperCache js_to_wasm_cache; | 696 JSToWasmWrapperCache js_to_wasm_cache; |
710 int func_index = 0; | 697 int func_index = 0; |
711 for (auto exp : module->export_table) { | 698 for (auto exp : module->export_table) { |
712 if (exp.kind != kExternalFunction) continue; | 699 if (exp.kind != kExternalFunction) continue; |
713 Handle<Code> wasm_code = EnsureExportedLazyDeoptData( | 700 Handle<Code> wasm_code = EnsureExportedLazyDeoptData( |
714 isolate_, Handle<WasmInstanceObject>::null(), code_table, exp.index); | 701 isolate_, Handle<WasmInstanceObject>::null(), code_table, exp.index); |
715 Handle<Code> wrapper_code = js_to_wasm_cache.CloneOrCompileJSToWasmWrapper( | 702 Handle<Code> wrapper_code = js_to_wasm_cache.CloneOrCompileJSToWasmWrapper( |
716 isolate_, module, wasm_code, exp.index); | 703 isolate_, module, wasm_code, exp.index); |
717 int export_index = static_cast<int>(module->functions.size() + func_index); | 704 int export_index = static_cast<int>(module->functions.size() + func_index); |
718 code_table->set(export_index, *wrapper_code); | 705 code_table->set(export_index, *wrapper_code); |
719 RecordStats(*wrapper_code, counters_); | 706 RecordStats(*wrapper_code, counters()); |
720 func_index++; | 707 func_index++; |
721 } | 708 } |
722 | 709 |
723 return WasmModuleObject::New(isolate_, compiled_module); | 710 return WasmModuleObject::New(isolate_, compiled_module); |
724 } | 711 } |
725 | 712 |
726 Handle<Code> JSToWasmWrapperCache::CloneOrCompileJSToWasmWrapper( | 713 Handle<Code> JSToWasmWrapperCache::CloneOrCompileJSToWasmWrapper( |
727 Isolate* isolate, const wasm::WasmModule* module, Handle<Code> wasm_code, | 714 Isolate* isolate, const wasm::WasmModule* module, Handle<Code> wasm_code, |
728 uint32_t index) { | 715 uint32_t index) { |
729 const wasm::WasmFunction* func = &module->functions[index]; | 716 const wasm::WasmFunction* func = &module->functions[index]; |
(...skipping 25 matching lines...) Expand all Loading... |
755 return code; | 742 return code; |
756 } | 743 } |
757 | 744 |
758 InstanceBuilder::InstanceBuilder( | 745 InstanceBuilder::InstanceBuilder( |
759 Isolate* isolate, ErrorThrower* thrower, | 746 Isolate* isolate, ErrorThrower* thrower, |
760 Handle<WasmModuleObject> module_object, MaybeHandle<JSReceiver> ffi, | 747 Handle<WasmModuleObject> module_object, MaybeHandle<JSReceiver> ffi, |
761 MaybeHandle<JSArrayBuffer> memory, | 748 MaybeHandle<JSArrayBuffer> memory, |
762 WeakCallbackInfo<void>::Callback instance_finalizer_callback) | 749 WeakCallbackInfo<void>::Callback instance_finalizer_callback) |
763 : isolate_(isolate), | 750 : isolate_(isolate), |
764 module_(module_object->compiled_module()->module()), | 751 module_(module_object->compiled_module()->module()), |
765 counters_shared_(isolate->counters_shared()), | 752 async_counters_(isolate->async_counters()), |
766 thrower_(thrower), | 753 thrower_(thrower), |
767 module_object_(module_object), | 754 module_object_(module_object), |
768 ffi_(ffi.is_null() ? Handle<JSReceiver>::null() : ffi.ToHandleChecked()), | 755 ffi_(ffi.is_null() ? Handle<JSReceiver>::null() : ffi.ToHandleChecked()), |
769 memory_(memory.is_null() ? Handle<JSArrayBuffer>::null() | 756 memory_(memory.is_null() ? Handle<JSArrayBuffer>::null() |
770 : memory.ToHandleChecked()), | 757 : memory.ToHandleChecked()), |
771 instance_finalizer_callback_(instance_finalizer_callback) { | 758 instance_finalizer_callback_(instance_finalizer_callback) {} |
772 counters_ = counters_shared_.get(); | |
773 } | |
774 | 759 |
775 // Build an instance, in all of its glory. | 760 // Build an instance, in all of its glory. |
776 MaybeHandle<WasmInstanceObject> InstanceBuilder::Build() { | 761 MaybeHandle<WasmInstanceObject> InstanceBuilder::Build() { |
777 // Check that an imports argument was provided, if the module requires it. | 762 // Check that an imports argument was provided, if the module requires it. |
778 // No point in continuing otherwise. | 763 // No point in continuing otherwise. |
779 if (!module_->import_table.empty() && ffi_.is_null()) { | 764 if (!module_->import_table.empty() && ffi_.is_null()) { |
780 thrower_->TypeError( | 765 thrower_->TypeError( |
781 "Imports argument must be present and must be an object"); | 766 "Imports argument must be present and must be an object"); |
782 return {}; | 767 return {}; |
783 } | 768 } |
784 | 769 |
785 // Record build time into correct bucket, then build instance. | 770 // Record build time into correct bucket, then build instance. |
786 HistogramTimerScope wasm_instantiate_module_time_scope( | 771 HistogramTimerScope wasm_instantiate_module_time_scope( |
787 module_->is_wasm() | 772 module_->is_wasm() ? counters()->wasm_instantiate_wasm_module_time() |
788 ? isolate_->counters()->wasm_instantiate_wasm_module_time() | 773 : counters()->wasm_instantiate_asm_module_time()); |
789 : isolate_->counters()->wasm_instantiate_asm_module_time()); | |
790 Factory* factory = isolate_->factory(); | 774 Factory* factory = isolate_->factory(); |
791 | 775 |
792 //-------------------------------------------------------------------------- | 776 //-------------------------------------------------------------------------- |
793 // Reuse the compiled module (if no owner), otherwise clone. | 777 // Reuse the compiled module (if no owner), otherwise clone. |
794 //-------------------------------------------------------------------------- | 778 //-------------------------------------------------------------------------- |
795 Handle<FixedArray> code_table; | 779 Handle<FixedArray> code_table; |
796 // We keep around a copy of the old code table, because we'll be replacing | 780 // We keep around a copy of the old code table, because we'll be replacing |
797 // imports for the new instance, and then we need the old imports to be | 781 // imports for the new instance, and then we need the old imports to be |
798 // able to relocate. | 782 // able to relocate. |
799 Handle<FixedArray> old_code_table; | 783 Handle<FixedArray> old_code_table; |
(...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
853 case Code::JS_TO_WASM_FUNCTION: | 837 case Code::JS_TO_WASM_FUNCTION: |
854 case Code::WASM_FUNCTION: { | 838 case Code::WASM_FUNCTION: { |
855 Handle<Code> code = factory->CopyCode(orig_code); | 839 Handle<Code> code = factory->CopyCode(orig_code); |
856 code_table->set(i, *code); | 840 code_table->set(i, *code); |
857 break; | 841 break; |
858 } | 842 } |
859 default: | 843 default: |
860 UNREACHABLE(); | 844 UNREACHABLE(); |
861 } | 845 } |
862 } | 846 } |
863 RecordStats(code_table, counters_); | 847 RecordStats(code_table, counters()); |
864 } else { | 848 } else { |
865 // There was no owner, so we can reuse the original. | 849 // There was no owner, so we can reuse the original. |
866 compiled_module_ = original; | 850 compiled_module_ = original; |
867 old_code_table = factory->CopyFixedArray(compiled_module_->code_table()); | 851 old_code_table = factory->CopyFixedArray(compiled_module_->code_table()); |
868 code_table = compiled_module_->code_table(); | 852 code_table = compiled_module_->code_table(); |
869 TRACE("Reusing existing instance %d\n", compiled_module_->instance_id()); | 853 TRACE("Reusing existing instance %d\n", compiled_module_->instance_id()); |
870 } | 854 } |
871 compiled_module_->set_native_context(isolate_->native_context()); | 855 compiled_module_->set_native_context(isolate_->native_context()); |
872 } | 856 } |
873 | 857 |
(...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
932 //-------------------------------------------------------------------------- | 916 //-------------------------------------------------------------------------- |
933 // Set up the indirect function tables for the new instance. | 917 // Set up the indirect function tables for the new instance. |
934 //-------------------------------------------------------------------------- | 918 //-------------------------------------------------------------------------- |
935 if (function_table_count > 0) | 919 if (function_table_count > 0) |
936 InitializeTables(instance, &code_specialization); | 920 InitializeTables(instance, &code_specialization); |
937 | 921 |
938 //-------------------------------------------------------------------------- | 922 //-------------------------------------------------------------------------- |
939 // Set up the memory for the new instance. | 923 // Set up the memory for the new instance. |
940 //-------------------------------------------------------------------------- | 924 //-------------------------------------------------------------------------- |
941 uint32_t min_mem_pages = module_->min_mem_pages; | 925 uint32_t min_mem_pages = module_->min_mem_pages; |
942 (module_->is_wasm() ? isolate_->counters()->wasm_wasm_min_mem_pages_count() | 926 (module_->is_wasm() ? counters()->wasm_wasm_min_mem_pages_count() |
943 : isolate_->counters()->wasm_asm_min_mem_pages_count()) | 927 : counters()->wasm_asm_min_mem_pages_count()) |
944 ->AddSample(min_mem_pages); | 928 ->AddSample(min_mem_pages); |
945 | 929 |
946 if (!memory_.is_null()) { | 930 if (!memory_.is_null()) { |
947 // Set externally passed ArrayBuffer non neuterable. | 931 // Set externally passed ArrayBuffer non neuterable. |
948 memory_->set_is_neuterable(false); | 932 memory_->set_is_neuterable(false); |
949 memory_->set_is_wasm_buffer(true); | 933 memory_->set_is_wasm_buffer(true); |
950 | 934 |
951 DCHECK_IMPLIES(EnableGuardRegions(), | 935 DCHECK_IMPLIES(EnableGuardRegions(), |
952 module_->is_asm_js() || memory_->has_guard_region()); | 936 module_->is_asm_js() || memory_->has_guard_region()); |
953 } else if (min_mem_pages > 0) { | 937 } else if (min_mem_pages > 0) { |
(...skipping 181 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1135 HandleScope scope(isolate_); | 1119 HandleScope scope(isolate_); |
1136 int start_index = module_->start_function_index; | 1120 int start_index = module_->start_function_index; |
1137 Handle<Code> startup_code = EnsureExportedLazyDeoptData( | 1121 Handle<Code> startup_code = EnsureExportedLazyDeoptData( |
1138 isolate_, instance, code_table, start_index); | 1122 isolate_, instance, code_table, start_index); |
1139 FunctionSig* sig = module_->functions[start_index].sig; | 1123 FunctionSig* sig = module_->functions[start_index].sig; |
1140 Handle<Code> wrapper_code = js_to_wasm_cache_.CloneOrCompileJSToWasmWrapper( | 1124 Handle<Code> wrapper_code = js_to_wasm_cache_.CloneOrCompileJSToWasmWrapper( |
1141 isolate_, module_, startup_code, start_index); | 1125 isolate_, module_, startup_code, start_index); |
1142 Handle<WasmExportedFunction> startup_fct = WasmExportedFunction::New( | 1126 Handle<WasmExportedFunction> startup_fct = WasmExportedFunction::New( |
1143 isolate_, instance, MaybeHandle<String>(), start_index, | 1127 isolate_, instance, MaybeHandle<String>(), start_index, |
1144 static_cast<int>(sig->parameter_count()), wrapper_code); | 1128 static_cast<int>(sig->parameter_count()), wrapper_code); |
1145 RecordStats(*startup_code, counters_); | 1129 RecordStats(*startup_code, counters()); |
1146 // Call the JS function. | 1130 // Call the JS function. |
1147 Handle<Object> undefined = factory->undefined_value(); | 1131 Handle<Object> undefined = factory->undefined_value(); |
1148 MaybeHandle<Object> retval = | 1132 MaybeHandle<Object> retval = |
1149 Execution::Call(isolate_, startup_fct, undefined, 0, nullptr); | 1133 Execution::Call(isolate_, startup_fct, undefined, 0, nullptr); |
1150 | 1134 |
1151 if (retval.is_null()) { | 1135 if (retval.is_null()) { |
1152 DCHECK(isolate_->has_pending_exception()); | 1136 DCHECK(isolate_->has_pending_exception()); |
1153 isolate_->OptionalRescheduleException(false); | 1137 isolate_->OptionalRescheduleException(false); |
1154 // It's unfortunate that the new instance is already linked in the | 1138 // It's unfortunate that the new instance is already linked in the |
1155 // chain. However, we need to set up everything before executing the | 1139 // chain. However, we need to set up everything before executing the |
(...skipping 176 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1332 Handle<Code> import_wrapper = UnwrapOrCompileImportWrapper( | 1316 Handle<Code> import_wrapper = UnwrapOrCompileImportWrapper( |
1333 isolate_, index, module_->functions[import.index].sig, | 1317 isolate_, index, module_->functions[import.index].sig, |
1334 Handle<JSReceiver>::cast(value), module_name, import_name, | 1318 Handle<JSReceiver>::cast(value), module_name, import_name, |
1335 module_->get_origin(), &imported_wasm_instances); | 1319 module_->get_origin(), &imported_wasm_instances); |
1336 if (import_wrapper.is_null()) { | 1320 if (import_wrapper.is_null()) { |
1337 ReportLinkError("imported function does not match the expected type", | 1321 ReportLinkError("imported function does not match the expected type", |
1338 index, module_name, import_name); | 1322 index, module_name, import_name); |
1339 return -1; | 1323 return -1; |
1340 } | 1324 } |
1341 code_table->set(num_imported_functions, *import_wrapper); | 1325 code_table->set(num_imported_functions, *import_wrapper); |
1342 RecordStats(*import_wrapper, counters_); | 1326 RecordStats(*import_wrapper, counters()); |
1343 num_imported_functions++; | 1327 num_imported_functions++; |
1344 break; | 1328 break; |
1345 } | 1329 } |
1346 case kExternalTable: { | 1330 case kExternalTable: { |
1347 if (!WasmJs::IsWasmTableObject(isolate_, value)) { | 1331 if (!WasmJs::IsWasmTableObject(isolate_, value)) { |
1348 ReportLinkError("table import requires a WebAssembly.Table", index, | 1332 ReportLinkError("table import requires a WebAssembly.Table", index, |
1349 module_name, import_name); | 1333 module_name, import_name); |
1350 return -1; | 1334 return -1; |
1351 } | 1335 } |
1352 WasmIndirectFunctionTable& table = | 1336 WasmIndirectFunctionTable& table = |
(...skipping 556 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1909 table_instance.function_table, table_instance.signature_table); | 1893 table_instance.function_table, table_instance.signature_table); |
1910 } | 1894 } |
1911 } | 1895 } |
1912 } | 1896 } |
1913 | 1897 |
1914 AsyncCompileJob::AsyncCompileJob(Isolate* isolate, | 1898 AsyncCompileJob::AsyncCompileJob(Isolate* isolate, |
1915 std::unique_ptr<byte[]> bytes_copy, | 1899 std::unique_ptr<byte[]> bytes_copy, |
1916 size_t length, Handle<Context> context, | 1900 size_t length, Handle<Context> context, |
1917 Handle<JSPromise> promise) | 1901 Handle<JSPromise> promise) |
1918 : isolate_(isolate), | 1902 : isolate_(isolate), |
1919 counters_shared_(isolate->counters_shared()), | 1903 async_counters_(isolate->async_counters()), |
1920 bytes_copy_(std::move(bytes_copy)), | 1904 bytes_copy_(std::move(bytes_copy)), |
1921 wire_bytes_(bytes_copy_.get(), bytes_copy_.get() + length) { | 1905 wire_bytes_(bytes_copy_.get(), bytes_copy_.get() + length) { |
1922 // The handles for the context and promise must be deferred. | 1906 // The handles for the context and promise must be deferred. |
1923 DeferredHandleScope deferred(isolate); | 1907 DeferredHandleScope deferred(isolate); |
1924 context_ = Handle<Context>(*context); | 1908 context_ = Handle<Context>(*context); |
1925 module_promise_ = Handle<JSPromise>(*promise); | 1909 module_promise_ = Handle<JSPromise>(*promise); |
1926 deferred_handles_.push_back(deferred.Detach()); | 1910 deferred_handles_.push_back(deferred.Detach()); |
1927 counters_ = counters_shared_.get(); | |
1928 } | 1911 } |
1929 | 1912 |
1930 void AsyncCompileJob::Start() { | 1913 void AsyncCompileJob::Start() { |
1931 DoAsync<DecodeModule>(); // -- | 1914 DoAsync<DecodeModule>(); // -- |
1932 } | 1915 } |
1933 | 1916 |
1934 AsyncCompileJob::~AsyncCompileJob() { | 1917 AsyncCompileJob::~AsyncCompileJob() { |
1935 background_task_manager_.CancelAndWait(); | 1918 background_task_manager_.CancelAndWait(); |
1936 for (auto d : deferred_handles_) delete d; | 1919 for (auto d : deferred_handles_) delete d; |
1937 } | 1920 } |
(...skipping 104 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2042 public: | 2025 public: |
2043 DecodeModule() : CompileStep(1) {} | 2026 DecodeModule() : CompileStep(1) {} |
2044 | 2027 |
2045 void RunInBackground() override { | 2028 void RunInBackground() override { |
2046 ModuleResult result; | 2029 ModuleResult result; |
2047 { | 2030 { |
2048 DisallowHandleAllocation no_handle; | 2031 DisallowHandleAllocation no_handle; |
2049 DisallowHeapAllocation no_allocation; | 2032 DisallowHeapAllocation no_allocation; |
2050 // Decode the module bytes. | 2033 // Decode the module bytes. |
2051 TRACE_COMPILE("(1) Decoding module...\n"); | 2034 TRACE_COMPILE("(1) Decoding module...\n"); |
2052 constexpr bool is_sync = true; | 2035 result = AsyncDecodeWasmModule(job_->isolate_, job_->wire_bytes_.start(), |
2053 result = DecodeWasmModule(job_->isolate_, job_->wire_bytes_.start(), | 2036 job_->wire_bytes_.end(), false, |
2054 job_->wire_bytes_.end(), false, kWasmOrigin, | 2037 kWasmOrigin, job_->counters()); |
2055 !is_sync); | |
2056 } | 2038 } |
2057 if (result.failed()) { | 2039 if (result.failed()) { |
2058 // Decoding failure; reject the promise and clean up. | 2040 // Decoding failure; reject the promise and clean up. |
2059 job_->DoSync<DecodeFail>(std::move(result)); | 2041 job_->DoSync<DecodeFail>(std::move(result)); |
2060 } else { | 2042 } else { |
2061 // Decode passed. | 2043 // Decode passed. |
2062 job_->DoSync<PrepareAndStartCompile>(std::move(result.val)); | 2044 job_->DoSync<PrepareAndStartCompile>(std::move(result.val)); |
2063 } | 2045 } |
2064 } | 2046 } |
2065 }; | 2047 }; |
(...skipping 65 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2131 | 2113 |
2132 // Initialize {code_table_} with the illegal builtin. All call sites | 2114 // Initialize {code_table_} with the illegal builtin. All call sites |
2133 // will be patched at instantiation. | 2115 // will be patched at instantiation. |
2134 Handle<Code> illegal_builtin = job_->isolate_->builtins()->Illegal(); | 2116 Handle<Code> illegal_builtin = job_->isolate_->builtins()->Illegal(); |
2135 // TODO(wasm): Fix this for lazy compilation. | 2117 // TODO(wasm): Fix this for lazy compilation. |
2136 for (uint32_t i = 0; i < module_->functions.size(); ++i) { | 2118 for (uint32_t i = 0; i < module_->functions.size(); ++i) { |
2137 job_->code_table_->set(static_cast<int>(i), *illegal_builtin); | 2119 job_->code_table_->set(static_cast<int>(i), *illegal_builtin); |
2138 job_->temp_instance_->function_code[i] = illegal_builtin; | 2120 job_->temp_instance_->function_code[i] = illegal_builtin; |
2139 } | 2121 } |
2140 | 2122 |
2141 job_->isolate_->counters()->wasm_functions_per_wasm_module()->AddSample( | 2123 job_->counters()->wasm_functions_per_wasm_module()->AddSample( |
2142 static_cast<int>(module_->functions.size())); | 2124 static_cast<int>(module_->functions.size())); |
2143 | 2125 |
2144 // Transfer ownership of the {WasmModule} to the {ModuleCompiler}, but | 2126 // Transfer ownership of the {WasmModule} to the {ModuleCompiler}, but |
2145 // keep a pointer. | 2127 // keep a pointer. |
2146 WasmModule* module = module_.get(); | 2128 WasmModule* module = module_.get(); |
2147 constexpr bool is_sync = true; | 2129 constexpr bool is_sync = true; |
2148 job_->compiler_.reset( | 2130 job_->compiler_.reset( |
2149 new ModuleCompiler(job_->isolate_, std::move(module_), !is_sync)); | 2131 new ModuleCompiler(job_->isolate_, std::move(module_), !is_sync)); |
2150 job_->compiler_->EnableThrottling(); | 2132 job_->compiler_->EnableThrottling(); |
2151 | 2133 |
(...skipping 133 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2285 // Step 5 (sync): Finish heap-allocated data structures. | 2267 // Step 5 (sync): Finish heap-allocated data structures. |
2286 //========================================================================== | 2268 //========================================================================== |
2287 class AsyncCompileJob::FinishCompile : public CompileStep { | 2269 class AsyncCompileJob::FinishCompile : public CompileStep { |
2288 void RunInForeground() override { | 2270 void RunInForeground() override { |
2289 TRACE_COMPILE("(5b) Finish compile...\n"); | 2271 TRACE_COMPILE("(5b) Finish compile...\n"); |
2290 HandleScope scope(job_->isolate_); | 2272 HandleScope scope(job_->isolate_); |
2291 // At this point, compilation has completed. Update the code table. | 2273 // At this point, compilation has completed. Update the code table. |
2292 for (size_t i = FLAG_skip_compiling_wasm_funcs; | 2274 for (size_t i = FLAG_skip_compiling_wasm_funcs; |
2293 i < job_->temp_instance_->function_code.size(); ++i) { | 2275 i < job_->temp_instance_->function_code.size(); ++i) { |
2294 Code* code = Code::cast(job_->code_table_->get(static_cast<int>(i))); | 2276 Code* code = Code::cast(job_->code_table_->get(static_cast<int>(i))); |
2295 RecordStats(code, job_->counters_); | 2277 RecordStats(code, job_->counters()); |
2296 } | 2278 } |
2297 | 2279 |
2298 // Create heap objects for script and module bytes to be stored in the | 2280 // Create heap objects for script and module bytes to be stored in the |
2299 // shared module data. Asm.js is not compiled asynchronously. | 2281 // shared module data. Asm.js is not compiled asynchronously. |
2300 Handle<Script> script = CreateWasmScript(job_->isolate_, job_->wire_bytes_); | 2282 Handle<Script> script = CreateWasmScript(job_->isolate_, job_->wire_bytes_); |
2301 Handle<ByteArray> asm_js_offset_table; | 2283 Handle<ByteArray> asm_js_offset_table; |
2302 // TODO(wasm): Improve efficiency of storing module wire bytes. | 2284 // TODO(wasm): Improve efficiency of storing module wire bytes. |
2303 // 1. Only store relevant sections, not function bodies | 2285 // 1. Only store relevant sections, not function bodies |
2304 // 2. Don't make a second copy of the bytes here; reuse the copy made | 2286 // 2. Don't make a second copy of the bytes here; reuse the copy made |
2305 // for asynchronous compilation and store it as an external one | 2287 // for asynchronous compilation and store it as an external one |
(...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2361 for (auto exp : module->export_table) { | 2343 for (auto exp : module->export_table) { |
2362 if (exp.kind != kExternalFunction) continue; | 2344 if (exp.kind != kExternalFunction) continue; |
2363 Handle<Code> wasm_code(Code::cast(job_->code_table_->get(exp.index)), | 2345 Handle<Code> wasm_code(Code::cast(job_->code_table_->get(exp.index)), |
2364 job_->isolate_); | 2346 job_->isolate_); |
2365 Handle<Code> wrapper_code = | 2347 Handle<Code> wrapper_code = |
2366 js_to_wasm_cache.CloneOrCompileJSToWasmWrapper(job_->isolate_, module, | 2348 js_to_wasm_cache.CloneOrCompileJSToWasmWrapper(job_->isolate_, module, |
2367 wasm_code, exp.index); | 2349 wasm_code, exp.index); |
2368 int export_index = | 2350 int export_index = |
2369 static_cast<int>(module->functions.size() + func_index); | 2351 static_cast<int>(module->functions.size() + func_index); |
2370 job_->code_table_->set(export_index, *wrapper_code); | 2352 job_->code_table_->set(export_index, *wrapper_code); |
2371 RecordStats(*wrapper_code, job_->counters_); | 2353 RecordStats(*wrapper_code, job_->counters()); |
2372 func_index++; | 2354 func_index++; |
2373 } | 2355 } |
2374 | 2356 |
2375 job_->DoSync<FinishModule>(); | 2357 job_->DoSync<FinishModule>(); |
2376 } | 2358 } |
2377 }; | 2359 }; |
2378 | 2360 |
2379 //========================================================================== | 2361 //========================================================================== |
2380 // Step 7 (sync): Finish the module and resolve the promise. | 2362 // Step 7 (sync): Finish the module and resolve the promise. |
2381 //========================================================================== | 2363 //========================================================================== |
2382 class AsyncCompileJob::FinishModule : public CompileStep { | 2364 class AsyncCompileJob::FinishModule : public CompileStep { |
2383 void RunInForeground() override { | 2365 void RunInForeground() override { |
2384 TRACE_COMPILE("(7) Finish module...\n"); | 2366 TRACE_COMPILE("(7) Finish module...\n"); |
2385 HandleScope scope(job_->isolate_); | 2367 HandleScope scope(job_->isolate_); |
2386 Handle<WasmModuleObject> result = | 2368 Handle<WasmModuleObject> result = |
2387 WasmModuleObject::New(job_->isolate_, job_->compiled_module_); | 2369 WasmModuleObject::New(job_->isolate_, job_->compiled_module_); |
2388 // {job_} is deleted in AsyncCompileSucceeded, therefore the {return}. | 2370 // {job_} is deleted in AsyncCompileSucceeded, therefore the {return}. |
2389 return job_->AsyncCompileSucceeded(result); | 2371 return job_->AsyncCompileSucceeded(result); |
2390 } | 2372 } |
2391 }; | 2373 }; |
2392 } // namespace wasm | 2374 } // namespace wasm |
2393 } // namespace internal | 2375 } // namespace internal |
2394 } // namespace v8 | 2376 } // namespace v8 |
OLD | NEW |