Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(124)

Side by Side Diff: src/wasm/wasm-module.cc

Issue 2008043006: [wasm] separate snapshot-able stages (Closed) Base URL: https://chromium.googlesource.com/v8/v8.git@refactoring
Patch Set: Created 4 years, 6 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « src/wasm/wasm-module.h ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 2015 the V8 project authors. All rights reserved. 1 // Copyright 2015 the V8 project authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "src/base/atomic-utils.h" 5 #include "src/base/atomic-utils.h"
6 #include "src/macro-assembler.h" 6 #include "src/macro-assembler.h"
7 #include "src/objects.h" 7 #include "src/objects.h"
8 #include "src/property-descriptor.h" 8 #include "src/property-descriptor.h"
9 #include "src/v8.h" 9 #include "src/v8.h"
10 10
11 #include "src/simulator.h" 11 #include "src/simulator.h"
12 12
13 #include "src/wasm/ast-decoder.h" 13 #include "src/wasm/ast-decoder.h"
14 #include "src/wasm/module-decoder.h" 14 #include "src/wasm/module-decoder.h"
15 #include "src/wasm/wasm-function-name-table.h" 15 #include "src/wasm/wasm-function-name-table.h"
16 #include "src/wasm/wasm-module.h" 16 #include "src/wasm/wasm-module.h"
17 #include "src/wasm/wasm-result.h" 17 #include "src/wasm/wasm-result.h"
18 18
19 #include "src/compiler/wasm-compiler.h" 19 #include "src/compiler/wasm-compiler.h"
20 20
21 namespace v8 { 21 namespace v8 {
22 namespace internal { 22 namespace internal {
23 namespace wasm { 23 namespace wasm {
24 24
25 static const int kPlaceholderMarker = 1000000000;
26
25 static const char* wasmSections[] = { 27 static const char* wasmSections[] = {
26 #define F(enumerator, order, string) string, 28 #define F(enumerator, order, string) string,
27 FOR_EACH_WASM_SECTION_TYPE(F) 29 FOR_EACH_WASM_SECTION_TYPE(F)
28 #undef F 30 #undef F
29 "<unknown>" // entry for "Max" 31 "<unknown>" // entry for "Max"
30 }; 32 };
31 33
32 static uint8_t wasmSectionsLengths[]{ 34 static uint8_t wasmSectionsLengths[]{
33 #define F(enumerator, order, string) sizeof(string) - 1, 35 #define F(enumerator, order, string) sizeof(string) - 1,
34 FOR_EACH_WASM_SECTION_TYPE(F) 36 FOR_EACH_WASM_SECTION_TYPE(F)
(...skipping 71 matching lines...) Expand 10 before | Expand all | Expand 10 after
106 } else { 108 } else {
107 os << "?"; 109 os << "?";
108 } 110 }
109 return os; 111 return os;
110 } 112 }
111 113
112 // A helper class for compiling multiple wasm functions that offers 114 // A helper class for compiling multiple wasm functions that offers
113 // placeholder code objects for calling functions that are not yet compiled. 115 // placeholder code objects for calling functions that are not yet compiled.
114 class WasmLinker { 116 class WasmLinker {
115 public: 117 public:
116 WasmLinker(Isolate* isolate, size_t size) 118 WasmLinker(Isolate* isolate, std::vector<Handle<Code>>* functions)
117 : isolate_(isolate), placeholder_code_(size), function_code_(size) {} 119 : isolate_(isolate),
120 placeholder_code_(functions->size()),
121 function_code_(functions) {
122 placeholder_code_.insert(placeholder_code_.begin(), function_code().begin(),
123 function_code().end());
124 }
125
126 void CreatePlaceholder(uint32_t index) {
127 DCHECK(index < function_code().size());
ahaas 2016/05/30 14:02:32 Could you add a DCHECK(function_code()[index].is_n
Mircea Trofin 2016/05/30 16:55:49 Done.
128 // Create a placeholder code object and encode the corresponding index in
129 // the {constant_pool_offset} field of the code object.
130 // TODO(titzer): placeholder code objects are somewhat dangerous.
131 byte buffer[] = {0, 0, 0, 0, 0, 0, 0, 0}; // fake instructions.
132 CodeDesc desc = {buffer, 8, 8, 0, 0, nullptr};
133 Handle<Code> code = isolate_->factory()->NewCode(
134 desc, Code::KindField::encode(Code::WASM_FUNCTION),
135 Handle<Object>::null());
136 code->set_constant_pool_offset(static_cast<int>(index) +
137 kPlaceholderMarker);
138 placeholder_code_[index] = code;
139 function_code()[index] = code;
140 }
118 141
119 // Get the code object for a function, allocating a placeholder if it has 142 // Get the code object for a function, allocating a placeholder if it has
120 // not yet been compiled. 143 // not yet been compiled.
121 Handle<Code> GetFunctionCode(uint32_t index) { 144 Handle<Code> GetFunctionCode(uint32_t index) {
122 DCHECK(index < function_code_.size()); 145 DCHECK(index < function_code().size());
123 if (function_code_[index].is_null()) { 146 if (function_code()[index].is_null()) {
124 // Create a placeholder code object and encode the corresponding index in 147 CreatePlaceholder(index);
125 // the {constant_pool_offset} field of the code object.
126 // TODO(titzer): placeholder code objects are somewhat dangerous.
127 byte buffer[] = {0, 0, 0, 0, 0, 0, 0, 0}; // fake instructions.
128 CodeDesc desc = {buffer, 8, 8, 0, 0, nullptr};
129 Handle<Code> code = isolate_->factory()->NewCode(
130 desc, Code::KindField::encode(Code::WASM_FUNCTION),
131 Handle<Object>::null());
132 code->set_constant_pool_offset(index + kPlaceholderMarker);
133 placeholder_code_[index] = code;
134 function_code_[index] = code;
135 } 148 }
136 return function_code_[index]; 149 return function_code()[index];
137 } 150 }
138 151
139 void Finish(uint32_t index, Handle<Code> code) { 152 void Finish(uint32_t index, Handle<Code> code) {
140 DCHECK(index < function_code_.size()); 153 DCHECK(index < function_code().size());
141 function_code_[index] = code; 154 function_code()[index] = code;
142 } 155 }
143 156
144 void Link(Handle<FixedArray> function_table, 157 void Link(Handle<FixedArray> function_table,
145 const std::vector<uint16_t>& functions) { 158 const std::vector<uint16_t>& functions) {
146 for (size_t i = 0; i < function_code_.size(); i++) { 159 for (size_t i = 0; i < function_code().size(); i++) {
147 LinkFunction(function_code_[i]); 160 LinkFunction(function_code()[i]);
148 } 161 }
149 if (!function_table.is_null()) { 162 if (!function_table.is_null()) {
150 int table_size = static_cast<int>(functions.size()); 163 int table_size = static_cast<int>(functions.size());
151 DCHECK_EQ(function_table->length(), table_size * 2); 164 DCHECK_EQ(function_table->length(), table_size * 2);
152 for (int i = 0; i < table_size; i++) { 165 for (int i = 0; i < table_size; i++) {
153 function_table->set(i + table_size, *function_code_[functions[i]]); 166 function_table->set(i + table_size, *function_code()[functions[i]]);
154 } 167 }
155 } 168 }
156 } 169 }
157 170
158 private: 171 private:
159 static const int kPlaceholderMarker = 1000000000; 172 std::vector<Handle<Code>>& function_code() { return *function_code_; }
160 173
161 Isolate* isolate_; 174 Isolate* isolate_;
162 std::vector<Handle<Code>> placeholder_code_; 175 std::vector<Handle<Code>> placeholder_code_;
163 std::vector<Handle<Code>> function_code_; 176 std::vector<Handle<Code>>* function_code_;
164 177
165 void LinkFunction(Handle<Code> code) { 178 void LinkFunction(Handle<Code> code) {
166 bool modified = false; 179 bool modified = false;
167 int mode_mask = RelocInfo::kCodeTargetMask; 180 int mode_mask = RelocInfo::kCodeTargetMask;
168 AllowDeferredHandleDereference embedding_raw_address; 181 AllowDeferredHandleDereference embedding_raw_address;
169 for (RelocIterator it(*code, mode_mask); !it.done(); it.next()) { 182 for (RelocIterator it(*code, mode_mask); !it.done(); it.next()) {
170 RelocInfo::Mode mode = it.rinfo()->rmode(); 183 RelocInfo::Mode mode = it.rinfo()->rmode();
171 if (RelocInfo::IsCodeTarget(mode)) { 184 if (RelocInfo::IsCodeTarget(mode)) {
172 Code* target = 185 Code* target =
173 Code::GetCodeFromTargetAddress(it.rinfo()->target_address()); 186 Code::GetCodeFromTargetAddress(it.rinfo()->target_address());
174 if (target->kind() == Code::WASM_FUNCTION && 187 if (target->kind() == Code::WASM_FUNCTION &&
175 target->constant_pool_offset() >= kPlaceholderMarker) { 188 target->constant_pool_offset() >= kPlaceholderMarker) {
176 // Patch direct calls to placeholder code objects. 189 // Patch direct calls to placeholder code objects.
177 uint32_t index = target->constant_pool_offset() - kPlaceholderMarker; 190 uint32_t index = target->constant_pool_offset() - kPlaceholderMarker;
178 CHECK(index < function_code_.size()); 191 CHECK(index < function_code().size());
179 Handle<Code> new_target = function_code_[index]; 192 Handle<Code> new_target = function_code()[index];
180 if (target != *new_target) { 193 if (target != *new_target) {
181 CHECK_EQ(*placeholder_code_[index], target); 194 CHECK_EQ(*placeholder_code_[index], target);
182 it.rinfo()->set_target_address(new_target->instruction_start(), 195 it.rinfo()->set_target_address(new_target->instruction_start(),
183 SKIP_WRITE_BARRIER, 196 SKIP_WRITE_BARRIER,
184 SKIP_ICACHE_FLUSH); 197 SKIP_ICACHE_FLUSH);
185 modified = true; 198 modified = true;
186 } 199 }
187 } 200 }
188 } 201 }
189 } 202 }
(...skipping 297 matching lines...) Expand 10 before | Expand all | Expand 10 after
487 index++; 500 index++;
488 } 501 }
489 } 502 }
490 return true; 503 return true;
491 } 504 }
492 505
493 void InitializeParallelCompilation( 506 void InitializeParallelCompilation(
494 Isolate* isolate, const std::vector<WasmFunction>& functions, 507 Isolate* isolate, const std::vector<WasmFunction>& functions,
495 std::vector<compiler::WasmCompilationUnit*>& compilation_units, 508 std::vector<compiler::WasmCompilationUnit*>& compilation_units,
496 ModuleEnv& module_env, ErrorThrower& thrower) { 509 ModuleEnv& module_env, ErrorThrower& thrower) {
497 // Create a placeholder code object for all functions.
498 // TODO(ahaas): Maybe we could skip this for external functions.
499 for (uint32_t i = 0; i < functions.size(); i++) {
500 module_env.linker->GetFunctionCode(i);
501 }
502
503 for (uint32_t i = FLAG_skip_compiling_wasm_funcs; i < functions.size(); i++) { 510 for (uint32_t i = FLAG_skip_compiling_wasm_funcs; i < functions.size(); i++) {
504 compilation_units[i] = new compiler::WasmCompilationUnit( 511 compilation_units[i] = new compiler::WasmCompilationUnit(
505 &thrower, isolate, &module_env, &functions[i], i); 512 &thrower, isolate, &module_env, &functions[i], i);
506 } 513 }
507 } 514 }
508 515
509 uint32_t* StartCompilationTasks( 516 uint32_t* StartCompilationTasks(
510 Isolate* isolate, 517 Isolate* isolate,
511 std::vector<compiler::WasmCompilationUnit*>& compilation_units, 518 std::vector<compiler::WasmCompilationUnit*>& compilation_units,
512 std::queue<compiler::WasmCompilationUnit*>& executed_units, 519 std::queue<compiler::WasmCompilationUnit*>& executed_units,
(...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after
549 compiler::WasmCompilationUnit* unit = nullptr; 556 compiler::WasmCompilationUnit* unit = nullptr;
550 { 557 {
551 base::LockGuard<base::Mutex> guard(&result_mutex); 558 base::LockGuard<base::Mutex> guard(&result_mutex);
552 if (executed_units.empty()) { 559 if (executed_units.empty()) {
553 break; 560 break;
554 } 561 }
555 unit = executed_units.front(); 562 unit = executed_units.front();
556 executed_units.pop(); 563 executed_units.pop();
557 } 564 }
558 int j = unit->index(); 565 int j = unit->index();
559 results[j] = unit->FinishCompilation(); 566 results[j] = unit->FinishCompilation();
ahaas 2016/05/30 14:02:32 I think this will be a data race with the GetFunct
Mircea Trofin 2016/05/30 16:55:49 Good catch, thanks! Replaced WasmLinker::GetFunct
560 delete unit; 567 delete unit;
561 } 568 }
562 } 569 }
563 570
564 bool FinishCompilation(Isolate* isolate, const WasmModule* module, 571 void CompileInParallel(Isolate* isolate, const WasmModule* module,
565 const Handle<JSReceiver> ffi, 572 std::vector<Handle<Code>>& functions,
566 const std::vector<Handle<Code>>& results, 573 ErrorThrower* thrower, ModuleEnv* module_env) {
567 const WasmModuleInstance& instance, 574 // Data structures for the parallel compilation.
568 const Handle<FixedArray>& code_table, 575 std::vector<compiler::WasmCompilationUnit*> compilation_units(
569 ErrorThrower& thrower, Factory* factory, 576 module->functions.size());
570 ModuleEnv& module_env, CodeStats& code_stats, 577 std::queue<compiler::WasmCompilationUnit*> executed_units;
571 PropertyDescriptor& desc) { 578
572 if (thrower.error()) return false; 579 // Create placeholders for all functions.
580 for (uint32_t i = FLAG_skip_compiling_wasm_funcs; i < functions.size(); ++i) {
581 module_env->linker->CreatePlaceholder(i);
582 }
583
584 //-----------------------------------------------------------------------
585 // For parallel compilation:
586 // 1) The main thread allocates a compilation unit for each wasm function
587 // and stores them in the vector {compilation_units}.
588 // 2) The main thread spawns {WasmCompilationTask} instances which run on
589 // the background threads.
590 // 3.a) The background threads and the main thread pick one compilation
591 // unit at a time and execute the parallel phase of the compilation
592 // unit. After finishing the execution of the parallel phase, the
593 // result is enqueued in {executed_units}.
594 // 3.b) If {executed_units} contains a compilation unit, the main thread
595 // dequeues it and finishes the compilation.
596 // 4) After the parallel phase of all compilation units has started, the
597 // main thread waits for all {WasmCompilationTask} instances to finish.
598 // 5) The main thread finishes the compilation.
599
600 // Turn on the {CanonicalHandleScope} so that the background threads can
601 // use the node cache.
602 CanonicalHandleScope canonical(isolate);
603
604 // 1) The main thread allocates a compilation unit for each wasm function
605 // and stores them in the vector {compilation_units}.
606 InitializeParallelCompilation(isolate, module->functions, compilation_units,
607 *module_env, *thrower);
608
609 // Objects for the synchronization with the background threads.
610 base::SmartPointer<base::Semaphore> pending_tasks(new base::Semaphore(0));
611 base::Mutex result_mutex;
612 base::AtomicNumber<size_t> next_unit(
613 static_cast<size_t>(FLAG_skip_compiling_wasm_funcs));
614
615 // 2) The main thread spawns {WasmCompilationTask} instances which run on
616 // the background threads.
617 base::SmartArrayPointer<uint32_t> task_ids(
618 StartCompilationTasks(isolate, compilation_units, executed_units,
619 pending_tasks, result_mutex, next_unit));
620
621 // 3.a) The background threads and the main thread pick one compilation
622 // unit at a time and execute the parallel phase of the compilation
623 // unit. After finishing the execution of the parallel phase, the
624 // result is enqueued in {executed_units}.
625 while (FetchAndExecuteCompilationUnit(isolate, &compilation_units,
626 &executed_units, &result_mutex,
627 &next_unit)) {
628 // 3.b) If {executed_units} contains a compilation unit, the main thread
629 // dequeues it and finishes the compilation unit. Compilation units
630 // are finished concurrently to the background threads to save
631 // memory.
632 FinishCompilationUnits(executed_units, functions, result_mutex);
633 }
634 // 4) After the parallel phase of all compilation units has started, the
635 // main thread waits for all {WasmCompilationTask} instances to finish.
636 WaitForCompilationTasks(isolate, task_ids.get(), pending_tasks);
637 // Finish the compilation of the remaining compilation units.
638 FinishCompilationUnits(executed_units, functions, result_mutex);
639 }
640
641 void CompileSequentially(Isolate* isolate, const WasmModule* module,
642 std::vector<Handle<Code>>& functions,
643 ErrorThrower* thrower, ModuleEnv* module_env) {
644 DCHECK(!thrower->error());
645
573 for (uint32_t i = FLAG_skip_compiling_wasm_funcs; 646 for (uint32_t i = FLAG_skip_compiling_wasm_funcs;
574 i < module->functions.size(); i++) { 647 i < module->functions.size(); i++) {
575 const WasmFunction& func = module->functions[i]; 648 const WasmFunction& func = module->functions[i];
576 649
577 DCHECK_EQ(i, func.func_index); 650 DCHECK_EQ(i, func.func_index);
578 WasmName str = module->GetName(func.name_offset, func.name_length); 651 WasmName str = module->GetName(func.name_offset, func.name_length);
579 Handle<Code> code = Handle<Code>::null(); 652 Handle<Code> code = Handle<Code>::null();
580 if (FLAG_wasm_num_compilation_tasks != 0) { 653 // Compile the function.
581 code = results[i]; 654 code = compiler::WasmCompilationUnit::CompileWasmFunction(
582 } else { 655 thrower, isolate, module_env, &func);
583 // Compile the function. 656 if (code.is_null()) {
584 code = compiler::WasmCompilationUnit::CompileWasmFunction( 657 thrower->Error("Compilation of #%d:%.*s failed.", i, str.length(),
585 &thrower, isolate, &module_env, &func); 658 str.start());
659 break;
586 } 660 }
587 if (code.is_null()) {
588 thrower.Error("Compilation of #%d:%.*s failed.", i, str.length(),
589 str.start());
590 return false;
591 }
592 if (!code.is_null()) {
593 // Install the code into the linker table. 661 // Install the code into the linker table.
594 module_env.linker->Finish(i, code); 662 functions[i] = code;
595 code_table->set(i, *code);
596 code_stats.Record(*code);
597 }
598 } 663 }
599 return true;
600 } 664 }
601 } // namespace 665 } // namespace
602 666
667 void SetDeoptimizationData(Factory* factory, Handle<JSObject> js_object,
668 std::vector<Handle<Code>>& functions) {
669 for (size_t i = FLAG_skip_compiling_wasm_funcs; i < functions.size(); ++i) {
670 Handle<Code> code = functions[i];
671 DCHECK(code->deoptimization_data() == nullptr ||
672 code->deoptimization_data()->length() == 0);
673 Handle<FixedArray> deopt_data = factory->NewFixedArray(2, TENURED);
674 if (!js_object.is_null()) {
675 deopt_data->set(0, *js_object);
676 }
677 deopt_data->set(1, Smi::FromInt(static_cast<int>(i)));
678 deopt_data->set_length(2);
679 code->set_deoptimization_data(*deopt_data);
680 }
681 }
682
603 // Instantiates a wasm module as a JSObject. 683 // Instantiates a wasm module as a JSObject.
604 // * allocates a backing store of {mem_size} bytes. 684 // * allocates a backing store of {mem_size} bytes.
605 // * installs a named property "memory" for that buffer if exported 685 // * installs a named property "memory" for that buffer if exported
606 // * installs named properties on the object for exported functions 686 // * installs named properties on the object for exported functions
607 // * compiles wasm code to machine code 687 // * compiles wasm code to machine code
608 MaybeHandle<JSObject> WasmModule::Instantiate( 688 MaybeHandle<JSObject> WasmModule::Instantiate(
609 Isolate* isolate, Handle<JSReceiver> ffi, 689 Isolate* isolate, Handle<JSReceiver> ffi,
610 Handle<JSArrayBuffer> memory) const { 690 Handle<JSArrayBuffer> memory) const {
611 HistogramTimerScope wasm_instantiate_module_time_scope( 691 HistogramTimerScope wasm_instantiate_module_time_scope(
612 isolate->counters()->wasm_instantiate_module_time()); 692 isolate->counters()->wasm_instantiate_module_time());
613 ErrorThrower thrower(isolate, "WasmModule::Instantiate()"); 693 ErrorThrower thrower(isolate, "WasmModule::Instantiate()");
614 Factory* factory = isolate->factory(); 694 Factory* factory = isolate->factory();
615 695
616 PropertyDescriptor desc;
617 desc.set_writable(false);
618
619 // If FLAG_print_wasm_code_size is set, this aggregates the sum of all code 696 // If FLAG_print_wasm_code_size is set, this aggregates the sum of all code
620 // objects created for this module. 697 // objects created for this module.
621 // TODO(titzer): switch this to TRACE_EVENT 698 // TODO(titzer): switch this to TRACE_EVENT
622 CodeStats code_stats; 699 CodeStats code_stats;
623 700
624 //------------------------------------------------------------------------- 701 //-------------------------------------------------------------------------
625 // Allocate the instance and its JS counterpart. 702 // Allocate the instance and its JS counterpart.
626 //------------------------------------------------------------------------- 703 //-------------------------------------------------------------------------
627 Handle<Map> map = factory->NewMap( 704 Handle<Map> map = factory->NewMap(
628 JS_OBJECT_TYPE, 705 JS_OBJECT_TYPE,
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after
660 } 737 }
661 if (!instance.globals_buffer.is_null()) { 738 if (!instance.globals_buffer.is_null()) {
662 instance.js_object->SetInternalField(kWasmGlobalsArrayBuffer, 739 instance.js_object->SetInternalField(kWasmGlobalsArrayBuffer,
663 *instance.globals_buffer); 740 *instance.globals_buffer);
664 } 741 }
665 742
666 HistogramTimerScope wasm_compile_module_time_scope( 743 HistogramTimerScope wasm_compile_module_time_scope(
667 isolate->counters()->wasm_compile_module_time()); 744 isolate->counters()->wasm_compile_module_time());
668 745
669 instance.function_table = BuildFunctionTable(isolate, this); 746 instance.function_table = BuildFunctionTable(isolate, this);
670 WasmLinker linker(isolate, functions.size()); 747 WasmLinker linker(isolate, &instance.function_code);
671 ModuleEnv module_env; 748 ModuleEnv module_env;
672 module_env.module = this; 749 module_env.module = this;
673 module_env.instance = &instance; 750 module_env.instance = &instance;
674 module_env.linker = &linker; 751 module_env.linker = &linker;
675 module_env.origin = origin; 752 module_env.origin = origin;
676 753
677 //------------------------------------------------------------------------- 754 //-------------------------------------------------------------------------
678 // Compile wrappers to imported functions. 755 // Compile wrappers to imported functions.
679 //------------------------------------------------------------------------- 756 //-------------------------------------------------------------------------
680 if (!CompileWrappersToImportedFunctions(isolate, this, ffi, &instance, 757 if (!CompileWrappersToImportedFunctions(isolate, this, ffi, &instance,
681 &thrower, factory, &module_env, 758 &thrower, factory, &module_env,
682 code_stats)) { 759 code_stats)) {
683 return MaybeHandle<JSObject>(); 760 return MaybeHandle<JSObject>();
684 } 761 }
685 //------------------------------------------------------------------------- 762 //-------------------------------------------------------------------------
686 // Compile all functions in the module. 763 // Compile all functions in the module.
687 //------------------------------------------------------------------------- 764 //-------------------------------------------------------------------------
688 { 765 {
689 isolate->counters()->wasm_functions_per_module()->AddSample( 766 isolate->counters()->wasm_functions_per_module()->AddSample(
690 static_cast<int>(functions.size())); 767 static_cast<int>(functions.size()));
768 if (FLAG_wasm_num_compilation_tasks != 0) {
769 CompileInParallel(isolate, this, instance.function_code, &thrower,
770 &module_env);
771 } else {
772 // 5) The main thread finishes the compilation.
773 CompileSequentially(isolate, this, instance.function_code, &thrower,
774 &module_env);
775 }
776 if (thrower.error()) {
777 return Handle<JSObject>::null();
778 }
691 779
692 // Data structures for the parallel compilation. 780 // At this point, compilation has completed. Update the code table
693 std::vector<compiler::WasmCompilationUnit*> compilation_units( 781 // and record sizes.
694 functions.size()); 782 for (size_t i = FLAG_skip_compiling_wasm_funcs;
695 std::queue<compiler::WasmCompilationUnit*> executed_units; 783 i < instance.function_code.size(); ++i) {
696 std::vector<Handle<Code>> results(functions.size()); 784 Code* code = *instance.function_code[i];
697 785 code_table->set(static_cast<int>(i), code);
698 if (FLAG_wasm_num_compilation_tasks != 0) { 786 code_stats.Record(code);
699 //-----------------------------------------------------------------------
700 // For parallel compilation:
701 // 1) The main thread allocates a compilation unit for each wasm function
702 // and stores them in the vector {compilation_units}.
703 // 2) The main thread spawns {WasmCompilationTask} instances which run on
704 // the background threads.
705 // 3.a) The background threads and the main thread pick one compilation
706 // unit at a time and execute the parallel phase of the compilation
707 // unit. After finishing the execution of the parallel phase, the
708 // result is enqueued in {executed_units}.
709 // 3.b) If {executed_units} contains a compilation unit, the main thread
710 // dequeues it and finishes the compilation.
711 // 4) After the parallel phase of all compilation units has started, the
712 // main thread waits for all {WasmCompilationTask} instances to finish.
713 // 5) The main thread finishes the compilation.
714
715 // Turn on the {CanonicalHandleScope} so that the background threads can
716 // use the node cache.
717 CanonicalHandleScope canonical(isolate);
718
719 // 1) The main thread allocates a compilation unit for each wasm function
720 // and stores them in the vector {compilation_units}.
721 InitializeParallelCompilation(isolate, functions, compilation_units,
722 module_env, thrower);
723
724 // Objects for the synchronization with the background threads.
725 base::SmartPointer<base::Semaphore> pending_tasks(new base::Semaphore(0));
726 base::Mutex result_mutex;
727 base::AtomicNumber<size_t> next_unit(
728 static_cast<size_t>(FLAG_skip_compiling_wasm_funcs));
729
730 // 2) The main thread spawns {WasmCompilationTask} instances which run on
731 // the background threads.
732 base::SmartArrayPointer<uint32_t> task_ids(
733 StartCompilationTasks(isolate, compilation_units, executed_units,
734 pending_tasks, result_mutex, next_unit));
735
736 // 3.a) The background threads and the main thread pick one compilation
737 // unit at a time and execute the parallel phase of the compilation
738 // unit. After finishing the execution of the parallel phase, the
739 // result is enqueued in {executed_units}.
740 while (FetchAndExecuteCompilationUnit(isolate, &compilation_units,
741 &executed_units, &result_mutex,
742 &next_unit)) {
743 // 3.b) If {executed_units} contains a compilation unit, the main thread
744 // dequeues it and finishes the compilation unit. Compilation units
745 // are finished concurrently to the background threads to save
746 // memory.
747 FinishCompilationUnits(executed_units, results, result_mutex);
748 }
749 // 4) After the parallel phase of all compilation units has started, the
750 // main thread waits for all {WasmCompilationTask} instances to finish.
751 WaitForCompilationTasks(isolate, task_ids.get(), pending_tasks);
752 // Finish the compilation of the remaining compilation units.
753 FinishCompilationUnits(executed_units, results, result_mutex);
754 }
755 // 5) The main thread finishes the compilation.
titzer 2016/05/27 16:03:28 Looks like this step somehow go left out of the pa
Mircea Trofin 2016/05/27 16:09:09 Not quite. It was doing 2 things: - compile sequen
756 if (!FinishCompilation(isolate, this, ffi, results, instance, code_table,
757 thrower, factory, module_env, code_stats, desc)) {
758 instance.js_object = Handle<JSObject>::null();
759 return instance.js_object;
760 } 787 }
761 788
762 // Patch all direct call sites. 789 // Patch all direct call sites.
763 linker.Link(instance.function_table, this->function_table); 790 linker.Link(instance.function_table, this->function_table);
764 instance.js_object->SetInternalField(kWasmModuleFunctionTable, 791 instance.js_object->SetInternalField(kWasmModuleFunctionTable,
765 Smi::FromInt(0)); 792 Smi::FromInt(0));
766 793
794 SetDeoptimizationData(factory, instance.js_object, instance.function_code);
795
767 //------------------------------------------------------------------------- 796 //-------------------------------------------------------------------------
768 // Create and populate the exports object. 797 // Create and populate the exports object.
769 //------------------------------------------------------------------------- 798 //-------------------------------------------------------------------------
770 if (export_table.size() > 0 || mem_export) { 799 if (export_table.size() > 0 || mem_export) {
771 Handle<JSObject> exports_object; 800 Handle<JSObject> exports_object;
772 if (origin == kWasmOrigin) { 801 if (origin == kWasmOrigin) {
773 // Create the "exports" object. 802 // Create the "exports" object.
774 Handle<JSFunction> object_function = Handle<JSFunction>( 803 Handle<JSFunction> object_function = Handle<JSFunction>(
775 isolate->native_context()->object_function(), isolate); 804 isolate->native_context()->object_function(), isolate);
776 exports_object = factory->NewJSObject(object_function, TENURED); 805 exports_object = factory->NewJSObject(object_function, TENURED);
777 Handle<String> exports_name = factory->InternalizeUtf8String("exports"); 806 Handle<String> exports_name = factory->InternalizeUtf8String("exports");
778 JSObject::AddProperty(instance.js_object, exports_name, exports_object, 807 JSObject::AddProperty(instance.js_object, exports_name, exports_object,
779 READ_ONLY); 808 READ_ONLY);
780 } else { 809 } else {
781 // Just export the functions directly on the object returned. 810 // Just export the functions directly on the object returned.
782 exports_object = instance.js_object; 811 exports_object = instance.js_object;
783 } 812 }
784 813
814 PropertyDescriptor desc;
815 desc.set_writable(false);
816
785 // Compile wrappers and add them to the exports object. 817 // Compile wrappers and add them to the exports object.
786 for (const WasmExport& exp : export_table) { 818 for (const WasmExport& exp : export_table) {
787 if (thrower.error()) break; 819 if (thrower.error()) break;
788 WasmName str = GetName(exp.name_offset, exp.name_length); 820 WasmName str = GetName(exp.name_offset, exp.name_length);
789 Handle<String> name = factory->InternalizeUtf8String(str); 821 Handle<String> name = factory->InternalizeUtf8String(str);
790 Handle<Code> code = linker.GetFunctionCode(exp.func_index); 822 Handle<Code> code = linker.GetFunctionCode(exp.func_index);
791 Handle<JSFunction> function = compiler::CompileJSToWasmWrapper( 823 Handle<JSFunction> function = compiler::CompileJSToWasmWrapper(
792 isolate, &module_env, name, code, instance.js_object, 824 isolate, &module_env, name, code, instance.js_object,
793 exp.func_index); 825 exp.func_index);
794 code_stats.Record(function->code()); 826 code_stats.Record(function->code());
(...skipping 105 matching lines...) Expand 10 before | Expand all | Expand 10 after
900 932
901 // Allocate the globals area if necessary. 933 // Allocate the globals area if necessary.
902 if (!AllocateGlobals(&thrower, isolate, &instance)) { 934 if (!AllocateGlobals(&thrower, isolate, &instance)) {
903 return -1; 935 return -1;
904 } 936 }
905 937
906 // Build the function table. 938 // Build the function table.
907 instance.function_table = BuildFunctionTable(isolate, module); 939 instance.function_table = BuildFunctionTable(isolate, module);
908 940
909 // Create module environment. 941 // Create module environment.
910 WasmLinker linker(isolate, module->functions.size()); 942 WasmLinker linker(isolate, &instance.function_code);
911 ModuleEnv module_env; 943 ModuleEnv module_env;
912 module_env.module = module; 944 module_env.module = module;
913 module_env.instance = &instance; 945 module_env.instance = &instance;
914 module_env.linker = &linker; 946 module_env.linker = &linker;
915 module_env.origin = module->origin; 947 module_env.origin = module->origin;
916 948
917 if (module->export_table.size() == 0) { 949 if (module->export_table.size() == 0) {
918 thrower.Error("WASM.compileRun() failed: no exported functions"); 950 thrower.Error("WASM.compileRun() failed: no exported functions");
919 return -2; 951 return -2;
920 } 952 }
(...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after
963 uint32_t func_index) { 995 uint32_t func_index) {
964 Object* func_names_arr_obj = wasm->GetInternalField(kWasmFunctionNamesArray); 996 Object* func_names_arr_obj = wasm->GetInternalField(kWasmFunctionNamesArray);
965 if (func_names_arr_obj->IsUndefined()) return Handle<String>::null(); 997 if (func_names_arr_obj->IsUndefined()) return Handle<String>::null();
966 return GetWasmFunctionNameFromTable( 998 return GetWasmFunctionNameFromTable(
967 handle(ByteArray::cast(func_names_arr_obj)), func_index); 999 handle(ByteArray::cast(func_names_arr_obj)), func_index);
968 } 1000 }
969 1001
970 } // namespace wasm 1002 } // namespace wasm
971 } // namespace internal 1003 } // namespace internal
972 } // namespace v8 1004 } // namespace v8
OLDNEW
« no previous file with comments | « src/wasm/wasm-module.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698