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 <memory> | 5 #include <memory> |
6 | 6 |
7 #include "src/base/atomic-utils.h" | 7 #include "src/base/atomic-utils.h" |
8 #include "src/code-stubs.h" | 8 #include "src/code-stubs.h" |
9 | 9 |
10 #include "src/macro-assembler.h" | 10 #include "src/macro-assembler.h" |
(...skipping 148 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
159 // TODO(mtrofin): Unnecessary once we stop using JS Heap for wasm code. | 159 // TODO(mtrofin): Unnecessary once we stop using JS Heap for wasm code. |
160 // For now, each field is expected to have the type commented by its side. | 160 // For now, each field is expected to have the type commented by its side. |
161 // The elements typed as "maybe" are optional. The others are mandatory. Since | 161 // The elements typed as "maybe" are optional. The others are mandatory. Since |
162 // the compiled module is either obtained from the current v8 instance, or from | 162 // the compiled module is either obtained from the current v8 instance, or from |
163 // a snapshot produced by a compatible (==identical) v8 instance, we simply | 163 // a snapshot produced by a compatible (==identical) v8 instance, we simply |
164 // fail at instantiation time, in the face of invalid data. | 164 // fail at instantiation time, in the face of invalid data. |
165 enum CompiledWasmObjectFields { | 165 enum CompiledWasmObjectFields { |
166 kFunctions, // FixedArray of Code | 166 kFunctions, // FixedArray of Code |
167 kImportData, // maybe FixedArray of FixedArray respecting the | 167 kImportData, // maybe FixedArray of FixedArray respecting the |
168 // WasmImportMetadata structure. | 168 // WasmImportMetadata structure. |
| 169 kImportMap, // FixedArray. The i-th element is the Code object used for |
| 170 // import i |
169 kExports, // maybe FixedArray of FixedArray of WasmExportMetadata | 171 kExports, // maybe FixedArray of FixedArray of WasmExportMetadata |
170 // structure | 172 // structure |
171 kStartupFunction, // maybe FixedArray of WasmExportMetadata structure | 173 kStartupFunction, // maybe FixedArray of WasmExportMetadata structure |
172 kTableOfIndirectFunctionTables, // maybe FixedArray of FixedArray of | 174 kTableOfIndirectFunctionTables, // maybe FixedArray of FixedArray of |
173 // WasmIndirectFunctionTableMetadata | 175 // WasmIndirectFunctionTableMetadata |
174 kModuleBytes, // maybe String | 176 kModuleBytes, // maybe String |
175 kFunctionNameTable, // maybe ByteArray | 177 kFunctionNameTable, // maybe ByteArray |
176 kMinRequiredMemory, // Smi. an uint32_t | 178 kMinRequiredMemory, // Smi. an uint32_t |
177 // The following 2 are either together present or absent: | 179 // The following 2 are either together present or absent: |
178 kDataSegmentsInfo, // maybe FixedArray of FixedArray respecting the | 180 kDataSegmentsInfo, // maybe FixedArray of FixedArray respecting the |
(...skipping 238 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
417 } | 419 } |
418 | 420 |
419 void LinkModuleFunctions(Isolate* isolate, | 421 void LinkModuleFunctions(Isolate* isolate, |
420 std::vector<Handle<Code>>& functions) { | 422 std::vector<Handle<Code>>& functions) { |
421 for (size_t i = 0; i < functions.size(); ++i) { | 423 for (size_t i = 0; i < functions.size(); ++i) { |
422 Handle<Code> code = functions[i]; | 424 Handle<Code> code = functions[i]; |
423 LinkFunction(code, functions, Code::WASM_FUNCTION); | 425 LinkFunction(code, functions, Code::WASM_FUNCTION); |
424 } | 426 } |
425 } | 427 } |
426 | 428 |
427 void LinkImports(Isolate* isolate, std::vector<Handle<Code>>& functions, | |
428 const std::vector<Handle<Code>>& imports) { | |
429 for (uint32_t i = 0; i < functions.size(); ++i) { | |
430 Handle<Code> code = functions[i]; | |
431 LinkFunction(code, imports, Code::WASM_TO_JS_FUNCTION); | |
432 } | |
433 } | |
434 | |
435 void FlushAssemblyCache(Isolate* isolate, Handle<FixedArray> functions) { | 429 void FlushAssemblyCache(Isolate* isolate, Handle<FixedArray> functions) { |
436 for (int i = 0; i < functions->length(); ++i) { | 430 for (int i = 0; i < functions->length(); ++i) { |
437 Handle<Code> code = functions->GetValueChecked<Code>(isolate, i); | 431 Handle<Code> code = functions->GetValueChecked<Code>(isolate, i); |
438 Assembler::FlushICache(isolate, code->instruction_start(), | 432 Assembler::FlushICache(isolate, code->instruction_start(), |
439 code->instruction_size()); | 433 code->instruction_size()); |
440 } | 434 } |
441 } | 435 } |
442 | 436 |
443 } // namespace | 437 } // namespace |
444 | 438 |
(...skipping 514 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
959 Handle<FixedArray> import_data; | 953 Handle<FixedArray> import_data; |
960 if (maybe_import_data.ToHandle(&import_data)) { | 954 if (maybe_import_data.ToHandle(&import_data)) { |
961 if (!CompileWrappersToImportedFunctions(isolate, ffi, import_code, | 955 if (!CompileWrappersToImportedFunctions(isolate, ffi, import_code, |
962 import_data, thrower)) { | 956 import_data, thrower)) { |
963 return false; | 957 return false; |
964 } | 958 } |
965 } | 959 } |
966 | 960 |
967 RecordStats(isolate, import_code); | 961 RecordStats(isolate, import_code); |
968 | 962 |
969 Handle<FixedArray> code_table = Handle<FixedArray>( | 963 if (import_code.empty()) return true; |
970 FixedArray::cast(instance->GetInternalField(kWasmModuleCodeTable))); | 964 |
971 // TODO(mtrofin): get the code off std::vector and on FixedArray, for | 965 { |
972 // consistency. | 966 DisallowHeapAllocation no_gc; |
973 std::vector<Handle<Code>> function_code(code_table->length()); | 967 std::map<Code*, int> import_to_index; |
974 for (int i = 0; i < code_table->length(); ++i) { | 968 Handle<FixedArray> mapping = |
975 Handle<Code> code = Handle<Code>(Code::cast(code_table->get(i))); | 969 compiled_module->GetValueChecked<FixedArray>(isolate, kImportMap); |
976 function_code[i] = code; | 970 for (int i = 0; i < mapping->length(); ++i) { |
| 971 import_to_index.insert(std::make_pair(Code::cast(mapping->get(i)), i)); |
| 972 } |
| 973 |
| 974 Handle<FixedArray> code_table = Handle<FixedArray>( |
| 975 FixedArray::cast(instance->GetInternalField(kWasmModuleCodeTable))); |
| 976 |
| 977 int mode_mask = RelocInfo::ModeMask(RelocInfo::CODE_TARGET); |
| 978 AllowDeferredHandleDereference embedding_raw_address; |
| 979 for (int i = 0; i < code_table->length(); ++i) { |
| 980 Handle<Code> wasm_function = |
| 981 code_table->GetValueChecked<Code>(isolate, i); |
| 982 for (RelocIterator it(*wasm_function, mode_mask); !it.done(); it.next()) { |
| 983 Code* target = |
| 984 Code::GetCodeFromTargetAddress(it.rinfo()->target_address()); |
| 985 if (target->kind() == Code::WASM_TO_JS_FUNCTION) { |
| 986 auto found_index = import_to_index.find(target); |
| 987 CHECK(found_index != import_to_index.end()); |
| 988 int index = found_index->second; |
| 989 CHECK(index < static_cast<int>(import_code.size())); |
| 990 Handle<Code> new_target = import_code[index]; |
| 991 it.rinfo()->set_target_address(new_target->instruction_start(), |
| 992 UPDATE_WRITE_BARRIER, |
| 993 SKIP_ICACHE_FLUSH); |
| 994 } |
| 995 } |
| 996 } |
977 } | 997 } |
| 998 Handle<FixedArray> new_mapping = |
| 999 isolate->factory()->NewFixedArray(static_cast<int>(import_code.size())); |
| 1000 for (int i = 0; i < new_mapping->length(); ++i) { |
| 1001 new_mapping->set(i, *import_code[i]); |
| 1002 } |
| 1003 compiled_module->set(kImportMap, *new_mapping); |
978 | 1004 |
979 LinkImports(isolate, function_code, import_code); | |
980 return true; | 1005 return true; |
981 } | 1006 } |
982 | 1007 |
983 bool SetupExportsObject(Handle<FixedArray> compiled_module, Isolate* isolate, | 1008 bool SetupExportsObject(Handle<FixedArray> compiled_module, Isolate* isolate, |
984 Handle<JSObject> instance, ErrorThrower* thrower) { | 1009 Handle<JSObject> instance, ErrorThrower* thrower) { |
985 Factory* factory = isolate->factory(); | 1010 Factory* factory = isolate->factory(); |
986 bool mem_export = | 1011 bool mem_export = |
987 static_cast<bool>(Smi::cast(compiled_module->get(kExportMem))->value()); | 1012 static_cast<bool>(Smi::cast(compiled_module->get(kExportMem))->value()); |
988 ModuleOrigin origin = static_cast<ModuleOrigin>( | 1013 ModuleOrigin origin = static_cast<ModuleOrigin>( |
989 Smi::cast(compiled_module->get(kOrigin))->value()); | 1014 Smi::cast(compiled_module->get(kOrigin))->value()); |
(...skipping 86 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1076 | 1101 |
1077 ModuleEnv module_env; | 1102 ModuleEnv module_env; |
1078 module_env.module = this; | 1103 module_env.module = this; |
1079 module_env.instance = &temp_instance_for_compilation; | 1104 module_env.instance = &temp_instance_for_compilation; |
1080 module_env.origin = origin; | 1105 module_env.origin = origin; |
1081 InitializePlaceholders(factory, &module_env.placeholders, functions.size()); | 1106 InitializePlaceholders(factory, &module_env.placeholders, functions.size()); |
1082 | 1107 |
1083 Handle<FixedArray> compiled_functions = | 1108 Handle<FixedArray> compiled_functions = |
1084 factory->NewFixedArray(static_cast<int>(functions.size()), TENURED); | 1109 factory->NewFixedArray(static_cast<int>(functions.size()), TENURED); |
1085 | 1110 |
1086 temp_instance_for_compilation.import_code.resize(import_table.size()); | 1111 MaybeHandle<FixedArray> maybe_imports; |
1087 for (uint32_t i = 0; i < import_table.size(); ++i) { | 1112 if (import_table.size() > 0) { |
1088 temp_instance_for_compilation.import_code[i] = | 1113 temp_instance_for_compilation.import_code.resize(import_table.size()); |
1089 CreatePlaceholder(factory, i, Code::WASM_TO_JS_FUNCTION); | 1114 Handle<FixedArray> imports = |
| 1115 factory->NewFixedArray(static_cast<int>(import_table.size())); |
| 1116 for (uint32_t i = 0; i < import_table.size(); ++i) { |
| 1117 Handle<Code> placeholder = |
| 1118 CreatePlaceholder(factory, i, Code::WASM_TO_JS_FUNCTION); |
| 1119 temp_instance_for_compilation.import_code[i] = placeholder; |
| 1120 imports->set(i, *placeholder); |
| 1121 } |
| 1122 maybe_imports = imports; |
1090 } | 1123 } |
1091 isolate->counters()->wasm_functions_per_module()->AddSample( | 1124 isolate->counters()->wasm_functions_per_module()->AddSample( |
1092 static_cast<int>(functions.size())); | 1125 static_cast<int>(functions.size())); |
1093 if (FLAG_wasm_num_compilation_tasks != 0) { | 1126 if (FLAG_wasm_num_compilation_tasks != 0) { |
1094 CompileInParallel(isolate, this, | 1127 CompileInParallel(isolate, this, |
1095 temp_instance_for_compilation.function_code, thrower, | 1128 temp_instance_for_compilation.function_code, thrower, |
1096 &module_env); | 1129 &module_env); |
1097 } else { | 1130 } else { |
1098 CompileSequentially(isolate, this, | 1131 CompileSequentially(isolate, this, |
1099 temp_instance_for_compilation.function_code, thrower, | 1132 temp_instance_for_compilation.function_code, thrower, |
(...skipping 11 matching lines...) Expand all Loading... |
1111 // Create the compiled module object, and populate with compiled functions | 1144 // Create the compiled module object, and populate with compiled functions |
1112 // and information needed at instantiation time. This object needs to be | 1145 // and information needed at instantiation time. This object needs to be |
1113 // serializable. Instantiation may occur off a deserialized version of this | 1146 // serializable. Instantiation may occur off a deserialized version of this |
1114 // object. | 1147 // object. |
1115 Handle<FixedArray> ret = | 1148 Handle<FixedArray> ret = |
1116 factory->NewFixedArray(kCompiledWasmObjectTableSize, TENURED); | 1149 factory->NewFixedArray(kCompiledWasmObjectTableSize, TENURED); |
1117 ret->set(kFunctions, *compiled_functions); | 1150 ret->set(kFunctions, *compiled_functions); |
1118 if (!indirect_table.is_null()) { | 1151 if (!indirect_table.is_null()) { |
1119 ret->set(kTableOfIndirectFunctionTables, *indirect_table.ToHandleChecked()); | 1152 ret->set(kTableOfIndirectFunctionTables, *indirect_table.ToHandleChecked()); |
1120 } | 1153 } |
| 1154 if (!maybe_imports.is_null()) { |
| 1155 ret->set(kImportMap, *maybe_imports.ToHandleChecked()); |
| 1156 } |
1121 Handle<FixedArray> import_data = GetImportsMetadata(factory, this); | 1157 Handle<FixedArray> import_data = GetImportsMetadata(factory, this); |
1122 ret->set(kImportData, *import_data); | 1158 ret->set(kImportData, *import_data); |
1123 | 1159 |
1124 // Compile export functions. | 1160 // Compile export functions. |
1125 int export_size = static_cast<int>(export_table.size()); | 1161 int export_size = static_cast<int>(export_table.size()); |
1126 Handle<Code> startup_fct; | 1162 Handle<Code> startup_fct; |
1127 if (export_size > 0) { | 1163 if (export_size > 0) { |
1128 Handle<FixedArray> exports = factory->NewFixedArray(export_size, TENURED); | 1164 Handle<FixedArray> exports = factory->NewFixedArray(export_size, TENURED); |
1129 for (int i = 0; i < export_size; ++i) { | 1165 for (int i = 0; i < export_size; ++i) { |
1130 Handle<FixedArray> export_metadata = | 1166 Handle<FixedArray> export_metadata = |
(...skipping 532 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1663 return static_cast<int32_t>(HeapNumber::cast(*result)->value()); | 1699 return static_cast<int32_t>(HeapNumber::cast(*result)->value()); |
1664 } | 1700 } |
1665 thrower->Error("WASM.compileRun() failed: Return value should be number"); | 1701 thrower->Error("WASM.compileRun() failed: Return value should be number"); |
1666 return -1; | 1702 return -1; |
1667 } | 1703 } |
1668 | 1704 |
1669 } // namespace testing | 1705 } // namespace testing |
1670 } // namespace wasm | 1706 } // namespace wasm |
1671 } // namespace internal | 1707 } // namespace internal |
1672 } // namespace v8 | 1708 } // namespace v8 |
OLD | NEW |