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

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

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

Powered by Google App Engine
This is Rietveld 408576698