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/macro-assembler.h" | 8 #include "src/macro-assembler.h" |
9 #include "src/objects.h" | 9 #include "src/objects.h" |
10 #include "src/property-descriptor.h" | 10 #include "src/property-descriptor.h" |
(...skipping 136 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
147 // the compiled module is either obtained from the current v8 instance, or from | 147 // the compiled module is either obtained from the current v8 instance, or from |
148 // a snapshot produced by a compatible (==identical) v8 instance, we simply | 148 // a snapshot produced by a compatible (==identical) v8 instance, we simply |
149 // fail at instantiation time, in the face of invalid data. | 149 // fail at instantiation time, in the face of invalid data. |
150 enum CompiledWasmObjectFields { | 150 enum CompiledWasmObjectFields { |
151 kFunctions, // FixedArray of Code | 151 kFunctions, // FixedArray of Code |
152 kImportData, // maybe FixedArray of FixedArray respecting the | 152 kImportData, // maybe FixedArray of FixedArray respecting the |
153 // WasmImportMetadata structure. | 153 // WasmImportMetadata structure. |
154 kExports, // maybe FixedArray of FixedArray of WasmExportMetadata | 154 kExports, // maybe FixedArray of FixedArray of WasmExportMetadata |
155 // structure | 155 // structure |
156 kStartupFunction, // maybe FixedArray of WasmExportMetadata structure | 156 kStartupFunction, // maybe FixedArray of WasmExportMetadata structure |
157 kIndirectFunctionTableSize, // Smi. Size of indirect function table. | 157 kTableOfIndirectFunctionTables, // maybe FixedArray of FixedArray of |
158 kIndirectFunctionTablePrototype, // maybe FixedArray | 158 // WasmIndirectFunctionTableMetadata |
159 kModuleBytes, // maybe String | 159 kModuleBytes, // maybe String |
160 kFunctionNameTable, // maybe ByteArray | 160 kFunctionNameTable, // maybe ByteArray |
161 kMinRequiredMemory, // Smi. an uint32_t | 161 kMinRequiredMemory, // Smi. an uint32_t |
162 // The following 2 are either together present or absent: | 162 // The following 2 are either together present or absent: |
163 kDataSegmentsInfo, // maybe FixedArray of FixedArray respecting the | 163 kDataSegmentsInfo, // maybe FixedArray of FixedArray respecting the |
164 // WasmSegmentInfo structure | 164 // WasmSegmentInfo structure |
165 kDataSegments, // maybe ByteArray. | 165 kDataSegments, // maybe ByteArray. |
166 | 166 |
167 kGlobalsSize, // Smi. an uint32_t | 167 kGlobalsSize, // Smi. an uint32_t |
168 kExportMem, // Smi. bool | 168 kExportMem, // Smi. bool |
169 kOrigin, // Smi. ModuleOrigin | 169 kOrigin, // Smi. ModuleOrigin |
170 kCompiledWasmObjectTableSize // Sentinel value. | 170 kCompiledWasmObjectTableSize // Sentinel value. |
171 }; | 171 }; |
(...skipping 13 matching lines...) Expand all Loading... |
185 kExportedFunctionIndex, // Smi, an uint32_t | 185 kExportedFunctionIndex, // Smi, an uint32_t |
186 kWasmExportMetadataTableSize // Sentinel value. | 186 kWasmExportMetadataTableSize // Sentinel value. |
187 }; | 187 }; |
188 | 188 |
189 enum WasmSegmentInfo { | 189 enum WasmSegmentInfo { |
190 kDestAddr, // Smi. an uint32_t | 190 kDestAddr, // Smi. an uint32_t |
191 kSourceSize, // Smi. an uint32_t | 191 kSourceSize, // Smi. an uint32_t |
192 kWasmSegmentInfoSize // Sentinel value. | 192 kWasmSegmentInfoSize // Sentinel value. |
193 }; | 193 }; |
194 | 194 |
| 195 enum WasmIndirectFunctionTableMetadata { |
| 196 kSize, // Smi. an uint32_t |
| 197 kTable, // FixedArray of indirect function table |
| 198 kWasmIndirectFunctionTableMetadataSize // Sentinel value. |
| 199 }; |
| 200 |
195 uint32_t GetMinModuleMemSize(const WasmModule* module) { | 201 uint32_t GetMinModuleMemSize(const WasmModule* module) { |
196 return WasmModule::kPageSize * module->min_mem_pages; | 202 return WasmModule::kPageSize * module->min_mem_pages; |
197 } | 203 } |
198 | 204 |
199 void LoadDataSegments(Handle<FixedArray> compiled_module, Address mem_addr, | 205 void LoadDataSegments(Handle<FixedArray> compiled_module, Address mem_addr, |
200 size_t mem_size) { | 206 size_t mem_size) { |
201 MaybeHandle<ByteArray> maybe_data = | 207 MaybeHandle<ByteArray> maybe_data = |
202 compiled_module->GetValue<ByteArray>(kDataSegments); | 208 compiled_module->GetValue<ByteArray>(kDataSegments); |
203 MaybeHandle<FixedArray> maybe_segments = | 209 MaybeHandle<FixedArray> maybe_segments = |
204 compiled_module->GetValue<FixedArray>(kDataSegmentsInfo); | 210 compiled_module->GetValue<FixedArray>(kDataSegmentsInfo); |
(...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
250 segments->set(i, *js_segment); | 256 segments->set(i, *js_segment); |
251 data->copy_in(last_insertion_pos, | 257 data->copy_in(last_insertion_pos, |
252 module->module_start + segment.source_offset, | 258 module->module_start + segment.source_offset, |
253 segment.source_size); | 259 segment.source_size); |
254 last_insertion_pos += segment.source_size; | 260 last_insertion_pos += segment.source_size; |
255 } | 261 } |
256 compiled_module->set(kDataSegmentsInfo, *segments); | 262 compiled_module->set(kDataSegmentsInfo, *segments); |
257 compiled_module->set(kDataSegments, *data); | 263 compiled_module->set(kDataSegments, *data); |
258 } | 264 } |
259 | 265 |
260 MaybeHandle<FixedArray> BuildFunctionTable(Isolate* isolate, | |
261 const WasmModule* module) { | |
262 // Compute the size of the indirect function table | |
263 uint32_t table_size = module->FunctionTableSize(); | |
264 if (table_size == 0) { | |
265 return MaybeHandle<FixedArray>(); | |
266 } | |
267 | |
268 DCHECK_GE(table_size, module->function_table.size()); | |
269 | |
270 Handle<FixedArray> fixed = isolate->factory()->NewFixedArray(2 * table_size); | |
271 for (uint32_t i = 0; i < module->function_table.size(); ++i) { | |
272 const WasmFunction* function = | |
273 &module->functions[module->function_table[i]]; | |
274 int fixed_array_index = static_cast<int>(i); | |
275 fixed->set(fixed_array_index, Smi::FromInt(function->sig_index)); | |
276 fixed->set(fixed_array_index + table_size, | |
277 Smi::FromInt(module->function_table[fixed_array_index])); | |
278 } | |
279 | |
280 // Set the remaining elements to -1 (instead of "undefined"). These | |
281 // elements are accessed directly as SMIs (without a check). On 64-bit | |
282 // platforms, it is possible to have the top bits of "undefined" take | |
283 // small integer values (or zero), which are more likely to be equal to | |
284 // the signature index we check against. | |
285 for (uint32_t i = static_cast<uint32_t>(module->function_table.size()); | |
286 i < table_size; | |
287 ++i) { | |
288 fixed->set(i, Smi::FromInt(-1)); | |
289 } | |
290 return fixed; | |
291 } | |
292 | |
293 void PatchFunctionTable(Handle<Code> code, | 266 void PatchFunctionTable(Handle<Code> code, |
294 Handle<FixedArray> old_indirect_table, | 267 Handle<FixedArray> old_indirect_table, |
295 Handle<FixedArray> new_indirect_table) { | 268 Handle<FixedArray> new_indirect_table) { |
296 for (RelocIterator it(*code, 1 << RelocInfo::EMBEDDED_OBJECT); !it.done(); | 269 for (RelocIterator it(*code, 1 << RelocInfo::EMBEDDED_OBJECT); !it.done(); |
297 it.next()) { | 270 it.next()) { |
298 if (it.rinfo()->target_object() == *old_indirect_table) { | 271 if (it.rinfo()->target_object() == *old_indirect_table) { |
299 it.rinfo()->set_target_object(*new_indirect_table); | 272 it.rinfo()->set_target_object(*new_indirect_table); |
300 } | 273 } |
301 } | 274 } |
302 } | 275 } |
(...skipping 67 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
370 } | 343 } |
371 } | 344 } |
372 } | 345 } |
373 | 346 |
374 Handle<Code> CreatePlaceholder(Factory* factory, uint32_t index, | 347 Handle<Code> CreatePlaceholder(Factory* factory, uint32_t index, |
375 Code::Kind kind) { | 348 Code::Kind kind) { |
376 // Create a placeholder code object and encode the corresponding index in | 349 // Create a placeholder code object and encode the corresponding index in |
377 // the {constant_pool_offset} field of the code object. | 350 // the {constant_pool_offset} field of the code object. |
378 // TODO(titzer): placeholder code objects are somewhat dangerous. | 351 // TODO(titzer): placeholder code objects are somewhat dangerous. |
379 static byte buffer[] = {0, 0, 0, 0, 0, 0, 0, 0}; // fake instructions. | 352 static byte buffer[] = {0, 0, 0, 0, 0, 0, 0, 0}; // fake instructions. |
380 static CodeDesc desc = {buffer, 8, 8, 0, 0, nullptr, 0, nullptr}; | 353 static CodeDesc desc = { |
| 354 buffer, arraysize(buffer), arraysize(buffer), 0, 0, nullptr, 0, nullptr}; |
381 Handle<Code> code = factory->NewCode(desc, Code::KindField::encode(kind), | 355 Handle<Code> code = factory->NewCode(desc, Code::KindField::encode(kind), |
382 Handle<Object>::null()); | 356 Handle<Object>::null()); |
383 code->set_constant_pool_offset(static_cast<int>(index) + kPlaceholderMarker); | 357 code->set_constant_pool_offset(static_cast<int>(index) + kPlaceholderMarker); |
384 return code; | 358 return code; |
385 } | 359 } |
386 | 360 |
387 // TODO(mtrofin): remove when we stop relying on placeholders. | 361 // TODO(mtrofin): remove when we stop relying on placeholders. |
388 void InitializePlaceholders(Factory* factory, | 362 void InitializePlaceholders(Factory* factory, |
389 std::vector<Handle<Code>>* placeholders, | 363 std::vector<Handle<Code>>* placeholders, |
390 size_t size) { | 364 size_t size) { |
(...skipping 63 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
454 WasmModule::WasmModule(byte* module_start) | 428 WasmModule::WasmModule(byte* module_start) |
455 : module_start(module_start), | 429 : module_start(module_start), |
456 module_end(nullptr), | 430 module_end(nullptr), |
457 min_mem_pages(0), | 431 min_mem_pages(0), |
458 max_mem_pages(0), | 432 max_mem_pages(0), |
459 mem_export(false), | 433 mem_export(false), |
460 mem_external(false), | 434 mem_external(false), |
461 start_function_index(-1), | 435 start_function_index(-1), |
462 origin(kWasmOrigin), | 436 origin(kWasmOrigin), |
463 globals_size(0), | 437 globals_size(0), |
464 indirect_table_size(0), | |
465 pending_tasks(new base::Semaphore(0)) {} | 438 pending_tasks(new base::Semaphore(0)) {} |
466 | 439 |
467 static MaybeHandle<JSFunction> ReportFFIError( | 440 static MaybeHandle<JSFunction> ReportFFIError( |
468 ErrorThrower& thrower, const char* error, uint32_t index, | 441 ErrorThrower& thrower, const char* error, uint32_t index, |
469 Handle<String> module_name, MaybeHandle<String> function_name) { | 442 Handle<String> module_name, MaybeHandle<String> function_name) { |
470 Handle<String> function_name_handle; | 443 Handle<String> function_name_handle; |
471 if (function_name.ToHandle(&function_name_handle)) { | 444 if (function_name.ToHandle(&function_name_handle)) { |
472 thrower.Error("Import #%d module=\"%.*s\" function=\"%.*s\" error: %s", | 445 thrower.Error("Import #%d module=\"%.*s\" function=\"%.*s\" error: %s", |
473 index, module_name->length(), module_name->ToCString().get(), | 446 index, module_name->length(), module_name->ToCString().get(), |
474 function_name_handle->length(), | 447 function_name_handle->length(), |
(...skipping 545 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1020 Factory* factory = isolate->factory(); | 993 Factory* factory = isolate->factory(); |
1021 | 994 |
1022 MaybeHandle<FixedArray> nothing; | 995 MaybeHandle<FixedArray> nothing; |
1023 | 996 |
1024 WasmModuleInstance temp_instance_for_compilation(this); | 997 WasmModuleInstance temp_instance_for_compilation(this); |
1025 temp_instance_for_compilation.context = isolate->native_context(); | 998 temp_instance_for_compilation.context = isolate->native_context(); |
1026 temp_instance_for_compilation.mem_size = GetMinModuleMemSize(this); | 999 temp_instance_for_compilation.mem_size = GetMinModuleMemSize(this); |
1027 temp_instance_for_compilation.mem_start = nullptr; | 1000 temp_instance_for_compilation.mem_start = nullptr; |
1028 temp_instance_for_compilation.globals_start = nullptr; | 1001 temp_instance_for_compilation.globals_start = nullptr; |
1029 | 1002 |
1030 MaybeHandle<FixedArray> indirect_table = BuildFunctionTable(isolate, this); | 1003 MaybeHandle<FixedArray> indirect_table = |
1031 if (!indirect_table.is_null()) { | 1004 function_tables.size() |
1032 temp_instance_for_compilation.function_table = | 1005 ? factory->NewFixedArray(static_cast<int>(function_tables.size())) |
1033 indirect_table.ToHandleChecked(); | 1006 : MaybeHandle<FixedArray>(); |
| 1007 for (uint32_t i = 0; i < function_tables.size(); ++i) { |
| 1008 Handle<FixedArray> values = wasm::BuildFunctionTable(isolate, i, this); |
| 1009 temp_instance_for_compilation.function_tables[i] = values; |
| 1010 |
| 1011 Handle<FixedArray> metadata = isolate->factory()->NewFixedArray( |
| 1012 kWasmIndirectFunctionTableMetadataSize); |
| 1013 metadata->set(kSize, Smi::FromInt(function_tables[i].size)); |
| 1014 metadata->set(kTable, *values); |
| 1015 indirect_table.ToHandleChecked()->set(i, *metadata); |
1034 } | 1016 } |
1035 | 1017 |
1036 HistogramTimerScope wasm_compile_module_time_scope( | 1018 HistogramTimerScope wasm_compile_module_time_scope( |
1037 isolate->counters()->wasm_compile_module_time()); | 1019 isolate->counters()->wasm_compile_module_time()); |
1038 | 1020 |
1039 ModuleEnv module_env; | 1021 ModuleEnv module_env; |
1040 module_env.module = this; | 1022 module_env.module = this; |
1041 module_env.instance = &temp_instance_for_compilation; | 1023 module_env.instance = &temp_instance_for_compilation; |
1042 module_env.origin = origin; | 1024 module_env.origin = origin; |
1043 InitializePlaceholders(factory, &module_env.placeholders, functions.size()); | 1025 InitializePlaceholders(factory, &module_env.placeholders, functions.size()); |
(...skipping 26 matching lines...) Expand all Loading... |
1070 compiled_functions->set(static_cast<int>(i), code); | 1052 compiled_functions->set(static_cast<int>(i), code); |
1071 } | 1053 } |
1072 | 1054 |
1073 // Create the compiled module object, and populate with compiled functions | 1055 // Create the compiled module object, and populate with compiled functions |
1074 // and information needed at instantiation time. This object needs to be | 1056 // and information needed at instantiation time. This object needs to be |
1075 // serializable. Instantiation may occur off a deserialized version of this | 1057 // serializable. Instantiation may occur off a deserialized version of this |
1076 // object. | 1058 // object. |
1077 Handle<FixedArray> ret = | 1059 Handle<FixedArray> ret = |
1078 factory->NewFixedArray(kCompiledWasmObjectTableSize, TENURED); | 1060 factory->NewFixedArray(kCompiledWasmObjectTableSize, TENURED); |
1079 ret->set(kFunctions, *compiled_functions); | 1061 ret->set(kFunctions, *compiled_functions); |
1080 ret->set(kIndirectFunctionTableSize, | |
1081 Smi::FromInt(static_cast<int>(function_table.size()))); | |
1082 if (!indirect_table.is_null()) { | 1062 if (!indirect_table.is_null()) { |
1083 ret->set(kIndirectFunctionTablePrototype, | 1063 ret->set(kTableOfIndirectFunctionTables, *indirect_table.ToHandleChecked()); |
1084 *indirect_table.ToHandleChecked()); | |
1085 } | 1064 } |
1086 Handle<FixedArray> import_data = GetImportsMetadata(factory, this); | 1065 Handle<FixedArray> import_data = GetImportsMetadata(factory, this); |
1087 ret->set(kImportData, *import_data); | 1066 ret->set(kImportData, *import_data); |
1088 | 1067 |
1089 // Compile export functions. | 1068 // Compile export functions. |
1090 int export_size = static_cast<int>(export_table.size()); | 1069 int export_size = static_cast<int>(export_table.size()); |
1091 Handle<Code> startup_fct; | 1070 Handle<Code> startup_fct; |
1092 if (export_size > 0) { | 1071 if (export_size > 0) { |
1093 Handle<FixedArray> exports = factory->NewFixedArray(export_size, TENURED); | 1072 Handle<FixedArray> exports = factory->NewFixedArray(export_size, TENURED); |
1094 for (int i = 0; i < export_size; ++i) { | 1073 for (int i = 0; i < export_size; ++i) { |
(...skipping 81 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1176 CHECK(seen); | 1155 CHECK(seen); |
1177 Assembler::FlushICache(isolate, wrapper->instruction_start(), | 1156 Assembler::FlushICache(isolate, wrapper->instruction_start(), |
1178 wrapper->instruction_size()); | 1157 wrapper->instruction_size()); |
1179 } | 1158 } |
1180 | 1159 |
1181 Handle<FixedArray> CloneModuleForInstance(Isolate* isolate, | 1160 Handle<FixedArray> CloneModuleForInstance(Isolate* isolate, |
1182 Handle<FixedArray> original) { | 1161 Handle<FixedArray> original) { |
1183 Factory* factory = isolate->factory(); | 1162 Factory* factory = isolate->factory(); |
1184 Handle<FixedArray> clone = factory->CopyFixedArray(original); | 1163 Handle<FixedArray> clone = factory->CopyFixedArray(original); |
1185 | 1164 |
| 1165 // Copy the outer table, each WasmIndirectFunctionTableMetadata table, and the |
| 1166 // inner kTable. |
| 1167 MaybeHandle<FixedArray> maybe_indirect_tables = |
| 1168 original->GetValue<FixedArray>(kTableOfIndirectFunctionTables); |
| 1169 Handle<FixedArray> indirect_tables, clone_indirect_tables; |
| 1170 if (maybe_indirect_tables.ToHandle(&indirect_tables)) { |
| 1171 clone_indirect_tables = factory->CopyFixedArray(indirect_tables); |
| 1172 clone->set(kTableOfIndirectFunctionTables, *clone_indirect_tables); |
| 1173 for (int i = 0; i < clone_indirect_tables->length(); ++i) { |
| 1174 Handle<FixedArray> orig_metadata = |
| 1175 clone_indirect_tables->GetValueChecked<FixedArray>(i); |
| 1176 Handle<FixedArray> clone_metadata = |
| 1177 factory->CopyFixedArray(orig_metadata); |
| 1178 clone_indirect_tables->set(i, *clone_metadata); |
| 1179 |
| 1180 Handle<FixedArray> orig_table = |
| 1181 clone_metadata->GetValueChecked<FixedArray>(kTable); |
| 1182 Handle<FixedArray> clone_table = factory->CopyFixedArray(orig_table); |
| 1183 clone_metadata->set(kTable, *clone_table); |
| 1184 } |
| 1185 } |
| 1186 |
| 1187 // Clone each code, then if indirect tables are used, patch the cloned code to |
| 1188 // refer to the cloned kTable. |
1186 Handle<FixedArray> orig_wasm_functions = | 1189 Handle<FixedArray> orig_wasm_functions = |
1187 original->GetValueChecked<FixedArray>(kFunctions); | 1190 original->GetValueChecked<FixedArray>(kFunctions); |
1188 Handle<FixedArray> clone_wasm_functions = | 1191 Handle<FixedArray> clone_wasm_functions = |
1189 factory->CopyFixedArray(orig_wasm_functions); | 1192 factory->CopyFixedArray(orig_wasm_functions); |
1190 clone->set(kFunctions, *clone_wasm_functions); | 1193 clone->set(kFunctions, *clone_wasm_functions); |
1191 | 1194 for (int i = 0; i < clone_wasm_functions->length(); ++i) { |
1192 MaybeHandle<FixedArray> maybe_indirect_table = | 1195 Handle<Code> orig_code = clone_wasm_functions->GetValueChecked<Code>(i); |
1193 original->GetValue<FixedArray>(kIndirectFunctionTablePrototype); | |
1194 | |
1195 Handle<FixedArray> indirect_table; | |
1196 Handle<FixedArray> old_table; | |
1197 if (maybe_indirect_table.ToHandle(&old_table)) { | |
1198 indirect_table = factory->CopyFixedArray(old_table); | |
1199 clone->set(kIndirectFunctionTablePrototype, *indirect_table); | |
1200 } | |
1201 | |
1202 for (int i = 0; i < orig_wasm_functions->length(); ++i) { | |
1203 Handle<Code> orig_code = orig_wasm_functions->GetValueChecked<Code>(i); | |
1204 Handle<Code> cloned_code = factory->CopyCode(orig_code); | 1196 Handle<Code> cloned_code = factory->CopyCode(orig_code); |
1205 clone_wasm_functions->set(i, *cloned_code); | 1197 clone_wasm_functions->set(i, *cloned_code); |
1206 if (!maybe_indirect_table.is_null()) { | 1198 |
1207 PatchFunctionTable(cloned_code, old_table, indirect_table); | 1199 if (!clone_indirect_tables.is_null()) { |
| 1200 for (int j = 0; j < clone_indirect_tables->length(); ++j) { |
| 1201 Handle<FixedArray> orig_metadata = |
| 1202 indirect_tables->GetValueChecked<FixedArray>(j); |
| 1203 Handle<FixedArray> orig_table = |
| 1204 orig_metadata->GetValueChecked<FixedArray>(kTable); |
| 1205 |
| 1206 Handle<FixedArray> clone_metadata = |
| 1207 clone_indirect_tables->GetValueChecked<FixedArray>(j); |
| 1208 Handle<FixedArray> clone_table = |
| 1209 clone_metadata->GetValueChecked<FixedArray>(kTable); |
| 1210 |
| 1211 PatchFunctionTable(cloned_code, orig_table, clone_table); |
| 1212 } |
1208 } | 1213 } |
1209 } | 1214 } |
1210 | 1215 |
1211 MaybeHandle<FixedArray> maybe_orig_exports = | 1216 MaybeHandle<FixedArray> maybe_orig_exports = |
1212 original->GetValue<FixedArray>(kExports); | 1217 original->GetValue<FixedArray>(kExports); |
1213 Handle<FixedArray> orig_exports; | 1218 Handle<FixedArray> orig_exports; |
1214 if (maybe_orig_exports.ToHandle(&orig_exports)) { | 1219 if (maybe_orig_exports.ToHandle(&orig_exports)) { |
1215 Handle<FixedArray> cloned_exports = factory->CopyFixedArray(orig_exports); | 1220 Handle<FixedArray> cloned_exports = factory->CopyFixedArray(orig_exports); |
1216 clone->set(kExports, *cloned_exports); | 1221 clone->set(kExports, *cloned_exports); |
1217 for (int i = 0; i < orig_exports->length(); ++i) { | 1222 for (int i = 0; i < orig_exports->length(); ++i) { |
(...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1269 isolate->counters()->wasm_instantiate_module_time()); | 1274 isolate->counters()->wasm_instantiate_module_time()); |
1270 ErrorThrower thrower(isolate, "WasmModule::Instantiate()"); | 1275 ErrorThrower thrower(isolate, "WasmModule::Instantiate()"); |
1271 Factory* factory = isolate->factory(); | 1276 Factory* factory = isolate->factory(); |
1272 | 1277 |
1273 compiled_module = CloneModuleForInstance(isolate, compiled_module); | 1278 compiled_module = CloneModuleForInstance(isolate, compiled_module); |
1274 | 1279 |
1275 // These fields are compulsory. | 1280 // These fields are compulsory. |
1276 Handle<FixedArray> code_table = | 1281 Handle<FixedArray> code_table = |
1277 compiled_module->GetValueChecked<FixedArray>(kFunctions); | 1282 compiled_module->GetValueChecked<FixedArray>(kFunctions); |
1278 | 1283 |
1279 { | 1284 std::vector<Handle<Code>> functions( |
1280 std::vector<Handle<Code>> functions( | 1285 static_cast<size_t>(code_table->length())); |
1281 static_cast<size_t>(code_table->length())); | 1286 for (int i = 0; i < code_table->length(); ++i) { |
1282 for (int i = 0; i < code_table->length(); ++i) { | 1287 functions[static_cast<size_t>(i)] = code_table->GetValueChecked<Code>(i); |
1283 functions[static_cast<size_t>(i)] = code_table->GetValueChecked<Code>(i); | |
1284 } | |
1285 LinkModuleFunctions(isolate, functions); | |
1286 } | 1288 } |
| 1289 LinkModuleFunctions(isolate, functions); |
1287 | 1290 |
1288 RecordStats(isolate, code_table); | 1291 RecordStats(isolate, code_table); |
1289 | 1292 |
1290 MaybeHandle<JSObject> nothing; | 1293 MaybeHandle<JSObject> nothing; |
1291 | 1294 |
1292 Handle<Map> map = factory->NewMap( | 1295 Handle<Map> map = factory->NewMap( |
1293 JS_OBJECT_TYPE, | 1296 JS_OBJECT_TYPE, |
1294 JSObject::kHeaderSize + kWasmModuleInternalFieldCount * kPointerSize); | 1297 JSObject::kHeaderSize + kWasmModuleInternalFieldCount * kPointerSize); |
1295 Handle<JSObject> js_object = factory->NewJSObjectFromMap(map, TENURED); | 1298 Handle<JSObject> js_object = factory->NewJSObjectFromMap(map, TENURED); |
1296 js_object->SetInternalField(kWasmModuleCodeTable, *code_table); | 1299 js_object->SetInternalField(kWasmModuleCodeTable, *code_table); |
1297 | 1300 |
1298 if (!(SetupInstanceHeap(isolate, compiled_module, js_object, memory, | 1301 if (!(SetupInstanceHeap(isolate, compiled_module, js_object, memory, |
1299 &thrower) && | 1302 &thrower) && |
1300 SetupGlobals(isolate, compiled_module, js_object, &thrower) && | 1303 SetupGlobals(isolate, compiled_module, js_object, &thrower) && |
1301 SetupImports(isolate, compiled_module, js_object, &thrower, ffi) && | 1304 SetupImports(isolate, compiled_module, js_object, &thrower, ffi) && |
1302 SetupExportsObject(compiled_module, isolate, js_object, &thrower))) { | 1305 SetupExportsObject(compiled_module, isolate, js_object, &thrower))) { |
1303 return nothing; | 1306 return nothing; |
1304 } | 1307 } |
1305 | 1308 |
1306 SetDebugSupport(factory, compiled_module, js_object); | 1309 SetDebugSupport(factory, compiled_module, js_object); |
1307 | 1310 |
1308 FlushAssemblyCache(isolate, code_table); | 1311 FlushAssemblyCache(isolate, code_table); |
1309 | 1312 |
1310 MaybeHandle<FixedArray> maybe_indirect_table = | 1313 MaybeHandle<FixedArray> maybe_indirect_tables = |
1311 compiled_module->GetValue<FixedArray>(kIndirectFunctionTablePrototype); | 1314 compiled_module->GetValue<FixedArray>(kTableOfIndirectFunctionTables); |
1312 Handle<FixedArray> indirect_table; | 1315 Handle<FixedArray> indirect_tables; |
1313 if (maybe_indirect_table.ToHandle(&indirect_table)) { | 1316 if (maybe_indirect_tables.ToHandle(&indirect_tables)) { |
1314 int table_size = | 1317 for (int i = 0; i < indirect_tables->length(); ++i) { |
1315 Smi::cast(compiled_module->get(kIndirectFunctionTableSize))->value(); | 1318 Handle<FixedArray> metadata = |
1316 int half_point = indirect_table->length() / 2; | 1319 indirect_tables->GetValueChecked<FixedArray>(i); |
1317 for (int i = half_point; i < half_point + table_size; ++i) { | 1320 uint32_t size = Smi::cast(metadata->get(kSize))->value(); |
1318 int index = Smi::cast(indirect_table->get(i))->value(); | 1321 Handle<FixedArray> table = metadata->GetValueChecked<FixedArray>(kTable); |
1319 DCHECK_GE(index, 0); | 1322 wasm::PopulateFunctionTable(table, size, &functions); |
1320 DCHECK_LT(index, code_table->length()); | |
1321 indirect_table->set(i, code_table->get(index)); | |
1322 } | 1323 } |
1323 js_object->SetInternalField(kWasmModuleFunctionTable, *indirect_table); | 1324 js_object->SetInternalField(kWasmModuleFunctionTable, *indirect_tables); |
1324 } | 1325 } |
1325 | 1326 |
1326 // Run the start function if one was specified. | 1327 // Run the start function if one was specified. |
1327 MaybeHandle<FixedArray> maybe_startup_fct = | 1328 MaybeHandle<FixedArray> maybe_startup_fct = |
1328 compiled_module->GetValue<FixedArray>(kStartupFunction); | 1329 compiled_module->GetValue<FixedArray>(kStartupFunction); |
1329 Handle<FixedArray> metadata; | 1330 Handle<FixedArray> metadata; |
1330 if (maybe_startup_fct.ToHandle(&metadata)) { | 1331 if (maybe_startup_fct.ToHandle(&metadata)) { |
1331 HandleScope scope(isolate); | 1332 HandleScope scope(isolate); |
1332 Handle<Code> startup_code = metadata->GetValueChecked<Code>(kExportCode); | 1333 Handle<Code> startup_code = metadata->GetValueChecked<Code>(kExportCode); |
1333 int arity = Smi::cast(metadata->get(kExportArity))->value(); | 1334 int arity = Smi::cast(metadata->get(kExportArity))->value(); |
(...skipping 134 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1468 if (RelocInfo::IsWasmMemoryReference(mode) || | 1469 if (RelocInfo::IsWasmMemoryReference(mode) || |
1469 RelocInfo::IsWasmMemorySizeReference(mode)) { | 1470 RelocInfo::IsWasmMemorySizeReference(mode)) { |
1470 it.rinfo()->update_wasm_memory_reference(old_start, new_start, old_size, | 1471 it.rinfo()->update_wasm_memory_reference(old_start, new_start, old_size, |
1471 new_size); | 1472 new_size); |
1472 } | 1473 } |
1473 } | 1474 } |
1474 } | 1475 } |
1475 return true; | 1476 return true; |
1476 } | 1477 } |
1477 | 1478 |
| 1479 Handle<FixedArray> BuildFunctionTable(Isolate* isolate, uint32_t index, |
| 1480 const WasmModule* module) { |
| 1481 const WasmIndirectFunctionTable* table = &module->function_tables[index]; |
| 1482 DCHECK_EQ(table->size, table->values.size()); |
| 1483 DCHECK_GE(table->max_size, table->size); |
| 1484 Handle<FixedArray> values = |
| 1485 isolate->factory()->NewFixedArray(2 * table->max_size); |
| 1486 for (uint32_t i = 0; i < table->size; ++i) { |
| 1487 const WasmFunction* function = &module->functions[table->values[i]]; |
| 1488 values->set(i, Smi::FromInt(function->sig_index)); |
| 1489 values->set(i + table->max_size, Smi::FromInt(table->values[i])); |
| 1490 } |
| 1491 // Set the remaining elements to -1 (instead of "undefined"). These |
| 1492 // elements are accessed directly as SMIs (without a check). On 64-bit |
| 1493 // platforms, it is possible to have the top bits of "undefined" take |
| 1494 // small integer values (or zero), which are more likely to be equal to |
| 1495 // the signature index we check against. |
| 1496 for (uint32_t i = table->size; i < table->max_size; i++) { |
| 1497 values->set(i, Smi::FromInt(-1)); |
| 1498 } |
| 1499 return values; |
| 1500 } |
| 1501 |
| 1502 void PopulateFunctionTable(Handle<FixedArray> table, uint32_t table_size, |
| 1503 const std::vector<Handle<Code>>* code_table) { |
| 1504 uint32_t max_size = table->length() / 2; |
| 1505 for (uint32_t i = max_size; i < max_size + table_size; ++i) { |
| 1506 int index = Smi::cast(table->get(static_cast<int>(i)))->value(); |
| 1507 DCHECK_GE(index, 0); |
| 1508 DCHECK_LT(static_cast<size_t>(index), code_table->size()); |
| 1509 table->set(static_cast<int>(i), *(*code_table)[index]); |
| 1510 } |
| 1511 } |
| 1512 |
1478 int GetNumberOfFunctions(JSObject* wasm) { | 1513 int GetNumberOfFunctions(JSObject* wasm) { |
1479 Object* func_names_obj = wasm->GetInternalField(kWasmFunctionNamesArray); | 1514 Object* func_names_obj = wasm->GetInternalField(kWasmFunctionNamesArray); |
1480 // TODO(clemensh): this looks inside an array constructed elsewhere. Refactor. | 1515 // TODO(clemensh): this looks inside an array constructed elsewhere. Refactor. |
1481 return ByteArray::cast(func_names_obj)->get_int(0); | 1516 return ByteArray::cast(func_names_obj)->get_int(0); |
1482 } | 1517 } |
1483 | 1518 |
1484 namespace testing { | 1519 namespace testing { |
1485 | 1520 |
1486 int32_t CompileAndRunWasmModule(Isolate* isolate, const byte* module_start, | 1521 int32_t CompileAndRunWasmModule(Isolate* isolate, const byte* module_start, |
1487 const byte* module_end, bool asm_js) { | 1522 const byte* module_end, bool asm_js) { |
(...skipping 62 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1550 return static_cast<int32_t>(HeapNumber::cast(*result)->value()); | 1585 return static_cast<int32_t>(HeapNumber::cast(*result)->value()); |
1551 } | 1586 } |
1552 thrower.Error("WASM.compileRun() failed: Return value should be number"); | 1587 thrower.Error("WASM.compileRun() failed: Return value should be number"); |
1553 return -1; | 1588 return -1; |
1554 } | 1589 } |
1555 | 1590 |
1556 } // namespace testing | 1591 } // namespace testing |
1557 } // namespace wasm | 1592 } // namespace wasm |
1558 } // namespace internal | 1593 } // namespace internal |
1559 } // namespace v8 | 1594 } // namespace v8 |
OLD | NEW |