| 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 |