| 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 154 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 165 kWasmMemArrayBuffer, | 165 kWasmMemArrayBuffer, |
| 166 kWasmGlobalsArrayBuffer, | 166 kWasmGlobalsArrayBuffer, |
| 167 // TODO(clemensh): Remove function name array, extract names from module | 167 // TODO(clemensh): Remove function name array, extract names from module |
| 168 // bytes. | 168 // bytes. |
| 169 kWasmFunctionNamesArray, | 169 kWasmFunctionNamesArray, |
| 170 kWasmModuleBytesString, | 170 kWasmModuleBytesString, |
| 171 kWasmDebugInfo, | 171 kWasmDebugInfo, |
| 172 kWasmModuleInternalFieldCount | 172 kWasmModuleInternalFieldCount |
| 173 }; | 173 }; |
| 174 | 174 |
| 175 // TODO(mtrofin): Unnecessary once we stop using JS Heap for wasm code. | 175 // // TODO(mtrofin): Unnecessary once we stop using JS Heap for wasm code. |
| 176 // For now, each field is expected to have the type commented by its side. | 176 // // For now, each field is expected to have the type commented by its side. |
| 177 // The elements typed as "maybe" are optional. The others are mandatory. Since | 177 // // The elements typed as "maybe" are optional. The others are mandatory. |
| 178 // the compiled module is either obtained from the current v8 instance, or from | 178 // Since |
| 179 // a snapshot produced by a compatible (==identical) v8 instance, we simply | 179 // // the compiled module is either obtained from the current v8 instance, or |
| 180 // fail at instantiation time, in the face of invalid data. | 180 // from |
| 181 enum CompiledWasmObjectFields { | 181 // // a snapshot produced by a compatible (==identical) v8 instance, we simply |
| 182 kFunctions, // FixedArray of Code | 182 // // fail at instantiation time, in the face of invalid data. |
| 183 kImportData, // maybe FixedArray of FixedArray respecting the | |
| 184 // WasmImportMetadata structure. | |
| 185 kImportMap, // FixedArray. The i-th element is the Code object used for | |
| 186 // import i | |
| 187 kExports, // maybe FixedArray of FixedArray of WasmExportMetadata | |
| 188 // structure | |
| 189 kStartupFunction, // maybe FixedArray of WasmExportMetadata structure | |
| 190 kTableOfIndirectFunctionTables, // maybe FixedArray of FixedArray of | |
| 191 // WasmIndirectFunctionTableMetadata | |
| 192 kModuleBytes, // maybe String | |
| 193 kFunctionNameTable, // maybe ByteArray | |
| 194 kMinRequiredMemory, // Smi. an uint32_t | |
| 195 // The following 2 are either together present or absent: | |
| 196 kDataSegmentsInfo, // maybe FixedArray of FixedArray respecting the | |
| 197 // WasmSegmentInfo structure | |
| 198 kDataSegments, // maybe ByteArray. | |
| 199 | |
| 200 kGlobalsSize, // Smi. an uint32_t | |
| 201 kMemSize, // Smi.an uint32_t | |
| 202 kMemStart, // MaybeHandle<ArrayBuffer> | |
| 203 kExportMem, // Smi. bool | |
| 204 kOrigin, // Smi. ModuleOrigin | |
| 205 kNextInstance, // WeakCell. See compiled code cloning. | |
| 206 kPrevInstance, // WeakCell. See compiled code cloning. | |
| 207 kOwningInstance, // WeakCell, pointing to the owning instance. | |
| 208 kModuleObject, // WeakCell, pointing to the module object. | |
| 209 kCompiledWasmObjectTableSize // Sentinel value. | |
| 210 }; | |
| 211 | |
| 212 enum WasmImportMetadata { | 183 enum WasmImportMetadata { |
| 213 kModuleName, // String | 184 kModuleName, // String |
| 214 kFunctionName, // maybe String | 185 kFunctionName, // maybe String |
| 215 kOutputCount, // Smi. an uint32_t | 186 kOutputCount, // Smi. an uint32_t |
| 216 kSignature, // ByteArray. A copy of the data in FunctionSig | 187 kSignature, // ByteArray. A copy of the data in FunctionSig |
| 217 kWasmImportDataTableSize // Sentinel value. | 188 kWasmImportDataTableSize // Sentinel value. |
| 218 }; | 189 }; |
| 219 | 190 |
| 220 enum WasmExportMetadata { | 191 enum WasmExportMetadata { |
| 221 kExportCode, // Code | 192 kExportCode, // Code |
| (...skipping 13 matching lines...) Expand all Loading... |
| 235 enum WasmIndirectFunctionTableMetadata { | 206 enum WasmIndirectFunctionTableMetadata { |
| 236 kSize, // Smi. an uint32_t | 207 kSize, // Smi. an uint32_t |
| 237 kTable, // FixedArray of indirect function table | 208 kTable, // FixedArray of indirect function table |
| 238 kWasmIndirectFunctionTableMetadataSize // Sentinel value. | 209 kWasmIndirectFunctionTableMetadataSize // Sentinel value. |
| 239 }; | 210 }; |
| 240 | 211 |
| 241 uint32_t GetMinModuleMemSize(const WasmModule* module) { | 212 uint32_t GetMinModuleMemSize(const WasmModule* module) { |
| 242 return WasmModule::kPageSize * module->min_mem_pages; | 213 return WasmModule::kPageSize * module->min_mem_pages; |
| 243 } | 214 } |
| 244 | 215 |
| 245 void LoadDataSegments(Handle<FixedArray> compiled_module, Address mem_addr, | 216 void LoadDataSegments(Handle<WasmCompiledModule> compiled_module, |
| 246 size_t mem_size) { | 217 Address mem_addr, size_t mem_size) { |
| 247 Isolate* isolate = compiled_module->GetIsolate(); | 218 Isolate* isolate = compiled_module->GetIsolate(); |
| 248 MaybeHandle<ByteArray> maybe_data = | |
| 249 compiled_module->GetValue<ByteArray>(isolate, kDataSegments); | |
| 250 MaybeHandle<FixedArray> maybe_segments = | |
| 251 compiled_module->GetValue<FixedArray>(isolate, kDataSegmentsInfo); | |
| 252 | 219 |
| 253 // We either have both or neither. | 220 // We either have both or neither. |
| 254 CHECK(maybe_data.is_null() == maybe_segments.is_null()); | 221 CHECK(compiled_module->has_data_segments() == |
| 222 compiled_module->has_data_segments_info()); |
| 255 // If we have neither, we're done. | 223 // If we have neither, we're done. |
| 256 if (maybe_data.is_null()) return; | 224 if (!compiled_module->has_data_segments()) return; |
| 257 | 225 |
| 258 Handle<ByteArray> data = maybe_data.ToHandleChecked(); | 226 Handle<ByteArray> data = compiled_module->data_segments(); |
| 259 Handle<FixedArray> segments = maybe_segments.ToHandleChecked(); | 227 Handle<FixedArray> segments = compiled_module->data_segments_info(); |
| 260 | 228 |
| 261 uint32_t last_extraction_pos = 0; | 229 uint32_t last_extraction_pos = 0; |
| 262 for (int i = 0; i < segments->length(); ++i) { | 230 for (int i = 0; i < segments->length(); ++i) { |
| 263 Handle<ByteArray> segment = | 231 Handle<ByteArray> segment = |
| 264 Handle<ByteArray>(ByteArray::cast(segments->get(i))); | 232 Handle<ByteArray>(ByteArray::cast(segments->get(i))); |
| 265 uint32_t dest_addr = static_cast<uint32_t>(segment->get_int(kDestAddr)); | 233 uint32_t dest_addr = static_cast<uint32_t>(segment->get_int(kDestAddr)); |
| 266 uint32_t source_size = static_cast<uint32_t>(segment->get_int(kSourceSize)); | 234 uint32_t source_size = static_cast<uint32_t>(segment->get_int(kSourceSize)); |
| 267 CHECK_LT(dest_addr, mem_size); | 235 CHECK_LT(dest_addr, mem_size); |
| 268 CHECK_LE(source_size, mem_size); | 236 CHECK_LE(source_size, mem_size); |
| 269 CHECK_LE(dest_addr, mem_size - source_size); | 237 CHECK_LE(dest_addr, mem_size - source_size); |
| 270 byte* addr = mem_addr + dest_addr; | 238 byte* addr = mem_addr + dest_addr; |
| 271 data->copy_out(last_extraction_pos, addr, source_size); | 239 data->copy_out(last_extraction_pos, addr, source_size); |
| 272 last_extraction_pos += source_size; | 240 last_extraction_pos += source_size; |
| 273 } | 241 } |
| 274 } | 242 } |
| 275 | 243 |
| 276 void SaveDataSegmentInfo(Factory* factory, const WasmModule* module, | 244 void SaveDataSegmentInfo(Factory* factory, const WasmModule* module, |
| 277 Handle<FixedArray> compiled_module) { | 245 Handle<WasmCompiledModule> compiled_module) { |
| 278 Handle<FixedArray> segments = factory->NewFixedArray( | 246 Handle<FixedArray> segments = factory->NewFixedArray( |
| 279 static_cast<int>(module->data_segments.size()), TENURED); | 247 static_cast<int>(module->data_segments.size()), TENURED); |
| 280 uint32_t data_size = 0; | 248 uint32_t data_size = 0; |
| 281 for (const WasmDataSegment& segment : module->data_segments) { | 249 for (const WasmDataSegment& segment : module->data_segments) { |
| 282 if (!segment.init) continue; | 250 if (!segment.init) continue; |
| 283 if (segment.source_size == 0) continue; | 251 if (segment.source_size == 0) continue; |
| 284 data_size += segment.source_size; | 252 data_size += segment.source_size; |
| 285 } | 253 } |
| 286 Handle<ByteArray> data = factory->NewByteArray(data_size, TENURED); | 254 Handle<ByteArray> data = factory->NewByteArray(data_size, TENURED); |
| 287 | 255 |
| 288 uint32_t last_insertion_pos = 0; | 256 uint32_t last_insertion_pos = 0; |
| 289 for (uint32_t i = 0; i < module->data_segments.size(); ++i) { | 257 for (uint32_t i = 0; i < module->data_segments.size(); ++i) { |
| 290 const WasmDataSegment& segment = module->data_segments[i]; | 258 const WasmDataSegment& segment = module->data_segments[i]; |
| 291 if (!segment.init) continue; | 259 if (!segment.init) continue; |
| 292 if (segment.source_size == 0) continue; | 260 if (segment.source_size == 0) continue; |
| 293 Handle<ByteArray> js_segment = | 261 Handle<ByteArray> js_segment = |
| 294 factory->NewByteArray(kWasmSegmentInfoSize * sizeof(uint32_t), TENURED); | 262 factory->NewByteArray(kWasmSegmentInfoSize * sizeof(uint32_t), TENURED); |
| 295 js_segment->set_int(kDestAddr, segment.dest_addr); | 263 js_segment->set_int(kDestAddr, segment.dest_addr); |
| 296 js_segment->set_int(kSourceSize, segment.source_size); | 264 js_segment->set_int(kSourceSize, segment.source_size); |
| 297 segments->set(i, *js_segment); | 265 segments->set(i, *js_segment); |
| 298 data->copy_in(last_insertion_pos, | 266 data->copy_in(last_insertion_pos, |
| 299 module->module_start + segment.source_offset, | 267 module->module_start + segment.source_offset, |
| 300 segment.source_size); | 268 segment.source_size); |
| 301 last_insertion_pos += segment.source_size; | 269 last_insertion_pos += segment.source_size; |
| 302 } | 270 } |
| 303 compiled_module->set(kDataSegmentsInfo, *segments); | 271 compiled_module->set_data_segments_info(segments); |
| 304 compiled_module->set(kDataSegments, *data); | 272 compiled_module->set_data_segments(data); |
| 305 } | 273 } |
| 306 | 274 |
| 307 void PatchFunctionTable(Handle<Code> code, | 275 void PatchFunctionTable(Handle<Code> code, |
| 308 Handle<FixedArray> old_indirect_table, | 276 Handle<FixedArray> old_indirect_table, |
| 309 Handle<FixedArray> new_indirect_table) { | 277 Handle<FixedArray> new_indirect_table) { |
| 310 for (RelocIterator it(*code, 1 << RelocInfo::EMBEDDED_OBJECT); !it.done(); | 278 for (RelocIterator it(*code, 1 << RelocInfo::EMBEDDED_OBJECT); !it.done(); |
| 311 it.next()) { | 279 it.next()) { |
| 312 if (it.rinfo()->target_object() == *old_indirect_table) { | 280 if (it.rinfo()->target_object() == *old_indirect_table) { |
| 313 it.rinfo()->set_target_object(*new_indirect_table); | 281 it.rinfo()->set_target_object(*new_indirect_table); |
| 314 } | 282 } |
| (...skipping 588 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 903 if (code.is_null()) { | 871 if (code.is_null()) { |
| 904 thrower->Error("Compilation of #%d:%.*s failed.", i, str.length(), | 872 thrower->Error("Compilation of #%d:%.*s failed.", i, str.length(), |
| 905 str.start()); | 873 str.start()); |
| 906 break; | 874 break; |
| 907 } | 875 } |
| 908 // Install the code into the linker table. | 876 // Install the code into the linker table. |
| 909 functions[i] = code; | 877 functions[i] = code; |
| 910 } | 878 } |
| 911 } | 879 } |
| 912 | 880 |
| 913 void SetDebugSupport(Factory* factory, Handle<FixedArray> compiled_module, | 881 void SetDebugSupport(Factory* factory, |
| 882 Handle<WasmCompiledModule> compiled_module, |
| 914 Handle<JSObject> js_object) { | 883 Handle<JSObject> js_object) { |
| 915 Isolate* isolate = compiled_module->GetIsolate(); | 884 Isolate* isolate = compiled_module->GetIsolate(); |
| 916 MaybeHandle<String> module_bytes_string = | 885 if (compiled_module->has_module_bytes()) { |
| 917 compiled_module->GetValue<String>(isolate, kModuleBytes); | |
| 918 if (!module_bytes_string.is_null()) { | |
| 919 js_object->SetInternalField(kWasmModuleBytesString, | 886 js_object->SetInternalField(kWasmModuleBytesString, |
| 920 *module_bytes_string.ToHandleChecked()); | 887 *compiled_module->module_bytes()); |
| 921 } | 888 } |
| 922 | 889 |
| 923 MaybeHandle<ByteArray> function_name_table = | 890 if (compiled_module->has_function_names()) { |
| 924 compiled_module->GetValue<ByteArray>(isolate, kFunctionNameTable); | |
| 925 if (!function_name_table.is_null()) { | |
| 926 js_object->SetInternalField(kWasmFunctionNamesArray, | 891 js_object->SetInternalField(kWasmFunctionNamesArray, |
| 927 *function_name_table.ToHandleChecked()); | 892 *compiled_module->function_names()); |
| 928 } | 893 } |
| 929 } | 894 } |
| 930 | 895 |
| 931 bool SetupGlobals(Isolate* isolate, MaybeHandle<JSObject> template_owner, | 896 bool SetupGlobals(Isolate* isolate, MaybeHandle<JSObject> template_owner, |
| 932 Handle<FixedArray> compiled_module, Handle<JSObject> instance, | 897 Handle<WasmCompiledModule> compiled_module, |
| 933 ErrorThrower* thrower) { | 898 Handle<JSObject> instance, ErrorThrower* thrower) { |
| 934 uint32_t globals_size = static_cast<uint32_t>( | 899 uint32_t globals_size = compiled_module->globals_size(); |
| 935 Smi::cast(compiled_module->get(kGlobalsSize))->value()); | |
| 936 if (globals_size > 0) { | 900 if (globals_size > 0) { |
| 937 Handle<JSArrayBuffer> globals_buffer = | 901 Handle<JSArrayBuffer> globals_buffer = |
| 938 NewArrayBuffer(isolate, globals_size); | 902 NewArrayBuffer(isolate, globals_size); |
| 939 if (globals_buffer.is_null()) { | 903 if (globals_buffer.is_null()) { |
| 940 thrower->Error("Out of memory: wasm globals"); | 904 thrower->Error("Out of memory: wasm globals"); |
| 941 return false; | 905 return false; |
| 942 } | 906 } |
| 943 Address old_address = | 907 Address old_address = |
| 944 template_owner.is_null() | 908 template_owner.is_null() |
| 945 ? nullptr | 909 ? nullptr |
| 946 : GetGlobalStartAddressFromCodeTemplate( | 910 : GetGlobalStartAddressFromCodeTemplate( |
| 947 *isolate->factory()->undefined_value(), | 911 *isolate->factory()->undefined_value(), |
| 948 JSObject::cast(*template_owner.ToHandleChecked())); | 912 JSObject::cast(*template_owner.ToHandleChecked())); |
| 949 RelocateGlobals(instance, old_address, | 913 RelocateGlobals(instance, old_address, |
| 950 static_cast<Address>(globals_buffer->backing_store())); | 914 static_cast<Address>(globals_buffer->backing_store())); |
| 951 instance->SetInternalField(kWasmGlobalsArrayBuffer, *globals_buffer); | 915 instance->SetInternalField(kWasmGlobalsArrayBuffer, *globals_buffer); |
| 952 } | 916 } |
| 953 return true; | 917 return true; |
| 954 } | 918 } |
| 955 | 919 |
| 956 bool SetupInstanceHeap(Isolate* isolate, Handle<FixedArray> compiled_module, | 920 bool SetupInstanceHeap(Isolate* isolate, |
| 921 Handle<WasmCompiledModule> compiled_module, |
| 957 Handle<JSObject> instance, Handle<JSArrayBuffer> memory, | 922 Handle<JSObject> instance, Handle<JSArrayBuffer> memory, |
| 958 ErrorThrower* thrower) { | 923 ErrorThrower* thrower) { |
| 959 uint32_t min_mem_pages = static_cast<uint32_t>( | 924 uint32_t min_mem_pages = compiled_module->min_required_memory(); |
| 960 Smi::cast(compiled_module->get(kMinRequiredMemory))->value()); | |
| 961 isolate->counters()->wasm_min_mem_pages_count()->AddSample(min_mem_pages); | 925 isolate->counters()->wasm_min_mem_pages_count()->AddSample(min_mem_pages); |
| 962 // TODO(wasm): re-enable counter for max_mem_pages when we use that field. | 926 // TODO(wasm): re-enable counter for max_mem_pages when we use that field. |
| 963 | 927 |
| 964 if (memory.is_null() && min_mem_pages > 0) { | 928 if (memory.is_null() && min_mem_pages > 0) { |
| 965 memory = AllocateMemory(thrower, isolate, min_mem_pages); | 929 memory = AllocateMemory(thrower, isolate, min_mem_pages); |
| 966 if (memory.is_null()) { | 930 if (memory.is_null()) { |
| 967 return false; | 931 return false; |
| 968 } | 932 } |
| 969 } | 933 } |
| 970 | 934 |
| 971 if (!memory.is_null()) { | 935 if (!memory.is_null()) { |
| 972 instance->SetInternalField(kWasmMemArrayBuffer, *memory); | 936 instance->SetInternalField(kWasmMemArrayBuffer, *memory); |
| 973 Address mem_start = static_cast<Address>(memory->backing_store()); | 937 Address mem_start = static_cast<Address>(memory->backing_store()); |
| 974 uint32_t mem_size = static_cast<uint32_t>(memory->byte_length()->Number()); | 938 uint32_t mem_size = static_cast<uint32_t>(memory->byte_length()->Number()); |
| 975 uint32_t old_mem_size = static_cast<uint32_t>( | 939 uint32_t old_mem_size = compiled_module->mem_size(); |
| 976 compiled_module->GetValueChecked<HeapNumber>(isolate, kMemSize) | |
| 977 ->value()); | |
| 978 MaybeHandle<JSArrayBuffer> old_mem = | |
| 979 compiled_module->GetValue<JSArrayBuffer>(isolate, kMemStart); | |
| 980 Address old_mem_start = | 940 Address old_mem_start = |
| 981 old_mem.is_null() | 941 compiled_module->has_mem_start() |
| 982 ? nullptr | 942 ? static_cast<Address>( |
| 983 : static_cast<Address>(old_mem.ToHandleChecked()->backing_store()); | 943 compiled_module->mem_start()->backing_store()) |
| 944 : nullptr; |
| 984 RelocateInstanceCode(instance, old_mem_start, mem_start, old_mem_size, | 945 RelocateInstanceCode(instance, old_mem_start, mem_start, old_mem_size, |
| 985 mem_size); | 946 mem_size); |
| 986 LoadDataSegments(compiled_module, mem_start, mem_size); | 947 LoadDataSegments(compiled_module, mem_start, mem_size); |
| 987 compiled_module->GetValueChecked<HeapNumber>(isolate, kMemSize) | 948 compiled_module->set_mem_size(mem_size); |
| 988 ->set_value(static_cast<double>(mem_size)); | 949 compiled_module->set_mem_start(memory); |
| 989 compiled_module->set(kMemStart, *memory); | |
| 990 } | 950 } |
| 991 return true; | 951 return true; |
| 992 } | 952 } |
| 993 | 953 |
| 994 void FixupFunctionsAndImports(Handle<FixedArray> old_functions, | 954 void FixupFunctionsAndImports(Handle<FixedArray> old_functions, |
| 995 Handle<FixedArray> new_functions, | 955 Handle<FixedArray> new_functions, |
| 996 MaybeHandle<FixedArray> maybe_old_imports, | 956 MaybeHandle<FixedArray> maybe_old_imports, |
| 997 MaybeHandle<FixedArray> maybe_new_imports) { | 957 MaybeHandle<FixedArray> maybe_new_imports) { |
| 998 DCHECK_EQ(new_functions->length(), old_functions->length()); | 958 DCHECK_EQ(new_functions->length(), old_functions->length()); |
| 999 | 959 |
| (...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1031 DCHECK(new_code->kind() == Code::WASM_FUNCTION); | 991 DCHECK(new_code->kind() == Code::WASM_FUNCTION); |
| 1032 continue; | 992 continue; |
| 1033 } | 993 } |
| 1034 it.rinfo()->set_target_address(new_code->instruction_start(), | 994 it.rinfo()->set_target_address(new_code->instruction_start(), |
| 1035 UPDATE_WRITE_BARRIER, SKIP_ICACHE_FLUSH); | 995 UPDATE_WRITE_BARRIER, SKIP_ICACHE_FLUSH); |
| 1036 } | 996 } |
| 1037 } | 997 } |
| 1038 } | 998 } |
| 1039 } | 999 } |
| 1040 | 1000 |
| 1041 bool SetupImports(Isolate* isolate, Handle<FixedArray> compiled_module, | 1001 bool SetupImports(Isolate* isolate, Handle<WasmCompiledModule> compiled_module, |
| 1042 Handle<JSObject> instance, ErrorThrower* thrower, | 1002 Handle<JSObject> instance, ErrorThrower* thrower, |
| 1043 Handle<JSReceiver> ffi) { | 1003 Handle<JSReceiver> ffi) { |
| 1044 //------------------------------------------------------------------------- | 1004 //------------------------------------------------------------------------- |
| 1045 // Compile wrappers to imported functions. | 1005 // Compile wrappers to imported functions. |
| 1046 //------------------------------------------------------------------------- | 1006 //------------------------------------------------------------------------- |
| 1047 std::vector<Handle<Code>> import_code; | 1007 std::vector<Handle<Code>> import_code; |
| 1048 MaybeHandle<FixedArray> maybe_import_data = | 1008 if (compiled_module->has_import_data()) { |
| 1049 compiled_module->GetValue<FixedArray>(isolate, kImportData); | |
| 1050 Handle<FixedArray> import_data; | |
| 1051 if (maybe_import_data.ToHandle(&import_data)) { | |
| 1052 if (!CompileWrappersToImportedFunctions(isolate, ffi, import_code, | 1009 if (!CompileWrappersToImportedFunctions(isolate, ffi, import_code, |
| 1053 import_data, thrower)) { | 1010 compiled_module->import_data(), |
| 1011 thrower)) { |
| 1054 return false; | 1012 return false; |
| 1055 } | 1013 } |
| 1056 } | 1014 } |
| 1057 | 1015 |
| 1058 RecordStats(isolate, import_code); | 1016 RecordStats(isolate, import_code); |
| 1059 if (import_code.empty()) return true; | 1017 if (import_code.empty()) return true; |
| 1060 | 1018 |
| 1061 Handle<FixedArray> new_imports = | 1019 Handle<FixedArray> new_imports = |
| 1062 isolate->factory()->NewFixedArray(static_cast<int>(import_code.size())); | 1020 isolate->factory()->NewFixedArray(static_cast<int>(import_code.size())); |
| 1063 for (int i = 0; i < new_imports->length(); ++i) { | 1021 for (int i = 0; i < new_imports->length(); ++i) { |
| 1064 new_imports->set(i, *import_code[i]); | 1022 new_imports->set(i, *import_code[i]); |
| 1065 } | 1023 } |
| 1066 compiled_module->set(kImportMap, *new_imports); | 1024 compiled_module->set_import_map(new_imports); |
| 1067 return true; | 1025 return true; |
| 1068 } | 1026 } |
| 1069 | 1027 |
| 1070 bool SetupExportsObject(Handle<FixedArray> compiled_module, Isolate* isolate, | 1028 bool SetupExportsObject(Handle<WasmCompiledModule> compiled_module, |
| 1071 Handle<JSObject> instance, ErrorThrower* thrower) { | 1029 Isolate* isolate, Handle<JSObject> instance, |
| 1030 ErrorThrower* thrower) { |
| 1072 Factory* factory = isolate->factory(); | 1031 Factory* factory = isolate->factory(); |
| 1073 bool mem_export = | 1032 bool mem_export = compiled_module->export_memory(); |
| 1074 static_cast<bool>(Smi::cast(compiled_module->get(kExportMem))->value()); | 1033 ModuleOrigin origin = compiled_module->origin(); |
| 1075 ModuleOrigin origin = static_cast<ModuleOrigin>( | |
| 1076 Smi::cast(compiled_module->get(kOrigin))->value()); | |
| 1077 | 1034 |
| 1078 MaybeHandle<FixedArray> maybe_exports = | 1035 if (compiled_module->has_exports() || mem_export) { |
| 1079 compiled_module->GetValue<FixedArray>(isolate, kExports); | |
| 1080 if (!maybe_exports.is_null() || mem_export) { | |
| 1081 PropertyDescriptor desc; | 1036 PropertyDescriptor desc; |
| 1082 desc.set_writable(false); | 1037 desc.set_writable(false); |
| 1083 | 1038 |
| 1084 Handle<JSObject> exports_object = instance; | 1039 Handle<JSObject> exports_object = instance; |
| 1085 if (origin == kWasmOrigin) { | 1040 if (origin == kWasmOrigin) { |
| 1086 // Create the "exports" object. | 1041 // Create the "exports" object. |
| 1087 Handle<JSFunction> object_function = Handle<JSFunction>( | 1042 Handle<JSFunction> object_function = Handle<JSFunction>( |
| 1088 isolate->native_context()->object_function(), isolate); | 1043 isolate->native_context()->object_function(), isolate); |
| 1089 exports_object = factory->NewJSObject(object_function, TENURED); | 1044 exports_object = factory->NewJSObject(object_function, TENURED); |
| 1090 Handle<String> exports_name = factory->InternalizeUtf8String("exports"); | 1045 Handle<String> exports_name = factory->InternalizeUtf8String("exports"); |
| 1091 JSObject::AddProperty(instance, exports_name, exports_object, READ_ONLY); | 1046 JSObject::AddProperty(instance, exports_name, exports_object, READ_ONLY); |
| 1092 } | 1047 } |
| 1093 Handle<FixedArray> exports; | 1048 if (compiled_module->has_exports()) { |
| 1094 if (maybe_exports.ToHandle(&exports)) { | 1049 Handle<FixedArray> exports = compiled_module->exports(); |
| 1095 int exports_size = exports->length(); | 1050 int exports_size = exports->length(); |
| 1096 for (int i = 0; i < exports_size; ++i) { | 1051 for (int i = 0; i < exports_size; ++i) { |
| 1097 if (thrower->error()) return false; | 1052 if (thrower->error()) return false; |
| 1098 Handle<FixedArray> export_metadata = | 1053 Handle<FixedArray> export_metadata = |
| 1099 exports->GetValueChecked<FixedArray>(isolate, i); | 1054 exports->GetValueChecked<FixedArray>(isolate, i); |
| 1100 Handle<Code> export_code = | 1055 Handle<Code> export_code = |
| 1101 export_metadata->GetValueChecked<Code>(isolate, kExportCode); | 1056 export_metadata->GetValueChecked<Code>(isolate, kExportCode); |
| 1102 RecordStats(isolate, *export_code); | 1057 RecordStats(isolate, *export_code); |
| 1103 Handle<String> name = | 1058 Handle<String> name = |
| 1104 export_metadata->GetValueChecked<String>(isolate, kExportName); | 1059 export_metadata->GetValueChecked<String>(isolate, kExportName); |
| (...skipping 16 matching lines...) Expand all Loading... |
| 1121 // Export the memory as a named property. | 1076 // Export the memory as a named property. |
| 1122 Handle<String> name = factory->InternalizeUtf8String("memory"); | 1077 Handle<String> name = factory->InternalizeUtf8String("memory"); |
| 1123 Handle<JSArrayBuffer> memory = Handle<JSArrayBuffer>( | 1078 Handle<JSArrayBuffer> memory = Handle<JSArrayBuffer>( |
| 1124 JSArrayBuffer::cast(instance->GetInternalField(kWasmMemArrayBuffer))); | 1079 JSArrayBuffer::cast(instance->GetInternalField(kWasmMemArrayBuffer))); |
| 1125 JSObject::AddProperty(exports_object, name, memory, READ_ONLY); | 1080 JSObject::AddProperty(exports_object, name, memory, READ_ONLY); |
| 1126 } | 1081 } |
| 1127 } | 1082 } |
| 1128 return true; | 1083 return true; |
| 1129 } | 1084 } |
| 1130 | 1085 |
| 1131 #define GET_COMPILED_MODULE_WEAK_RELATION_OR_NULL(Field) \ | |
| 1132 WeakCell* Get##Field(const FixedArray* compiled_module) { \ | |
| 1133 Object* obj = compiled_module->get(k##Field); \ | |
| 1134 DCHECK_NOT_NULL(obj); \ | |
| 1135 if (obj->IsWeakCell()) { \ | |
| 1136 return WeakCell::cast(obj); \ | |
| 1137 } else { \ | |
| 1138 return nullptr; \ | |
| 1139 } \ | |
| 1140 } | |
| 1141 | |
| 1142 GET_COMPILED_MODULE_WEAK_RELATION_OR_NULL(NextInstance) | |
| 1143 GET_COMPILED_MODULE_WEAK_RELATION_OR_NULL(PrevInstance) | |
| 1144 GET_COMPILED_MODULE_WEAK_RELATION_OR_NULL(OwningInstance) | |
| 1145 GET_COMPILED_MODULE_WEAK_RELATION_OR_NULL(ModuleObject) | |
| 1146 | |
| 1147 static void ResetCompiledModule(Isolate* isolate, JSObject* owner, | 1086 static void ResetCompiledModule(Isolate* isolate, JSObject* owner, |
| 1148 FixedArray* compiled_module) { | 1087 WasmCompiledModule* compiled_module) { |
| 1149 Object* undefined = *isolate->factory()->undefined_value(); | 1088 Object* undefined = *isolate->factory()->undefined_value(); |
| 1150 Object* mem_size_obj = compiled_module->get(kMemSize); | 1089 uint32_t old_mem_size = compiled_module->mem_size(); |
| 1151 DCHECK(mem_size_obj->IsMutableHeapNumber()); | 1090 Object* mem_start = compiled_module->ptr_to_mem_start(); |
| 1152 uint32_t old_mem_size = | |
| 1153 static_cast<uint32_t>(HeapNumber::cast(mem_size_obj)->value()); | |
| 1154 Object* mem_start = compiled_module->get(kMemStart); | |
| 1155 Address old_mem_address = nullptr; | 1091 Address old_mem_address = nullptr; |
| 1156 Address globals_start = | 1092 Address globals_start = |
| 1157 GetGlobalStartAddressFromCodeTemplate(undefined, owner); | 1093 GetGlobalStartAddressFromCodeTemplate(undefined, owner); |
| 1158 | 1094 |
| 1159 if (old_mem_size > 0) { | 1095 if (old_mem_size > 0) { |
| 1160 CHECK_NE(mem_start, undefined); | 1096 CHECK_NE(mem_start, undefined); |
| 1161 old_mem_address = | 1097 old_mem_address = |
| 1162 static_cast<Address>(JSArrayBuffer::cast(mem_start)->backing_store()); | 1098 static_cast<Address>(JSArrayBuffer::cast(mem_start)->backing_store()); |
| 1163 } | 1099 } |
| 1164 int mode_mask = RelocInfo::ModeMask(RelocInfo::WASM_MEMORY_REFERENCE) | | 1100 int mode_mask = RelocInfo::ModeMask(RelocInfo::WASM_MEMORY_REFERENCE) | |
| 1165 RelocInfo::ModeMask(RelocInfo::WASM_MEMORY_SIZE_REFERENCE) | | 1101 RelocInfo::ModeMask(RelocInfo::WASM_MEMORY_SIZE_REFERENCE) | |
| 1166 RelocInfo::ModeMask(RelocInfo::WASM_GLOBAL_REFERENCE); | 1102 RelocInfo::ModeMask(RelocInfo::WASM_GLOBAL_REFERENCE); |
| 1167 | 1103 |
| 1168 Object* fct_obj = compiled_module->get(kFunctions); | 1104 Object* fct_obj = compiled_module->ptr_to_functions(); |
| 1169 if (fct_obj != nullptr && fct_obj != undefined && | 1105 if (fct_obj != nullptr && fct_obj != undefined && |
| 1170 (old_mem_size > 0 || globals_start != nullptr)) { | 1106 (old_mem_size > 0 || globals_start != nullptr)) { |
| 1171 FixedArray* functions = FixedArray::cast(fct_obj); | 1107 FixedArray* functions = FixedArray::cast(fct_obj); |
| 1172 for (int i = 0; i < functions->length(); ++i) { | 1108 for (int i = 0; i < functions->length(); ++i) { |
| 1173 Code* code = Code::cast(functions->get(i)); | 1109 Code* code = Code::cast(functions->get(i)); |
| 1174 bool changed = false; | 1110 bool changed = false; |
| 1175 for (RelocIterator it(code, mode_mask); !it.done(); it.next()) { | 1111 for (RelocIterator it(code, mode_mask); !it.done(); it.next()) { |
| 1176 RelocInfo::Mode mode = it.rinfo()->rmode(); | 1112 RelocInfo::Mode mode = it.rinfo()->rmode(); |
| 1177 if (RelocInfo::IsWasmMemoryReference(mode) || | 1113 if (RelocInfo::IsWasmMemoryReference(mode) || |
| 1178 RelocInfo::IsWasmMemorySizeReference(mode)) { | 1114 RelocInfo::IsWasmMemorySizeReference(mode)) { |
| 1179 it.rinfo()->update_wasm_memory_reference(old_mem_address, nullptr, | 1115 it.rinfo()->update_wasm_memory_reference(old_mem_address, nullptr, |
| 1180 old_mem_size, old_mem_size); | 1116 old_mem_size, old_mem_size); |
| 1181 changed = true; | 1117 changed = true; |
| 1182 } else { | 1118 } else { |
| 1183 CHECK(RelocInfo::IsWasmGlobalReference(mode)); | 1119 CHECK(RelocInfo::IsWasmGlobalReference(mode)); |
| 1184 it.rinfo()->update_wasm_global_reference(globals_start, nullptr); | 1120 it.rinfo()->update_wasm_global_reference(globals_start, nullptr); |
| 1185 changed = true; | 1121 changed = true; |
| 1186 } | 1122 } |
| 1187 } | 1123 } |
| 1188 if (changed) { | 1124 if (changed) { |
| 1189 Assembler::FlushICache(isolate, code->instruction_start(), | 1125 Assembler::FlushICache(isolate, code->instruction_start(), |
| 1190 code->instruction_size()); | 1126 code->instruction_size()); |
| 1191 } | 1127 } |
| 1192 } | 1128 } |
| 1193 } | 1129 } |
| 1194 compiled_module->set(kOwningInstance, undefined); | 1130 compiled_module->reset_weak_owning_instance(isolate); |
| 1195 compiled_module->set(kMemStart, undefined); | 1131 compiled_module->reset_mem_start(isolate); |
| 1196 } | 1132 } |
| 1197 | 1133 |
| 1198 static void InstanceFinalizer(const v8::WeakCallbackInfo<void>& data) { | 1134 static void InstanceFinalizer(const v8::WeakCallbackInfo<void>& data) { |
| 1199 JSObject** p = reinterpret_cast<JSObject**>(data.GetParameter()); | 1135 JSObject** p = reinterpret_cast<JSObject**>(data.GetParameter()); |
| 1200 JSObject* owner = *p; | 1136 JSObject* owner = *p; |
| 1201 FixedArray* compiled_module = | 1137 WasmCompiledModule* compiled_module = |
| 1202 FixedArray::cast(owner->GetInternalField(kWasmCompiledModule)); | 1138 WasmCompiledModule::cast(owner->GetInternalField(kWasmCompiledModule)); |
| 1203 Isolate* isolate = reinterpret_cast<Isolate*>(data.GetIsolate()); | 1139 Isolate* isolate = reinterpret_cast<Isolate*>(data.GetIsolate()); |
| 1204 Object* undefined = *isolate->factory()->undefined_value(); | 1140 Object* undefined = *isolate->factory()->undefined_value(); |
| 1205 WeakCell* weak_module_obj = GetModuleObject(compiled_module); | 1141 DCHECK(compiled_module->has_weak_module_object()); |
| 1206 DCHECK_NOT_NULL(weak_module_obj); | 1142 WeakCell* weak_module_obj = compiled_module->ptr_to_weak_module_object(); |
| 1207 // weak_module_obj may have been cleared, meaning the module object | 1143 // weak_module_obj may have been cleared, meaning the module object |
| 1208 // was GC-ed. In that case, there won't be any new instances created, | 1144 // was GC-ed. In that case, there won't be any new instances created, |
| 1209 // and we don't need to maintain the links between instances. | 1145 // and we don't need to maintain the links between instances. |
| 1210 if (!weak_module_obj->cleared()) { | 1146 if (!weak_module_obj->cleared()) { |
| 1211 JSObject* module_obj = JSObject::cast(weak_module_obj->value()); | 1147 JSObject* module_obj = JSObject::cast(weak_module_obj->value()); |
| 1212 FixedArray* current_template = | 1148 WasmCompiledModule* current_template = |
| 1213 FixedArray::cast(module_obj->GetInternalField(0)); | 1149 WasmCompiledModule::cast(module_obj->GetInternalField(0)); |
| 1214 DCHECK_NULL(GetPrevInstance(current_template)); | 1150 DCHECK(!current_template->has_weak_prev_instance()); |
| 1215 WeakCell* next = GetNextInstance(compiled_module); | 1151 WeakCell* next = compiled_module->ptr_to_weak_next_instance(); |
| 1216 WeakCell* prev = GetPrevInstance(compiled_module); | 1152 WeakCell* prev = compiled_module->ptr_to_weak_prev_instance(); |
| 1217 | 1153 |
| 1218 if (current_template == compiled_module) { | 1154 if (current_template == compiled_module) { |
| 1219 if (next == nullptr) { | 1155 if (next == nullptr) { |
| 1220 ResetCompiledModule(isolate, owner, compiled_module); | 1156 ResetCompiledModule(isolate, owner, compiled_module); |
| 1221 } else { | 1157 } else { |
| 1222 DCHECK(next->value()->IsFixedArray()); | 1158 DCHECK(next->value()->IsFixedArray()); |
| 1223 module_obj->SetInternalField(0, next->value()); | 1159 module_obj->SetInternalField(0, next->value()); |
| 1224 DCHECK_NULL(prev); | 1160 DCHECK_NULL(prev); |
| 1225 FixedArray::cast(next->value())->set(kPrevInstance, undefined); | 1161 WasmCompiledModule::cast(next->value()) |
| 1162 ->reset_weak_prev_instance(isolate); |
| 1226 } | 1163 } |
| 1227 } else { | 1164 } else { |
| 1228 DCHECK(!(prev == nullptr && next == nullptr)); | 1165 DCHECK(!(prev == nullptr && next == nullptr)); |
| 1229 // the only reason prev or next would be cleared is if the | 1166 // the only reason prev or next would be cleared is if the |
| 1230 // respective objects got collected, but if that happened, | 1167 // respective objects got collected, but if that happened, |
| 1231 // we would have relinked the list. | 1168 // we would have relinked the list. |
| 1232 if (prev != nullptr) { | 1169 if (prev != nullptr) { |
| 1233 DCHECK(!prev->cleared()); | 1170 DCHECK(!prev->cleared()); |
| 1234 FixedArray::cast(prev->value()) | 1171 if (next == nullptr) { |
| 1235 ->set(kNextInstance, next == nullptr ? undefined : next); | 1172 WasmCompiledModule::cast(prev->value()) |
| 1173 ->reset_weak_next_instance(isolate); |
| 1174 } else { |
| 1175 WasmCompiledModule::cast(prev->value()) |
| 1176 ->set_ptr_to_weak_next_instance(next); |
| 1177 } |
| 1236 } | 1178 } |
| 1237 if (next != nullptr) { | 1179 if (next != nullptr) { |
| 1238 DCHECK(!next->cleared()); | 1180 DCHECK(!next->cleared()); |
| 1239 FixedArray::cast(next->value()) | 1181 if (prev == nullptr) { |
| 1240 ->set(kPrevInstance, prev == nullptr ? undefined : prev); | 1182 WasmCompiledModule::cast(next->value()) |
| 1183 ->reset_weak_prev_instance(isolate); |
| 1184 } else { |
| 1185 WasmCompiledModule::cast(next->value()) |
| 1186 ->set_ptr_to_weak_prev_instance(prev); |
| 1187 } |
| 1241 } | 1188 } |
| 1242 } | 1189 } |
| 1243 } | 1190 } |
| 1244 GlobalHandles::Destroy(reinterpret_cast<Object**>(p)); | 1191 GlobalHandles::Destroy(reinterpret_cast<Object**>(p)); |
| 1245 } | 1192 } |
| 1246 | 1193 |
| 1247 } // namespace | 1194 } // namespace |
| 1248 | 1195 |
| 1249 MaybeHandle<FixedArray> WasmModule::CompileFunctions( | 1196 MaybeHandle<WasmCompiledModule> WasmModule::CompileFunctions( |
| 1250 Isolate* isolate, ErrorThrower* thrower) const { | 1197 Isolate* isolate, ErrorThrower* thrower) const { |
| 1251 Factory* factory = isolate->factory(); | 1198 Factory* factory = isolate->factory(); |
| 1252 | 1199 |
| 1253 MaybeHandle<FixedArray> nothing; | 1200 MaybeHandle<WasmCompiledModule> nothing; |
| 1254 | 1201 |
| 1255 WasmModuleInstance temp_instance_for_compilation(this); | 1202 WasmModuleInstance temp_instance_for_compilation(this); |
| 1256 temp_instance_for_compilation.context = isolate->native_context(); | 1203 temp_instance_for_compilation.context = isolate->native_context(); |
| 1257 temp_instance_for_compilation.mem_size = GetMinModuleMemSize(this); | 1204 temp_instance_for_compilation.mem_size = GetMinModuleMemSize(this); |
| 1258 temp_instance_for_compilation.mem_start = nullptr; | 1205 temp_instance_for_compilation.mem_start = nullptr; |
| 1259 temp_instance_for_compilation.globals_start = nullptr; | 1206 temp_instance_for_compilation.globals_start = nullptr; |
| 1260 | 1207 |
| 1261 MaybeHandle<FixedArray> indirect_table = | 1208 MaybeHandle<FixedArray> indirect_table = |
| 1262 function_tables.size() | 1209 function_tables.size() |
| 1263 ? factory->NewFixedArray(static_cast<int>(function_tables.size()), | 1210 ? factory->NewFixedArray(static_cast<int>(function_tables.size()), |
| (...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1321 | 1268 |
| 1322 LinkModuleFunctions(isolate, compiled_functions); | 1269 LinkModuleFunctions(isolate, compiled_functions); |
| 1323 | 1270 |
| 1324 // TODO(mtrofin): do we need to flush the cache here? | 1271 // TODO(mtrofin): do we need to flush the cache here? |
| 1325 FlushAssemblyCache(isolate, compiled_functions); | 1272 FlushAssemblyCache(isolate, compiled_functions); |
| 1326 | 1273 |
| 1327 // Create the compiled module object, and populate with compiled functions | 1274 // Create the compiled module object, and populate with compiled functions |
| 1328 // and information needed at instantiation time. This object needs to be | 1275 // and information needed at instantiation time. This object needs to be |
| 1329 // serializable. Instantiation may occur off a deserialized version of this | 1276 // serializable. Instantiation may occur off a deserialized version of this |
| 1330 // object. | 1277 // object. |
| 1331 Handle<FixedArray> ret = | 1278 Handle<WasmCompiledModule> ret = WasmCompiledModule::New(isolate); |
| 1332 factory->NewFixedArray(kCompiledWasmObjectTableSize, TENURED); | 1279 |
| 1333 ret->set(kFunctions, *compiled_functions); | 1280 ret->set_functions(compiled_functions); |
| 1334 if (!indirect_table.is_null()) { | 1281 if (!indirect_table.is_null()) { |
| 1335 ret->set(kTableOfIndirectFunctionTables, *indirect_table.ToHandleChecked()); | 1282 ret->set_indirect_function_tables(indirect_table.ToHandleChecked()); |
| 1336 } | 1283 } |
| 1337 if (!maybe_imports.is_null()) { | 1284 if (!maybe_imports.is_null()) { |
| 1338 ret->set(kImportMap, *maybe_imports.ToHandleChecked()); | 1285 ret->set_import_map(maybe_imports.ToHandleChecked()); |
| 1339 } | 1286 } |
| 1340 Handle<FixedArray> import_data = GetImportsMetadata(factory, this); | 1287 Handle<FixedArray> import_data = GetImportsMetadata(factory, this); |
| 1341 ret->set(kImportData, *import_data); | 1288 ret->set_import_data(import_data); |
| 1342 | 1289 |
| 1343 // Compile export functions. | 1290 // Compile export functions. |
| 1344 int export_size = static_cast<int>(export_table.size()); | 1291 int export_size = static_cast<int>(export_table.size()); |
| 1345 Handle<Code> startup_fct; | 1292 Handle<Code> startup_fct; |
| 1346 if (export_size > 0) { | 1293 if (export_size > 0) { |
| 1347 Handle<FixedArray> exports = factory->NewFixedArray(export_size, TENURED); | 1294 Handle<FixedArray> exports = factory->NewFixedArray(export_size, TENURED); |
| 1348 for (int i = 0; i < export_size; ++i) { | 1295 for (int i = 0; i < export_size; ++i) { |
| 1349 Handle<FixedArray> export_metadata = | 1296 Handle<FixedArray> export_metadata = |
| 1350 factory->NewFixedArray(kWasmExportMetadataTableSize, TENURED); | 1297 factory->NewFixedArray(kWasmExportMetadataTableSize, TENURED); |
| 1351 const WasmExport& exp = export_table[i]; | 1298 const WasmExport& exp = export_table[i]; |
| (...skipping 18 matching lines...) Expand all Loading... |
| 1370 export_metadata->set( | 1317 export_metadata->set( |
| 1371 kExportArity, Smi::FromInt(static_cast<int>( | 1318 kExportArity, Smi::FromInt(static_cast<int>( |
| 1372 functions[exp.func_index].sig->parameter_count()))); | 1319 functions[exp.func_index].sig->parameter_count()))); |
| 1373 export_metadata->set(kExportedFunctionIndex, | 1320 export_metadata->set(kExportedFunctionIndex, |
| 1374 Smi::FromInt(static_cast<int>(exp.func_index))); | 1321 Smi::FromInt(static_cast<int>(exp.func_index))); |
| 1375 exports->set(i, *export_metadata); | 1322 exports->set(i, *export_metadata); |
| 1376 if (exp.func_index == start_function_index) { | 1323 if (exp.func_index == start_function_index) { |
| 1377 startup_fct = export_code; | 1324 startup_fct = export_code; |
| 1378 } | 1325 } |
| 1379 } | 1326 } |
| 1380 ret->set(kExports, *exports); | 1327 ret->set_exports(exports); |
| 1381 } | 1328 } |
| 1382 | 1329 |
| 1383 // Compile startup function, if we haven't already. | 1330 // Compile startup function, if we haven't already. |
| 1384 if (start_function_index >= 0) { | 1331 if (start_function_index >= 0) { |
| 1385 uint32_t index = static_cast<uint32_t>(start_function_index); | 1332 uint32_t index = static_cast<uint32_t>(start_function_index); |
| 1386 HandleScope scope(isolate); | 1333 HandleScope scope(isolate); |
| 1387 if (startup_fct.is_null()) { | 1334 if (startup_fct.is_null()) { |
| 1388 Handle<Code> code = temp_instance_for_compilation.function_code[index]; | 1335 Handle<Code> code = temp_instance_for_compilation.function_code[index]; |
| 1389 DCHECK_EQ(0, functions[index].sig->parameter_count()); | 1336 DCHECK_EQ(0, functions[index].sig->parameter_count()); |
| 1390 startup_fct = | 1337 startup_fct = |
| 1391 compiler::CompileJSToWasmWrapper(isolate, &module_env, code, index); | 1338 compiler::CompileJSToWasmWrapper(isolate, &module_env, code, index); |
| 1392 } | 1339 } |
| 1393 Handle<FixedArray> metadata = | 1340 Handle<FixedArray> metadata = |
| 1394 factory->NewFixedArray(kWasmExportMetadataTableSize, TENURED); | 1341 factory->NewFixedArray(kWasmExportMetadataTableSize, TENURED); |
| 1395 metadata->set(kExportCode, *startup_fct); | 1342 metadata->set(kExportCode, *startup_fct); |
| 1396 metadata->set(kExportArity, Smi::FromInt(0)); | 1343 metadata->set(kExportArity, Smi::FromInt(0)); |
| 1397 metadata->set(kExportedFunctionIndex, Smi::FromInt(start_function_index)); | 1344 metadata->set(kExportedFunctionIndex, Smi::FromInt(start_function_index)); |
| 1398 ret->set(kStartupFunction, *metadata); | 1345 ret->set_startup_function(metadata); |
| 1399 } | 1346 } |
| 1400 | 1347 |
| 1401 // TODO(wasm): saving the module bytes for debugging is wasteful. We should | 1348 // TODO(wasm): saving the module bytes for debugging is wasteful. We should |
| 1402 // consider downloading this on-demand. | 1349 // consider downloading this on-demand. |
| 1403 { | 1350 { |
| 1404 size_t module_bytes_len = module_end - module_start; | 1351 size_t module_bytes_len = module_end - module_start; |
| 1405 DCHECK_LE(module_bytes_len, static_cast<size_t>(kMaxInt)); | 1352 DCHECK_LE(module_bytes_len, static_cast<size_t>(kMaxInt)); |
| 1406 Vector<const uint8_t> module_bytes_vec(module_start, | 1353 Vector<const uint8_t> module_bytes_vec(module_start, |
| 1407 static_cast<int>(module_bytes_len)); | 1354 static_cast<int>(module_bytes_len)); |
| 1408 Handle<String> module_bytes_string = | 1355 Handle<String> module_bytes_string = |
| 1409 factory->NewStringFromOneByte(module_bytes_vec, TENURED) | 1356 factory->NewStringFromOneByte(module_bytes_vec, TENURED) |
| 1410 .ToHandleChecked(); | 1357 .ToHandleChecked(); |
| 1411 ret->set(kModuleBytes, *module_bytes_string); | 1358 ret->set_module_bytes(module_bytes_string); |
| 1412 } | 1359 } |
| 1413 | 1360 |
| 1414 Handle<ByteArray> function_name_table = | 1361 Handle<ByteArray> function_name_table = |
| 1415 BuildFunctionNamesTable(isolate, module_env.module); | 1362 BuildFunctionNamesTable(isolate, module_env.module); |
| 1416 ret->set(kFunctionNameTable, *function_name_table); | 1363 ret->set_function_names(function_name_table); |
| 1417 ret->set(kMinRequiredMemory, Smi::FromInt(min_mem_pages)); | 1364 ret->set_min_required_memory(min_mem_pages); |
| 1418 if (data_segments.size() > 0) SaveDataSegmentInfo(factory, this, ret); | 1365 if (data_segments.size() > 0) SaveDataSegmentInfo(factory, this, ret); |
| 1419 ret->set(kGlobalsSize, Smi::FromInt(globals_size)); | 1366 ret->set_globals_size(globals_size); |
| 1420 ret->set(kExportMem, Smi::FromInt(mem_export)); | 1367 ret->set_export_memory(mem_export); |
| 1421 ret->set(kOrigin, Smi::FromInt(origin)); | 1368 ret->set_origin(origin); |
| 1422 Handle<HeapNumber> size_as_object = factory->NewHeapNumber( | 1369 ret->set_mem_size(temp_instance_for_compilation.mem_size); |
| 1423 static_cast<double>(temp_instance_for_compilation.mem_size), MUTABLE, | |
| 1424 TENURED); | |
| 1425 ret->set(kMemSize, *size_as_object); | |
| 1426 return ret; | 1370 return ret; |
| 1427 } | 1371 } |
| 1428 | 1372 |
| 1429 void PatchJSWrapper(Isolate* isolate, Handle<Code> wrapper, | 1373 void PatchJSWrapper(Isolate* isolate, Handle<Code> wrapper, |
| 1430 Handle<Code> new_target) { | 1374 Handle<Code> new_target) { |
| 1431 AllowDeferredHandleDereference embedding_raw_address; | 1375 AllowDeferredHandleDereference embedding_raw_address; |
| 1432 bool seen = false; | 1376 bool seen = false; |
| 1433 for (RelocIterator it(*wrapper, 1 << RelocInfo::CODE_TARGET); !it.done(); | 1377 for (RelocIterator it(*wrapper, 1 << RelocInfo::CODE_TARGET); !it.done(); |
| 1434 it.next()) { | 1378 it.next()) { |
| 1435 Code* target = Code::GetCodeFromTargetAddress(it.rinfo()->target_address()); | 1379 Code* target = Code::GetCodeFromTargetAddress(it.rinfo()->target_address()); |
| (...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1468 ->GetValueChecked<FixedArray>(isolate, kTable); | 1412 ->GetValueChecked<FixedArray>(isolate, kTable); |
| 1469 for (int fct_index = 0; fct_index < wasm_functions->length(); ++fct_index) { | 1413 for (int fct_index = 0; fct_index < wasm_functions->length(); ++fct_index) { |
| 1470 Handle<Code> wasm_function = | 1414 Handle<Code> wasm_function = |
| 1471 wasm_functions->GetValueChecked<Code>(isolate, fct_index); | 1415 wasm_functions->GetValueChecked<Code>(isolate, fct_index); |
| 1472 PatchFunctionTable(wasm_function, table_to_replace, cloned_table); | 1416 PatchFunctionTable(wasm_function, table_to_replace, cloned_table); |
| 1473 } | 1417 } |
| 1474 } | 1418 } |
| 1475 return cloned_indirect_tables; | 1419 return cloned_indirect_tables; |
| 1476 } | 1420 } |
| 1477 | 1421 |
| 1478 Handle<FixedArray> CloneModuleForInstance(Isolate* isolate, | 1422 Handle<WasmCompiledModule> CloneModuleForInstance( |
| 1479 Handle<JSObject> module_object, | 1423 Isolate* isolate, Handle<JSObject> module_object, bool* template_is_owned, |
| 1480 bool* template_is_owned, | 1424 Handle<WasmCompiledModule>* module_template) { |
| 1481 Handle<FixedArray>* module_template) { | |
| 1482 Factory* factory = isolate->factory(); | 1425 Factory* factory = isolate->factory(); |
| 1483 | 1426 |
| 1484 Handle<FixedArray> original; | 1427 Handle<WasmCompiledModule> original; |
| 1485 for (int i = 0; i < 2; ++i) { | 1428 for (int i = 0; i < 2; ++i) { |
| 1486 original = handle(FixedArray::cast(module_object->GetInternalField(0))); | 1429 original = |
| 1487 if (GetOwningInstance(*original) == nullptr) { | 1430 handle(WasmCompiledModule::cast(module_object->GetInternalField(0))); |
| 1431 if (!original->has_weak_owning_instance()) { |
| 1488 *template_is_owned = false; | 1432 *template_is_owned = false; |
| 1489 *module_template = original; | 1433 *module_template = original; |
| 1490 return original; | 1434 return original; |
| 1491 } | 1435 } |
| 1492 if (i < 1) { | 1436 if (i < 1) { |
| 1493 isolate->heap()->CollectAllGarbage(Heap::kNoGCFlags, | 1437 isolate->heap()->CollectAllGarbage(Heap::kNoGCFlags, |
| 1494 GarbageCollectionReason::kRuntime); | 1438 GarbageCollectionReason::kRuntime); |
| 1495 } | 1439 } |
| 1496 } | 1440 } |
| 1497 *template_is_owned = true; | 1441 *template_is_owned = true; |
| 1498 *module_template = original; | 1442 *module_template = original; |
| 1499 | 1443 |
| 1500 // We insert the latest clone in front. | 1444 // We insert the latest clone in front. |
| 1501 Handle<FixedArray> clone = factory->CopyFixedArray(original); | 1445 Handle<WasmCompiledModule> clone = |
| 1502 Handle<WeakCell> weak_link_to_wasm_obj = | 1446 Handle<WasmCompiledModule>::cast(factory->CopyFixedArray(original)); |
| 1503 original->GetValueChecked<WeakCell>(isolate, kModuleObject); | 1447 Handle<WeakCell> weak_link_to_wasm_obj = original->weak_module_object(); |
| 1504 | 1448 |
| 1505 clone->set(kModuleObject, *weak_link_to_wasm_obj); | 1449 clone->set_weak_module_object(weak_link_to_wasm_obj); |
| 1506 Handle<WeakCell> link_to_original = factory->NewWeakCell(original); | 1450 Handle<WeakCell> link_to_original = factory->NewWeakCell(original); |
| 1507 clone->set(kNextInstance, *link_to_original); | 1451 clone->set_weak_next_instance(link_to_original); |
| 1508 Handle<WeakCell> link_to_clone = factory->NewWeakCell(clone); | 1452 Handle<WeakCell> link_to_clone = factory->NewWeakCell(clone); |
| 1509 original->set(kPrevInstance, *link_to_clone); | 1453 original->set_weak_prev_instance(link_to_clone); |
| 1510 JSObject::cast(weak_link_to_wasm_obj->value())->SetInternalField(0, *clone); | 1454 JSObject::cast(weak_link_to_wasm_obj->value())->SetInternalField(0, *clone); |
| 1511 | 1455 |
| 1512 // Clone each wasm code object. | 1456 // Clone each wasm code object. |
| 1513 Handle<FixedArray> orig_wasm_functions = | 1457 Handle<FixedArray> orig_wasm_functions = original->functions(); |
| 1514 original->GetValueChecked<FixedArray>(isolate, kFunctions); | |
| 1515 Handle<FixedArray> clone_wasm_functions = | 1458 Handle<FixedArray> clone_wasm_functions = |
| 1516 factory->CopyFixedArray(orig_wasm_functions); | 1459 factory->CopyFixedArray(orig_wasm_functions); |
| 1517 clone->set(kFunctions, *clone_wasm_functions); | 1460 clone->set_functions(clone_wasm_functions); |
| 1518 for (int i = 0; i < clone_wasm_functions->length(); ++i) { | 1461 for (int i = 0; i < clone_wasm_functions->length(); ++i) { |
| 1519 Handle<Code> orig_code = | 1462 Handle<Code> orig_code = |
| 1520 clone_wasm_functions->GetValueChecked<Code>(isolate, i); | 1463 clone_wasm_functions->GetValueChecked<Code>(isolate, i); |
| 1521 Handle<Code> cloned_code = factory->CopyCode(orig_code); | 1464 Handle<Code> cloned_code = factory->CopyCode(orig_code); |
| 1522 clone_wasm_functions->set(i, *cloned_code); | 1465 clone_wasm_functions->set(i, *cloned_code); |
| 1523 } | 1466 } |
| 1524 | 1467 |
| 1525 MaybeHandle<FixedArray> maybe_orig_exports = | 1468 if (original->has_exports()) { |
| 1526 original->GetValue<FixedArray>(isolate, kExports); | 1469 Handle<FixedArray> orig_exports = original->exports(); |
| 1527 Handle<FixedArray> orig_exports; | |
| 1528 if (maybe_orig_exports.ToHandle(&orig_exports)) { | |
| 1529 Handle<FixedArray> cloned_exports = factory->CopyFixedArray(orig_exports); | 1470 Handle<FixedArray> cloned_exports = factory->CopyFixedArray(orig_exports); |
| 1530 clone->set(kExports, *cloned_exports); | 1471 clone->set_exports(cloned_exports); |
| 1531 for (int i = 0; i < orig_exports->length(); ++i) { | 1472 for (int i = 0; i < orig_exports->length(); ++i) { |
| 1532 Handle<FixedArray> export_metadata = | 1473 Handle<FixedArray> export_metadata = |
| 1533 orig_exports->GetValueChecked<FixedArray>(isolate, i); | 1474 orig_exports->GetValueChecked<FixedArray>(isolate, i); |
| 1534 Handle<FixedArray> clone_metadata = | 1475 Handle<FixedArray> clone_metadata = |
| 1535 factory->CopyFixedArray(export_metadata); | 1476 factory->CopyFixedArray(export_metadata); |
| 1536 cloned_exports->set(i, *clone_metadata); | 1477 cloned_exports->set(i, *clone_metadata); |
| 1537 Handle<Code> orig_code = | 1478 Handle<Code> orig_code = |
| 1538 export_metadata->GetValueChecked<Code>(isolate, kExportCode); | 1479 export_metadata->GetValueChecked<Code>(isolate, kExportCode); |
| 1539 Handle<Code> cloned_code = factory->CopyCode(orig_code); | 1480 Handle<Code> cloned_code = factory->CopyCode(orig_code); |
| 1540 clone_metadata->set(kExportCode, *cloned_code); | 1481 clone_metadata->set(kExportCode, *cloned_code); |
| 1541 // TODO(wasm): This is actually a uint32_t, but since FixedArray indexes | 1482 // TODO(wasm): This is actually a uint32_t, but since FixedArray indexes |
| 1542 // in int, we are taking the risk of invalid values. | 1483 // in int, we are taking the risk of invalid values. |
| 1543 int exported_fct_index = | 1484 int exported_fct_index = |
| 1544 Smi::cast(export_metadata->get(kExportedFunctionIndex))->value(); | 1485 Smi::cast(export_metadata->get(kExportedFunctionIndex))->value(); |
| 1545 CHECK_GE(exported_fct_index, 0); | 1486 CHECK_GE(exported_fct_index, 0); |
| 1546 CHECK_LT(exported_fct_index, clone_wasm_functions->length()); | 1487 CHECK_LT(exported_fct_index, clone_wasm_functions->length()); |
| 1547 Handle<Code> new_target = clone_wasm_functions->GetValueChecked<Code>( | 1488 Handle<Code> new_target = clone_wasm_functions->GetValueChecked<Code>( |
| 1548 isolate, exported_fct_index); | 1489 isolate, exported_fct_index); |
| 1549 PatchJSWrapper(isolate, cloned_code, new_target); | 1490 PatchJSWrapper(isolate, cloned_code, new_target); |
| 1550 } | 1491 } |
| 1551 } | 1492 } |
| 1552 | 1493 |
| 1553 MaybeHandle<FixedArray> maybe_startup = | 1494 if (original->has_startup_function()) { |
| 1554 original->GetValue<FixedArray>(isolate, kStartupFunction); | |
| 1555 if (!maybe_startup.is_null()) { | |
| 1556 Handle<FixedArray> startup_metadata = | 1495 Handle<FixedArray> startup_metadata = |
| 1557 factory->CopyFixedArray(maybe_startup.ToHandleChecked()); | 1496 factory->CopyFixedArray(original->startup_function()); |
| 1558 Handle<Code> startup_fct_clone = factory->CopyCode( | 1497 Handle<Code> startup_fct_clone = factory->CopyCode( |
| 1559 startup_metadata->GetValueChecked<Code>(isolate, kExportCode)); | 1498 startup_metadata->GetValueChecked<Code>(isolate, kExportCode)); |
| 1560 startup_metadata->set(kExportCode, *startup_fct_clone); | 1499 startup_metadata->set(kExportCode, *startup_fct_clone); |
| 1561 clone->set(kStartupFunction, *startup_metadata); | 1500 clone->set_startup_function(startup_metadata); |
| 1562 // TODO(wasm): see todo above about int vs size_t indexing in FixedArray. | 1501 // TODO(wasm): see todo above about int vs size_t indexing in FixedArray. |
| 1563 int startup_fct_index = | 1502 int startup_fct_index = |
| 1564 Smi::cast(startup_metadata->get(kExportedFunctionIndex))->value(); | 1503 Smi::cast(startup_metadata->get(kExportedFunctionIndex))->value(); |
| 1565 CHECK_GE(startup_fct_index, 0); | 1504 CHECK_GE(startup_fct_index, 0); |
| 1566 CHECK_LT(startup_fct_index, clone_wasm_functions->length()); | 1505 CHECK_LT(startup_fct_index, clone_wasm_functions->length()); |
| 1567 Handle<Code> new_target = | 1506 Handle<Code> new_target = |
| 1568 clone_wasm_functions->GetValueChecked<Code>(isolate, startup_fct_index); | 1507 clone_wasm_functions->GetValueChecked<Code>(isolate, startup_fct_index); |
| 1569 PatchJSWrapper(isolate, startup_fct_clone, new_target); | 1508 PatchJSWrapper(isolate, startup_fct_clone, new_target); |
| 1570 } | 1509 } |
| 1571 clone->set(kImportMap, *isolate->factory()->undefined_value()); | 1510 clone->reset_import_map(isolate); |
| 1572 return clone; | 1511 return clone; |
| 1573 } | 1512 } |
| 1574 | 1513 |
| 1575 // Instantiates a wasm module as a JSObject. | 1514 // Instantiates a wasm module as a JSObject. |
| 1576 // * allocates a backing store of {mem_size} bytes. | 1515 // * allocates a backing store of {mem_size} bytes. |
| 1577 // * installs a named property "memory" for that buffer if exported | 1516 // * installs a named property "memory" for that buffer if exported |
| 1578 // * installs named properties on the object for exported functions | 1517 // * installs named properties on the object for exported functions |
| 1579 // * compiles wasm code to machine code | 1518 // * compiles wasm code to machine code |
| 1580 MaybeHandle<JSObject> WasmModule::Instantiate(Isolate* isolate, | 1519 MaybeHandle<JSObject> WasmModule::Instantiate(Isolate* isolate, |
| 1581 Handle<JSObject> module_object, | 1520 Handle<JSObject> module_object, |
| 1582 Handle<JSReceiver> ffi, | 1521 Handle<JSReceiver> ffi, |
| 1583 Handle<JSArrayBuffer> memory) { | 1522 Handle<JSArrayBuffer> memory) { |
| 1584 HistogramTimerScope wasm_instantiate_module_time_scope( | 1523 HistogramTimerScope wasm_instantiate_module_time_scope( |
| 1585 isolate->counters()->wasm_instantiate_module_time()); | 1524 isolate->counters()->wasm_instantiate_module_time()); |
| 1586 ErrorThrower thrower(isolate, "WasmModule::Instantiate()"); | 1525 ErrorThrower thrower(isolate, "WasmModule::Instantiate()"); |
| 1587 Factory* factory = isolate->factory(); | 1526 Factory* factory = isolate->factory(); |
| 1588 | 1527 |
| 1589 bool template_is_owned = false; | 1528 bool template_is_owned = false; |
| 1590 Handle<FixedArray> compiled_module_template; | 1529 Handle<WasmCompiledModule> compiled_module_template; |
| 1591 Handle<FixedArray> compiled_module = CloneModuleForInstance( | 1530 Handle<WasmCompiledModule> compiled_module = CloneModuleForInstance( |
| 1592 isolate, module_object, &template_is_owned, &compiled_module_template); | 1531 isolate, module_object, &template_is_owned, &compiled_module_template); |
| 1593 | 1532 |
| 1594 MaybeHandle<JSObject> template_owner; | 1533 MaybeHandle<JSObject> template_owner; |
| 1595 if (template_is_owned) { | 1534 if (template_is_owned) { |
| 1596 Handle<WeakCell> weak_owner = | 1535 template_owner = compiled_module_template->owning_instance(); |
| 1597 compiled_module_template->GetValueChecked<WeakCell>(isolate, | |
| 1598 kOwningInstance); | |
| 1599 template_owner = handle(JSObject::cast(weak_owner->value())); | |
| 1600 } | 1536 } |
| 1601 // These fields are compulsory. | 1537 // These fields are compulsory. |
| 1602 Handle<FixedArray> code_table = | 1538 Handle<FixedArray> code_table = compiled_module->functions(); |
| 1603 compiled_module->GetValueChecked<FixedArray>(isolate, kFunctions); | |
| 1604 | |
| 1605 RecordStats(isolate, code_table); | 1539 RecordStats(isolate, code_table); |
| 1606 | 1540 |
| 1607 MaybeHandle<JSObject> nothing; | 1541 MaybeHandle<JSObject> nothing; |
| 1608 | 1542 |
| 1609 Handle<Map> map = factory->NewMap( | 1543 Handle<Map> map = factory->NewMap( |
| 1610 JS_OBJECT_TYPE, | 1544 JS_OBJECT_TYPE, |
| 1611 JSObject::kHeaderSize + kWasmModuleInternalFieldCount * kPointerSize); | 1545 JSObject::kHeaderSize + kWasmModuleInternalFieldCount * kPointerSize); |
| 1612 Handle<JSObject> js_object = factory->NewJSObjectFromMap(map, TENURED); | 1546 Handle<JSObject> js_object = factory->NewJSObjectFromMap(map, TENURED); |
| 1613 js_object->SetInternalField(kWasmModuleCodeTable, *code_table); | 1547 js_object->SetInternalField(kWasmModuleCodeTable, *code_table); |
| 1614 | 1548 |
| 1615 // Remember the old imports, for the case when we are at the first instance - | 1549 // Remember the old imports, for the case when we are at the first instance - |
| 1616 // they will be replaced with the instance's actual imports in SetupImports. | 1550 // they will be replaced with the instance's actual imports in SetupImports. |
| 1617 MaybeHandle<FixedArray> old_imports = | 1551 MaybeHandle<FixedArray> old_imports = |
| 1618 compiled_module_template->GetValue<FixedArray>(isolate, kImportMap); | 1552 compiled_module_template->maybe_import_map(); |
| 1619 if (!(SetupInstanceHeap(isolate, compiled_module, js_object, memory, | 1553 if (!(SetupInstanceHeap(isolate, compiled_module, js_object, memory, |
| 1620 &thrower) && | 1554 &thrower) && |
| 1621 SetupGlobals(isolate, template_owner, compiled_module, js_object, | 1555 SetupGlobals(isolate, template_owner, compiled_module, js_object, |
| 1622 &thrower) && | 1556 &thrower) && |
| 1623 SetupImports(isolate, compiled_module, js_object, &thrower, ffi) && | 1557 SetupImports(isolate, compiled_module, js_object, &thrower, ffi) && |
| 1624 SetupExportsObject(compiled_module, isolate, js_object, &thrower))) { | 1558 SetupExportsObject(compiled_module, isolate, js_object, &thrower))) { |
| 1625 return nothing; | 1559 return nothing; |
| 1626 } | 1560 } |
| 1627 | 1561 |
| 1628 FixupFunctionsAndImports( | 1562 FixupFunctionsAndImports(compiled_module_template->functions(), code_table, |
| 1629 compiled_module_template->GetValueChecked<FixedArray>(isolate, | 1563 old_imports, compiled_module->maybe_import_map()); |
| 1630 kFunctions), | |
| 1631 code_table, old_imports, | |
| 1632 compiled_module->GetValue<FixedArray>(isolate, kImportMap)); | |
| 1633 | 1564 |
| 1634 SetDebugSupport(factory, compiled_module, js_object); | 1565 SetDebugSupport(factory, compiled_module, js_object); |
| 1635 SetRuntimeSupport(isolate, js_object); | 1566 SetRuntimeSupport(isolate, js_object); |
| 1636 | 1567 |
| 1637 FlushAssemblyCache(isolate, code_table); | 1568 FlushAssemblyCache(isolate, code_table); |
| 1638 | 1569 |
| 1639 { | 1570 { |
| 1640 std::vector<Handle<Code>> functions( | 1571 std::vector<Handle<Code>> functions( |
| 1641 static_cast<size_t>(code_table->length())); | 1572 static_cast<size_t>(code_table->length())); |
| 1642 for (int i = 0; i < code_table->length(); ++i) { | 1573 for (int i = 0; i < code_table->length(); ++i) { |
| 1643 functions[static_cast<size_t>(i)] = | 1574 functions[static_cast<size_t>(i)] = |
| 1644 code_table->GetValueChecked<Code>(isolate, i); | 1575 code_table->GetValueChecked<Code>(isolate, i); |
| 1645 } | 1576 } |
| 1646 | 1577 |
| 1647 MaybeHandle<FixedArray> maybe_indirect_tables = | 1578 if (compiled_module->has_indirect_function_tables()) { |
| 1648 compiled_module->GetValue<FixedArray>(isolate, | 1579 Handle<FixedArray> indirect_tables_template = |
| 1649 kTableOfIndirectFunctionTables); | 1580 compiled_module->indirect_function_tables(); |
| 1650 Handle<FixedArray> indirect_tables_template; | |
| 1651 if (maybe_indirect_tables.ToHandle(&indirect_tables_template)) { | |
| 1652 Handle<FixedArray> to_replace = | 1581 Handle<FixedArray> to_replace = |
| 1653 template_owner.is_null() | 1582 template_owner.is_null() |
| 1654 ? indirect_tables_template | 1583 ? indirect_tables_template |
| 1655 : handle(FixedArray::cast( | 1584 : handle(FixedArray::cast( |
| 1656 template_owner.ToHandleChecked()->GetInternalField( | 1585 template_owner.ToHandleChecked()->GetInternalField( |
| 1657 kWasmModuleFunctionTable))); | 1586 kWasmModuleFunctionTable))); |
| 1658 Handle<FixedArray> indirect_tables = SetupIndirectFunctionTable( | 1587 Handle<FixedArray> indirect_tables = SetupIndirectFunctionTable( |
| 1659 isolate, code_table, indirect_tables_template, to_replace); | 1588 isolate, code_table, indirect_tables_template, to_replace); |
| 1660 for (int i = 0; i < indirect_tables->length(); ++i) { | 1589 for (int i = 0; i < indirect_tables->length(); ++i) { |
| 1661 Handle<FixedArray> metadata = | 1590 Handle<FixedArray> metadata = |
| 1662 indirect_tables->GetValueChecked<FixedArray>(isolate, i); | 1591 indirect_tables->GetValueChecked<FixedArray>(isolate, i); |
| 1663 uint32_t size = Smi::cast(metadata->get(kSize))->value(); | 1592 uint32_t size = Smi::cast(metadata->get(kSize))->value(); |
| 1664 Handle<FixedArray> table = | 1593 Handle<FixedArray> table = |
| 1665 metadata->GetValueChecked<FixedArray>(isolate, kTable); | 1594 metadata->GetValueChecked<FixedArray>(isolate, kTable); |
| 1666 wasm::PopulateFunctionTable(table, size, &functions); | 1595 wasm::PopulateFunctionTable(table, size, &functions); |
| 1667 } | 1596 } |
| 1668 js_object->SetInternalField(kWasmModuleFunctionTable, *indirect_tables); | 1597 js_object->SetInternalField(kWasmModuleFunctionTable, *indirect_tables); |
| 1669 } | 1598 } |
| 1670 } | 1599 } |
| 1671 | 1600 |
| 1672 // Run the start function if one was specified. | 1601 // Run the start function if one was specified. |
| 1673 MaybeHandle<FixedArray> maybe_startup_fct = | 1602 if (compiled_module->has_startup_function()) { |
| 1674 compiled_module->GetValue<FixedArray>(isolate, kStartupFunction); | 1603 Handle<FixedArray> metadata = compiled_module->startup_function(); |
| 1675 Handle<FixedArray> metadata; | |
| 1676 if (maybe_startup_fct.ToHandle(&metadata)) { | |
| 1677 HandleScope scope(isolate); | 1604 HandleScope scope(isolate); |
| 1678 Handle<Code> startup_code = | 1605 Handle<Code> startup_code = |
| 1679 metadata->GetValueChecked<Code>(isolate, kExportCode); | 1606 metadata->GetValueChecked<Code>(isolate, kExportCode); |
| 1680 int arity = Smi::cast(metadata->get(kExportArity))->value(); | 1607 int arity = Smi::cast(metadata->get(kExportArity))->value(); |
| 1681 MaybeHandle<ByteArray> startup_signature = | 1608 MaybeHandle<ByteArray> startup_signature = |
| 1682 metadata->GetValue<ByteArray>(isolate, kExportedSignature); | 1609 metadata->GetValue<ByteArray>(isolate, kExportedSignature); |
| 1683 Handle<JSFunction> startup_fct = WrapExportCodeAsJSFunction( | 1610 Handle<JSFunction> startup_fct = WrapExportCodeAsJSFunction( |
| 1684 isolate, startup_code, factory->InternalizeUtf8String("start"), arity, | 1611 isolate, startup_code, factory->InternalizeUtf8String("start"), arity, |
| 1685 startup_signature, js_object); | 1612 startup_signature, js_object); |
| 1686 RecordStats(isolate, *startup_code); | 1613 RecordStats(isolate, *startup_code); |
| 1687 // Call the JS function. | 1614 // Call the JS function. |
| 1688 Handle<Object> undefined = isolate->factory()->undefined_value(); | 1615 Handle<Object> undefined = isolate->factory()->undefined_value(); |
| 1689 MaybeHandle<Object> retval = | 1616 MaybeHandle<Object> retval = |
| 1690 Execution::Call(isolate, startup_fct, undefined, 0, nullptr); | 1617 Execution::Call(isolate, startup_fct, undefined, 0, nullptr); |
| 1691 | 1618 |
| 1692 if (retval.is_null()) { | 1619 if (retval.is_null()) { |
| 1693 thrower.Error("WASM.instantiateModule(): start function failed"); | 1620 thrower.Error("WASM.instantiateModule(): start function failed"); |
| 1694 return nothing; | 1621 return nothing; |
| 1695 } | 1622 } |
| 1696 } | 1623 } |
| 1697 | 1624 |
| 1698 DCHECK(wasm::IsWasmObject(*js_object)); | 1625 DCHECK(wasm::IsWasmObject(*js_object)); |
| 1699 | 1626 |
| 1700 if (!compiled_module->GetValue<WeakCell>(isolate, kModuleObject).is_null()) { | 1627 if (compiled_module->has_weak_module_object()) { |
| 1701 js_object->SetInternalField(kWasmCompiledModule, *compiled_module); | 1628 js_object->SetInternalField(kWasmCompiledModule, *compiled_module); |
| 1702 Handle<WeakCell> link_to_owner = factory->NewWeakCell(js_object); | 1629 Handle<WeakCell> link_to_owner = factory->NewWeakCell(js_object); |
| 1703 compiled_module->set(kOwningInstance, *link_to_owner); | 1630 compiled_module->set_weak_owning_instance(link_to_owner); |
| 1704 | 1631 |
| 1705 Handle<Object> global_handle = | 1632 Handle<Object> global_handle = |
| 1706 isolate->global_handles()->Create(*js_object); | 1633 isolate->global_handles()->Create(*js_object); |
| 1707 GlobalHandles::MakeWeak(global_handle.location(), global_handle.location(), | 1634 GlobalHandles::MakeWeak(global_handle.location(), global_handle.location(), |
| 1708 &InstanceFinalizer, | 1635 &InstanceFinalizer, |
| 1709 v8::WeakCallbackType::kFinalizer); | 1636 v8::WeakCallbackType::kFinalizer); |
| 1710 } | 1637 } |
| 1711 | 1638 |
| 1712 return js_object; | 1639 return js_object; |
| 1713 } | 1640 } |
| (...skipping 176 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1890 Handle<Map> map = isolate->factory()->NewMap( | 1817 Handle<Map> map = isolate->factory()->NewMap( |
| 1891 JS_OBJECT_TYPE, JSObject::kHeaderSize + kPointerSize); | 1818 JS_OBJECT_TYPE, JSObject::kHeaderSize + kPointerSize); |
| 1892 module_obj = isolate->factory()->NewJSObjectFromMap(map, TENURED); | 1819 module_obj = isolate->factory()->NewJSObjectFromMap(map, TENURED); |
| 1893 } | 1820 } |
| 1894 module_obj->SetInternalField(0, *compiled_module); | 1821 module_obj->SetInternalField(0, *compiled_module); |
| 1895 if (origin == ModuleOrigin::kWasmOrigin) { | 1822 if (origin == ModuleOrigin::kWasmOrigin) { |
| 1896 Handle<Symbol> module_sym(isolate->native_context()->wasm_module_sym()); | 1823 Handle<Symbol> module_sym(isolate->native_context()->wasm_module_sym()); |
| 1897 Object::SetProperty(module_obj, module_sym, module_obj, STRICT).Check(); | 1824 Object::SetProperty(module_obj, module_sym, module_obj, STRICT).Check(); |
| 1898 } | 1825 } |
| 1899 Handle<WeakCell> link_to_module = isolate->factory()->NewWeakCell(module_obj); | 1826 Handle<WeakCell> link_to_module = isolate->factory()->NewWeakCell(module_obj); |
| 1900 compiled_module->set(kModuleObject, *link_to_module); | 1827 WasmCompiledModule::cast(*compiled_module) |
| 1828 ->set_weak_module_object(link_to_module); |
| 1901 return module_obj; | 1829 return module_obj; |
| 1902 } | 1830 } |
| 1903 | 1831 |
| 1904 MaybeHandle<JSObject> CreateModuleObjectFromBytes(Isolate* isolate, | 1832 MaybeHandle<JSObject> CreateModuleObjectFromBytes(Isolate* isolate, |
| 1905 const byte* start, | 1833 const byte* start, |
| 1906 const byte* end, | 1834 const byte* end, |
| 1907 ErrorThrower* thrower, | 1835 ErrorThrower* thrower, |
| 1908 ModuleOrigin origin) { | 1836 ModuleOrigin origin) { |
| 1909 MaybeHandle<JSObject> nothing; | 1837 MaybeHandle<JSObject> nothing; |
| 1910 Zone zone(isolate->allocator()); | 1838 Zone zone(isolate->allocator()); |
| (...skipping 19 matching lines...) Expand all Loading... |
| 1930 if (mem->IsUndefined(isolate)) return MaybeHandle<JSArrayBuffer>(); | 1858 if (mem->IsUndefined(isolate)) return MaybeHandle<JSArrayBuffer>(); |
| 1931 return Handle<JSArrayBuffer>(JSArrayBuffer::cast(mem)); | 1859 return Handle<JSArrayBuffer>(JSArrayBuffer::cast(mem)); |
| 1932 } | 1860 } |
| 1933 | 1861 |
| 1934 void SetInstanceMemory(Handle<JSObject> instance, JSArrayBuffer* buffer) { | 1862 void SetInstanceMemory(Handle<JSObject> instance, JSArrayBuffer* buffer) { |
| 1935 DisallowHeapAllocation no_gc; | 1863 DisallowHeapAllocation no_gc; |
| 1936 DCHECK(IsWasmObject(*instance)); | 1864 DCHECK(IsWasmObject(*instance)); |
| 1937 instance->SetInternalField(kWasmMemArrayBuffer, buffer); | 1865 instance->SetInternalField(kWasmMemArrayBuffer, buffer); |
| 1938 Object* module = instance->GetInternalField(kWasmCompiledModule); | 1866 Object* module = instance->GetInternalField(kWasmCompiledModule); |
| 1939 if (module->IsFixedArray()) { | 1867 if (module->IsFixedArray()) { |
| 1940 HeapNumber::cast(FixedArray::cast(module)->get(kMemSize)) | 1868 WasmCompiledModule::cast(module)->set_mem_size( |
| 1941 ->set_value(buffer->byte_length()->Number()); | 1869 buffer->byte_length()->Number()); |
| 1942 } | 1870 } |
| 1943 } | 1871 } |
| 1944 | 1872 |
| 1945 namespace testing { | 1873 namespace testing { |
| 1946 | 1874 |
| 1947 void ValidateInstancesChain(Isolate* isolate, Handle<JSObject> module_obj, | 1875 void ValidateInstancesChain(Isolate* isolate, Handle<JSObject> module_obj, |
| 1948 int instance_count) { | 1876 int instance_count) { |
| 1949 CHECK_GE(instance_count, 0); | 1877 CHECK_GE(instance_count, 0); |
| 1950 DisallowHeapAllocation no_gc; | 1878 DisallowHeapAllocation no_gc; |
| 1951 FixedArray* compiled_module = | 1879 WasmCompiledModule* compiled_module = |
| 1952 FixedArray::cast(module_obj->GetInternalField(0)); | 1880 WasmCompiledModule::cast(module_obj->GetInternalField(0)); |
| 1953 CHECK_EQ(JSObject::cast(GetModuleObject(compiled_module)->value()), | 1881 CHECK_EQ( |
| 1954 *module_obj); | 1882 JSObject::cast(compiled_module->ptr_to_weak_module_object()->value()), |
| 1883 *module_obj); |
| 1955 Object* prev = nullptr; | 1884 Object* prev = nullptr; |
| 1956 int found_instances = GetOwningInstance(compiled_module) == nullptr ? 0 : 1; | 1885 int found_instances = compiled_module->has_weak_owning_instance() ? 1 : 0; |
| 1957 FixedArray* current_instance = compiled_module; | 1886 WasmCompiledModule* current_instance = compiled_module; |
| 1958 while (GetNextInstance(current_instance) != nullptr) { | 1887 while (current_instance->has_weak_next_instance()) { |
| 1959 CHECK((prev == nullptr && GetPrevInstance(current_instance) == nullptr) || | 1888 CHECK((prev == nullptr && !current_instance->has_weak_prev_instance()) || |
| 1960 GetPrevInstance(current_instance)->value() == prev); | 1889 current_instance->ptr_to_weak_prev_instance()->value() == prev); |
| 1961 CHECK_EQ(GetModuleObject(current_instance)->value(), *module_obj); | 1890 CHECK_EQ(current_instance->ptr_to_weak_module_object()->value(), |
| 1962 CHECK(IsWasmObject(GetOwningInstance(current_instance)->value())); | 1891 *module_obj); |
| 1892 CHECK( |
| 1893 IsWasmObject(current_instance->ptr_to_weak_owning_instance()->value())); |
| 1963 prev = current_instance; | 1894 prev = current_instance; |
| 1964 current_instance = | 1895 current_instance = WasmCompiledModule::cast( |
| 1965 FixedArray::cast(GetNextInstance(current_instance)->value()); | 1896 current_instance->ptr_to_weak_next_instance()->value()); |
| 1966 ++found_instances; | 1897 ++found_instances; |
| 1967 CHECK_LE(found_instances, instance_count); | 1898 CHECK_LE(found_instances, instance_count); |
| 1968 } | 1899 } |
| 1969 CHECK_EQ(found_instances, instance_count); | 1900 CHECK_EQ(found_instances, instance_count); |
| 1970 } | 1901 } |
| 1971 | 1902 |
| 1972 void ValidateModuleState(Isolate* isolate, Handle<JSObject> module_obj) { | 1903 void ValidateModuleState(Isolate* isolate, Handle<JSObject> module_obj) { |
| 1973 DisallowHeapAllocation no_gc; | 1904 DisallowHeapAllocation no_gc; |
| 1974 FixedArray* compiled_module = | 1905 WasmCompiledModule* compiled_module = |
| 1975 FixedArray::cast(module_obj->GetInternalField(0)); | 1906 WasmCompiledModule::cast(module_obj->GetInternalField(0)); |
| 1976 CHECK_NOT_NULL(GetModuleObject(compiled_module)); | 1907 CHECK(compiled_module->has_weak_module_object()); |
| 1977 CHECK_EQ(GetModuleObject(compiled_module)->value(), *module_obj); | 1908 CHECK_EQ(compiled_module->ptr_to_weak_module_object()->value(), *module_obj); |
| 1978 CHECK_NULL(GetPrevInstance(compiled_module)); | 1909 CHECK(!compiled_module->has_weak_prev_instance()); |
| 1979 CHECK_NULL(GetNextInstance(compiled_module)); | 1910 CHECK(!compiled_module->has_weak_next_instance()); |
| 1980 CHECK_NULL(GetOwningInstance(compiled_module)); | 1911 CHECK(!compiled_module->has_weak_owning_instance()); |
| 1981 } | 1912 } |
| 1982 | 1913 |
| 1983 void ValidateOrphanedInstance(Isolate* isolate, Handle<JSObject> instance) { | 1914 void ValidateOrphanedInstance(Isolate* isolate, Handle<JSObject> instance) { |
| 1984 DisallowHeapAllocation no_gc; | 1915 DisallowHeapAllocation no_gc; |
| 1985 CHECK(IsWasmObject(*instance)); | 1916 CHECK(IsWasmObject(*instance)); |
| 1986 FixedArray* compiled_module = | 1917 WasmCompiledModule* compiled_module = |
| 1987 FixedArray::cast(instance->GetInternalField(kWasmCompiledModule)); | 1918 WasmCompiledModule::cast(instance->GetInternalField(kWasmCompiledModule)); |
| 1988 CHECK_NOT_NULL(GetModuleObject(compiled_module)); | 1919 CHECK(compiled_module->has_weak_module_object()); |
| 1989 CHECK(GetModuleObject(compiled_module)->cleared()); | 1920 CHECK(compiled_module->ptr_to_weak_module_object()->cleared()); |
| 1990 } | 1921 } |
| 1991 | 1922 |
| 1992 } // namespace testing | 1923 } // namespace testing |
| 1993 } // namespace wasm | 1924 } // namespace wasm |
| 1994 } // namespace internal | 1925 } // namespace internal |
| 1995 } // namespace v8 | 1926 } // namespace v8 |
| OLD | NEW |