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 |