OLD | NEW |
1 // Copyright 2015 the V8 project authors. All rights reserved. | 1 // Copyright 2015 the V8 project authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include <memory> | 5 #include <memory> |
6 | 6 |
7 #include "src/base/atomic-utils.h" | 7 #include "src/base/atomic-utils.h" |
8 #include "src/code-stubs.h" | 8 #include "src/code-stubs.h" |
9 | 9 |
10 #include "src/macro-assembler.h" | 10 #include "src/macro-assembler.h" |
(...skipping 10 matching lines...) Expand all Loading... |
21 #include "src/wasm/wasm-js.h" | 21 #include "src/wasm/wasm-js.h" |
22 #include "src/wasm/wasm-module.h" | 22 #include "src/wasm/wasm-module.h" |
23 #include "src/wasm/wasm-result.h" | 23 #include "src/wasm/wasm-result.h" |
24 | 24 |
25 #include "src/compiler/wasm-compiler.h" | 25 #include "src/compiler/wasm-compiler.h" |
26 | 26 |
27 namespace v8 { | 27 namespace v8 { |
28 namespace internal { | 28 namespace internal { |
29 namespace wasm { | 29 namespace wasm { |
30 | 30 |
31 const char* SectionName(WasmSectionCode code) { | 31 namespace { |
32 switch (code) { | 32 |
33 case kUnknownSectionCode: | 33 static const int kPlaceholderMarker = 1000000000; |
34 return "Unknown"; | |
35 case kTypeSectionCode: | |
36 return "Type"; | |
37 case kImportSectionCode: | |
38 return "Import"; | |
39 case kFunctionSectionCode: | |
40 return "Function"; | |
41 case kTableSectionCode: | |
42 return "Table"; | |
43 case kMemorySectionCode: | |
44 return "Memory"; | |
45 case kGlobalSectionCode: | |
46 return "Global"; | |
47 case kExportSectionCode: | |
48 return "Export"; | |
49 case kStartSectionCode: | |
50 return "Start"; | |
51 case kCodeSectionCode: | |
52 return "Code"; | |
53 case kElementSectionCode: | |
54 return "Element"; | |
55 case kDataSectionCode: | |
56 return "Data"; | |
57 case kNameSectionCode: | |
58 return "Name"; | |
59 default: | |
60 return "<unknown>"; | |
61 } | |
62 } | |
63 | 34 |
64 enum JSFunctionExportInternalField { | 35 enum JSFunctionExportInternalField { |
65 kInternalModuleInstance, | 36 kInternalModuleInstance, |
66 kInternalArity, | 37 kInternalArity, |
67 kInternalSignature | 38 kInternalSignature |
68 }; | 39 }; |
69 | 40 |
70 static const int kPlaceholderMarker = 1000000000; | |
71 | |
72 std::ostream& operator<<(std::ostream& os, const WasmModule& module) { | |
73 os << "WASM module with "; | |
74 os << (module.min_mem_pages * module.kPageSize) << " min mem"; | |
75 os << (module.max_mem_pages * module.kPageSize) << " max mem"; | |
76 os << module.functions.size() << " functions"; | |
77 os << module.functions.size() << " globals"; | |
78 os << module.functions.size() << " data segments"; | |
79 return os; | |
80 } | |
81 | |
82 std::ostream& operator<<(std::ostream& os, const WasmFunction& function) { | |
83 os << "WASM function with signature " << *function.sig; | |
84 | |
85 os << " code bytes: " | |
86 << (function.code_end_offset - function.code_start_offset); | |
87 return os; | |
88 } | |
89 | |
90 std::ostream& operator<<(std::ostream& os, const WasmFunctionName& pair) { | |
91 os << "#" << pair.function_->func_index << ":"; | |
92 if (pair.function_->name_offset > 0) { | |
93 if (pair.module_) { | |
94 WasmName name = pair.module_->GetName(pair.function_->name_offset, | |
95 pair.function_->name_length); | |
96 os.write(name.start(), name.length()); | |
97 } else { | |
98 os << "+" << pair.function_->func_index; | |
99 } | |
100 } else { | |
101 os << "?"; | |
102 } | |
103 return os; | |
104 } | |
105 | |
106 Handle<JSFunction> WrapExportCodeAsJSFunction( | |
107 Isolate* isolate, Handle<Code> export_code, Handle<String> name, int arity, | |
108 MaybeHandle<ByteArray> maybe_signature, Handle<JSObject> module_instance) { | |
109 Handle<SharedFunctionInfo> shared = | |
110 isolate->factory()->NewSharedFunctionInfo(name, export_code, false); | |
111 shared->set_length(arity); | |
112 shared->set_internal_formal_parameter_count(arity); | |
113 Handle<JSFunction> function = isolate->factory()->NewFunction( | |
114 isolate->wasm_function_map(), name, export_code); | |
115 function->set_shared(*shared); | |
116 | |
117 function->SetInternalField(kInternalModuleInstance, *module_instance); | |
118 // add another Internal Field as the function arity | |
119 function->SetInternalField(kInternalArity, Smi::FromInt(arity)); | |
120 // add another Internal Field as the signature of the foreign function | |
121 Handle<ByteArray> signature; | |
122 if (maybe_signature.ToHandle(&signature)) { | |
123 function->SetInternalField(kInternalSignature, *signature); | |
124 } | |
125 return function; | |
126 } | |
127 | |
128 Object* GetOwningWasmInstance(Object* undefined, Code* code) { | |
129 DCHECK(code->kind() == Code::WASM_FUNCTION); | |
130 DisallowHeapAllocation no_gc; | |
131 FixedArray* deopt_data = code->deoptimization_data(); | |
132 DCHECK_NOT_NULL(deopt_data); | |
133 DCHECK(deopt_data->length() == 2); | |
134 Object* weak_link = deopt_data->get(0); | |
135 if (weak_link == undefined) return undefined; | |
136 WeakCell* cell = WeakCell::cast(weak_link); | |
137 return cell->value(); | |
138 } | |
139 | |
140 namespace { | |
141 // Internal constants for the layout of the module object. | 41 // Internal constants for the layout of the module object. |
142 enum WasmInstanceObjectFields { | 42 enum WasmInstanceObjectFields { |
143 kWasmCompiledModule = 0, | 43 kWasmCompiledModule = 0, |
144 kWasmModuleFunctionTable, | 44 kWasmModuleFunctionTable, |
145 kWasmModuleCodeTable, | 45 kWasmModuleCodeTable, |
146 kWasmMemArrayBuffer, | 46 kWasmMemArrayBuffer, |
147 kWasmGlobalsArrayBuffer, | 47 kWasmGlobalsArrayBuffer, |
148 // TODO(clemensh): Remove function name array, extract names from module | 48 // TODO(clemensh): Remove function name array, extract names from module |
149 // bytes. | 49 // bytes. |
150 kWasmFunctionNamesArray, | 50 kWasmFunctionNamesArray, |
(...skipping 223 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
374 return modified; | 274 return modified; |
375 } | 275 } |
376 | 276 |
377 void FlushICache(Isolate* isolate, Handle<FixedArray> functions) { | 277 void FlushICache(Isolate* isolate, Handle<FixedArray> functions) { |
378 for (int i = 0; i < functions->length(); ++i) { | 278 for (int i = 0; i < functions->length(); ++i) { |
379 Handle<Code> code = functions->GetValueChecked<Code>(isolate, i); | 279 Handle<Code> code = functions->GetValueChecked<Code>(isolate, i); |
380 Assembler::FlushICache(isolate, code->instruction_start(), | 280 Assembler::FlushICache(isolate, code->instruction_start(), |
381 code->instruction_size()); | 281 code->instruction_size()); |
382 } | 282 } |
383 } | 283 } |
384 } // namespace | |
385 | 284 |
386 uint32_t GetNumImportedFunctions(Handle<JSObject> wasm_object) { | |
387 return static_cast<uint32_t>( | |
388 Smi::cast(wasm_object->GetInternalField(kWasmNumImportedFunctions)) | |
389 ->value()); | |
390 } | |
391 | |
392 WasmModule::WasmModule(byte* module_start) | |
393 : module_start(module_start), | |
394 module_end(nullptr), | |
395 min_mem_pages(0), | |
396 max_mem_pages(0), | |
397 mem_export(false), | |
398 start_function_index(-1), | |
399 origin(kWasmOrigin), | |
400 globals_size(0), | |
401 num_imported_functions(0), | |
402 num_declared_functions(0), | |
403 num_exported_functions(0), | |
404 pending_tasks(new base::Semaphore(0)) {} | |
405 | |
406 static MaybeHandle<JSFunction> ReportFFIError( | |
407 ErrorThrower* thrower, const char* error, uint32_t index, | |
408 Handle<String> module_name, MaybeHandle<String> function_name) { | |
409 Handle<String> function_name_handle; | |
410 if (function_name.ToHandle(&function_name_handle)) { | |
411 thrower->Error("Import #%d module=\"%.*s\" function=\"%.*s\" error: %s", | |
412 index, module_name->length(), module_name->ToCString().get(), | |
413 function_name_handle->length(), | |
414 function_name_handle->ToCString().get(), error); | |
415 } else { | |
416 thrower->Error("Import #%d module=\"%.*s\" error: %s", index, | |
417 module_name->length(), module_name->ToCString().get(), | |
418 error); | |
419 } | |
420 thrower->Error("Import "); | |
421 return MaybeHandle<JSFunction>(); | |
422 } | |
423 | |
424 static MaybeHandle<JSReceiver> LookupFunction( | |
425 ErrorThrower* thrower, Factory* factory, Handle<JSReceiver> ffi, | |
426 uint32_t index, Handle<String> module_name, | |
427 MaybeHandle<String> function_name) { | |
428 if (ffi.is_null()) { | |
429 return ReportFFIError(thrower, "FFI is not an object", index, module_name, | |
430 function_name); | |
431 } | |
432 | |
433 // Look up the module first. | |
434 MaybeHandle<Object> result = Object::GetProperty(ffi, module_name); | |
435 if (result.is_null()) { | |
436 return ReportFFIError(thrower, "module not found", index, module_name, | |
437 function_name); | |
438 } | |
439 | |
440 Handle<Object> module = result.ToHandleChecked(); | |
441 | |
442 if (!module->IsJSReceiver()) { | |
443 return ReportFFIError(thrower, "module is not an object or function", index, | |
444 module_name, function_name); | |
445 } | |
446 | |
447 Handle<Object> function; | |
448 if (!function_name.is_null()) { | |
449 // Look up the function in the module. | |
450 MaybeHandle<Object> result = | |
451 Object::GetProperty(module, function_name.ToHandleChecked()); | |
452 if (result.is_null()) { | |
453 return ReportFFIError(thrower, "function not found", index, module_name, | |
454 function_name); | |
455 } | |
456 function = result.ToHandleChecked(); | |
457 } else { | |
458 // No function specified. Use the "default export". | |
459 function = module; | |
460 } | |
461 | |
462 if (!function->IsCallable()) { | |
463 return ReportFFIError(thrower, "not a callable", index, module_name, | |
464 function_name); | |
465 } | |
466 | |
467 return Handle<JSReceiver>::cast(function); | |
468 } | |
469 | |
470 namespace { | |
471 // Fetches the compilation unit of a wasm function and executes its parallel | 285 // Fetches the compilation unit of a wasm function and executes its parallel |
472 // phase. | 286 // phase. |
473 bool FetchAndExecuteCompilationUnit( | 287 bool FetchAndExecuteCompilationUnit( |
474 Isolate* isolate, | 288 Isolate* isolate, |
475 std::vector<compiler::WasmCompilationUnit*>* compilation_units, | 289 std::vector<compiler::WasmCompilationUnit*>* compilation_units, |
476 std::queue<compiler::WasmCompilationUnit*>* executed_units, | 290 std::queue<compiler::WasmCompilationUnit*>* executed_units, |
477 base::Mutex* result_mutex, base::AtomicNumber<size_t>* next_unit) { | 291 base::Mutex* result_mutex, base::AtomicNumber<size_t>* next_unit) { |
478 DisallowHeapAllocation no_allocation; | 292 DisallowHeapAllocation no_allocation; |
479 DisallowHandleAllocation no_handles; | 293 DisallowHandleAllocation no_handles; |
480 DisallowHandleDereference no_deref; | 294 DisallowHandleDereference no_deref; |
(...skipping 100 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
581 encoded_import->set(kFunctionName, *function_name_string); | 395 encoded_import->set(kFunctionName, *function_name_string); |
582 } | 396 } |
583 encoded_import->set(kOutputCount, | 397 encoded_import->set(kOutputCount, |
584 Smi::FromInt(static_cast<int>(fsig->return_count()))); | 398 Smi::FromInt(static_cast<int>(fsig->return_count()))); |
585 encoded_import->set(kSignature, *sig); | 399 encoded_import->set(kSignature, *sig); |
586 ret->set(static_cast<int>(i), *encoded_import); | 400 ret->set(static_cast<int>(i), *encoded_import); |
587 } | 401 } |
588 return ret; | 402 return ret; |
589 } | 403 } |
590 | 404 |
| 405 static MaybeHandle<JSFunction> ReportFFIError( |
| 406 ErrorThrower* thrower, const char* error, uint32_t index, |
| 407 Handle<String> module_name, MaybeHandle<String> function_name) { |
| 408 Handle<String> function_name_handle; |
| 409 if (function_name.ToHandle(&function_name_handle)) { |
| 410 thrower->Error("Import #%d module=\"%.*s\" function=\"%.*s\" error: %s", |
| 411 index, module_name->length(), module_name->ToCString().get(), |
| 412 function_name_handle->length(), |
| 413 function_name_handle->ToCString().get(), error); |
| 414 } else { |
| 415 thrower->Error("Import #%d module=\"%.*s\" error: %s", index, |
| 416 module_name->length(), module_name->ToCString().get(), |
| 417 error); |
| 418 } |
| 419 thrower->Error("Import "); |
| 420 return MaybeHandle<JSFunction>(); |
| 421 } |
| 422 |
| 423 static MaybeHandle<JSReceiver> LookupFunction( |
| 424 ErrorThrower* thrower, Factory* factory, Handle<JSReceiver> ffi, |
| 425 uint32_t index, Handle<String> module_name, |
| 426 MaybeHandle<String> function_name) { |
| 427 if (ffi.is_null()) { |
| 428 return ReportFFIError(thrower, "FFI is not an object", index, module_name, |
| 429 function_name); |
| 430 } |
| 431 |
| 432 // Look up the module first. |
| 433 MaybeHandle<Object> result = Object::GetProperty(ffi, module_name); |
| 434 if (result.is_null()) { |
| 435 return ReportFFIError(thrower, "module not found", index, module_name, |
| 436 function_name); |
| 437 } |
| 438 |
| 439 Handle<Object> module = result.ToHandleChecked(); |
| 440 |
| 441 if (!module->IsJSReceiver()) { |
| 442 return ReportFFIError(thrower, "module is not an object or function", index, |
| 443 module_name, function_name); |
| 444 } |
| 445 |
| 446 Handle<Object> function; |
| 447 if (!function_name.is_null()) { |
| 448 // Look up the function in the module. |
| 449 MaybeHandle<Object> result = |
| 450 Object::GetProperty(module, function_name.ToHandleChecked()); |
| 451 if (result.is_null()) { |
| 452 return ReportFFIError(thrower, "function not found", index, module_name, |
| 453 function_name); |
| 454 } |
| 455 function = result.ToHandleChecked(); |
| 456 } else { |
| 457 // No function specified. Use the "default export". |
| 458 function = module; |
| 459 } |
| 460 |
| 461 if (!function->IsCallable()) { |
| 462 return ReportFFIError(thrower, "not a callable", index, module_name, |
| 463 function_name); |
| 464 } |
| 465 |
| 466 return Handle<JSReceiver>::cast(function); |
| 467 } |
| 468 |
591 Handle<Code> CompileImportWrapper(Isolate* isolate, | 469 Handle<Code> CompileImportWrapper(Isolate* isolate, |
592 const Handle<JSReceiver> ffi, int index, | 470 const Handle<JSReceiver> ffi, int index, |
593 Handle<FixedArray> import_data, | 471 Handle<FixedArray> import_data, |
594 ErrorThrower* thrower) { | 472 ErrorThrower* thrower) { |
595 Handle<FixedArray> data = | 473 Handle<FixedArray> data = |
596 import_data->GetValueChecked<FixedArray>(isolate, index); | 474 import_data->GetValueChecked<FixedArray>(isolate, index); |
597 Handle<String> module_name = | 475 Handle<String> module_name = |
598 data->GetValueChecked<String>(isolate, kModuleName); | 476 data->GetValueChecked<String>(isolate, kModuleName); |
599 MaybeHandle<String> function_name = | 477 MaybeHandle<String> function_name = |
600 data->GetValue<String>(isolate, kFunctionName); | 478 data->GetValue<String>(isolate, kFunctionName); |
(...skipping 348 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
949 } else { | 827 } else { |
950 WasmCompiledModule::cast(next->value()) | 828 WasmCompiledModule::cast(next->value()) |
951 ->set_ptr_to_weak_prev_instance(prev); | 829 ->set_ptr_to_weak_prev_instance(prev); |
952 } | 830 } |
953 } | 831 } |
954 } | 832 } |
955 } | 833 } |
956 GlobalHandles::Destroy(reinterpret_cast<Object**>(p)); | 834 GlobalHandles::Destroy(reinterpret_cast<Object**>(p)); |
957 } | 835 } |
958 | 836 |
| 837 Handle<FixedArray> SetupIndirectFunctionTable( |
| 838 Isolate* isolate, Handle<FixedArray> wasm_functions, |
| 839 Handle<FixedArray> indirect_table_template, |
| 840 Handle<FixedArray> tables_to_replace) { |
| 841 Factory* factory = isolate->factory(); |
| 842 Handle<FixedArray> cloned_indirect_tables = |
| 843 factory->CopyFixedArray(indirect_table_template); |
| 844 for (int i = 0; i < cloned_indirect_tables->length(); ++i) { |
| 845 Handle<FixedArray> orig_metadata = |
| 846 cloned_indirect_tables->GetValueChecked<FixedArray>(isolate, i); |
| 847 Handle<FixedArray> cloned_metadata = factory->CopyFixedArray(orig_metadata); |
| 848 cloned_indirect_tables->set(i, *cloned_metadata); |
| 849 |
| 850 Handle<FixedArray> orig_table = |
| 851 cloned_metadata->GetValueChecked<FixedArray>(isolate, kTable); |
| 852 Handle<FixedArray> cloned_table = factory->CopyFixedArray(orig_table); |
| 853 cloned_metadata->set(kTable, *cloned_table); |
| 854 // Patch the cloned code to refer to the cloned kTable. |
| 855 Handle<FixedArray> table_to_replace = |
| 856 tables_to_replace->GetValueChecked<FixedArray>(isolate, i) |
| 857 ->GetValueChecked<FixedArray>(isolate, kTable); |
| 858 for (int fct_index = 0; fct_index < wasm_functions->length(); ++fct_index) { |
| 859 Handle<Code> wasm_function = |
| 860 wasm_functions->GetValueChecked<Code>(isolate, fct_index); |
| 861 PatchFunctionTable(wasm_function, table_to_replace, cloned_table); |
| 862 } |
| 863 } |
| 864 return cloned_indirect_tables; |
| 865 } |
| 866 |
959 } // namespace | 867 } // namespace |
960 | 868 |
| 869 const char* SectionName(WasmSectionCode code) { |
| 870 switch (code) { |
| 871 case kUnknownSectionCode: |
| 872 return "Unknown"; |
| 873 case kTypeSectionCode: |
| 874 return "Type"; |
| 875 case kImportSectionCode: |
| 876 return "Import"; |
| 877 case kFunctionSectionCode: |
| 878 return "Function"; |
| 879 case kTableSectionCode: |
| 880 return "Table"; |
| 881 case kMemorySectionCode: |
| 882 return "Memory"; |
| 883 case kGlobalSectionCode: |
| 884 return "Global"; |
| 885 case kExportSectionCode: |
| 886 return "Export"; |
| 887 case kStartSectionCode: |
| 888 return "Start"; |
| 889 case kCodeSectionCode: |
| 890 return "Code"; |
| 891 case kElementSectionCode: |
| 892 return "Element"; |
| 893 case kDataSectionCode: |
| 894 return "Data"; |
| 895 case kNameSectionCode: |
| 896 return "Name"; |
| 897 default: |
| 898 return "<unknown>"; |
| 899 } |
| 900 } |
| 901 |
| 902 std::ostream& operator<<(std::ostream& os, const WasmModule& module) { |
| 903 os << "WASM module with "; |
| 904 os << (module.min_mem_pages * module.kPageSize) << " min mem"; |
| 905 os << (module.max_mem_pages * module.kPageSize) << " max mem"; |
| 906 os << module.functions.size() << " functions"; |
| 907 os << module.functions.size() << " globals"; |
| 908 os << module.functions.size() << " data segments"; |
| 909 return os; |
| 910 } |
| 911 |
| 912 std::ostream& operator<<(std::ostream& os, const WasmFunction& function) { |
| 913 os << "WASM function with signature " << *function.sig; |
| 914 |
| 915 os << " code bytes: " |
| 916 << (function.code_end_offset - function.code_start_offset); |
| 917 return os; |
| 918 } |
| 919 |
| 920 std::ostream& operator<<(std::ostream& os, const WasmFunctionName& pair) { |
| 921 os << "#" << pair.function_->func_index << ":"; |
| 922 if (pair.function_->name_offset > 0) { |
| 923 if (pair.module_) { |
| 924 WasmName name = pair.module_->GetName(pair.function_->name_offset, |
| 925 pair.function_->name_length); |
| 926 os.write(name.start(), name.length()); |
| 927 } else { |
| 928 os << "+" << pair.function_->func_index; |
| 929 } |
| 930 } else { |
| 931 os << "?"; |
| 932 } |
| 933 return os; |
| 934 } |
| 935 |
| 936 Handle<JSFunction> WrapExportCodeAsJSFunction( |
| 937 Isolate* isolate, Handle<Code> export_code, Handle<String> name, int arity, |
| 938 MaybeHandle<ByteArray> maybe_signature, Handle<JSObject> module_instance) { |
| 939 Handle<SharedFunctionInfo> shared = |
| 940 isolate->factory()->NewSharedFunctionInfo(name, export_code, false); |
| 941 shared->set_length(arity); |
| 942 shared->set_internal_formal_parameter_count(arity); |
| 943 Handle<JSFunction> function = isolate->factory()->NewFunction( |
| 944 isolate->wasm_function_map(), name, export_code); |
| 945 function->set_shared(*shared); |
| 946 |
| 947 function->SetInternalField(kInternalModuleInstance, *module_instance); |
| 948 // add another Internal Field as the function arity |
| 949 function->SetInternalField(kInternalArity, Smi::FromInt(arity)); |
| 950 // add another Internal Field as the signature of the foreign function |
| 951 Handle<ByteArray> signature; |
| 952 if (maybe_signature.ToHandle(&signature)) { |
| 953 function->SetInternalField(kInternalSignature, *signature); |
| 954 } |
| 955 return function; |
| 956 } |
| 957 |
| 958 Object* GetOwningWasmInstance(Code* code) { |
| 959 DCHECK(code->kind() == Code::WASM_FUNCTION); |
| 960 DisallowHeapAllocation no_gc; |
| 961 FixedArray* deopt_data = code->deoptimization_data(); |
| 962 DCHECK_NOT_NULL(deopt_data); |
| 963 DCHECK(deopt_data->length() == 2); |
| 964 Object* weak_link = deopt_data->get(0); |
| 965 if (!weak_link->IsWeakCell()) return nullptr; |
| 966 WeakCell* cell = WeakCell::cast(weak_link); |
| 967 return cell->value(); |
| 968 } |
| 969 |
| 970 uint32_t GetNumImportedFunctions(Handle<JSObject> wasm_object) { |
| 971 return static_cast<uint32_t>( |
| 972 Smi::cast(wasm_object->GetInternalField(kWasmNumImportedFunctions)) |
| 973 ->value()); |
| 974 } |
| 975 |
| 976 WasmModule::WasmModule(byte* module_start) |
| 977 : module_start(module_start), |
| 978 module_end(nullptr), |
| 979 min_mem_pages(0), |
| 980 max_mem_pages(0), |
| 981 mem_export(false), |
| 982 start_function_index(-1), |
| 983 origin(kWasmOrigin), |
| 984 globals_size(0), |
| 985 num_imported_functions(0), |
| 986 num_declared_functions(0), |
| 987 num_exported_functions(0), |
| 988 pending_tasks(new base::Semaphore(0)) {} |
| 989 |
961 MaybeHandle<WasmCompiledModule> WasmModule::CompileFunctions( | 990 MaybeHandle<WasmCompiledModule> WasmModule::CompileFunctions( |
962 Isolate* isolate, ErrorThrower* thrower) const { | 991 Isolate* isolate, ErrorThrower* thrower) const { |
963 Factory* factory = isolate->factory(); | 992 Factory* factory = isolate->factory(); |
964 | 993 |
965 MaybeHandle<WasmCompiledModule> nothing; | 994 MaybeHandle<WasmCompiledModule> nothing; |
966 | 995 |
967 WasmModuleInstance temp_instance(this); | 996 WasmModuleInstance temp_instance(this); |
968 temp_instance.context = isolate->native_context(); | 997 temp_instance.context = isolate->native_context(); |
969 temp_instance.mem_size = GetMinModuleMemSize(this); | 998 temp_instance.mem_size = GetMinModuleMemSize(this); |
970 temp_instance.mem_start = nullptr; | 999 temp_instance.mem_start = nullptr; |
(...skipping 155 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1126 } | 1155 } |
1127 | 1156 |
1128 Handle<ByteArray> function_name_table = | 1157 Handle<ByteArray> function_name_table = |
1129 BuildFunctionNamesTable(isolate, module_env.module); | 1158 BuildFunctionNamesTable(isolate, module_env.module); |
1130 ret->set_function_names(function_name_table); | 1159 ret->set_function_names(function_name_table); |
1131 if (data_segments.size() > 0) SaveDataSegmentInfo(factory, this, ret); | 1160 if (data_segments.size() > 0) SaveDataSegmentInfo(factory, this, ret); |
1132 DCHECK_EQ(ret->default_mem_size(), temp_instance.mem_size); | 1161 DCHECK_EQ(ret->default_mem_size(), temp_instance.mem_size); |
1133 return ret; | 1162 return ret; |
1134 } | 1163 } |
1135 | 1164 |
1136 void PatchJSWrapper(Isolate* isolate, Handle<Code> wrapper, | |
1137 Handle<Code> new_target) { | |
1138 AllowDeferredHandleDereference embedding_raw_address; | |
1139 bool seen = false; | |
1140 for (RelocIterator it(*wrapper, 1 << RelocInfo::CODE_TARGET); !it.done(); | |
1141 it.next()) { | |
1142 Code* target = Code::GetCodeFromTargetAddress(it.rinfo()->target_address()); | |
1143 if (target->kind() == Code::WASM_FUNCTION) { | |
1144 DCHECK(!seen); | |
1145 seen = true; | |
1146 it.rinfo()->set_target_address(new_target->instruction_start(), | |
1147 UPDATE_WRITE_BARRIER, SKIP_ICACHE_FLUSH); | |
1148 } | |
1149 } | |
1150 CHECK(seen); | |
1151 Assembler::FlushICache(isolate, wrapper->instruction_start(), | |
1152 wrapper->instruction_size()); | |
1153 } | |
1154 | |
1155 Handle<FixedArray> SetupIndirectFunctionTable( | |
1156 Isolate* isolate, Handle<FixedArray> wasm_functions, | |
1157 Handle<FixedArray> indirect_table_template, | |
1158 Handle<FixedArray> tables_to_replace) { | |
1159 Factory* factory = isolate->factory(); | |
1160 Handle<FixedArray> cloned_indirect_tables = | |
1161 factory->CopyFixedArray(indirect_table_template); | |
1162 for (int i = 0; i < cloned_indirect_tables->length(); ++i) { | |
1163 Handle<FixedArray> orig_metadata = | |
1164 cloned_indirect_tables->GetValueChecked<FixedArray>(isolate, i); | |
1165 Handle<FixedArray> cloned_metadata = factory->CopyFixedArray(orig_metadata); | |
1166 cloned_indirect_tables->set(i, *cloned_metadata); | |
1167 | |
1168 Handle<FixedArray> orig_table = | |
1169 cloned_metadata->GetValueChecked<FixedArray>(isolate, kTable); | |
1170 Handle<FixedArray> cloned_table = factory->CopyFixedArray(orig_table); | |
1171 cloned_metadata->set(kTable, *cloned_table); | |
1172 // Patch the cloned code to refer to the cloned kTable. | |
1173 Handle<FixedArray> table_to_replace = | |
1174 tables_to_replace->GetValueChecked<FixedArray>(isolate, i) | |
1175 ->GetValueChecked<FixedArray>(isolate, kTable); | |
1176 for (int fct_index = 0; fct_index < wasm_functions->length(); ++fct_index) { | |
1177 Handle<Code> wasm_function = | |
1178 wasm_functions->GetValueChecked<Code>(isolate, fct_index); | |
1179 PatchFunctionTable(wasm_function, table_to_replace, cloned_table); | |
1180 } | |
1181 } | |
1182 return cloned_indirect_tables; | |
1183 } | |
1184 | |
1185 // Instantiates a WASM module, creating a WebAssembly.Instance from a | 1165 // Instantiates a WASM module, creating a WebAssembly.Instance from a |
1186 // WebAssembly.Module. | 1166 // WebAssembly.Module. |
1187 MaybeHandle<JSObject> WasmModule::Instantiate(Isolate* isolate, | 1167 MaybeHandle<JSObject> WasmModule::Instantiate(Isolate* isolate, |
1188 ErrorThrower* thrower, | 1168 ErrorThrower* thrower, |
1189 Handle<JSObject> module_object, | 1169 Handle<JSObject> module_object, |
1190 Handle<JSReceiver> ffi, | 1170 Handle<JSReceiver> ffi, |
1191 Handle<JSArrayBuffer> memory) { | 1171 Handle<JSArrayBuffer> memory) { |
1192 MaybeHandle<JSObject> nothing; | 1172 MaybeHandle<JSObject> nothing; |
1193 HistogramTimerScope wasm_instantiate_module_time_scope( | 1173 HistogramTimerScope wasm_instantiate_module_time_scope( |
1194 isolate->counters()->wasm_instantiate_module_time()); | 1174 isolate->counters()->wasm_instantiate_module_time()); |
(...skipping 354 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1549 // the globals size. The CHECK guards this assumption. | 1529 // the globals size. The CHECK guards this assumption. |
1550 CHECK_GE(static_cast<int>(globals_size), 0); | 1530 CHECK_GE(static_cast<int>(globals_size), 0); |
1551 ret->set(kID_min_memory_pages, | 1531 ret->set(kID_min_memory_pages, |
1552 Smi::FromInt(static_cast<int>(min_memory_pages))); | 1532 Smi::FromInt(static_cast<int>(min_memory_pages))); |
1553 ret->set(kID_globals_size, Smi::FromInt(static_cast<int>(globals_size))); | 1533 ret->set(kID_globals_size, Smi::FromInt(static_cast<int>(globals_size))); |
1554 ret->set(kID_export_memory, Smi::FromInt(static_cast<int>(export_memory))); | 1534 ret->set(kID_export_memory, Smi::FromInt(static_cast<int>(export_memory))); |
1555 ret->set(kID_origin, Smi::FromInt(static_cast<int>(origin))); | 1535 ret->set(kID_origin, Smi::FromInt(static_cast<int>(origin))); |
1556 return handle(WasmCompiledModule::cast(*ret)); | 1536 return handle(WasmCompiledModule::cast(*ret)); |
1557 } | 1537 } |
1558 | 1538 |
1559 compiler::CallDescriptor* ModuleEnv::GetCallDescriptor(Zone* zone, | |
1560 uint32_t index) { | |
1561 DCHECK(IsValidFunction(index)); | |
1562 // Always make a direct call to whatever is in the table at that location. | |
1563 // A wrapper will be generated for FFI calls. | |
1564 const WasmFunction* function = &module->functions[index]; | |
1565 return GetWasmCallDescriptor(zone, function->sig); | |
1566 } | |
1567 | |
1568 Handle<Object> GetWasmFunctionNameOrNull(Isolate* isolate, Handle<Object> wasm, | 1539 Handle<Object> GetWasmFunctionNameOrNull(Isolate* isolate, Handle<Object> wasm, |
1569 uint32_t func_index) { | 1540 uint32_t func_index) { |
1570 if (!wasm->IsUndefined(isolate)) { | 1541 if (!wasm->IsUndefined(isolate)) { |
1571 Handle<ByteArray> func_names_arr_obj( | 1542 Handle<ByteArray> func_names_arr_obj( |
1572 ByteArray::cast(Handle<JSObject>::cast(wasm)->GetInternalField( | 1543 ByteArray::cast(Handle<JSObject>::cast(wasm)->GetInternalField( |
1573 kWasmFunctionNamesArray)), | 1544 kWasmFunctionNamesArray)), |
1574 isolate); | 1545 isolate); |
1575 // TODO(clemens): Extract this from the module bytes; skip whole function | 1546 // TODO(clemens): Extract this from the module bytes; skip whole function |
1576 // name table. | 1547 // name table. |
1577 Handle<Object> name; | 1548 Handle<Object> name; |
(...skipping 254 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1832 WasmCompiledModule* compiled_module = | 1803 WasmCompiledModule* compiled_module = |
1833 WasmCompiledModule::cast(instance->GetInternalField(kWasmCompiledModule)); | 1804 WasmCompiledModule::cast(instance->GetInternalField(kWasmCompiledModule)); |
1834 CHECK(compiled_module->has_weak_module_object()); | 1805 CHECK(compiled_module->has_weak_module_object()); |
1835 CHECK(compiled_module->ptr_to_weak_module_object()->cleared()); | 1806 CHECK(compiled_module->ptr_to_weak_module_object()->cleared()); |
1836 } | 1807 } |
1837 | 1808 |
1838 } // namespace testing | 1809 } // namespace testing |
1839 } // namespace wasm | 1810 } // namespace wasm |
1840 } // namespace internal | 1811 } // namespace internal |
1841 } // namespace v8 | 1812 } // namespace v8 |
OLD | NEW |