Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(82)

Side by Side Diff: src/wasm/wasm-module.cc

Issue 2174123002: [wasm] Add support for multiple indirect function tables (Closed) Base URL: https://chromium.googlesource.com/v8/v8.git@master
Patch Set: Fix GC issue Created 4 years, 4 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « src/wasm/wasm-module.h ('k') | test/cctest/wasm/test-run-wasm.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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
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
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
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
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
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
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
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
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
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
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
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
OLDNEW
« no previous file with comments | « src/wasm/wasm-module.h ('k') | test/cctest/wasm/test-run-wasm.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698