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 458 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
469 }; | 469 }; |
470 | 470 |
471 // Records statistics on the code generated by compiling WASM functions. | 471 // Records statistics on the code generated by compiling WASM functions. |
472 struct CodeStats { | 472 struct CodeStats { |
473 size_t code_size; | 473 size_t code_size; |
474 size_t reloc_size; | 474 size_t reloc_size; |
475 | 475 |
476 inline CodeStats() : code_size(0), reloc_size(0) {} | 476 inline CodeStats() : code_size(0), reloc_size(0) {} |
477 | 477 |
478 inline void Record(Code* code) { | 478 inline void Record(Code* code) { |
479 if (FLAG_print_wasm_code_size) { | 479 code_size += code->body_size(); |
480 code_size += code->body_size(); | 480 reloc_size += code->relocation_info()->length(); |
481 reloc_size += code->relocation_info()->length(); | |
482 } | |
483 } | 481 } |
484 | 482 |
485 inline void Report() { | 483 inline void Report() { |
486 if (FLAG_print_wasm_code_size) { | 484 PrintF("Total generated wasm code: %zu bytes\n", code_size); |
487 PrintF("Total generated wasm code: %zu bytes\n", code_size); | 485 PrintF("Total generated wasm reloc: %zu bytes\n", reloc_size); |
488 PrintF("Total generated wasm reloc: %zu bytes\n", reloc_size); | |
489 } | |
490 } | 486 } |
491 }; | 487 }; |
492 | 488 |
493 bool CompileWrappersToImportedFunctions( | 489 bool CompileWrappersToImportedFunctions(Isolate* isolate, |
494 Isolate* isolate, const WasmModule* module, const Handle<JSReceiver> ffi, | 490 const WasmModule* module, |
495 WasmModuleInstance* instance, ErrorThrower* thrower, Factory* factory, | 491 const Handle<JSReceiver> ffi, |
496 ModuleEnv* module_env, CodeStats& code_stats) { | 492 WasmModuleInstance* instance, |
| 493 ErrorThrower* thrower, Factory* factory, |
| 494 ModuleEnv* module_env) { |
497 if (module->import_table.size() > 0) { | 495 if (module->import_table.size() > 0) { |
498 instance->import_code.reserve(module->import_table.size()); | 496 instance->import_code.reserve(module->import_table.size()); |
499 for (uint32_t index = 0; index < module->import_table.size(); ++index) { | 497 for (uint32_t index = 0; index < module->import_table.size(); ++index) { |
500 const WasmImport& import = module->import_table[index]; | 498 const WasmImport& import = module->import_table[index]; |
501 WasmName module_name = module->GetNameOrNull(import.module_name_offset, | 499 WasmName module_name = module->GetNameOrNull(import.module_name_offset, |
502 import.module_name_length); | 500 import.module_name_length); |
503 WasmName function_name = module->GetNameOrNull( | 501 WasmName function_name = module->GetNameOrNull( |
504 import.function_name_offset, import.function_name_length); | 502 import.function_name_offset, import.function_name_length); |
505 MaybeHandle<JSFunction> function = LookupFunction( | 503 MaybeHandle<JSFunction> function = LookupFunction( |
506 *thrower, factory, ffi, index, module_name, function_name); | 504 *thrower, factory, ffi, index, module_name, function_name); |
507 if (function.is_null()) return false; | 505 if (function.is_null()) return false; |
508 | 506 |
509 Handle<Code> code = compiler::CompileWasmToJSWrapper( | 507 Handle<Code> code = compiler::CompileWasmToJSWrapper( |
510 isolate, module_env, function.ToHandleChecked(), import.sig, | 508 isolate, module_env, function.ToHandleChecked(), import.sig, |
511 module_name, function_name); | 509 module_name, function_name); |
512 instance->import_code[index] = code; | 510 instance->import_code[index] = code; |
513 code_stats.Record(*code); | |
514 } | 511 } |
515 } | 512 } |
516 return true; | 513 return true; |
517 } | 514 } |
518 | 515 |
519 void InitializeParallelCompilation( | 516 void InitializeParallelCompilation( |
520 Isolate* isolate, const std::vector<WasmFunction>& functions, | 517 Isolate* isolate, const std::vector<WasmFunction>& functions, |
521 std::vector<compiler::WasmCompilationUnit*>& compilation_units, | 518 std::vector<compiler::WasmCompilationUnit*>& compilation_units, |
522 ModuleEnv& module_env, ErrorThrower& thrower) { | 519 ModuleEnv& module_env, ErrorThrower& thrower) { |
523 for (uint32_t i = FLAG_skip_compiling_wasm_funcs; i < functions.size(); i++) { | 520 for (uint32_t i = FLAG_skip_compiling_wasm_funcs; i < functions.size(); i++) { |
(...skipping 172 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
696 } | 693 } |
697 deopt_data->set(1, Smi::FromInt(static_cast<int>(i))); | 694 deopt_data->set(1, Smi::FromInt(static_cast<int>(i))); |
698 deopt_data->set_length(2); | 695 deopt_data->set_length(2); |
699 code->set_deoptimization_data(*deopt_data); | 696 code->set_deoptimization_data(*deopt_data); |
700 } | 697 } |
701 } | 698 } |
702 | 699 |
703 Handle<FixedArray> WasmModule::CompileFunctions(Isolate* isolate) const { | 700 Handle<FixedArray> WasmModule::CompileFunctions(Isolate* isolate) const { |
704 Factory* factory = isolate->factory(); | 701 Factory* factory = isolate->factory(); |
705 ErrorThrower thrower(isolate, "WasmModule::CompileFunctions()"); | 702 ErrorThrower thrower(isolate, "WasmModule::CompileFunctions()"); |
706 CodeStats code_stats; | |
707 | 703 |
708 WasmModuleInstance temp_instance_for_compilation(this); | 704 WasmModuleInstance temp_instance_for_compilation(this); |
709 temp_instance_for_compilation.function_table = | 705 temp_instance_for_compilation.function_table = |
710 BuildFunctionTable(isolate, this); | 706 BuildFunctionTable(isolate, this); |
711 temp_instance_for_compilation.context = isolate->native_context(); | 707 temp_instance_for_compilation.context = isolate->native_context(); |
712 temp_instance_for_compilation.mem_size = GetMinModuleMemSize(this); | 708 temp_instance_for_compilation.mem_size = GetMinModuleMemSize(this); |
713 temp_instance_for_compilation.mem_start = nullptr; | 709 temp_instance_for_compilation.mem_start = nullptr; |
714 temp_instance_for_compilation.globals_start = nullptr; | 710 temp_instance_for_compilation.globals_start = nullptr; |
715 | 711 |
716 ModuleEnv module_env; | 712 ModuleEnv module_env; |
(...skipping 26 matching lines...) Expand all Loading... |
743 } | 739 } |
744 | 740 |
745 LinkModuleFunctions(isolate, temp_instance_for_compilation.function_code); | 741 LinkModuleFunctions(isolate, temp_instance_for_compilation.function_code); |
746 | 742 |
747 // At this point, compilation has completed. Update the code table | 743 // At this point, compilation has completed. Update the code table |
748 // and record sizes. | 744 // and record sizes. |
749 for (size_t i = FLAG_skip_compiling_wasm_funcs; | 745 for (size_t i = FLAG_skip_compiling_wasm_funcs; |
750 i < temp_instance_for_compilation.function_code.size(); ++i) { | 746 i < temp_instance_for_compilation.function_code.size(); ++i) { |
751 Code* code = *temp_instance_for_compilation.function_code[i]; | 747 Code* code = *temp_instance_for_compilation.function_code[i]; |
752 ret->set(static_cast<int>(i), code); | 748 ret->set(static_cast<int>(i), code); |
753 code_stats.Record(code); | |
754 } | 749 } |
755 | 750 |
756 PopulateFunctionTable(&temp_instance_for_compilation); | 751 PopulateFunctionTable(&temp_instance_for_compilation); |
757 | 752 |
758 return ret; | 753 return ret; |
759 } | 754 } |
760 | 755 |
761 // Instantiates a wasm module as a JSObject. | 756 // Instantiates a wasm module as a JSObject. |
762 // * allocates a backing store of {mem_size} bytes. | 757 // * allocates a backing store of {mem_size} bytes. |
763 // * installs a named property "memory" for that buffer if exported | 758 // * installs a named property "memory" for that buffer if exported |
764 // * installs named properties on the object for exported functions | 759 // * installs named properties on the object for exported functions |
765 // * compiles wasm code to machine code | 760 // * compiles wasm code to machine code |
766 MaybeHandle<JSObject> WasmModule::Instantiate( | 761 MaybeHandle<JSObject> WasmModule::Instantiate( |
767 Isolate* isolate, Handle<JSReceiver> ffi, | 762 Isolate* isolate, Handle<JSReceiver> ffi, |
768 Handle<JSArrayBuffer> memory) const { | 763 Handle<JSArrayBuffer> memory) const { |
769 HistogramTimerScope wasm_instantiate_module_time_scope( | 764 HistogramTimerScope wasm_instantiate_module_time_scope( |
770 isolate->counters()->wasm_instantiate_module_time()); | 765 isolate->counters()->wasm_instantiate_module_time()); |
771 ErrorThrower thrower(isolate, "WasmModule::Instantiate()"); | 766 ErrorThrower thrower(isolate, "WasmModule::Instantiate()"); |
772 Factory* factory = isolate->factory(); | 767 Factory* factory = isolate->factory(); |
773 | 768 |
774 // If FLAG_print_wasm_code_size is set, this aggregates the sum of all code | |
775 // objects created for this module. | |
776 // TODO(titzer): switch this to TRACE_EVENT | |
777 CodeStats code_stats; | |
778 | |
779 //------------------------------------------------------------------------- | 769 //------------------------------------------------------------------------- |
780 // Allocate the instance and its JS counterpart. | 770 // Allocate the instance and its JS counterpart. |
781 //------------------------------------------------------------------------- | 771 //------------------------------------------------------------------------- |
782 Handle<Map> map = factory->NewMap( | 772 Handle<Map> map = factory->NewMap( |
783 JS_OBJECT_TYPE, | 773 JS_OBJECT_TYPE, |
784 JSObject::kHeaderSize + kWasmModuleInternalFieldCount * kPointerSize); | 774 JSObject::kHeaderSize + kWasmModuleInternalFieldCount * kPointerSize); |
785 WasmModuleInstance instance(this); | 775 WasmModuleInstance instance(this); |
786 instance.context = isolate->native_context(); | 776 instance.context = isolate->native_context(); |
787 instance.js_object = factory->NewJSObjectFromMap(map, TENURED); | 777 instance.js_object = factory->NewJSObjectFromMap(map, TENURED); |
788 | 778 |
(...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
840 | 830 |
841 ModuleEnv module_env; | 831 ModuleEnv module_env; |
842 module_env.module = this; | 832 module_env.module = this; |
843 module_env.instance = &instance; | 833 module_env.instance = &instance; |
844 module_env.origin = origin; | 834 module_env.origin = origin; |
845 | 835 |
846 //------------------------------------------------------------------------- | 836 //------------------------------------------------------------------------- |
847 // Compile wrappers to imported functions. | 837 // Compile wrappers to imported functions. |
848 //------------------------------------------------------------------------- | 838 //------------------------------------------------------------------------- |
849 if (!CompileWrappersToImportedFunctions(isolate, this, ffi, &instance, | 839 if (!CompileWrappersToImportedFunctions(isolate, this, ffi, &instance, |
850 &thrower, factory, &module_env, | 840 &thrower, factory, &module_env)) { |
851 code_stats)) { | |
852 return MaybeHandle<JSObject>(); | 841 return MaybeHandle<JSObject>(); |
853 } | 842 } |
| 843 |
| 844 // If FLAG_print_wasm_code_size is set, this aggregates the sum of all code |
| 845 // objects created for this module. |
| 846 // TODO(titzer): switch this to TRACE_EVENT |
| 847 CodeStats code_stats; |
| 848 if (FLAG_print_wasm_code_size) { |
| 849 for (Handle<Code> c : instance.function_code) code_stats.Record(*c); |
| 850 for (Handle<Code> c : instance.import_code) code_stats.Record(*c); |
| 851 } |
| 852 |
854 { | 853 { |
855 instance.js_object->SetInternalField(kWasmModuleFunctionTable, | 854 instance.js_object->SetInternalField(kWasmModuleFunctionTable, |
856 Smi::FromInt(0)); | 855 Smi::FromInt(0)); |
857 LinkImports(isolate, instance.function_code, instance.import_code); | 856 LinkImports(isolate, instance.function_code, instance.import_code); |
858 | 857 |
859 SetDeoptimizationData(factory, instance.js_object, instance.function_code); | 858 SetDeoptimizationData(factory, instance.js_object, instance.function_code); |
860 | 859 |
861 //------------------------------------------------------------------------- | 860 //------------------------------------------------------------------------- |
862 // Create and populate the exports object. | 861 // Create and populate the exports object. |
863 //------------------------------------------------------------------------- | 862 //------------------------------------------------------------------------- |
(...skipping 17 matching lines...) Expand all Loading... |
881 | 880 |
882 // Compile wrappers and add them to the exports object. | 881 // Compile wrappers and add them to the exports object. |
883 for (const WasmExport& exp : export_table) { | 882 for (const WasmExport& exp : export_table) { |
884 if (thrower.error()) break; | 883 if (thrower.error()) break; |
885 WasmName str = GetName(exp.name_offset, exp.name_length); | 884 WasmName str = GetName(exp.name_offset, exp.name_length); |
886 Handle<String> name = factory->InternalizeUtf8String(str); | 885 Handle<String> name = factory->InternalizeUtf8String(str); |
887 Handle<Code> code = instance.function_code[exp.func_index]; | 886 Handle<Code> code = instance.function_code[exp.func_index]; |
888 Handle<JSFunction> function = compiler::CompileJSToWasmWrapper( | 887 Handle<JSFunction> function = compiler::CompileJSToWasmWrapper( |
889 isolate, &module_env, name, code, instance.js_object, | 888 isolate, &module_env, name, code, instance.js_object, |
890 exp.func_index); | 889 exp.func_index); |
891 code_stats.Record(function->code()); | 890 if (FLAG_print_wasm_code_size) { |
| 891 code_stats.Record(function->code()); |
| 892 } |
892 desc.set_value(function); | 893 desc.set_value(function); |
893 Maybe<bool> status = JSReceiver::DefineOwnProperty( | 894 Maybe<bool> status = JSReceiver::DefineOwnProperty( |
894 isolate, exports_object, name, &desc, Object::THROW_ON_ERROR); | 895 isolate, exports_object, name, &desc, Object::THROW_ON_ERROR); |
895 if (!status.IsJust()) { | 896 if (!status.IsJust()) { |
896 thrower.Error("export of %.*s failed.", str.length(), str.start()); | 897 thrower.Error("export of %.*s failed.", str.length(), str.start()); |
897 break; | 898 break; |
898 } | 899 } |
899 } | 900 } |
900 | 901 |
901 if (mem_export) { | 902 if (mem_export) { |
902 // Export the memory as a named property. | 903 // Export the memory as a named property. |
903 Handle<String> name = factory->InternalizeUtf8String("memory"); | 904 Handle<String> name = factory->InternalizeUtf8String("memory"); |
904 JSObject::AddProperty(exports_object, name, instance.mem_buffer, | 905 JSObject::AddProperty(exports_object, name, instance.mem_buffer, |
905 READ_ONLY); | 906 READ_ONLY); |
906 } | 907 } |
907 } | 908 } |
908 } | 909 } |
909 | 910 |
| 911 if (FLAG_print_wasm_code_size) { |
| 912 code_stats.Report(); |
| 913 } |
910 //------------------------------------------------------------------------- | 914 //------------------------------------------------------------------------- |
911 // Attach the function name table. | 915 // Attach the function name table. |
912 //------------------------------------------------------------------------- | 916 //------------------------------------------------------------------------- |
913 Handle<ByteArray> function_name_table = | 917 Handle<ByteArray> function_name_table = |
914 BuildFunctionNamesTable(isolate, module_env.module); | 918 BuildFunctionNamesTable(isolate, module_env.module); |
915 instance.js_object->SetInternalField(kWasmFunctionNamesArray, | 919 instance.js_object->SetInternalField(kWasmFunctionNamesArray, |
916 *function_name_table); | 920 *function_name_table); |
917 | 921 |
918 code_stats.Report(); | |
919 | |
920 // Run the start function if one was specified. | 922 // Run the start function if one was specified. |
921 if (this->start_function_index >= 0) { | 923 if (this->start_function_index >= 0) { |
922 HandleScope scope(isolate); | 924 HandleScope scope(isolate); |
923 uint32_t index = static_cast<uint32_t>(this->start_function_index); | 925 uint32_t index = static_cast<uint32_t>(this->start_function_index); |
924 Handle<String> name = isolate->factory()->NewStringFromStaticChars("start"); | 926 Handle<String> name = isolate->factory()->NewStringFromStaticChars("start"); |
925 Handle<Code> code = instance.function_code[index]; | 927 Handle<Code> code = instance.function_code[index]; |
926 Handle<JSFunction> jsfunc = compiler::CompileJSToWasmWrapper( | 928 Handle<JSFunction> jsfunc = compiler::CompileJSToWasmWrapper( |
927 isolate, &module_env, name, code, instance.js_object, index); | 929 isolate, &module_env, name, code, instance.js_object, index); |
928 | 930 |
929 // Call the JS function. | 931 // Call the JS function. |
(...skipping 186 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1116 Object* info = wasm->GetInternalField(kWasmDebugInfo); | 1118 Object* info = wasm->GetInternalField(kWasmDebugInfo); |
1117 if (!info->IsUndefined(wasm->GetIsolate())) return WasmDebugInfo::cast(info); | 1119 if (!info->IsUndefined(wasm->GetIsolate())) return WasmDebugInfo::cast(info); |
1118 Handle<WasmDebugInfo> new_info = WasmDebugInfo::New(handle(wasm)); | 1120 Handle<WasmDebugInfo> new_info = WasmDebugInfo::New(handle(wasm)); |
1119 wasm->SetInternalField(kWasmDebugInfo, *new_info); | 1121 wasm->SetInternalField(kWasmDebugInfo, *new_info); |
1120 return *new_info; | 1122 return *new_info; |
1121 } | 1123 } |
1122 | 1124 |
1123 } // namespace wasm | 1125 } // namespace wasm |
1124 } // namespace internal | 1126 } // namespace internal |
1125 } // namespace v8 | 1127 } // namespace v8 |
OLD | NEW |