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

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

Issue 1965243003: Revert of [wasm] Implement parallel compilation. (Closed) Base URL: https://chromium.googlesource.com/v8/v8.git@master
Patch Set: Created 4 years, 7 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/flag-definitions.h ('k') | test/mjsunit/wasm/parallel_compilation.js » ('j') | 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"
6 #include "src/macro-assembler.h" 5 #include "src/macro-assembler.h"
7 #include "src/objects.h" 6 #include "src/objects.h"
8 #include "src/property-descriptor.h" 7 #include "src/property-descriptor.h"
9 #include "src/v8.h" 8 #include "src/v8.h"
10 9
11 #include "src/simulator.h" 10 #include "src/simulator.h"
12 11
13 #include "src/wasm/ast-decoder.h" 12 #include "src/wasm/ast-decoder.h"
14 #include "src/wasm/module-decoder.h" 13 #include "src/wasm/module-decoder.h"
15 #include "src/wasm/wasm-function-name-table.h" 14 #include "src/wasm/wasm-function-name-table.h"
(...skipping 107 matching lines...) Expand 10 before | Expand all | Expand 10 after
123 : isolate_(isolate), placeholder_code_(size), function_code_(size) {} 122 : isolate_(isolate), placeholder_code_(size), function_code_(size) {}
124 123
125 // Get the code object for a function, allocating a placeholder if it has 124 // Get the code object for a function, allocating a placeholder if it has
126 // not yet been compiled. 125 // not yet been compiled.
127 Handle<Code> GetFunctionCode(uint32_t index) { 126 Handle<Code> GetFunctionCode(uint32_t index) {
128 DCHECK(index < function_code_.size()); 127 DCHECK(index < function_code_.size());
129 if (function_code_[index].is_null()) { 128 if (function_code_[index].is_null()) {
130 // Create a placeholder code object and encode the corresponding index in 129 // Create a placeholder code object and encode the corresponding index in
131 // the {constant_pool_offset} field of the code object. 130 // the {constant_pool_offset} field of the code object.
132 // TODO(titzer): placeholder code objects are somewhat dangerous. 131 // TODO(titzer): placeholder code objects are somewhat dangerous.
132 Handle<Code> self(nullptr, isolate_);
133 byte buffer[] = {0, 0, 0, 0, 0, 0, 0, 0}; // fake instructions. 133 byte buffer[] = {0, 0, 0, 0, 0, 0, 0, 0}; // fake instructions.
134 CodeDesc desc = {buffer, 8, 8, 0, 0, nullptr}; 134 CodeDesc desc = {buffer, 8, 8, 0, 0, nullptr};
135 Handle<Code> code = isolate_->factory()->NewCode( 135 Handle<Code> code = isolate_->factory()->NewCode(
136 desc, Code::KindField::encode(Code::WASM_FUNCTION), 136 desc, Code::KindField::encode(Code::WASM_FUNCTION), self);
137 Handle<Object>::null());
138 code->set_constant_pool_offset(index + kPlaceholderMarker); 137 code->set_constant_pool_offset(index + kPlaceholderMarker);
139 placeholder_code_[index] = code; 138 placeholder_code_[index] = code;
140 function_code_[index] = code; 139 function_code_[index] = code;
141 } 140 }
142 return function_code_[index]; 141 return function_code_[index];
143 } 142 }
144 143
145 void Finish(uint32_t index, Handle<Code> code) { 144 void Finish(uint32_t index, Handle<Code> code) {
146 DCHECK(index < function_code_.size()); 145 DCHECK(index < function_code_.size());
147 function_code_[index] = code; 146 function_code_[index] = code;
(...skipping 241 matching lines...) Expand 10 before | Expand all | Expand 10 after
389 } 388 }
390 389
391 if (!function->IsJSFunction()) { 390 if (!function->IsJSFunction()) {
392 return ReportFFIError(thrower, "not a function", index, module_name, 391 return ReportFFIError(thrower, "not a function", index, module_name,
393 function_name); 392 function_name);
394 } 393 }
395 394
396 return Handle<JSFunction>::cast(function); 395 return Handle<JSFunction>::cast(function);
397 } 396 }
398 397
399 namespace {
400 // Fetches the compilation unit of a wasm function and executes its parallel
401 // phase.
402 bool FetchAndExecuteCompilationUnit(
403 Isolate* isolate,
404 std::vector<compiler::WasmCompilationUnit*>* compilation_units,
405 std::queue<compiler::WasmCompilationUnit*>* executed_units,
406 base::Mutex* result_mutex, base::AtomicNumber<size_t>* next_unit) {
407 DisallowHeapAllocation no_allocation;
408 DisallowHandleAllocation no_handles;
409 DisallowHandleDereference no_deref;
410 DisallowCodeDependencyChange no_dependency_change;
411
412 // - 1 because AtomicIntrement returns the value after the atomic increment.
413 size_t index = next_unit->Increment(1) - 1;
414 if (index >= compilation_units->size()) {
415 return false;
416 }
417
418 compiler::WasmCompilationUnit* unit = compilation_units->at(index);
419 if (unit != nullptr) {
420 compiler::ExecuteCompilation(unit);
421 {
422 base::LockGuard<base::Mutex> guard(result_mutex);
423 executed_units->push(unit);
424 }
425 }
426 return true;
427 }
428
429 class WasmCompilationTask : public CancelableTask {
430 public:
431 WasmCompilationTask(
432 Isolate* isolate,
433 std::vector<compiler::WasmCompilationUnit*>* compilation_units,
434 std::queue<compiler::WasmCompilationUnit*>* executed_units,
435 base::Semaphore* on_finished, base::Mutex* result_mutex,
436 base::AtomicNumber<size_t>* next_unit)
437 : CancelableTask(isolate),
438 isolate_(isolate),
439 compilation_units_(compilation_units),
440 executed_units_(executed_units),
441 on_finished_(on_finished),
442 result_mutex_(result_mutex),
443 next_unit_(next_unit) {}
444
445 void RunInternal() override {
446 while (FetchAndExecuteCompilationUnit(isolate_, compilation_units_,
447 executed_units_, result_mutex_,
448 next_unit_)) {
449 }
450 on_finished_->Signal();
451 }
452
453 Isolate* isolate_;
454 std::vector<compiler::WasmCompilationUnit*>* compilation_units_;
455 std::queue<compiler::WasmCompilationUnit*>* executed_units_;
456 base::Semaphore* on_finished_;
457 base::Mutex* result_mutex_;
458 base::AtomicNumber<size_t>* next_unit_;
459 };
460
461 void record_code_size(uint32_t& total_code_size, Code* code) {
462 if (FLAG_print_wasm_code_size) {
463 total_code_size += code->body_size() + code->relocation_info()->length();
464 }
465 }
466
467 bool CompileWrappersToImportedFunctions(Isolate* isolate, WasmModule* module,
468 const Handle<JSReceiver> ffi,
469 WasmModuleInstance* instance,
470 ErrorThrower* thrower, Factory* factory,
471 ModuleEnv* module_env,
472 uint32_t& total_code_size) {
473 uint32_t index = 0;
474 if (module->import_table.size() > 0) {
475 instance->import_code.reserve(module->import_table.size());
476 for (const WasmImport& import : module->import_table) {
477 WasmName module_name = module->GetNameOrNull(import.module_name_offset,
478 import.module_name_length);
479 WasmName function_name = module->GetNameOrNull(
480 import.function_name_offset, import.function_name_length);
481 MaybeHandle<JSFunction> function = LookupFunction(
482 *thrower, factory, ffi, index, module_name, function_name);
483 if (function.is_null()) return false;
484
485 Handle<Code> code = compiler::CompileWasmToJSWrapper(
486 isolate, module_env, function.ToHandleChecked(), import.sig,
487 module_name, function_name);
488 instance->import_code.push_back(code);
489 record_code_size(total_code_size, *code);
490 index++;
491 }
492 }
493 return true;
494 }
495
496 void InitializeParallelCompilation(
497 Isolate* isolate, std::vector<WasmFunction>& functions,
498 std::vector<compiler::WasmCompilationUnit*>& compilation_units,
499 ModuleEnv& module_env, ErrorThrower& thrower) {
500 // Create a placeholder code object for all functions.
501 // TODO(ahaas): Maybe we could skip this for external functions.
502 for (uint32_t i = 0; i < functions.size(); i++) {
503 module_env.linker->GetFunctionCode(i);
504 }
505
506 for (uint32_t i = FLAG_skip_compiling_wasm_funcs; i < functions.size(); i++) {
507 if (!functions[i].external) {
508 compilation_units[i] = compiler::CreateWasmCompilationUnit(
509 &thrower, isolate, &module_env, &functions[i], i);
510 } else {
511 compilation_units[i] = nullptr;
512 }
513 }
514 }
515
516 uint32_t* StartCompilationTasks(
517 Isolate* isolate,
518 std::vector<compiler::WasmCompilationUnit*>& compilation_units,
519 std::queue<compiler::WasmCompilationUnit*>& executed_units,
520 const base::SmartPointer<base::Semaphore>& pending_tasks,
521 base::Mutex& result_mutex, base::AtomicNumber<size_t>& next_unit) {
522 const size_t num_tasks =
523 Min(static_cast<size_t>(FLAG_wasm_num_compilation_tasks),
524 V8::GetCurrentPlatform()->NumberOfAvailableBackgroundThreads());
525 uint32_t* task_ids = new uint32_t[num_tasks];
526 for (size_t i = 0; i < num_tasks; i++) {
527 WasmCompilationTask* task =
528 new WasmCompilationTask(isolate, &compilation_units, &executed_units,
529 pending_tasks.get(), &result_mutex, &next_unit);
530 task_ids[i] = task->id();
531 V8::GetCurrentPlatform()->CallOnBackgroundThread(
532 task, v8::Platform::kShortRunningTask);
533 }
534 return task_ids;
535 }
536
537 void WaitForCompilationTasks(
538 Isolate* isolate, uint32_t* task_ids,
539 const base::SmartPointer<base::Semaphore>& pending_tasks) {
540 const size_t num_tasks =
541 Min(static_cast<size_t>(FLAG_wasm_num_compilation_tasks),
542 V8::GetCurrentPlatform()->NumberOfAvailableBackgroundThreads());
543 for (size_t i = 0; i < num_tasks; i++) {
544 // If the task has not started yet, then we abort it. Otherwise we wait for
545 // it to finish.
546 if (!isolate->cancelable_task_manager()->TryAbort(task_ids[i])) {
547 pending_tasks->Wait();
548 }
549 }
550 }
551
552 void FinishCompilationUnits(
553 WasmModule* module,
554 std::queue<compiler::WasmCompilationUnit*>& executed_units,
555 std::vector<Handle<Code>>& results, base::Mutex& result_mutex) {
556 while (!executed_units.empty()) {
557 compiler::WasmCompilationUnit* unit = nullptr;
558 {
559 base::LockGuard<base::Mutex> guard(&result_mutex);
560 unit = executed_units.front();
561 executed_units.pop();
562 }
563 int j = compiler::GetIndexOfWasmCompilationUnit(unit);
564 if (!module->functions[j].external) {
565 results[j] = compiler::FinishCompilation(unit);
566 }
567 }
568 }
569
570 bool FinishCompilation(Isolate* isolate, WasmModule* module,
571 const Handle<JSReceiver> ffi,
572 const std::vector<Handle<Code>>& results,
573 const WasmModuleInstance& instance,
574 const Handle<FixedArray>& code_table,
575 ErrorThrower& thrower, Factory* factory,
576 ModuleEnv& module_env, uint32_t& total_code_size,
577 PropertyDescriptor& desc) {
578 for (uint32_t i = FLAG_skip_compiling_wasm_funcs;
579 i < module->functions.size(); i++) {
580 const WasmFunction& func = module->functions[i];
581 if (thrower.error()) break;
582
583 DCHECK_EQ(i, func.func_index);
584 WasmName str = module->GetName(func.name_offset, func.name_length);
585 WasmName str_null = {nullptr, 0};
586 Handle<String> name = factory->InternalizeUtf8String(str);
587 Handle<Code> code = Handle<Code>::null();
588 Handle<JSFunction> function = Handle<JSFunction>::null();
589 if (func.external) {
590 // Lookup external function in FFI object.
591 MaybeHandle<JSFunction> function =
592 LookupFunction(thrower, factory, ffi, i, str, str_null);
593 if (function.is_null()) {
594 return false;
595 }
596 code = compiler::CompileWasmToJSWrapper(isolate, &module_env,
597 function.ToHandleChecked(),
598 func.sig, str, str_null);
599 } else {
600 if (FLAG_wasm_num_compilation_tasks != 0) {
601 code = results[i];
602 } else {
603 // Compile the function.
604 code = compiler::CompileWasmFunction(&thrower, isolate, &module_env,
605 &func);
606 }
607 if (code.is_null()) {
608 thrower.Error("Compilation of #%d:%.*s failed.", i, str.length(),
609 str.start());
610 return false;
611 }
612 if (func.exported) {
613 function = compiler::CompileJSToWasmWrapper(
614 isolate, &module_env, name, code, instance.js_object, i);
615 record_code_size(total_code_size, function->code());
616 }
617 }
618 if (!code.is_null()) {
619 // Install the code into the linker table.
620 module_env.linker->Finish(i, code);
621 code_table->set(i, *code);
622 record_code_size(total_code_size, *code);
623 }
624 if (func.exported) {
625 // Exported functions are installed as read-only properties on the
626 // module.
627 desc.set_value(function);
628 Maybe<bool> status = JSReceiver::DefineOwnProperty(
629 isolate, instance.js_object, name, &desc, Object::THROW_ON_ERROR);
630 if (!status.IsJust())
631 thrower.Error("export of %.*s failed.", str.length(), str.start());
632 }
633 }
634 return true;
635 }
636 } // namespace
637
638 // Instantiates a wasm module as a JSObject. 398 // Instantiates a wasm module as a JSObject.
639 // * allocates a backing store of {mem_size} bytes. 399 // * allocates a backing store of {mem_size} bytes.
640 // * installs a named property "memory" for that buffer if exported 400 // * installs a named property "memory" for that buffer if exported
641 // * installs named properties on the object for exported functions 401 // * installs named properties on the object for exported functions
642 // * compiles wasm code to machine code 402 // * compiles wasm code to machine code
643 MaybeHandle<JSObject> WasmModule::Instantiate(Isolate* isolate, 403 MaybeHandle<JSObject> WasmModule::Instantiate(Isolate* isolate,
644 Handle<JSReceiver> ffi, 404 Handle<JSReceiver> ffi,
645 Handle<JSArrayBuffer> memory) { 405 Handle<JSArrayBuffer> memory) {
646 HistogramTimerScope wasm_instantiate_module_time_scope( 406 HistogramTimerScope wasm_instantiate_module_time_scope(
647 isolate->counters()->wasm_instantiate_module_time()); 407 isolate->counters()->wasm_instantiate_module_time());
648 this->shared_isolate = isolate; // TODO(titzer): have a real shared isolate. 408 this->shared_isolate = isolate; // TODO(titzer): have a real shared isolate.
649 ErrorThrower thrower(isolate, "WasmModule::Instantiate()"); 409 ErrorThrower thrower(isolate, "WasmModule::Instantiate()");
650 Factory* factory = isolate->factory(); 410 Factory* factory = isolate->factory();
651 411
652 PropertyDescriptor desc; 412 PropertyDescriptor desc;
653 desc.set_writable(false); 413 desc.set_writable(false);
654 414
655 // If FLAG_print_wasm_code_size is set, this aggregates the sum of all code 415 // If FLAG_print_wasm_code_size is set, this aggregates the sum of all code
656 // objects created for this module. 416 // objects created for this module.
657 // TODO(titzer): switch this to TRACE_EVENT 417 // TODO(titzer): switch this to TRACE_EVENT
658 uint32_t total_code_size = 0; 418 uint32_t total_code_size = 0;
419 auto record_code_size = [&total_code_size](Code* code) {
420 if (FLAG_print_wasm_code_size)
421 total_code_size += code->body_size() + code->relocation_info()->length();
422 };
659 423
660 //------------------------------------------------------------------------- 424 //-------------------------------------------------------------------------
661 // Allocate the instance and its JS counterpart. 425 // Allocate the instance and its JS counterpart.
662 //------------------------------------------------------------------------- 426 //-------------------------------------------------------------------------
663 Handle<Map> map = factory->NewMap( 427 Handle<Map> map = factory->NewMap(
664 JS_OBJECT_TYPE, 428 JS_OBJECT_TYPE,
665 JSObject::kHeaderSize + kWasmModuleInternalFieldCount * kPointerSize); 429 JSObject::kHeaderSize + kWasmModuleInternalFieldCount * kPointerSize);
666 WasmModuleInstance instance(this); 430 WasmModuleInstance instance(this);
667 instance.context = isolate->native_context(); 431 instance.context = isolate->native_context();
668 instance.js_object = factory->NewJSObjectFromMap(map, TENURED); 432 instance.js_object = factory->NewJSObjectFromMap(map, TENURED);
(...skipping 26 matching lines...) Expand all
695 return MaybeHandle<JSObject>(); 459 return MaybeHandle<JSObject>();
696 } 460 }
697 if (!instance.globals_buffer.is_null()) { 461 if (!instance.globals_buffer.is_null()) {
698 instance.js_object->SetInternalField(kWasmGlobalsArrayBuffer, 462 instance.js_object->SetInternalField(kWasmGlobalsArrayBuffer,
699 *instance.globals_buffer); 463 *instance.globals_buffer);
700 } 464 }
701 465
702 HistogramTimerScope wasm_compile_module_time_scope( 466 HistogramTimerScope wasm_compile_module_time_scope(
703 isolate->counters()->wasm_compile_module_time()); 467 isolate->counters()->wasm_compile_module_time());
704 468
469 //-------------------------------------------------------------------------
470 // Compile wrappers to imported functions.
471 //-------------------------------------------------------------------------
472 uint32_t index = 0;
705 instance.function_table = BuildFunctionTable(isolate, this); 473 instance.function_table = BuildFunctionTable(isolate, this);
706 WasmLinker linker(isolate, functions.size()); 474 WasmLinker linker(isolate, functions.size());
707 ModuleEnv module_env; 475 ModuleEnv module_env;
708 module_env.module = this; 476 module_env.module = this;
709 module_env.instance = &instance; 477 module_env.instance = &instance;
710 module_env.linker = &linker; 478 module_env.linker = &linker;
711 module_env.origin = origin; 479 module_env.origin = origin;
712 480
713 //------------------------------------------------------------------------- 481 if (import_table.size() > 0) {
714 // Compile wrappers to imported functions. 482 instance.import_code.reserve(import_table.size());
715 //------------------------------------------------------------------------- 483 for (const WasmImport& import : import_table) {
716 if (!CompileWrappersToImportedFunctions(isolate, this, ffi, &instance, 484 WasmName module_name =
717 &thrower, factory, &module_env, 485 GetNameOrNull(import.module_name_offset, import.module_name_length);
718 total_code_size)) { 486 WasmName function_name = GetNameOrNull(import.function_name_offset,
719 return MaybeHandle<JSObject>(); 487 import.function_name_length);
488 MaybeHandle<JSFunction> function = LookupFunction(
489 thrower, factory, ffi, index, module_name, function_name);
490 if (function.is_null()) return MaybeHandle<JSObject>();
491 Handle<Code> code = compiler::CompileWasmToJSWrapper(
492 isolate, &module_env, function.ToHandleChecked(), import.sig,
493 module_name, function_name);
494 instance.import_code.push_back(code);
495 record_code_size(*code);
496 index++;
497 }
720 } 498 }
499
721 //------------------------------------------------------------------------- 500 //-------------------------------------------------------------------------
722 // Compile all functions in the module. 501 // Compile all functions in the module.
723 //------------------------------------------------------------------------- 502 //-------------------------------------------------------------------------
724 { 503 {
725 isolate->counters()->wasm_functions_per_module()->AddSample( 504 isolate->counters()->wasm_functions_per_module()->AddSample(
726 static_cast<int>(functions.size())); 505 static_cast<int>(functions.size()));
727 506
728 // Data structures for the parallel compilation.
729 std::vector<compiler::WasmCompilationUnit*> compilation_units( 507 std::vector<compiler::WasmCompilationUnit*> compilation_units(
730 functions.size()); 508 functions.size());
731 std::queue<compiler::WasmCompilationUnit*> executed_units; 509 std::queue<compiler::WasmCompilationUnit*> executed_units;
732 std::vector<Handle<Code>> results(functions.size()); 510 std::vector<Handle<Code>> results(functions.size());
733 511
734 if (FLAG_wasm_num_compilation_tasks != 0) { 512 if (FLAG_wasm_parallel_compilation) {
735 //----------------------------------------------------------------------- 513 // Create a placeholder code object for all functions.
736 // For parallel compilation: 514 // TODO(ahaas): Maybe we could skip this for external functions.
737 // 1) The main thread allocates a compilation unit for each wasm function 515 for (uint32_t i = 0; i < functions.size(); i++) {
738 // and stores them in the vector {compilation_units}. 516 linker.GetFunctionCode(i);
739 // 2) The main thread spawns {WasmCompilationTask} instances which run on 517 }
740 // the background threads.
741 // 3.a) The background threads and the main thread pick one compilation
742 // unit at a time and execute the parallel phase of the compilation
743 // unit. After finishing the execution of the parallel phase, the
744 // result is enqueued in {executed_units}.
745 // 3.b) If {executed_units} contains a compilation unit, the main thread
746 // dequeues it and finishes the compilation.
747 // 4) After the parallel phase of all compilation units has started, the
748 // main thread waits for all {WasmCompilationTask} instances to finish.
749 // 5) The main thread finishes the compilation.
750 518
751 // Turn on the {CanonicalHandleScope} so that the background threads can 519 for (uint32_t i = FLAG_skip_compiling_wasm_funcs; i < functions.size();
752 // use the node cache. 520 i++) {
753 CanonicalHandleScope canonical(isolate); 521 if (!functions[i].external) {
522 compilation_units[i] = compiler::CreateWasmCompilationUnit(
523 &thrower, isolate, &module_env, &functions[i], i);
524 }
525 }
754 526
755 // 1) The main thread allocates a compilation unit for each wasm function 527 index = FLAG_skip_compiling_wasm_funcs;
756 // and stores them in the vector {compilation_units}. 528 while (true) {
757 InitializeParallelCompilation(isolate, functions, compilation_units, 529 while (!executed_units.empty()) {
758 module_env, thrower); 530 compiler::WasmCompilationUnit* unit = executed_units.front();
759 531 executed_units.pop();
760 // Objects for the synchronization with the background threads. 532 int i = compiler::GetIndexOfWasmCompilationUnit(unit);
761 base::SmartPointer<base::Semaphore> pending_tasks(new base::Semaphore(0)); 533 results[i] = compiler::FinishCompilation(unit);
762 base::Mutex result_mutex; 534 }
763 base::AtomicNumber<size_t> next_unit( 535 if (index < functions.size()) {
764 static_cast<size_t>(FLAG_skip_compiling_wasm_funcs)); 536 if (!functions[index].external) {
765 537 compiler::ExecuteCompilation(compilation_units[index]);
766 // 2) The main thread spawns {WasmCompilationTask} instances which run on 538 executed_units.push(compilation_units[index]);
767 // the background threads. 539 index++;
768 base::SmartArrayPointer<uint32_t> task_ids( 540 }
769 StartCompilationTasks(isolate, compilation_units, executed_units, 541 } else {
770 pending_tasks, result_mutex, next_unit)); 542 break;
771 543 }
772 // 3.a) The background threads and the main thread pick one compilation
773 // unit at a time and execute the parallel phase of the compilation
774 // unit. After finishing the execution of the parallel phase, the
775 // result is enqueued in {executed_units}.
776 while (FetchAndExecuteCompilationUnit(isolate, &compilation_units,
777 &executed_units, &result_mutex,
778 &next_unit)) {
779 // 3.b) If {executed_units} contains a compilation unit, the main thread
780 // dequeues it and finishes the compilation unit. Compilation units
781 // are finished concurrently to the background threads to save
782 // memory.
783 FinishCompilationUnits(this, executed_units, results, result_mutex);
784 } 544 }
785 // 4) After the parallel phase of all compilation units has started, the
786 // main thread waits for all {WasmCompilationTask} instances to finish.
787 WaitForCompilationTasks(isolate, task_ids.get(), pending_tasks);
788 // Finish the compilation of the remaining compilation units.
789 FinishCompilationUnits(this, executed_units, results, result_mutex);
790 }
791 // 5) The main thread finishes the compilation.
792 if (!FinishCompilation(isolate, this, ffi, results, instance, code_table,
793 thrower, factory, module_env, total_code_size,
794 desc)) {
795 return MaybeHandle<JSObject>();
796 } 545 }
797 546
798 // Patch all direct call sites. 547 // First pass: compile each function and initialize the code table.
548 for (uint32_t i = FLAG_skip_compiling_wasm_funcs; i < functions.size();
549 i++) {
550 const WasmFunction& func = functions[i];
551 if (thrower.error()) break;
552 DCHECK_EQ(i, func.func_index);
553
554 WasmName str = GetName(func.name_offset, func.name_length);
555 WasmName str_null = {nullptr, 0};
556 Handle<String> name = factory->InternalizeUtf8String(str);
557 Handle<Code> code = Handle<Code>::null();
558 Handle<JSFunction> function = Handle<JSFunction>::null();
559 if (func.external) {
560 // Lookup external function in FFI object.
561 MaybeHandle<JSFunction> function =
562 LookupFunction(thrower, factory, ffi, i, str, str_null);
563 if (function.is_null()) return MaybeHandle<JSObject>();
564 code = compiler::CompileWasmToJSWrapper(isolate, &module_env,
565 function.ToHandleChecked(),
566 func.sig, str, str_null);
567 } else {
568 if (FLAG_wasm_parallel_compilation) {
569 code = results[i];
570 } else {
571 // Compile the function.
572 code = compiler::CompileWasmFunction(&thrower, isolate, &module_env,
573 &func);
574 }
575 if (code.is_null()) {
576 thrower.Error("Compilation of #%d:%.*s failed.", i, str.length(),
577 str.start());
578 return MaybeHandle<JSObject>();
579 }
580 if (func.exported) {
581 function = compiler::CompileJSToWasmWrapper(
582 isolate, &module_env, name, code, instance.js_object, i);
583 record_code_size(function->code());
584 }
585 }
586 if (!code.is_null()) {
587 // Install the code into the linker table.
588 linker.Finish(i, code);
589 code_table->set(i, *code);
590 record_code_size(*code);
591 }
592 if (func.exported) {
593 // Exported functions are installed as read-only properties on the
594 // module.
595 desc.set_value(function);
596 Maybe<bool> status = JSReceiver::DefineOwnProperty(
597 isolate, instance.js_object, name, &desc, Object::THROW_ON_ERROR);
598 if (!status.IsJust())
599 thrower.Error("export of %.*s failed.", str.length(), str.start());
600 }
601 }
602
603 // Second pass: patch all direct call sites.
799 linker.Link(instance.function_table, this->function_table); 604 linker.Link(instance.function_table, this->function_table);
800 instance.js_object->SetInternalField(kWasmModuleFunctionTable, 605 instance.js_object->SetInternalField(kWasmModuleFunctionTable,
801 Smi::FromInt(0)); 606 Smi::FromInt(0));
802 607
803 //------------------------------------------------------------------------- 608 //-------------------------------------------------------------------------
804 // Create and populate the exports object. 609 // Create and populate the exports object.
805 //------------------------------------------------------------------------- 610 //-------------------------------------------------------------------------
806 if (export_table.size() > 0 || mem_export) { 611 if (export_table.size() > 0 || mem_export) {
807 // Create the "exports" object. 612 // Create the "exports" object.
808 Handle<JSFunction> object_function = Handle<JSFunction>( 613 Handle<JSFunction> object_function = Handle<JSFunction>(
809 isolate->native_context()->object_function(), isolate); 614 isolate->native_context()->object_function(), isolate);
810 Handle<JSObject> exports_object = 615 Handle<JSObject> exports_object =
811 factory->NewJSObject(object_function, TENURED); 616 factory->NewJSObject(object_function, TENURED);
812 Handle<String> exports_name = factory->InternalizeUtf8String("exports"); 617 Handle<String> exports_name = factory->InternalizeUtf8String("exports");
813 JSObject::AddProperty(instance.js_object, exports_name, exports_object, 618 JSObject::AddProperty(instance.js_object, exports_name, exports_object,
814 READ_ONLY); 619 READ_ONLY);
815 620
816 // Compile wrappers and add them to the exports object. 621 // Compile wrappers and add them to the exports object.
817 for (const WasmExport& exp : export_table) { 622 for (const WasmExport& exp : export_table) {
818 if (thrower.error()) break; 623 if (thrower.error()) break;
819 WasmName str = GetName(exp.name_offset, exp.name_length); 624 WasmName str = GetName(exp.name_offset, exp.name_length);
820 Handle<String> name = factory->InternalizeUtf8String(str); 625 Handle<String> name = factory->InternalizeUtf8String(str);
821 Handle<Code> code = linker.GetFunctionCode(exp.func_index); 626 Handle<Code> code = linker.GetFunctionCode(exp.func_index);
822 Handle<JSFunction> function = compiler::CompileJSToWasmWrapper( 627 Handle<JSFunction> function = compiler::CompileJSToWasmWrapper(
823 isolate, &module_env, name, code, instance.js_object, 628 isolate, &module_env, name, code, instance.js_object,
824 exp.func_index); 629 exp.func_index);
825 record_code_size(total_code_size, function->code()); 630 record_code_size(function->code());
826 desc.set_value(function); 631 desc.set_value(function);
827 Maybe<bool> status = JSReceiver::DefineOwnProperty( 632 Maybe<bool> status = JSReceiver::DefineOwnProperty(
828 isolate, exports_object, name, &desc, Object::THROW_ON_ERROR); 633 isolate, exports_object, name, &desc, Object::THROW_ON_ERROR);
829 if (!status.IsJust()) 634 if (!status.IsJust())
830 thrower.Error("export of %.*s failed.", str.length(), str.start()); 635 thrower.Error("export of %.*s failed.", str.length(), str.start());
831 } 636 }
832 637
833 if (mem_export) { 638 if (mem_export) {
834 // Export the memory as a named property. 639 // Export the memory as a named property.
835 Handle<String> name = factory->InternalizeUtf8String("memory"); 640 Handle<String> name = factory->InternalizeUtf8String("memory");
(...skipping 168 matching lines...) Expand 10 before | Expand all | Expand 10 after
1004 wasm->GetInternalField(kWasmFunctionNamesArray), wasm->GetIsolate()); 809 wasm->GetInternalField(kWasmFunctionNamesArray), wasm->GetIsolate());
1005 if (func_names_arr_obj->IsUndefined()) 810 if (func_names_arr_obj->IsUndefined())
1006 return func_names_arr_obj; // Return undefined. 811 return func_names_arr_obj; // Return undefined.
1007 return GetWasmFunctionNameFromTable( 812 return GetWasmFunctionNameFromTable(
1008 Handle<ByteArray>::cast(func_names_arr_obj), func_index); 813 Handle<ByteArray>::cast(func_names_arr_obj), func_index);
1009 } 814 }
1010 815
1011 } // namespace wasm 816 } // namespace wasm
1012 } // namespace internal 817 } // namespace internal
1013 } // namespace v8 818 } // namespace v8
OLDNEW
« no previous file with comments | « src/flag-definitions.h ('k') | test/mjsunit/wasm/parallel_compilation.js » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698