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 94 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
105 os.write(name.start(), name.length()); | 105 os.write(name.start(), name.length()); |
106 } else { | 106 } else { |
107 os << "+" << pair.function_->func_index; | 107 os << "+" << pair.function_->func_index; |
108 } | 108 } |
109 } else { | 109 } else { |
110 os << "?"; | 110 os << "?"; |
111 } | 111 } |
112 return os; | 112 return os; |
113 } | 113 } |
114 | 114 |
| 115 Handle<JSFunction> WrapExportCodeAsJSFunction( |
| 116 Isolate* isolate, Handle<Code> export_code, Handle<String> name, int arity, |
| 117 Handle<JSObject> module_instance) { |
| 118 Handle<SharedFunctionInfo> shared = |
| 119 isolate->factory()->NewSharedFunctionInfo(name, export_code, false); |
| 120 shared->set_length(arity); |
| 121 shared->set_internal_formal_parameter_count(arity); |
| 122 Handle<JSFunction> function = isolate->factory()->NewFunction( |
| 123 isolate->wasm_function_map(), name, export_code); |
| 124 function->set_shared(*shared); |
| 125 |
| 126 function->SetInternalField(0, *module_instance); |
| 127 return function; |
| 128 } |
| 129 |
115 namespace { | 130 namespace { |
116 // Internal constants for the layout of the module object. | 131 // Internal constants for the layout of the module object. |
117 const int kWasmModuleFunctionTable = 0; | 132 const int kWasmModuleFunctionTable = 0; |
118 const int kWasmModuleCodeTable = 1; | 133 const int kWasmModuleCodeTable = 1; |
119 const int kWasmMemArrayBuffer = 2; | 134 const int kWasmMemArrayBuffer = 2; |
120 const int kWasmGlobalsArrayBuffer = 3; | 135 const int kWasmGlobalsArrayBuffer = 3; |
121 // TODO(clemensh): Remove function name array, extract names from module bytes. | 136 // TODO(clemensh): Remove function name array, extract names from module bytes. |
122 const int kWasmFunctionNamesArray = 4; | 137 const int kWasmFunctionNamesArray = 4; |
123 const int kWasmModuleBytesString = 5; | 138 const int kWasmModuleBytesString = 5; |
124 const int kWasmDebugInfo = 6; | 139 const int kWasmDebugInfo = 6; |
125 const int kWasmModuleInternalFieldCount = 7; | 140 const int kWasmModuleInternalFieldCount = 7; |
126 | 141 |
127 // TODO(mtrofin): Unnecessary once we stop using JS Heap for wasm code. | 142 // TODO(mtrofin): Unnecessary once we stop using JS Heap for wasm code. |
128 // For now, each field is expected to have the type commented by its side. | 143 // For now, each field is expected to have the type commented by its side. |
129 // The elements typed as "maybe" are optional. The others are mandatory. Since | 144 // The elements typed as "maybe" are optional. The others are mandatory. Since |
130 // the compiled module is either obtained from the current v8 instance, or from | 145 // the compiled module is either obtained from the current v8 instance, or from |
131 // a snapshot produced by a compatible (==identical) v8 instance, we simply | 146 // a snapshot produced by a compatible (==identical) v8 instance, we simply |
132 // fail at instantiation time, in the face of invalid data. | 147 // fail at instantiation time, in the face of invalid data. |
133 enum CompiledWasmObjectFields { | 148 enum CompiledWasmObjectFields { |
134 kFunctions, // FixedArray of Code | 149 kFunctions, // FixedArray of Code |
135 kImportData, // maybe FixedArray of FixedArray respecting the | 150 kImportData, // maybe FixedArray of FixedArray respecting the |
136 // WasmImportMetadata structure. | 151 // WasmImportMetadata structure. |
137 kExports, // maybe FixedArray of JSFunction | 152 kExports, // maybe FixedArray of FixedArray of WasmExportMetadata |
138 kStartupFunction, // maybe JSFunction | 153 // structure |
139 kModuleBytes, // maybe String | 154 kStartupFunction, // maybe FixedArray of WasmExportMetadata structure |
140 kFunctionNameTable, // maybe ByteArray | 155 kIndirectFunctionTableSize, // Smi. Size of indirect function table. |
141 kMinRequiredMemory, // Smi. an uint32_t | 156 kIndirectFunctionTablePrototype, // maybe FixedArray |
| 157 kModuleBytes, // maybe String |
| 158 kFunctionNameTable, // maybe ByteArray |
| 159 kMinRequiredMemory, // Smi. an uint32_t |
142 // The following 2 are either together present or absent: | 160 // The following 2 are either together present or absent: |
143 kDataSegmentsInfo, // maybe FixedArray of FixedArray respecting the | 161 kDataSegmentsInfo, // maybe FixedArray of FixedArray respecting the |
144 // WasmSegmentInfo structure | 162 // WasmSegmentInfo structure |
145 kDataSegments, // maybe ByteArray. | 163 kDataSegments, // maybe ByteArray. |
146 | 164 |
147 kGlobalsSize, // Smi. an uint32_t | 165 kGlobalsSize, // Smi. an uint32_t |
148 kExportMem, // Smi. bool | 166 kExportMem, // Smi. bool |
149 kOrigin, // Smi. ModuleOrigin | 167 kOrigin, // Smi. ModuleOrigin |
150 kCompiledWasmObjectTableSize // Sentinel value. | 168 kCompiledWasmObjectTableSize // Sentinel value. |
151 }; | 169 }; |
152 | 170 |
153 enum WasmImportMetadata { | 171 enum WasmImportMetadata { |
154 kModuleName, // String | 172 kModuleName, // String |
155 kFunctionName, // maybe String | 173 kFunctionName, // maybe String |
156 kOutputCount, // Smi. an uint32_t | 174 kOutputCount, // Smi. an uint32_t |
157 kSignature, // ByteArray. A copy of the data in FunctionSig | 175 kSignature, // ByteArray. A copy of the data in FunctionSig |
158 kWasmImportDataTableSize // Sentinel value. | 176 kWasmImportDataTableSize // Sentinel value. |
159 }; | 177 }; |
160 | 178 |
| 179 enum WasmExportMetadata { |
| 180 kExportCode, // Code |
| 181 kExportName, // String |
| 182 kExportArity, // Smi, an int |
| 183 kExportedFunctionIndex, // Smi, an uint32_t |
| 184 kWasmExportMetadataTableSize // Sentinel value. |
| 185 }; |
| 186 |
161 enum WasmSegmentInfo { | 187 enum WasmSegmentInfo { |
162 kDestAddr, // Smi. an uint32_t | 188 kDestAddr, // Smi. an uint32_t |
163 kSourceSize, // Smi. an uint32_t | 189 kSourceSize, // Smi. an uint32_t |
164 kWasmSegmentInfoSize // Sentinel value. | 190 kWasmSegmentInfoSize // Sentinel value. |
165 }; | 191 }; |
166 | 192 |
167 uint32_t GetMinModuleMemSize(const WasmModule* module) { | 193 uint32_t GetMinModuleMemSize(const WasmModule* module) { |
168 return WasmModule::kPageSize * module->min_mem_pages; | 194 return WasmModule::kPageSize * module->min_mem_pages; |
169 } | 195 } |
170 | 196 |
(...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
222 segments->set(i, *js_segment); | 248 segments->set(i, *js_segment); |
223 data->copy_in(last_insertion_pos, | 249 data->copy_in(last_insertion_pos, |
224 module->module_start + segment.source_offset, | 250 module->module_start + segment.source_offset, |
225 segment.source_size); | 251 segment.source_size); |
226 last_insertion_pos += segment.source_size; | 252 last_insertion_pos += segment.source_size; |
227 } | 253 } |
228 compiled_module->set(kDataSegmentsInfo, *segments); | 254 compiled_module->set(kDataSegmentsInfo, *segments); |
229 compiled_module->set(kDataSegments, *data); | 255 compiled_module->set(kDataSegments, *data); |
230 } | 256 } |
231 | 257 |
232 Handle<FixedArray> BuildFunctionTable(Isolate* isolate, | 258 MaybeHandle<FixedArray> BuildFunctionTable(Isolate* isolate, |
233 const WasmModule* module) { | 259 const WasmModule* module) { |
234 // Compute the size of the indirect function table | 260 // Compute the size of the indirect function table |
235 uint32_t table_size = module->FunctionTableSize(); | 261 uint32_t table_size = module->FunctionTableSize(); |
236 if (table_size == 0) { | 262 if (table_size == 0) { |
237 return Handle<FixedArray>::null(); | 263 return MaybeHandle<FixedArray>(); |
238 } | 264 } |
239 | 265 |
| 266 DCHECK_GE(table_size, module->function_table.size()); |
| 267 |
240 Handle<FixedArray> fixed = isolate->factory()->NewFixedArray(2 * table_size); | 268 Handle<FixedArray> fixed = isolate->factory()->NewFixedArray(2 * table_size); |
241 for (uint32_t i = 0; | 269 for (uint32_t i = 0; i < module->function_table.size(); ++i) { |
242 i < static_cast<uint32_t>(module->function_table.size()); | |
243 ++i) { | |
244 const WasmFunction* function = | 270 const WasmFunction* function = |
245 &module->functions[module->function_table[i]]; | 271 &module->functions[module->function_table[i]]; |
246 fixed->set(i, Smi::FromInt(function->sig_index)); | 272 int fixed_array_index = static_cast<int>(i); |
| 273 fixed->set(fixed_array_index, Smi::FromInt(function->sig_index)); |
| 274 fixed->set(fixed_array_index + table_size, |
| 275 Smi::FromInt(module->function_table[fixed_array_index])); |
247 } | 276 } |
| 277 |
248 // Set the remaining elements to -1 (instead of "undefined"). These | 278 // Set the remaining elements to -1 (instead of "undefined"). These |
249 // elements are accessed directly as SMIs (without a check). On 64-bit | 279 // elements are accessed directly as SMIs (without a check). On 64-bit |
250 // platforms, it is possible to have the top bits of "undefined" take | 280 // platforms, it is possible to have the top bits of "undefined" take |
251 // small integer values (or zero), which are more likely to be equal to | 281 // small integer values (or zero), which are more likely to be equal to |
252 // the signature index we check against. | 282 // the signature index we check against. |
253 for (uint32_t i = static_cast<uint32_t>(module->function_table.size()); | 283 for (uint32_t i = static_cast<uint32_t>(module->function_table.size()); |
254 i < table_size; | 284 i < table_size; |
255 ++i) { | 285 ++i) { |
256 fixed->set(i, Smi::FromInt(-1)); | 286 fixed->set(i, Smi::FromInt(-1)); |
257 } | 287 } |
258 return fixed; | 288 return fixed; |
259 } | 289 } |
260 | 290 |
| 291 void PatchFunctionTable(Handle<Code> code, |
| 292 Handle<FixedArray> old_indirect_table, |
| 293 Handle<FixedArray> new_indirect_table) { |
| 294 for (RelocIterator it(*code, 1 << RelocInfo::EMBEDDED_OBJECT); !it.done(); |
| 295 it.next()) { |
| 296 if (it.rinfo()->target_object() == *old_indirect_table) { |
| 297 it.rinfo()->set_target_object(*new_indirect_table); |
| 298 } |
| 299 } |
| 300 } |
| 301 |
261 Handle<JSArrayBuffer> NewArrayBuffer(Isolate* isolate, size_t size) { | 302 Handle<JSArrayBuffer> NewArrayBuffer(Isolate* isolate, size_t size) { |
262 if (size > (WasmModule::kMaxMemPages * WasmModule::kPageSize)) { | 303 if (size > (WasmModule::kMaxMemPages * WasmModule::kPageSize)) { |
263 // TODO(titzer): lift restriction on maximum memory allocated here. | 304 // TODO(titzer): lift restriction on maximum memory allocated here. |
264 return Handle<JSArrayBuffer>::null(); | 305 return Handle<JSArrayBuffer>::null(); |
265 } | 306 } |
266 void* memory = isolate->array_buffer_allocator()->Allocate(size); | 307 void* memory = isolate->array_buffer_allocator()->Allocate(size); |
267 if (memory == nullptr) { | 308 if (memory == nullptr) { |
268 return Handle<JSArrayBuffer>::null(); | 309 return Handle<JSArrayBuffer>::null(); |
269 } | 310 } |
270 | 311 |
(...skipping 108 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
379 } | 420 } |
380 } | 421 } |
381 } | 422 } |
382 return modified; | 423 return modified; |
383 } | 424 } |
384 | 425 |
385 void LinkModuleFunctions(Isolate* isolate, | 426 void LinkModuleFunctions(Isolate* isolate, |
386 std::vector<Handle<Code>>& functions) { | 427 std::vector<Handle<Code>>& functions) { |
387 for (size_t i = 0; i < functions.size(); ++i) { | 428 for (size_t i = 0; i < functions.size(); ++i) { |
388 Handle<Code> code = functions[i]; | 429 Handle<Code> code = functions[i]; |
389 bool modified = LinkFunction(code, functions, Code::WASM_FUNCTION); | 430 LinkFunction(code, functions, Code::WASM_FUNCTION); |
390 if (modified) { | |
391 Assembler::FlushICache(isolate, code->instruction_start(), | |
392 code->instruction_size()); | |
393 } | |
394 } | 431 } |
395 } | 432 } |
396 | 433 |
397 void LinkImports(Isolate* isolate, std::vector<Handle<Code>>& functions, | 434 void LinkImports(Isolate* isolate, std::vector<Handle<Code>>& functions, |
398 const std::vector<Handle<Code>>& imports) { | 435 const std::vector<Handle<Code>>& imports) { |
399 for (uint32_t i = 0; i < functions.size(); ++i) { | 436 for (uint32_t i = 0; i < functions.size(); ++i) { |
400 Handle<Code> code = functions[i]; | 437 Handle<Code> code = functions[i]; |
401 bool modified = LinkFunction(code, imports, Code::WASM_TO_JS_FUNCTION); | 438 LinkFunction(code, imports, Code::WASM_TO_JS_FUNCTION); |
402 if (modified) { | |
403 Assembler::FlushICache(isolate, code->instruction_start(), | |
404 code->instruction_size()); | |
405 } | |
406 } | 439 } |
407 } | 440 } |
408 | 441 |
| 442 void FlushAssemblyCache(Isolate* isolate, Handle<FixedArray> functions) { |
| 443 for (int i = 0; i < functions->length(); ++i) { |
| 444 Handle<Code> code = functions->GetValueChecked<Code>(i); |
| 445 Assembler::FlushICache(isolate, code->instruction_start(), |
| 446 code->instruction_size()); |
| 447 } |
| 448 } |
| 449 |
409 } // namespace | 450 } // namespace |
410 | 451 |
411 WasmModule::WasmModule() | 452 WasmModule::WasmModule() |
412 : module_start(nullptr), | 453 : module_start(nullptr), |
413 module_end(nullptr), | 454 module_end(nullptr), |
414 min_mem_pages(0), | 455 min_mem_pages(0), |
415 max_mem_pages(0), | 456 max_mem_pages(0), |
416 mem_export(false), | 457 mem_export(false), |
417 mem_external(false), | 458 mem_external(false), |
418 start_function_index(-1), | 459 start_function_index(-1), |
419 origin(kWasmOrigin), | 460 origin(kWasmOrigin), |
420 globals_size(0), | 461 globals_size(0), |
421 indirect_table_size(0), | 462 indirect_table_size(0), |
422 pending_tasks(new base::Semaphore(0)) {} | 463 pending_tasks(new base::Semaphore(0)) {} |
423 | 464 |
424 static MaybeHandle<JSFunction> ReportFFIError( | 465 static MaybeHandle<JSFunction> ReportFFIError( |
425 ErrorThrower& thrower, const char* error, uint32_t index, | 466 ErrorThrower& thrower, const char* error, uint32_t index, |
426 Handle<String> module_name, MaybeHandle<String> function_name) { | 467 Handle<String> module_name, MaybeHandle<String> function_name) { |
427 if (!function_name.is_null()) { | 468 Handle<String> function_name_handle; |
428 Handle<String> function_name_handle = function_name.ToHandleChecked(); | 469 if (function_name.ToHandle(&function_name_handle)) { |
429 thrower.Error("Import #%d module=\"%.*s\" function=\"%.*s\" error: %s", | 470 thrower.Error("Import #%d module=\"%.*s\" function=\"%.*s\" error: %s", |
430 index, module_name->length(), module_name->ToCString().get(), | 471 index, module_name->length(), module_name->ToCString().get(), |
431 function_name_handle->length(), | 472 function_name_handle->length(), |
432 function_name_handle->ToCString().get(), error); | 473 function_name_handle->ToCString().get(), error); |
433 } else { | 474 } else { |
434 thrower.Error("Import #%d module=\"%.*s\" error: %s", index, | 475 thrower.Error("Import #%d module=\"%.*s\" error: %s", index, |
435 module_name->length(), module_name->ToCString().get(), error); | 476 module_name->length(), module_name->ToCString().get(), error); |
436 } | 477 } |
437 thrower.Error("Import "); | 478 thrower.Error("Import "); |
438 return MaybeHandle<JSFunction>(); | 479 return MaybeHandle<JSFunction>(); |
(...skipping 356 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
795 if (code.is_null()) { | 836 if (code.is_null()) { |
796 thrower->Error("Compilation of #%d:%.*s failed.", i, str.length(), | 837 thrower->Error("Compilation of #%d:%.*s failed.", i, str.length(), |
797 str.start()); | 838 str.start()); |
798 break; | 839 break; |
799 } | 840 } |
800 // Install the code into the linker table. | 841 // Install the code into the linker table. |
801 functions[i] = code; | 842 functions[i] = code; |
802 } | 843 } |
803 } | 844 } |
804 | 845 |
805 void PopulateFunctionTable(WasmModuleInstance* instance) { | |
806 if (!instance->function_table.is_null()) { | |
807 uint32_t table_size = instance->module->FunctionTableSize(); | |
808 DCHECK_EQ(table_size * 2, instance->function_table->length()); | |
809 uint32_t populated_table_size = | |
810 static_cast<uint32_t>(instance->module->function_table.size()); | |
811 for (uint32_t i = 0; i < populated_table_size; ++i) { | |
812 instance->function_table->set( | |
813 i + table_size, | |
814 *instance->function_code[instance->module->function_table[i]]); | |
815 } | |
816 } | |
817 } | |
818 | |
819 void SetDebugSupport(Factory* factory, Handle<FixedArray> compiled_module, | 846 void SetDebugSupport(Factory* factory, Handle<FixedArray> compiled_module, |
820 Handle<JSObject> js_object) { | 847 Handle<JSObject> js_object) { |
821 MaybeHandle<String> module_bytes_string = | 848 MaybeHandle<String> module_bytes_string = |
822 compiled_module->GetValue<String>(kModuleBytes); | 849 compiled_module->GetValue<String>(kModuleBytes); |
823 if (!module_bytes_string.is_null()) { | 850 if (!module_bytes_string.is_null()) { |
824 js_object->SetInternalField(kWasmModuleBytesString, | 851 js_object->SetInternalField(kWasmModuleBytesString, |
825 *module_bytes_string.ToHandleChecked()); | 852 *module_bytes_string.ToHandleChecked()); |
826 } | 853 } |
827 Handle<FixedArray> functions = Handle<FixedArray>( | 854 Handle<FixedArray> functions = Handle<FixedArray>( |
828 FixedArray::cast(js_object->GetInternalField(kWasmModuleCodeTable))); | 855 FixedArray::cast(js_object->GetInternalField(kWasmModuleCodeTable))); |
(...skipping 65 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
894 | 921 |
895 bool SetupImports(Isolate* isolate, Handle<FixedArray> compiled_module, | 922 bool SetupImports(Isolate* isolate, Handle<FixedArray> compiled_module, |
896 Handle<JSObject> instance, ErrorThrower* thrower, | 923 Handle<JSObject> instance, ErrorThrower* thrower, |
897 Handle<JSReceiver> ffi) { | 924 Handle<JSReceiver> ffi) { |
898 //------------------------------------------------------------------------- | 925 //------------------------------------------------------------------------- |
899 // Compile wrappers to imported functions. | 926 // Compile wrappers to imported functions. |
900 //------------------------------------------------------------------------- | 927 //------------------------------------------------------------------------- |
901 std::vector<Handle<Code>> import_code; | 928 std::vector<Handle<Code>> import_code; |
902 MaybeHandle<FixedArray> maybe_import_data = | 929 MaybeHandle<FixedArray> maybe_import_data = |
903 compiled_module->GetValue<FixedArray>(kImportData); | 930 compiled_module->GetValue<FixedArray>(kImportData); |
904 if (!maybe_import_data.is_null()) { | 931 Handle<FixedArray> import_data; |
905 Handle<FixedArray> import_data = maybe_import_data.ToHandleChecked(); | 932 if (maybe_import_data.ToHandle(&import_data)) { |
906 if (!CompileWrappersToImportedFunctions(isolate, ffi, import_code, | 933 if (!CompileWrappersToImportedFunctions(isolate, ffi, import_code, |
907 import_data, thrower)) { | 934 import_data, thrower)) { |
908 return false; | 935 return false; |
909 } | 936 } |
910 } | 937 } |
911 | 938 |
912 RecordStats(isolate, import_code); | 939 RecordStats(isolate, import_code); |
913 | 940 |
914 Handle<FixedArray> code_table = Handle<FixedArray>( | 941 Handle<FixedArray> code_table = Handle<FixedArray>( |
915 FixedArray::cast(instance->GetInternalField(kWasmModuleCodeTable))); | 942 FixedArray::cast(instance->GetInternalField(kWasmModuleCodeTable))); |
916 // TODO(mtrofin): get the code off std::vector and on FixedArray, for | 943 // TODO(mtrofin): get the code off std::vector and on FixedArray, for |
917 // consistency. | 944 // consistency. |
918 std::vector<Handle<Code>> function_code(code_table->length()); | 945 std::vector<Handle<Code>> function_code(code_table->length()); |
919 for (int i = 0; i < code_table->length(); ++i) { | 946 for (int i = 0; i < code_table->length(); ++i) { |
920 Handle<Code> code = Handle<Code>(Code::cast(code_table->get(i))); | 947 Handle<Code> code = Handle<Code>(Code::cast(code_table->get(i))); |
921 function_code[i] = code; | 948 function_code[i] = code; |
922 } | 949 } |
923 | 950 |
924 instance->SetInternalField(kWasmModuleFunctionTable, Smi::FromInt(0)); | |
925 LinkImports(isolate, function_code, import_code); | 951 LinkImports(isolate, function_code, import_code); |
926 return true; | 952 return true; |
927 } | 953 } |
928 | 954 |
929 bool SetupExportsObject(Handle<FixedArray> compiled_module, Isolate* isolate, | 955 bool SetupExportsObject(Handle<FixedArray> compiled_module, Isolate* isolate, |
930 Handle<JSObject> instance, ErrorThrower* thrower) { | 956 Handle<JSObject> instance, ErrorThrower* thrower) { |
931 Factory* factory = isolate->factory(); | 957 Factory* factory = isolate->factory(); |
932 bool mem_export = | 958 bool mem_export = |
933 static_cast<bool>(Smi::cast(compiled_module->get(kExportMem))->value()); | 959 static_cast<bool>(Smi::cast(compiled_module->get(kExportMem))->value()); |
934 ModuleOrigin origin = static_cast<ModuleOrigin>( | 960 ModuleOrigin origin = static_cast<ModuleOrigin>( |
935 Smi::cast(compiled_module->get(kOrigin))->value()); | 961 Smi::cast(compiled_module->get(kOrigin))->value()); |
936 | 962 |
937 MaybeHandle<FixedArray> maybe_exports = | 963 MaybeHandle<FixedArray> maybe_exports = |
938 compiled_module->GetValue<FixedArray>(kExports); | 964 compiled_module->GetValue<FixedArray>(kExports); |
939 if (!maybe_exports.is_null() || mem_export) { | 965 if (!maybe_exports.is_null() || mem_export) { |
940 PropertyDescriptor desc; | 966 PropertyDescriptor desc; |
941 desc.set_writable(false); | 967 desc.set_writable(false); |
942 | 968 |
943 Handle<JSObject> exports_object = instance; | 969 Handle<JSObject> exports_object = instance; |
944 if (origin == kWasmOrigin) { | 970 if (origin == kWasmOrigin) { |
945 // Create the "exports" object. | 971 // Create the "exports" object. |
946 Handle<JSFunction> object_function = Handle<JSFunction>( | 972 Handle<JSFunction> object_function = Handle<JSFunction>( |
947 isolate->native_context()->object_function(), isolate); | 973 isolate->native_context()->object_function(), isolate); |
948 exports_object = factory->NewJSObject(object_function, TENURED); | 974 exports_object = factory->NewJSObject(object_function, TENURED); |
949 Handle<String> exports_name = factory->InternalizeUtf8String("exports"); | 975 Handle<String> exports_name = factory->InternalizeUtf8String("exports"); |
950 JSObject::AddProperty(instance, exports_name, exports_object, READ_ONLY); | 976 JSObject::AddProperty(instance, exports_name, exports_object, READ_ONLY); |
951 } | 977 } |
952 if (!maybe_exports.is_null()) { | 978 Handle<FixedArray> exports; |
953 Handle<FixedArray> exports = maybe_exports.ToHandleChecked(); | 979 if (maybe_exports.ToHandle(&exports)) { |
954 | |
955 int exports_size = exports->length(); | 980 int exports_size = exports->length(); |
956 for (int i = 0; i < exports_size; ++i) { | 981 for (int i = 0; i < exports_size; ++i) { |
957 if (thrower->error()) return false; | 982 if (thrower->error()) return false; |
958 Handle<JSFunction> function = exports->GetValueChecked<JSFunction>(i); | 983 Handle<FixedArray> export_metadata = |
959 RecordStats(isolate, function->code()); | 984 exports->GetValueChecked<FixedArray>(i); |
| 985 Handle<Code> export_code = |
| 986 export_metadata->GetValueChecked<Code>(kExportCode); |
| 987 RecordStats(isolate, *export_code); |
960 Handle<String> name = | 988 Handle<String> name = |
961 Handle<String>(String::cast(function->shared()->name())); | 989 export_metadata->GetValueChecked<String>(kExportName); |
962 function->SetInternalField(0, *instance); | 990 int arity = Smi::cast(export_metadata->get(kExportArity))->value(); |
963 | 991 Handle<JSFunction> function = WrapExportCodeAsJSFunction( |
| 992 isolate, export_code, name, arity, instance); |
964 desc.set_value(function); | 993 desc.set_value(function); |
965 Maybe<bool> status = JSReceiver::DefineOwnProperty( | 994 Maybe<bool> status = JSReceiver::DefineOwnProperty( |
966 isolate, exports_object, name, &desc, Object::THROW_ON_ERROR); | 995 isolate, exports_object, name, &desc, Object::THROW_ON_ERROR); |
967 if (!status.IsJust()) { | 996 if (!status.IsJust()) { |
968 thrower->Error("export of %.*s failed.", name->length(), | 997 thrower->Error("export of %.*s failed.", name->length(), |
969 name->ToCString().get()); | 998 name->ToCString().get()); |
970 return false; | 999 return false; |
971 } | 1000 } |
972 } | 1001 } |
973 } | 1002 } |
(...skipping 10 matching lines...) Expand all Loading... |
984 | 1013 |
985 } // namespace | 1014 } // namespace |
986 | 1015 |
987 MaybeHandle<FixedArray> WasmModule::CompileFunctions(Isolate* isolate) const { | 1016 MaybeHandle<FixedArray> WasmModule::CompileFunctions(Isolate* isolate) const { |
988 Factory* factory = isolate->factory(); | 1017 Factory* factory = isolate->factory(); |
989 ErrorThrower thrower(isolate, "WasmModule::CompileFunctions()"); | 1018 ErrorThrower thrower(isolate, "WasmModule::CompileFunctions()"); |
990 | 1019 |
991 MaybeHandle<FixedArray> nothing; | 1020 MaybeHandle<FixedArray> nothing; |
992 | 1021 |
993 WasmModuleInstance temp_instance_for_compilation(this); | 1022 WasmModuleInstance temp_instance_for_compilation(this); |
994 temp_instance_for_compilation.function_table = | |
995 BuildFunctionTable(isolate, this); | |
996 temp_instance_for_compilation.context = isolate->native_context(); | 1023 temp_instance_for_compilation.context = isolate->native_context(); |
997 temp_instance_for_compilation.mem_size = GetMinModuleMemSize(this); | 1024 temp_instance_for_compilation.mem_size = GetMinModuleMemSize(this); |
998 temp_instance_for_compilation.mem_start = nullptr; | 1025 temp_instance_for_compilation.mem_start = nullptr; |
999 temp_instance_for_compilation.globals_start = nullptr; | 1026 temp_instance_for_compilation.globals_start = nullptr; |
1000 | 1027 |
| 1028 MaybeHandle<FixedArray> indirect_table = BuildFunctionTable(isolate, this); |
| 1029 if (!indirect_table.is_null()) { |
| 1030 temp_instance_for_compilation.function_table = |
| 1031 indirect_table.ToHandleChecked(); |
| 1032 } |
| 1033 |
1001 HistogramTimerScope wasm_compile_module_time_scope( | 1034 HistogramTimerScope wasm_compile_module_time_scope( |
1002 isolate->counters()->wasm_compile_module_time()); | 1035 isolate->counters()->wasm_compile_module_time()); |
1003 | 1036 |
1004 ModuleEnv module_env; | 1037 ModuleEnv module_env; |
1005 module_env.module = this; | 1038 module_env.module = this; |
1006 module_env.instance = &temp_instance_for_compilation; | 1039 module_env.instance = &temp_instance_for_compilation; |
1007 module_env.origin = origin; | 1040 module_env.origin = origin; |
1008 InitializePlaceholders(factory, &module_env.placeholders, functions.size()); | 1041 InitializePlaceholders(factory, &module_env.placeholders, functions.size()); |
1009 | 1042 |
1010 Handle<FixedArray> compiled_functions = | 1043 Handle<FixedArray> compiled_functions = |
(...skipping 10 matching lines...) Expand all Loading... |
1021 CompileInParallel(isolate, this, | 1054 CompileInParallel(isolate, this, |
1022 temp_instance_for_compilation.function_code, &thrower, | 1055 temp_instance_for_compilation.function_code, &thrower, |
1023 &module_env); | 1056 &module_env); |
1024 } else { | 1057 } else { |
1025 CompileSequentially(isolate, this, | 1058 CompileSequentially(isolate, this, |
1026 temp_instance_for_compilation.function_code, &thrower, | 1059 temp_instance_for_compilation.function_code, &thrower, |
1027 &module_env); | 1060 &module_env); |
1028 } | 1061 } |
1029 if (thrower.error()) return nothing; | 1062 if (thrower.error()) return nothing; |
1030 | 1063 |
1031 LinkModuleFunctions(isolate, temp_instance_for_compilation.function_code); | |
1032 | |
1033 // At this point, compilation has completed. Update the code table. | 1064 // At this point, compilation has completed. Update the code table. |
1034 for (size_t i = FLAG_skip_compiling_wasm_funcs; | 1065 for (size_t i = FLAG_skip_compiling_wasm_funcs; |
1035 i < temp_instance_for_compilation.function_code.size(); ++i) { | 1066 i < temp_instance_for_compilation.function_code.size(); ++i) { |
1036 Code* code = *temp_instance_for_compilation.function_code[i]; | 1067 Code* code = *temp_instance_for_compilation.function_code[i]; |
1037 compiled_functions->set(static_cast<int>(i), code); | 1068 compiled_functions->set(static_cast<int>(i), code); |
1038 } | 1069 } |
1039 | 1070 |
1040 PopulateFunctionTable(&temp_instance_for_compilation); | |
1041 | |
1042 // Create the compiled module object, and populate with compiled functions | 1071 // Create the compiled module object, and populate with compiled functions |
1043 // and information needed at instantiation time. This object needs to be | 1072 // and information needed at instantiation time. This object needs to be |
1044 // serializable. Instantiation may occur off a deserialized version of this | 1073 // serializable. Instantiation may occur off a deserialized version of this |
1045 // object. | 1074 // object. |
1046 Handle<FixedArray> ret = | 1075 Handle<FixedArray> ret = |
1047 factory->NewFixedArray(kCompiledWasmObjectTableSize, TENURED); | 1076 factory->NewFixedArray(kCompiledWasmObjectTableSize, TENURED); |
1048 ret->set(kFunctions, *compiled_functions); | 1077 ret->set(kFunctions, *compiled_functions); |
1049 | 1078 ret->set(kIndirectFunctionTableSize, |
| 1079 Smi::FromInt(static_cast<int>(function_table.size()))); |
| 1080 if (!indirect_table.is_null()) { |
| 1081 ret->set(kIndirectFunctionTablePrototype, |
| 1082 *indirect_table.ToHandleChecked()); |
| 1083 } |
1050 Handle<FixedArray> import_data = GetImportsMetadata(factory, this); | 1084 Handle<FixedArray> import_data = GetImportsMetadata(factory, this); |
1051 ret->set(kImportData, *import_data); | 1085 ret->set(kImportData, *import_data); |
1052 | 1086 |
1053 // Compile export functions. | 1087 // Compile export functions. |
1054 int export_size = static_cast<int>(export_table.size()); | 1088 int export_size = static_cast<int>(export_table.size()); |
1055 Handle<JSFunction> startup_fct; | 1089 Handle<Code> startup_fct; |
1056 if (export_size > 0) { | 1090 if (export_size > 0) { |
1057 Handle<FixedArray> exports = factory->NewFixedArray(export_size, TENURED); | 1091 Handle<FixedArray> exports = factory->NewFixedArray(export_size, TENURED); |
1058 for (int i = 0; i < export_size; ++i) { | 1092 for (int i = 0; i < export_size; ++i) { |
| 1093 Handle<FixedArray> export_metadata = |
| 1094 factory->NewFixedArray(kWasmExportMetadataTableSize, TENURED); |
1059 const WasmExport& exp = export_table[i]; | 1095 const WasmExport& exp = export_table[i]; |
1060 WasmName str = GetName(exp.name_offset, exp.name_length); | 1096 WasmName str = GetName(exp.name_offset, exp.name_length); |
1061 Handle<String> name = factory->InternalizeUtf8String(str); | 1097 Handle<String> name = factory->InternalizeUtf8String(str); |
1062 Handle<Code> code = | 1098 Handle<Code> code = |
1063 temp_instance_for_compilation.function_code[exp.func_index]; | 1099 temp_instance_for_compilation.function_code[exp.func_index]; |
1064 Handle<JSFunction> function = compiler::CompileJSToWasmWrapper( | 1100 Handle<Code> export_code = compiler::CompileJSToWasmWrapper( |
1065 isolate, &module_env, name, code, exp.func_index); | 1101 isolate, &module_env, code, exp.func_index); |
1066 if (thrower.error()) return nothing; | 1102 if (thrower.error()) return nothing; |
1067 exports->set(i, *function); | 1103 export_metadata->set(kExportCode, *export_code); |
| 1104 export_metadata->set(kExportName, *name); |
| 1105 export_metadata->set( |
| 1106 kExportArity, Smi::FromInt(static_cast<int>( |
| 1107 functions[exp.func_index].sig->parameter_count()))); |
| 1108 export_metadata->set(kExportedFunctionIndex, |
| 1109 Smi::FromInt(static_cast<int>(exp.func_index))); |
| 1110 exports->set(i, *export_metadata); |
1068 if (exp.func_index == start_function_index) { | 1111 if (exp.func_index == start_function_index) { |
1069 startup_fct = function; | 1112 startup_fct = export_code; |
1070 } | 1113 } |
1071 } | 1114 } |
1072 ret->set(kExports, *exports); | 1115 ret->set(kExports, *exports); |
1073 } | 1116 } |
1074 | 1117 |
1075 // Compile startup function, if we haven't already. | 1118 // Compile startup function, if we haven't already. |
1076 if (start_function_index >= 0) { | 1119 if (start_function_index >= 0) { |
| 1120 uint32_t index = static_cast<uint32_t>(start_function_index); |
1077 HandleScope scope(isolate); | 1121 HandleScope scope(isolate); |
1078 if (startup_fct.is_null()) { | 1122 if (startup_fct.is_null()) { |
1079 uint32_t index = static_cast<uint32_t>(start_function_index); | |
1080 Handle<String> name = factory->NewStringFromStaticChars("start"); | |
1081 Handle<Code> code = temp_instance_for_compilation.function_code[index]; | 1123 Handle<Code> code = temp_instance_for_compilation.function_code[index]; |
1082 startup_fct = compiler::CompileJSToWasmWrapper(isolate, &module_env, name, | 1124 DCHECK_EQ(0, functions[index].sig->parameter_count()); |
1083 code, index); | 1125 startup_fct = |
| 1126 compiler::CompileJSToWasmWrapper(isolate, &module_env, code, index); |
1084 } | 1127 } |
1085 ret->set(kStartupFunction, *startup_fct); | 1128 Handle<FixedArray> metadata = |
| 1129 factory->NewFixedArray(kWasmExportMetadataTableSize, TENURED); |
| 1130 metadata->set(kExportCode, *startup_fct); |
| 1131 metadata->set(kExportArity, Smi::FromInt(0)); |
| 1132 metadata->set(kExportedFunctionIndex, Smi::FromInt(start_function_index)); |
| 1133 ret->set(kStartupFunction, *metadata); |
1086 } | 1134 } |
1087 | 1135 |
1088 // TODO(wasm): saving the module bytes for debugging is wasteful. We should | 1136 // TODO(wasm): saving the module bytes for debugging is wasteful. We should |
1089 // consider downloading this on-demand. | 1137 // consider downloading this on-demand. |
1090 { | 1138 { |
1091 size_t module_bytes_len = module_end - module_start; | 1139 size_t module_bytes_len = module_end - module_start; |
1092 DCHECK_LE(module_bytes_len, static_cast<size_t>(kMaxInt)); | 1140 DCHECK_LE(module_bytes_len, static_cast<size_t>(kMaxInt)); |
1093 Vector<const uint8_t> module_bytes_vec(module_start, | 1141 Vector<const uint8_t> module_bytes_vec(module_start, |
1094 static_cast<int>(module_bytes_len)); | 1142 static_cast<int>(module_bytes_len)); |
1095 Handle<String> module_bytes_string = | 1143 Handle<String> module_bytes_string = |
1096 factory->NewStringFromOneByte(module_bytes_vec, TENURED) | 1144 factory->NewStringFromOneByte(module_bytes_vec, TENURED) |
1097 .ToHandleChecked(); | 1145 .ToHandleChecked(); |
1098 ret->set(kModuleBytes, *module_bytes_string); | 1146 ret->set(kModuleBytes, *module_bytes_string); |
1099 } | 1147 } |
1100 | 1148 |
1101 Handle<ByteArray> function_name_table = | 1149 Handle<ByteArray> function_name_table = |
1102 BuildFunctionNamesTable(isolate, module_env.module); | 1150 BuildFunctionNamesTable(isolate, module_env.module); |
1103 ret->set(kFunctionNameTable, *function_name_table); | 1151 ret->set(kFunctionNameTable, *function_name_table); |
1104 ret->set(kMinRequiredMemory, Smi::FromInt(min_mem_pages)); | 1152 ret->set(kMinRequiredMemory, Smi::FromInt(min_mem_pages)); |
1105 if (data_segments.size() > 0) SaveDataSegmentInfo(factory, this, ret); | 1153 if (data_segments.size() > 0) SaveDataSegmentInfo(factory, this, ret); |
1106 ret->set(kGlobalsSize, Smi::FromInt(globals_size)); | 1154 ret->set(kGlobalsSize, Smi::FromInt(globals_size)); |
1107 ret->set(kExportMem, Smi::FromInt(mem_export)); | 1155 ret->set(kExportMem, Smi::FromInt(mem_export)); |
1108 ret->set(kOrigin, Smi::FromInt(origin)); | 1156 ret->set(kOrigin, Smi::FromInt(origin)); |
1109 return ret; | 1157 return ret; |
1110 } | 1158 } |
1111 | 1159 |
| 1160 void PatchJSWrapper(Isolate* isolate, Handle<Code> wrapper, |
| 1161 Handle<Code> new_target) { |
| 1162 AllowDeferredHandleDereference embedding_raw_address; |
| 1163 bool seen = false; |
| 1164 for (RelocIterator it(*wrapper, 1 << RelocInfo::CODE_TARGET); !it.done(); |
| 1165 it.next()) { |
| 1166 Code* target = Code::GetCodeFromTargetAddress(it.rinfo()->target_address()); |
| 1167 if (target->kind() == Code::WASM_FUNCTION) { |
| 1168 DCHECK(!seen); |
| 1169 seen = true; |
| 1170 it.rinfo()->set_target_address(new_target->instruction_start(), |
| 1171 UPDATE_WRITE_BARRIER, SKIP_ICACHE_FLUSH); |
| 1172 } |
| 1173 } |
| 1174 CHECK(seen); |
| 1175 Assembler::FlushICache(isolate, wrapper->instruction_start(), |
| 1176 wrapper->instruction_size()); |
| 1177 } |
| 1178 |
| 1179 Handle<FixedArray> CloneModuleForInstance(Isolate* isolate, |
| 1180 Handle<FixedArray> original) { |
| 1181 Factory* factory = isolate->factory(); |
| 1182 Handle<FixedArray> clone = factory->CopyFixedArray(original); |
| 1183 |
| 1184 Handle<FixedArray> orig_wasm_functions = |
| 1185 original->GetValueChecked<FixedArray>(kFunctions); |
| 1186 Handle<FixedArray> clone_wasm_functions = |
| 1187 factory->CopyFixedArray(orig_wasm_functions); |
| 1188 clone->set(kFunctions, *clone_wasm_functions); |
| 1189 |
| 1190 MaybeHandle<FixedArray> maybe_indirect_table = |
| 1191 original->GetValue<FixedArray>(kIndirectFunctionTablePrototype); |
| 1192 |
| 1193 Handle<FixedArray> indirect_table; |
| 1194 Handle<FixedArray> old_table; |
| 1195 if (maybe_indirect_table.ToHandle(&old_table)) { |
| 1196 indirect_table = factory->CopyFixedArray(old_table); |
| 1197 clone->set(kIndirectFunctionTablePrototype, *indirect_table); |
| 1198 } |
| 1199 |
| 1200 for (int i = 0; i < orig_wasm_functions->length(); ++i) { |
| 1201 Handle<Code> orig_code = orig_wasm_functions->GetValueChecked<Code>(i); |
| 1202 Handle<Code> cloned_code = factory->CopyCode(orig_code); |
| 1203 clone_wasm_functions->set(i, *cloned_code); |
| 1204 if (!maybe_indirect_table.is_null()) { |
| 1205 PatchFunctionTable(cloned_code, old_table, indirect_table); |
| 1206 } |
| 1207 } |
| 1208 |
| 1209 MaybeHandle<FixedArray> maybe_orig_exports = |
| 1210 original->GetValue<FixedArray>(kExports); |
| 1211 Handle<FixedArray> orig_exports; |
| 1212 if (maybe_orig_exports.ToHandle(&orig_exports)) { |
| 1213 Handle<FixedArray> cloned_exports = factory->CopyFixedArray(orig_exports); |
| 1214 clone->set(kExports, *cloned_exports); |
| 1215 for (int i = 0; i < orig_exports->length(); ++i) { |
| 1216 Handle<FixedArray> export_metadata = |
| 1217 orig_exports->GetValueChecked<FixedArray>(i); |
| 1218 Handle<FixedArray> clone_metadata = |
| 1219 factory->CopyFixedArray(export_metadata); |
| 1220 cloned_exports->set(i, *clone_metadata); |
| 1221 Handle<Code> orig_code = |
| 1222 export_metadata->GetValueChecked<Code>(kExportCode); |
| 1223 Handle<Code> cloned_code = factory->CopyCode(orig_code); |
| 1224 clone_metadata->set(kExportCode, *cloned_code); |
| 1225 // TODO(wasm): This is actually a uint32_t, but since FixedArray indexes |
| 1226 // in int, we are taking the risk of invalid values. |
| 1227 int exported_fct_index = |
| 1228 Smi::cast(export_metadata->get(kExportedFunctionIndex))->value(); |
| 1229 CHECK_GE(exported_fct_index, 0); |
| 1230 CHECK_LT(exported_fct_index, clone_wasm_functions->length()); |
| 1231 Handle<Code> new_target = |
| 1232 clone_wasm_functions->GetValueChecked<Code>(exported_fct_index); |
| 1233 PatchJSWrapper(isolate, cloned_code, new_target); |
| 1234 } |
| 1235 } |
| 1236 |
| 1237 MaybeHandle<FixedArray> maybe_startup = |
| 1238 original->GetValue<FixedArray>(kStartupFunction); |
| 1239 if (!maybe_startup.is_null()) { |
| 1240 Handle<FixedArray> startup_metadata = |
| 1241 factory->CopyFixedArray(maybe_startup.ToHandleChecked()); |
| 1242 Handle<Code> startup_fct_clone = |
| 1243 factory->CopyCode(startup_metadata->GetValueChecked<Code>(kExportCode)); |
| 1244 startup_metadata->set(kExportCode, *startup_fct_clone); |
| 1245 clone->set(kStartupFunction, *startup_metadata); |
| 1246 // TODO(wasm): see todo above about int vs size_t indexing in FixedArray. |
| 1247 int startup_fct_index = |
| 1248 Smi::cast(startup_metadata->get(kExportedFunctionIndex))->value(); |
| 1249 CHECK_GE(startup_fct_index, 0); |
| 1250 CHECK_LT(startup_fct_index, clone_wasm_functions->length()); |
| 1251 Handle<Code> new_target = |
| 1252 clone_wasm_functions->GetValueChecked<Code>(startup_fct_index); |
| 1253 PatchJSWrapper(isolate, startup_fct_clone, new_target); |
| 1254 } |
| 1255 return clone; |
| 1256 } |
| 1257 |
1112 // Instantiates a wasm module as a JSObject. | 1258 // Instantiates a wasm module as a JSObject. |
1113 // * allocates a backing store of {mem_size} bytes. | 1259 // * allocates a backing store of {mem_size} bytes. |
1114 // * installs a named property "memory" for that buffer if exported | 1260 // * installs a named property "memory" for that buffer if exported |
1115 // * installs named properties on the object for exported functions | 1261 // * installs named properties on the object for exported functions |
1116 // * compiles wasm code to machine code | 1262 // * compiles wasm code to machine code |
1117 MaybeHandle<JSObject> WasmModule::Instantiate( | 1263 MaybeHandle<JSObject> WasmModule::Instantiate( |
1118 Isolate* isolate, Handle<FixedArray> compiled_module, | 1264 Isolate* isolate, Handle<FixedArray> compiled_module, |
1119 Handle<JSReceiver> ffi, Handle<JSArrayBuffer> memory) { | 1265 Handle<JSReceiver> ffi, Handle<JSArrayBuffer> memory) { |
1120 HistogramTimerScope wasm_instantiate_module_time_scope( | 1266 HistogramTimerScope wasm_instantiate_module_time_scope( |
1121 isolate->counters()->wasm_instantiate_module_time()); | 1267 isolate->counters()->wasm_instantiate_module_time()); |
1122 ErrorThrower thrower(isolate, "WasmModule::Instantiate()"); | 1268 ErrorThrower thrower(isolate, "WasmModule::Instantiate()"); |
1123 Factory* factory = isolate->factory(); | 1269 Factory* factory = isolate->factory(); |
1124 | 1270 |
| 1271 compiled_module = CloneModuleForInstance(isolate, compiled_module); |
| 1272 |
1125 // These fields are compulsory. | 1273 // These fields are compulsory. |
1126 Handle<FixedArray> code_table = | 1274 Handle<FixedArray> code_table = |
1127 compiled_module->GetValueChecked<FixedArray>(kFunctions); | 1275 compiled_module->GetValueChecked<FixedArray>(kFunctions); |
1128 | 1276 |
| 1277 { |
| 1278 std::vector<Handle<Code>> functions( |
| 1279 static_cast<size_t>(code_table->length())); |
| 1280 for (int i = 0; i < code_table->length(); ++i) { |
| 1281 functions[static_cast<size_t>(i)] = code_table->GetValueChecked<Code>(i); |
| 1282 } |
| 1283 LinkModuleFunctions(isolate, functions); |
| 1284 } |
| 1285 |
1129 RecordStats(isolate, code_table); | 1286 RecordStats(isolate, code_table); |
1130 | 1287 |
1131 MaybeHandle<JSObject> nothing; | 1288 MaybeHandle<JSObject> nothing; |
1132 | 1289 |
1133 Handle<Map> map = factory->NewMap( | 1290 Handle<Map> map = factory->NewMap( |
1134 JS_OBJECT_TYPE, | 1291 JS_OBJECT_TYPE, |
1135 JSObject::kHeaderSize + kWasmModuleInternalFieldCount * kPointerSize); | 1292 JSObject::kHeaderSize + kWasmModuleInternalFieldCount * kPointerSize); |
1136 Handle<JSObject> js_object = factory->NewJSObjectFromMap(map, TENURED); | 1293 Handle<JSObject> js_object = factory->NewJSObjectFromMap(map, TENURED); |
1137 js_object->SetInternalField(kWasmModuleCodeTable, *code_table); | 1294 js_object->SetInternalField(kWasmModuleCodeTable, *code_table); |
1138 | 1295 |
1139 if (!(SetupInstanceHeap(isolate, compiled_module, js_object, memory, | 1296 if (!(SetupInstanceHeap(isolate, compiled_module, js_object, memory, |
1140 &thrower) && | 1297 &thrower) && |
1141 SetupGlobals(isolate, compiled_module, js_object, &thrower) && | 1298 SetupGlobals(isolate, compiled_module, js_object, &thrower) && |
1142 SetupImports(isolate, compiled_module, js_object, &thrower, ffi) && | 1299 SetupImports(isolate, compiled_module, js_object, &thrower, ffi) && |
1143 SetupExportsObject(compiled_module, isolate, js_object, &thrower))) { | 1300 SetupExportsObject(compiled_module, isolate, js_object, &thrower))) { |
1144 return nothing; | 1301 return nothing; |
1145 } | 1302 } |
1146 | 1303 |
1147 SetDebugSupport(factory, compiled_module, js_object); | 1304 SetDebugSupport(factory, compiled_module, js_object); |
1148 | 1305 |
| 1306 FlushAssemblyCache(isolate, code_table); |
| 1307 |
| 1308 MaybeHandle<FixedArray> maybe_indirect_table = |
| 1309 compiled_module->GetValue<FixedArray>(kIndirectFunctionTablePrototype); |
| 1310 Handle<FixedArray> indirect_table; |
| 1311 if (maybe_indirect_table.ToHandle(&indirect_table)) { |
| 1312 int table_size = |
| 1313 Smi::cast(compiled_module->get(kIndirectFunctionTableSize))->value(); |
| 1314 int half_point = indirect_table->length() / 2; |
| 1315 for (int i = half_point; i < half_point + table_size; ++i) { |
| 1316 int index = Smi::cast(indirect_table->get(i))->value(); |
| 1317 DCHECK_GE(index, 0); |
| 1318 DCHECK_LT(index, code_table->length()); |
| 1319 indirect_table->set(i, code_table->get(index)); |
| 1320 } |
| 1321 js_object->SetInternalField(kWasmModuleFunctionTable, *indirect_table); |
| 1322 } |
| 1323 |
1149 // Run the start function if one was specified. | 1324 // Run the start function if one was specified. |
1150 MaybeHandle<JSFunction> maybe_startup_fct = | 1325 MaybeHandle<FixedArray> maybe_startup_fct = |
1151 compiled_module->GetValue<JSFunction>(kStartupFunction); | 1326 compiled_module->GetValue<FixedArray>(kStartupFunction); |
1152 if (!maybe_startup_fct.is_null()) { | 1327 Handle<FixedArray> metadata; |
| 1328 if (maybe_startup_fct.ToHandle(&metadata)) { |
1153 HandleScope scope(isolate); | 1329 HandleScope scope(isolate); |
1154 Handle<JSFunction> startup_fct = maybe_startup_fct.ToHandleChecked(); | 1330 Handle<Code> startup_code = metadata->GetValueChecked<Code>(kExportCode); |
1155 RecordStats(isolate, startup_fct->code()); | 1331 int arity = Smi::cast(metadata->get(kExportArity))->value(); |
1156 startup_fct->SetInternalField(0, *js_object); | 1332 Handle<JSFunction> startup_fct = WrapExportCodeAsJSFunction( |
| 1333 isolate, startup_code, factory->InternalizeUtf8String("start"), arity, |
| 1334 js_object); |
| 1335 RecordStats(isolate, *startup_code); |
1157 // Call the JS function. | 1336 // Call the JS function. |
1158 Handle<Object> undefined = isolate->factory()->undefined_value(); | 1337 Handle<Object> undefined = isolate->factory()->undefined_value(); |
1159 MaybeHandle<Object> retval = | 1338 MaybeHandle<Object> retval = |
1160 Execution::Call(isolate, startup_fct, undefined, 0, nullptr); | 1339 Execution::Call(isolate, startup_fct, undefined, 0, nullptr); |
1161 | 1340 |
1162 if (retval.is_null()) { | 1341 if (retval.is_null()) { |
1163 thrower.Error("WASM.instantiateModule(): start function failed"); | 1342 thrower.Error("WASM.instantiateModule(): start function failed"); |
1164 return nothing; | 1343 return nothing; |
1165 } | 1344 } |
1166 } | 1345 } |
(...skipping 160 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1327 } | 1506 } |
1328 if (module->export_table.size() == 0) { | 1507 if (module->export_table.size() == 0) { |
1329 thrower.Error("Not supported: module has no exports."); | 1508 thrower.Error("Not supported: module has no exports."); |
1330 } | 1509 } |
1331 | 1510 |
1332 if (thrower.error()) return -1; | 1511 if (thrower.error()) return -1; |
1333 MaybeHandle<FixedArray> compiled_module = module->CompileFunctions(isolate); | 1512 MaybeHandle<FixedArray> compiled_module = module->CompileFunctions(isolate); |
1334 | 1513 |
1335 if (compiled_module.is_null()) return -1; | 1514 if (compiled_module.is_null()) return -1; |
1336 Handle<JSObject> instance = | 1515 Handle<JSObject> instance = |
1337 module | 1516 WasmModule::Instantiate(isolate, compiled_module.ToHandleChecked(), |
1338 ->Instantiate(isolate, compiled_module.ToHandleChecked(), | 1517 Handle<JSReceiver>::null(), |
1339 Handle<JSReceiver>::null(), | 1518 Handle<JSArrayBuffer>::null()) |
1340 Handle<JSArrayBuffer>::null()) | |
1341 .ToHandleChecked(); | 1519 .ToHandleChecked(); |
1342 | 1520 |
1343 Handle<Name> exports = isolate->factory()->InternalizeUtf8String("exports"); | 1521 Handle<Name> exports = isolate->factory()->InternalizeUtf8String("exports"); |
1344 Handle<JSObject> exports_object = Handle<JSObject>::cast( | 1522 Handle<JSObject> exports_object = Handle<JSObject>::cast( |
1345 JSObject::GetProperty(instance, exports).ToHandleChecked()); | 1523 JSObject::GetProperty(instance, exports).ToHandleChecked()); |
1346 Handle<Name> main_name = isolate->factory()->NewStringFromStaticChars("main"); | 1524 Handle<Name> main_name = isolate->factory()->NewStringFromStaticChars("main"); |
1347 PropertyDescriptor desc; | 1525 PropertyDescriptor desc; |
1348 Maybe<bool> property_found = JSReceiver::GetOwnPropertyDescriptor( | 1526 Maybe<bool> property_found = JSReceiver::GetOwnPropertyDescriptor( |
1349 isolate, exports_object, main_name, &desc); | 1527 isolate, exports_object, main_name, &desc); |
1350 if (!property_found.FromMaybe(false)) return -1; | 1528 if (!property_found.FromMaybe(false)) return -1; |
(...skipping 18 matching lines...) Expand all Loading... |
1369 return static_cast<int32_t>(HeapNumber::cast(*result)->value()); | 1547 return static_cast<int32_t>(HeapNumber::cast(*result)->value()); |
1370 } | 1548 } |
1371 thrower.Error("WASM.compileRun() failed: Return value should be number"); | 1549 thrower.Error("WASM.compileRun() failed: Return value should be number"); |
1372 return -1; | 1550 return -1; |
1373 } | 1551 } |
1374 | 1552 |
1375 } // namespace testing | 1553 } // namespace testing |
1376 } // namespace wasm | 1554 } // namespace wasm |
1377 } // namespace internal | 1555 } // namespace internal |
1378 } // namespace v8 | 1556 } // namespace v8 |
OLD | NEW |