| 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 528 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 539 } | 539 } |
| 540 | 540 |
| 541 Isolate* isolate_; | 541 Isolate* isolate_; |
| 542 std::vector<compiler::WasmCompilationUnit*>* compilation_units_; | 542 std::vector<compiler::WasmCompilationUnit*>* compilation_units_; |
| 543 std::queue<compiler::WasmCompilationUnit*>* executed_units_; | 543 std::queue<compiler::WasmCompilationUnit*>* executed_units_; |
| 544 base::Semaphore* on_finished_; | 544 base::Semaphore* on_finished_; |
| 545 base::Mutex* result_mutex_; | 545 base::Mutex* result_mutex_; |
| 546 base::AtomicNumber<size_t>* next_unit_; | 546 base::AtomicNumber<size_t>* next_unit_; |
| 547 }; | 547 }; |
| 548 | 548 |
| 549 // Records statistics on the code generated by compiling WASM functions. | 549 static void RecordStats(Isolate* isolate, Code* code) { |
| 550 struct CodeStats { | 550 isolate->counters()->wasm_generated_code_size()->Increment(code->body_size()); |
| 551 size_t code_size; | 551 isolate->counters()->wasm_reloc_size()->Increment( |
| 552 size_t reloc_size; | 552 code->relocation_info()->length()); |
| 553 } |
| 553 | 554 |
| 554 inline CodeStats() : code_size(0), reloc_size(0) {} | 555 static void RecordStats(Isolate* isolate, |
| 556 const std::vector<Handle<Code>>& functions) { |
| 557 for (Handle<Code> c : functions) RecordStats(isolate, *c); |
| 558 } |
| 555 | 559 |
| 556 inline void Record(Code* code) { | 560 static void RecordStats(Isolate* isolate, Handle<FixedArray> functions) { |
| 557 if (FLAG_print_wasm_code_size) { | 561 DisallowHeapAllocation no_gc; |
| 558 code_size += code->body_size(); | 562 for (int i = 0; i < functions->length(); ++i) { |
| 559 reloc_size += code->relocation_info()->length(); | 563 RecordStats(isolate, Code::cast(functions->get(i))); |
| 560 } | |
| 561 } | 564 } |
| 562 | 565 } |
| 563 void Record(const std::vector<Handle<Code>>& functions) { | |
| 564 if (FLAG_print_wasm_code_size) { | |
| 565 for (Handle<Code> c : functions) Record(*c); | |
| 566 } | |
| 567 } | |
| 568 | |
| 569 void Record(Handle<FixedArray> functions) { | |
| 570 if (FLAG_print_wasm_code_size) { | |
| 571 DisallowHeapAllocation no_gc; | |
| 572 for (int i = 0; i < functions->length(); ++i) { | |
| 573 Code* code = Code::cast(functions->get(i)); | |
| 574 Record(code); | |
| 575 } | |
| 576 } | |
| 577 } | |
| 578 | |
| 579 inline void Report() { | |
| 580 if (FLAG_print_wasm_code_size) { | |
| 581 PrintF("Total generated wasm code: %zu bytes\n", code_size); | |
| 582 PrintF("Total generated wasm reloc: %zu bytes\n", reloc_size); | |
| 583 } | |
| 584 } | |
| 585 }; | |
| 586 | 566 |
| 587 Handle<FixedArray> GetImportsMetadata(Factory* factory, | 567 Handle<FixedArray> GetImportsMetadata(Factory* factory, |
| 588 const WasmModule* module) { | 568 const WasmModule* module) { |
| 589 Handle<FixedArray> ret = factory->NewFixedArray( | 569 Handle<FixedArray> ret = factory->NewFixedArray( |
| 590 static_cast<int>(module->import_table.size()), TENURED); | 570 static_cast<int>(module->import_table.size()), TENURED); |
| 591 for (size_t i = 0; i < module->import_table.size(); ++i) { | 571 for (size_t i = 0; i < module->import_table.size(); ++i) { |
| 592 const WasmImport& import = module->import_table[i]; | 572 const WasmImport& import = module->import_table[i]; |
| 593 WasmName module_name = module->GetNameOrNull(import.module_name_offset, | 573 WasmName module_name = module->GetNameOrNull(import.module_name_offset, |
| 594 import.module_name_length); | 574 import.module_name_length); |
| 595 WasmName function_name = module->GetNameOrNull(import.function_name_offset, | 575 WasmName function_name = module->GetNameOrNull(import.function_name_offset, |
| (...skipping 311 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 907 uint32_t mem_size = static_cast<uint32_t>(memory->byte_length()->Number()); | 887 uint32_t mem_size = static_cast<uint32_t>(memory->byte_length()->Number()); |
| 908 RelocateInstanceCode(instance, mem_start, | 888 RelocateInstanceCode(instance, mem_start, |
| 909 WasmModule::kPageSize * min_mem_pages, mem_size); | 889 WasmModule::kPageSize * min_mem_pages, mem_size); |
| 910 LoadDataSegments(compiled_module, mem_start, mem_size); | 890 LoadDataSegments(compiled_module, mem_start, mem_size); |
| 911 } | 891 } |
| 912 return true; | 892 return true; |
| 913 } | 893 } |
| 914 | 894 |
| 915 bool SetupImports(Isolate* isolate, Handle<FixedArray> compiled_module, | 895 bool SetupImports(Isolate* isolate, Handle<FixedArray> compiled_module, |
| 916 Handle<JSObject> instance, ErrorThrower* thrower, | 896 Handle<JSObject> instance, ErrorThrower* thrower, |
| 917 Handle<JSReceiver> ffi, CodeStats* stats) { | 897 Handle<JSReceiver> ffi) { |
| 918 //------------------------------------------------------------------------- | 898 //------------------------------------------------------------------------- |
| 919 // Compile wrappers to imported functions. | 899 // Compile wrappers to imported functions. |
| 920 //------------------------------------------------------------------------- | 900 //------------------------------------------------------------------------- |
| 921 std::vector<Handle<Code>> import_code; | 901 std::vector<Handle<Code>> import_code; |
| 922 MaybeHandle<FixedArray> maybe_import_data = | 902 MaybeHandle<FixedArray> maybe_import_data = |
| 923 compiled_module->GetValue<FixedArray>(kImportData); | 903 compiled_module->GetValue<FixedArray>(kImportData); |
| 924 if (!maybe_import_data.is_null()) { | 904 if (!maybe_import_data.is_null()) { |
| 925 Handle<FixedArray> import_data = maybe_import_data.ToHandleChecked(); | 905 Handle<FixedArray> import_data = maybe_import_data.ToHandleChecked(); |
| 926 if (!CompileWrappersToImportedFunctions(isolate, ffi, import_code, | 906 if (!CompileWrappersToImportedFunctions(isolate, ffi, import_code, |
| 927 import_data, thrower)) { | 907 import_data, thrower)) { |
| 928 return false; | 908 return false; |
| 929 } | 909 } |
| 930 } | 910 } |
| 931 | 911 |
| 932 stats->Record(import_code); | 912 RecordStats(isolate, import_code); |
| 933 | 913 |
| 934 Handle<FixedArray> code_table = Handle<FixedArray>( | 914 Handle<FixedArray> code_table = Handle<FixedArray>( |
| 935 FixedArray::cast(instance->GetInternalField(kWasmModuleCodeTable))); | 915 FixedArray::cast(instance->GetInternalField(kWasmModuleCodeTable))); |
| 936 // TODO(mtrofin): get the code off std::vector and on FixedArray, for | 916 // TODO(mtrofin): get the code off std::vector and on FixedArray, for |
| 937 // consistency. | 917 // consistency. |
| 938 std::vector<Handle<Code>> function_code(code_table->length()); | 918 std::vector<Handle<Code>> function_code(code_table->length()); |
| 939 for (int i = 0; i < code_table->length(); ++i) { | 919 for (int i = 0; i < code_table->length(); ++i) { |
| 940 Handle<Code> code = Handle<Code>(Code::cast(code_table->get(i))); | 920 Handle<Code> code = Handle<Code>(Code::cast(code_table->get(i))); |
| 941 function_code[i] = code; | 921 function_code[i] = code; |
| 942 } | 922 } |
| 943 | 923 |
| 944 instance->SetInternalField(kWasmModuleFunctionTable, Smi::FromInt(0)); | 924 instance->SetInternalField(kWasmModuleFunctionTable, Smi::FromInt(0)); |
| 945 LinkImports(isolate, function_code, import_code); | 925 LinkImports(isolate, function_code, import_code); |
| 946 return true; | 926 return true; |
| 947 } | 927 } |
| 948 | 928 |
| 949 bool SetupExportsObject(Handle<FixedArray> compiled_module, Isolate* isolate, | 929 bool SetupExportsObject(Handle<FixedArray> compiled_module, Isolate* isolate, |
| 950 Handle<JSObject> instance, ErrorThrower* thrower, | 930 Handle<JSObject> instance, ErrorThrower* thrower) { |
| 951 CodeStats* stats) { | |
| 952 Factory* factory = isolate->factory(); | 931 Factory* factory = isolate->factory(); |
| 953 bool mem_export = | 932 bool mem_export = |
| 954 static_cast<bool>(Smi::cast(compiled_module->get(kExportMem))->value()); | 933 static_cast<bool>(Smi::cast(compiled_module->get(kExportMem))->value()); |
| 955 ModuleOrigin origin = static_cast<ModuleOrigin>( | 934 ModuleOrigin origin = static_cast<ModuleOrigin>( |
| 956 Smi::cast(compiled_module->get(kOrigin))->value()); | 935 Smi::cast(compiled_module->get(kOrigin))->value()); |
| 957 | 936 |
| 958 MaybeHandle<FixedArray> maybe_exports = | 937 MaybeHandle<FixedArray> maybe_exports = |
| 959 compiled_module->GetValue<FixedArray>(kExports); | 938 compiled_module->GetValue<FixedArray>(kExports); |
| 960 if (!maybe_exports.is_null() || mem_export) { | 939 if (!maybe_exports.is_null() || mem_export) { |
| 961 PropertyDescriptor desc; | 940 PropertyDescriptor desc; |
| 962 desc.set_writable(false); | 941 desc.set_writable(false); |
| 963 | 942 |
| 964 Handle<JSObject> exports_object = instance; | 943 Handle<JSObject> exports_object = instance; |
| 965 if (origin == kWasmOrigin) { | 944 if (origin == kWasmOrigin) { |
| 966 // Create the "exports" object. | 945 // Create the "exports" object. |
| 967 Handle<JSFunction> object_function = Handle<JSFunction>( | 946 Handle<JSFunction> object_function = Handle<JSFunction>( |
| 968 isolate->native_context()->object_function(), isolate); | 947 isolate->native_context()->object_function(), isolate); |
| 969 exports_object = factory->NewJSObject(object_function, TENURED); | 948 exports_object = factory->NewJSObject(object_function, TENURED); |
| 970 Handle<String> exports_name = factory->InternalizeUtf8String("exports"); | 949 Handle<String> exports_name = factory->InternalizeUtf8String("exports"); |
| 971 JSObject::AddProperty(instance, exports_name, exports_object, READ_ONLY); | 950 JSObject::AddProperty(instance, exports_name, exports_object, READ_ONLY); |
| 972 } | 951 } |
| 973 if (!maybe_exports.is_null()) { | 952 if (!maybe_exports.is_null()) { |
| 974 Handle<FixedArray> exports = maybe_exports.ToHandleChecked(); | 953 Handle<FixedArray> exports = maybe_exports.ToHandleChecked(); |
| 975 | 954 |
| 976 int exports_size = exports->length(); | 955 int exports_size = exports->length(); |
| 977 for (int i = 0; i < exports_size; ++i) { | 956 for (int i = 0; i < exports_size; ++i) { |
| 978 if (thrower->error()) return false; | 957 if (thrower->error()) return false; |
| 979 Handle<JSFunction> function = exports->GetValueChecked<JSFunction>(i); | 958 Handle<JSFunction> function = exports->GetValueChecked<JSFunction>(i); |
| 980 stats->Record(function->code()); | 959 RecordStats(isolate, function->code()); |
| 981 Handle<String> name = | 960 Handle<String> name = |
| 982 Handle<String>(String::cast(function->shared()->name())); | 961 Handle<String>(String::cast(function->shared()->name())); |
| 983 function->SetInternalField(0, *instance); | 962 function->SetInternalField(0, *instance); |
| 984 | 963 |
| 985 desc.set_value(function); | 964 desc.set_value(function); |
| 986 Maybe<bool> status = JSReceiver::DefineOwnProperty( | 965 Maybe<bool> status = JSReceiver::DefineOwnProperty( |
| 987 isolate, exports_object, name, &desc, Object::THROW_ON_ERROR); | 966 isolate, exports_object, name, &desc, Object::THROW_ON_ERROR); |
| 988 if (!status.IsJust()) { | 967 if (!status.IsJust()) { |
| 989 thrower->Error("export of %.*s failed.", name->length(), | 968 thrower->Error("export of %.*s failed.", name->length(), |
| 990 name->ToCString().get()); | 969 name->ToCString().get()); |
| (...skipping 145 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1136 // * installs named properties on the object for exported functions | 1115 // * installs named properties on the object for exported functions |
| 1137 // * compiles wasm code to machine code | 1116 // * compiles wasm code to machine code |
| 1138 MaybeHandle<JSObject> WasmModule::Instantiate( | 1117 MaybeHandle<JSObject> WasmModule::Instantiate( |
| 1139 Isolate* isolate, Handle<FixedArray> compiled_module, | 1118 Isolate* isolate, Handle<FixedArray> compiled_module, |
| 1140 Handle<JSReceiver> ffi, Handle<JSArrayBuffer> memory) { | 1119 Handle<JSReceiver> ffi, Handle<JSArrayBuffer> memory) { |
| 1141 HistogramTimerScope wasm_instantiate_module_time_scope( | 1120 HistogramTimerScope wasm_instantiate_module_time_scope( |
| 1142 isolate->counters()->wasm_instantiate_module_time()); | 1121 isolate->counters()->wasm_instantiate_module_time()); |
| 1143 ErrorThrower thrower(isolate, "WasmModule::Instantiate()"); | 1122 ErrorThrower thrower(isolate, "WasmModule::Instantiate()"); |
| 1144 Factory* factory = isolate->factory(); | 1123 Factory* factory = isolate->factory(); |
| 1145 | 1124 |
| 1146 CodeStats code_stats; | |
| 1147 // These fields are compulsory. | 1125 // These fields are compulsory. |
| 1148 Handle<FixedArray> code_table = | 1126 Handle<FixedArray> code_table = |
| 1149 compiled_module->GetValueChecked<FixedArray>(kFunctions); | 1127 compiled_module->GetValueChecked<FixedArray>(kFunctions); |
| 1150 | 1128 |
| 1151 code_stats.Record(code_table); | 1129 RecordStats(isolate, code_table); |
| 1152 | 1130 |
| 1153 MaybeHandle<JSObject> nothing; | 1131 MaybeHandle<JSObject> nothing; |
| 1154 | 1132 |
| 1155 Handle<Map> map = factory->NewMap( | 1133 Handle<Map> map = factory->NewMap( |
| 1156 JS_OBJECT_TYPE, | 1134 JS_OBJECT_TYPE, |
| 1157 JSObject::kHeaderSize + kWasmModuleInternalFieldCount * kPointerSize); | 1135 JSObject::kHeaderSize + kWasmModuleInternalFieldCount * kPointerSize); |
| 1158 Handle<JSObject> js_object = factory->NewJSObjectFromMap(map, TENURED); | 1136 Handle<JSObject> js_object = factory->NewJSObjectFromMap(map, TENURED); |
| 1159 js_object->SetInternalField(kWasmModuleCodeTable, *code_table); | 1137 js_object->SetInternalField(kWasmModuleCodeTable, *code_table); |
| 1160 | 1138 |
| 1161 if (!(SetupInstanceHeap(isolate, compiled_module, js_object, memory, | 1139 if (!(SetupInstanceHeap(isolate, compiled_module, js_object, memory, |
| 1162 &thrower) && | 1140 &thrower) && |
| 1163 SetupGlobals(isolate, compiled_module, js_object, &thrower) && | 1141 SetupGlobals(isolate, compiled_module, js_object, &thrower) && |
| 1164 SetupImports(isolate, compiled_module, js_object, &thrower, ffi, | 1142 SetupImports(isolate, compiled_module, js_object, &thrower, ffi) && |
| 1165 &code_stats) && | 1143 SetupExportsObject(compiled_module, isolate, js_object, &thrower))) { |
| 1166 SetupExportsObject(compiled_module, isolate, js_object, &thrower, | |
| 1167 &code_stats))) { | |
| 1168 return nothing; | 1144 return nothing; |
| 1169 } | 1145 } |
| 1170 | 1146 |
| 1171 SetDebugSupport(factory, compiled_module, js_object); | 1147 SetDebugSupport(factory, compiled_module, js_object); |
| 1172 | 1148 |
| 1173 // Run the start function if one was specified. | 1149 // Run the start function if one was specified. |
| 1174 MaybeHandle<JSFunction> maybe_startup_fct = | 1150 MaybeHandle<JSFunction> maybe_startup_fct = |
| 1175 compiled_module->GetValue<JSFunction>(kStartupFunction); | 1151 compiled_module->GetValue<JSFunction>(kStartupFunction); |
| 1176 if (!maybe_startup_fct.is_null()) { | 1152 if (!maybe_startup_fct.is_null()) { |
| 1177 HandleScope scope(isolate); | 1153 HandleScope scope(isolate); |
| 1178 Handle<JSFunction> startup_fct = maybe_startup_fct.ToHandleChecked(); | 1154 Handle<JSFunction> startup_fct = maybe_startup_fct.ToHandleChecked(); |
| 1179 code_stats.Record(startup_fct->code()); | 1155 RecordStats(isolate, startup_fct->code()); |
| 1180 startup_fct->SetInternalField(0, *js_object); | 1156 startup_fct->SetInternalField(0, *js_object); |
| 1181 // Call the JS function. | 1157 // Call the JS function. |
| 1182 Handle<Object> undefined = isolate->factory()->undefined_value(); | 1158 Handle<Object> undefined = isolate->factory()->undefined_value(); |
| 1183 MaybeHandle<Object> retval = | 1159 MaybeHandle<Object> retval = |
| 1184 Execution::Call(isolate, startup_fct, undefined, 0, nullptr); | 1160 Execution::Call(isolate, startup_fct, undefined, 0, nullptr); |
| 1185 | 1161 |
| 1186 if (retval.is_null()) { | 1162 if (retval.is_null()) { |
| 1187 thrower.Error("WASM.instantiateModule(): start function failed"); | 1163 thrower.Error("WASM.instantiateModule(): start function failed"); |
| 1188 return nothing; | 1164 return nothing; |
| 1189 } | 1165 } |
| 1190 } | 1166 } |
| 1191 | 1167 |
| 1192 code_stats.Report(); | |
| 1193 | |
| 1194 DCHECK(wasm::IsWasmObject(*js_object)); | 1168 DCHECK(wasm::IsWasmObject(*js_object)); |
| 1195 return js_object; | 1169 return js_object; |
| 1196 } | 1170 } |
| 1197 | 1171 |
| 1198 // TODO(mtrofin): remove this once we move to WASM_DIRECT_CALL | 1172 // TODO(mtrofin): remove this once we move to WASM_DIRECT_CALL |
| 1199 Handle<Code> ModuleEnv::GetCodeOrPlaceholder(uint32_t index) const { | 1173 Handle<Code> ModuleEnv::GetCodeOrPlaceholder(uint32_t index) const { |
| 1200 DCHECK(IsValidFunction(index)); | 1174 DCHECK(IsValidFunction(index)); |
| 1201 if (!placeholders.empty()) return placeholders[index]; | 1175 if (!placeholders.empty()) return placeholders[index]; |
| 1202 DCHECK_NOT_NULL(instance); | 1176 DCHECK_NOT_NULL(instance); |
| 1203 return instance->function_code[index]; | 1177 return instance->function_code[index]; |
| (...skipping 189 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1393 return static_cast<int32_t>(HeapNumber::cast(*result)->value()); | 1367 return static_cast<int32_t>(HeapNumber::cast(*result)->value()); |
| 1394 } | 1368 } |
| 1395 thrower.Error("WASM.compileRun() failed: Return value should be number"); | 1369 thrower.Error("WASM.compileRun() failed: Return value should be number"); |
| 1396 return -1; | 1370 return -1; |
| 1397 } | 1371 } |
| 1398 | 1372 |
| 1399 } // namespace testing | 1373 } // namespace testing |
| 1400 } // namespace wasm | 1374 } // namespace wasm |
| 1401 } // namespace internal | 1375 } // namespace internal |
| 1402 } // namespace v8 | 1376 } // namespace v8 |
| OLD | NEW |