OLD | NEW |
---|---|
1 // Copyright 2015 the V8 project authors. All rights reserved. | 1 // Copyright 2015 the V8 project authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "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 |
(...skipping 401 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
412 index++; | 412 index++; |
413 } | 413 } |
414 } | 414 } |
415 return true; | 415 return true; |
416 } | 416 } |
417 | 417 |
418 void InitializeParallelCompilation( | 418 void InitializeParallelCompilation( |
419 Isolate* isolate, const std::vector<WasmFunction>& functions, | 419 Isolate* isolate, const std::vector<WasmFunction>& functions, |
420 std::vector<compiler::WasmCompilationUnit*>& compilation_units, | 420 std::vector<compiler::WasmCompilationUnit*>& compilation_units, |
421 ModuleEnv& module_env, ErrorThrower& thrower) { | 421 ModuleEnv& module_env, ErrorThrower& thrower) { |
422 // Create a placeholder code object for all functions. | |
423 // TODO(ahaas): Maybe we could skip this for external functions. | |
titzer
2016/05/26 15:12:25
Why did you delete this code? It's necessary to cr
Mircea Trofin
2016/05/26 15:53:18
The CL has the refactoring one as a dependency. Th
| |
424 for (uint32_t i = 0; i < functions.size(); i++) { | |
425 module_env.linker->GetFunctionCode(i); | |
426 } | |
427 | |
428 for (uint32_t i = FLAG_skip_compiling_wasm_funcs; i < functions.size(); i++) { | 422 for (uint32_t i = FLAG_skip_compiling_wasm_funcs; i < functions.size(); i++) { |
429 compilation_units[i] = new compiler::WasmCompilationUnit( | 423 compilation_units[i] = new compiler::WasmCompilationUnit( |
430 &thrower, isolate, &module_env, &functions[i], i); | 424 &thrower, isolate, &module_env, &functions[i], i); |
431 } | 425 } |
432 } | 426 } |
433 | 427 |
434 uint32_t* StartCompilationTasks( | 428 uint32_t* StartCompilationTasks( |
435 Isolate* isolate, | 429 Isolate* isolate, |
436 std::vector<compiler::WasmCompilationUnit*>& compilation_units, | 430 std::vector<compiler::WasmCompilationUnit*>& compilation_units, |
437 std::queue<compiler::WasmCompilationUnit*>& executed_units, | 431 std::queue<compiler::WasmCompilationUnit*>& executed_units, |
(...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
479 } | 473 } |
480 unit = executed_units.front(); | 474 unit = executed_units.front(); |
481 executed_units.pop(); | 475 executed_units.pop(); |
482 } | 476 } |
483 int j = unit->index(); | 477 int j = unit->index(); |
484 results[j] = unit->FinishCompilation(); | 478 results[j] = unit->FinishCompilation(); |
485 delete unit; | 479 delete unit; |
486 } | 480 } |
487 } | 481 } |
488 | 482 |
489 bool FinishCompilation(Isolate* isolate, const WasmModule* module, | 483 void CompileSequentially(Isolate* isolate, WasmModuleInstance* instance, |
titzer
2016/05/26 15:12:25
I like the old name better.
Mircea Trofin
2016/05/26 15:53:18
It doesn't finish anything anymore now. It does th
| |
490 const Handle<JSReceiver> ffi, | 484 ErrorThrower* thrower, ModuleEnv* module_env) { |
491 const std::vector<Handle<Code>>& results, | 485 DCHECK(!thrower->error()); |
492 const WasmModuleInstance& instance, | 486 const WasmModule* module = instance->module(); |
493 const Handle<FixedArray>& code_table, | 487 |
494 ErrorThrower& thrower, Factory* factory, | |
495 ModuleEnv& module_env, CodeStats& code_stats, | |
496 PropertyDescriptor& desc) { | |
497 if (thrower.error()) return false; | |
498 for (uint32_t i = FLAG_skip_compiling_wasm_funcs; | 488 for (uint32_t i = FLAG_skip_compiling_wasm_funcs; |
499 i < module->functions.size(); i++) { | 489 i < module->functions.size(); i++) { |
500 const WasmFunction& func = module->functions[i]; | 490 const WasmFunction& func = module->functions[i]; |
501 | 491 |
502 DCHECK_EQ(i, func.func_index); | 492 DCHECK_EQ(i, func.func_index); |
503 WasmName str = module->GetName(func.name_offset, func.name_length); | 493 WasmName str = module->GetName(func.name_offset, func.name_length); |
504 Handle<Code> code = Handle<Code>::null(); | 494 Handle<Code> code = Handle<Code>::null(); |
505 if (FLAG_wasm_num_compilation_tasks != 0) { | 495 // Compile the function. |
titzer
2016/05/26 15:12:25
wat
Mircea Trofin
2016/05/26 15:53:17
Typo?
| |
506 code = results[i]; | 496 code = compiler::WasmCompilationUnit::CompileWasmFunction( |
507 } else { | 497 thrower, isolate, module_env, &func); |
508 // Compile the function. | 498 if (code.is_null()) { |
509 code = compiler::WasmCompilationUnit::CompileWasmFunction( | 499 thrower->Error("Compilation of #%d:%.*s failed.", i, str.length(), |
510 &thrower, isolate, &module_env, &func); | 500 str.start()); |
501 break; | |
511 } | 502 } |
512 if (code.is_null()) { | |
513 thrower.Error("Compilation of #%d:%.*s failed.", i, str.length(), | |
514 str.start()); | |
515 return false; | |
516 } | |
517 if (!code.is_null()) { | |
518 // Install the code into the linker table. | 503 // Install the code into the linker table. |
519 module_env.linker->Finish(i, code); | 504 instance->function_code()[i] = code; |
520 code_table->set(i, *code); | |
521 code_stats.Record(*code); | |
522 } | |
523 } | 505 } |
524 return true; | |
525 } | 506 } |
526 } // namespace | 507 } // namespace |
527 | 508 |
528 void WasmModuleInstance::LoadDataSegments() { | 509 void WasmModuleInstance::LoadDataSegments() { |
529 for (const WasmDataSegment& segment : module()->data_segments) { | 510 for (const WasmDataSegment& segment : module()->data_segments) { |
530 if (!segment.init) continue; | 511 if (!segment.init) continue; |
531 if (!segment.source_size) continue; | 512 if (!segment.source_size) continue; |
532 CHECK_LT(segment.dest_addr, mem_size()); | 513 CHECK_LT(segment.dest_addr, mem_size()); |
533 CHECK_LE(segment.source_size, mem_size()); | 514 CHECK_LE(segment.source_size, mem_size()); |
534 CHECK_LE(segment.dest_addr + segment.source_size, mem_size()); | 515 CHECK_LE(segment.dest_addr + segment.source_size, mem_size()); |
(...skipping 79 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
614 CodeDesc desc = {buffer, 8, 8, 0, 0, nullptr}; | 595 CodeDesc desc = {buffer, 8, 8, 0, 0, nullptr}; |
615 Handle<Code> code = isolate_->factory()->NewCode( | 596 Handle<Code> code = isolate_->factory()->NewCode( |
616 desc, Code::KindField::encode(Code::WASM_FUNCTION), | 597 desc, Code::KindField::encode(Code::WASM_FUNCTION), |
617 Handle<Object>::null()); | 598 Handle<Object>::null()); |
618 code->set_constant_pool_offset(static_cast<int>(index) + | 599 code->set_constant_pool_offset(static_cast<int>(index) + |
619 kPlaceholderMarker); | 600 kPlaceholderMarker); |
620 function_code()[index] = code; | 601 function_code()[index] = code; |
621 } | 602 } |
622 } | 603 } |
623 | 604 |
605 void WasmModuleInstance::ProcessFunctionsPostLinking() { | |
titzer
2016/05/26 15:12:25
Please name this function for what it does. SetDeo
Mircea Trofin
2016/05/26 15:53:18
Agreed.
Mircea Trofin
2016/05/27 01:17:33
Actually... Perhaps SetStackTracingHelpers may be
| |
606 for (size_t i = FLAG_skip_compiling_wasm_funcs; i < function_code().size(); | |
607 ++i) { | |
608 Handle<Code> code = function_code()[i]; | |
609 DCHECK(code->deoptimization_data() == nullptr || | |
610 code->deoptimization_data()->length() == 0); | |
611 Handle<FixedArray> deopt_data = | |
612 isolate_->factory()->NewFixedArray(2, TENURED); | |
613 if (!js_object().is_null()) { | |
614 deopt_data->set(0, *js_object()); | |
615 } | |
616 deopt_data->set(1, Smi::FromInt(static_cast<int>(i))); | |
617 deopt_data->set_length(2); | |
618 code->set_deoptimization_data(*deopt_data); | |
619 } | |
620 } | |
621 | |
624 // Instantiates a wasm module as a JSObject. | 622 // Instantiates a wasm module as a JSObject. |
625 // * allocates a backing store of {mem_size} bytes. | 623 // * allocates a backing store of {mem_size} bytes. |
626 // * installs a named property "memory" for that buffer if exported | 624 // * installs a named property "memory" for that buffer if exported |
627 // * installs named properties on the object for exported functions | 625 // * installs named properties on the object for exported functions |
628 // * compiles wasm code to machine code | 626 // * compiles wasm code to machine code |
629 MaybeHandle<JSObject> WasmModule::Instantiate( | 627 MaybeHandle<JSObject> WasmModule::Instantiate( |
630 Isolate* isolate, Handle<JSReceiver> ffi, | 628 Isolate* isolate, Handle<JSReceiver> ffi, |
631 Handle<JSArrayBuffer> memory) const { | 629 Handle<JSArrayBuffer> memory) const { |
632 HistogramTimerScope wasm_instantiate_module_time_scope( | 630 HistogramTimerScope wasm_instantiate_module_time_scope( |
633 isolate->counters()->wasm_instantiate_module_time()); | 631 isolate->counters()->wasm_instantiate_module_time()); |
634 ErrorThrower thrower(isolate, "WasmModule::Instantiate()"); | 632 ErrorThrower thrower(isolate, "WasmModule::Instantiate()"); |
635 Factory* factory = isolate->factory(); | 633 Factory* factory = isolate->factory(); |
636 | 634 |
637 PropertyDescriptor desc; | |
638 desc.set_writable(false); | |
639 | |
640 // If FLAG_print_wasm_code_size is set, this aggregates the sum of all code | 635 // If FLAG_print_wasm_code_size is set, this aggregates the sum of all code |
641 // objects created for this module. | 636 // objects created for this module. |
642 // TODO(titzer): switch this to TRACE_EVENT | 637 // TODO(titzer): switch this to TRACE_EVENT |
643 CodeStats code_stats; | 638 CodeStats code_stats; |
644 | 639 |
645 //------------------------------------------------------------------------- | 640 //------------------------------------------------------------------------- |
646 // Allocate the instance and its JS counterpart. | 641 // Allocate the instance and its JS counterpart. |
647 //------------------------------------------------------------------------- | 642 //------------------------------------------------------------------------- |
648 WasmModuleInstance instance(this, isolate); | 643 WasmModuleInstance instance(this, isolate); |
649 instance.set_native_context(isolate->native_context()); | 644 instance.set_native_context(isolate->native_context()); |
(...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
695 // Compile all functions in the module. | 690 // Compile all functions in the module. |
696 //------------------------------------------------------------------------- | 691 //------------------------------------------------------------------------- |
697 { | 692 { |
698 isolate->counters()->wasm_functions_per_module()->AddSample( | 693 isolate->counters()->wasm_functions_per_module()->AddSample( |
699 static_cast<int>(functions.size())); | 694 static_cast<int>(functions.size())); |
700 | 695 |
701 // Data structures for the parallel compilation. | 696 // Data structures for the parallel compilation. |
702 std::vector<compiler::WasmCompilationUnit*> compilation_units( | 697 std::vector<compiler::WasmCompilationUnit*> compilation_units( |
703 functions.size()); | 698 functions.size()); |
704 std::queue<compiler::WasmCompilationUnit*> executed_units; | 699 std::queue<compiler::WasmCompilationUnit*> executed_units; |
705 std::vector<Handle<Code>> results(functions.size()); | |
706 | 700 |
707 if (FLAG_wasm_num_compilation_tasks != 0) { | 701 if (FLAG_wasm_num_compilation_tasks != 0) { |
708 //----------------------------------------------------------------------- | 702 //----------------------------------------------------------------------- |
709 // For parallel compilation: | 703 // For parallel compilation: |
710 // 1) The main thread allocates a compilation unit for each wasm function | 704 // 1) The main thread allocates a compilation unit for each wasm function |
711 // and stores them in the vector {compilation_units}. | 705 // and stores them in the vector {compilation_units}. |
712 // 2) The main thread spawns {WasmCompilationTask} instances which run on | 706 // 2) The main thread spawns {WasmCompilationTask} instances which run on |
713 // the background threads. | 707 // the background threads. |
714 // 3.a) The background threads and the main thread pick one compilation | 708 // 3.a) The background threads and the main thread pick one compilation |
715 // unit at a time and execute the parallel phase of the compilation | 709 // unit at a time and execute the parallel phase of the compilation |
(...skipping 30 matching lines...) Expand all Loading... | |
746 // unit at a time and execute the parallel phase of the compilation | 740 // unit at a time and execute the parallel phase of the compilation |
747 // unit. After finishing the execution of the parallel phase, the | 741 // unit. After finishing the execution of the parallel phase, the |
748 // result is enqueued in {executed_units}. | 742 // result is enqueued in {executed_units}. |
749 while (FetchAndExecuteCompilationUnit(isolate, &compilation_units, | 743 while (FetchAndExecuteCompilationUnit(isolate, &compilation_units, |
750 &executed_units, &result_mutex, | 744 &executed_units, &result_mutex, |
751 &next_unit)) { | 745 &next_unit)) { |
752 // 3.b) If {executed_units} contains a compilation unit, the main thread | 746 // 3.b) If {executed_units} contains a compilation unit, the main thread |
753 // dequeues it and finishes the compilation unit. Compilation units | 747 // dequeues it and finishes the compilation unit. Compilation units |
754 // are finished concurrently to the background threads to save | 748 // are finished concurrently to the background threads to save |
755 // memory. | 749 // memory. |
756 FinishCompilationUnits(executed_units, results, result_mutex); | 750 FinishCompilationUnits(executed_units, instance.function_code(), |
751 result_mutex); | |
757 } | 752 } |
758 // 4) After the parallel phase of all compilation units has started, the | 753 // 4) After the parallel phase of all compilation units has started, the |
759 // main thread waits for all {WasmCompilationTask} instances to finish. | 754 // main thread waits for all {WasmCompilationTask} instances to finish. |
760 WaitForCompilationTasks(isolate, task_ids.get(), pending_tasks); | 755 WaitForCompilationTasks(isolate, task_ids.get(), pending_tasks); |
761 // Finish the compilation of the remaining compilation units. | 756 // Finish the compilation of the remaining compilation units. |
762 FinishCompilationUnits(executed_units, results, result_mutex); | 757 FinishCompilationUnits(executed_units, instance.function_code(), |
758 result_mutex); | |
759 } else { | |
760 // 5) The main thread finishes the compilation. | |
761 CompileSequentially(isolate, &instance, &thrower, &module_env); | |
763 } | 762 } |
764 // 5) The main thread finishes the compilation. | 763 if (thrower.error()) { |
765 if (!FinishCompilation(isolate, this, ffi, results, instance, code_table, | |
766 thrower, factory, module_env, code_stats, desc)) { | |
767 return Handle<JSObject>::null(); | 764 return Handle<JSObject>::null(); |
768 } | 765 } |
769 | 766 |
767 // At this point, compilation has completed. Update the code table | |
768 // and record sizes. | |
769 for (size_t i = FLAG_skip_compiling_wasm_funcs; | |
770 i < instance.function_code().size(); ++i) { | |
771 Code* code = *instance.function_code()[i]; | |
772 code_table->set(static_cast<int>(i), code); | |
773 code_stats.Record(code); | |
774 } | |
775 | |
770 // Patch all direct call sites. | 776 // Patch all direct call sites. |
771 linker.Link(instance.function_table(), this->function_table); | 777 linker.Link(instance.function_table(), this->function_table); |
772 instance.js_object()->SetInternalField(kWasmModuleFunctionTable, | 778 instance.js_object()->SetInternalField(kWasmModuleFunctionTable, |
773 Smi::FromInt(0)); | 779 Smi::FromInt(0)); |
774 | 780 |
781 instance.ProcessFunctionsPostLinking(); | |
782 | |
775 //------------------------------------------------------------------------- | 783 //------------------------------------------------------------------------- |
776 // Create and populate the exports object. | 784 // Create and populate the exports object. |
777 //------------------------------------------------------------------------- | 785 //------------------------------------------------------------------------- |
778 if (export_table.size() > 0 || mem_export) { | 786 if (export_table.size() > 0 || mem_export) { |
779 Handle<JSObject> exports_object; | 787 Handle<JSObject> exports_object; |
780 if (origin == kWasmOrigin) { | 788 if (origin == kWasmOrigin) { |
781 // Create the "exports" object. | 789 // Create the "exports" object. |
782 Handle<JSFunction> object_function = Handle<JSFunction>( | 790 Handle<JSFunction> object_function = Handle<JSFunction>( |
783 isolate->native_context()->object_function(), isolate); | 791 isolate->native_context()->object_function(), isolate); |
784 exports_object = factory->NewJSObject(object_function, TENURED); | 792 exports_object = factory->NewJSObject(object_function, TENURED); |
785 Handle<String> exports_name = factory->InternalizeUtf8String("exports"); | 793 Handle<String> exports_name = factory->InternalizeUtf8String("exports"); |
786 JSObject::AddProperty(instance.js_object(), exports_name, | 794 JSObject::AddProperty(instance.js_object(), exports_name, |
787 exports_object, READ_ONLY); | 795 exports_object, READ_ONLY); |
788 } else { | 796 } else { |
789 // Just export the functions directly on the object returned. | 797 // Just export the functions directly on the object returned. |
790 exports_object = instance.js_object(); | 798 exports_object = instance.js_object(); |
791 } | 799 } |
792 | 800 |
801 PropertyDescriptor desc; | |
802 desc.set_writable(false); | |
803 | |
793 // Compile wrappers and add them to the exports object. | 804 // Compile wrappers and add them to the exports object. |
794 for (const WasmExport& exp : export_table) { | 805 for (const WasmExport& exp : export_table) { |
795 if (thrower.error()) break; | 806 if (thrower.error()) break; |
796 WasmName str = GetName(exp.name_offset, exp.name_length); | 807 WasmName str = GetName(exp.name_offset, exp.name_length); |
797 Handle<String> name = factory->InternalizeUtf8String(str); | 808 Handle<String> name = factory->InternalizeUtf8String(str); |
798 Handle<Code> code = linker.GetFunctionCode(exp.func_index); | 809 Handle<Code> code = linker.GetFunctionCode(exp.func_index); |
799 Handle<JSFunction> function = compiler::CompileJSToWasmWrapper( | 810 Handle<JSFunction> function = compiler::CompileJSToWasmWrapper( |
800 isolate, &module_env, name, code, instance.js_object(), | 811 isolate, &module_env, name, code, instance.js_object(), |
801 exp.func_index); | 812 exp.func_index); |
802 code_stats.Record(function->code()); | 813 code_stats.Record(function->code()); |
(...skipping 166 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
969 uint32_t func_index) { | 980 uint32_t func_index) { |
970 Object* func_names_arr_obj = wasm->GetInternalField(kWasmFunctionNamesArray); | 981 Object* func_names_arr_obj = wasm->GetInternalField(kWasmFunctionNamesArray); |
971 if (func_names_arr_obj->IsUndefined()) return Handle<String>::null(); | 982 if (func_names_arr_obj->IsUndefined()) return Handle<String>::null(); |
972 return GetWasmFunctionNameFromTable( | 983 return GetWasmFunctionNameFromTable( |
973 handle(ByteArray::cast(func_names_arr_obj)), func_index); | 984 handle(ByteArray::cast(func_names_arr_obj)), func_index); |
974 } | 985 } |
975 | 986 |
976 } // namespace wasm | 987 } // namespace wasm |
977 } // namespace internal | 988 } // namespace internal |
978 } // namespace v8 | 989 } // namespace v8 |
OLD | NEW |