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

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
(...skipping 401 matching lines...) Expand 10 before | Expand all | Expand 10 after
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
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
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
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
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
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
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