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 140 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
151 DCHECK_NOT_NULL(deopt_data); | 151 DCHECK_NOT_NULL(deopt_data); |
152 DCHECK(deopt_data->length() == 2); | 152 DCHECK(deopt_data->length() == 2); |
153 Object* weak_link = deopt_data->get(0); | 153 Object* weak_link = deopt_data->get(0); |
154 if (weak_link == undefined) return undefined; | 154 if (weak_link == undefined) return undefined; |
155 WeakCell* cell = WeakCell::cast(weak_link); | 155 WeakCell* cell = WeakCell::cast(weak_link); |
156 return cell->value(); | 156 return cell->value(); |
157 } | 157 } |
158 | 158 |
159 namespace { | 159 namespace { |
160 // Internal constants for the layout of the module object. | 160 // Internal constants for the layout of the module object. |
161 enum WasmInstanceFields { | 161 const int kWasmModuleFunctionTable = 0; |
162 kWasmCompiledModule = 0, | 162 const int kWasmModuleCodeTable = 1; |
163 kWasmModuleFunctionTable, | 163 const int kWasmMemArrayBuffer = 2; |
164 kWasmModuleCodeTable, | 164 const int kWasmGlobalsArrayBuffer = 3; |
165 kWasmMemArrayBuffer, | 165 // TODO(clemensh): Remove function name array, extract names from module bytes. |
166 kWasmGlobalsArrayBuffer, | 166 const int kWasmFunctionNamesArray = 4; |
167 // TODO(clemensh): Remove function name array, extract names from module | 167 const int kWasmModuleBytesString = 5; |
168 // bytes. | 168 const int kWasmDebugInfo = 6; |
169 kWasmFunctionNamesArray, | 169 const int kWasmModuleInternalFieldCount = 7; |
170 kWasmModuleBytesString, | |
171 kWasmDebugInfo, | |
172 kWasmModuleInternalFieldCount | |
173 }; | |
174 | 170 |
175 // TODO(mtrofin): Unnecessary once we stop using JS Heap for wasm code. | 171 // 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. | 172 // 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 | 173 // The elements typed as "maybe" are optional. The others are mandatory. Since |
178 // the compiled module is either obtained from the current v8 instance, or from | 174 // the compiled module is either obtained from the current v8 instance, or from |
179 // a snapshot produced by a compatible (==identical) v8 instance, we simply | 175 // a snapshot produced by a compatible (==identical) v8 instance, we simply |
180 // fail at instantiation time, in the face of invalid data. | 176 // fail at instantiation time, in the face of invalid data. |
181 enum CompiledWasmObjectFields { | 177 enum CompiledWasmObjectFields { |
182 kFunctions, // FixedArray of Code | 178 kFunctions, // FixedArray of Code |
183 kImportData, // maybe FixedArray of FixedArray respecting the | 179 kImportData, // maybe FixedArray of FixedArray respecting the |
184 // WasmImportMetadata structure. | 180 // WasmImportMetadata structure. |
185 kImportMap, // FixedArray. The i-th element is the Code object used for | 181 kImportMap, // FixedArray. The i-th element is the Code object used for |
186 // import i | 182 // import i |
187 kExports, // maybe FixedArray of FixedArray of WasmExportMetadata | 183 kExports, // maybe FixedArray of FixedArray of WasmExportMetadata |
188 // structure | 184 // structure |
189 kStartupFunction, // maybe FixedArray of WasmExportMetadata structure | 185 kStartupFunction, // maybe FixedArray of WasmExportMetadata structure |
190 kTableOfIndirectFunctionTables, // maybe FixedArray of FixedArray of | 186 kTableOfIndirectFunctionTables, // maybe FixedArray of FixedArray of |
191 // WasmIndirectFunctionTableMetadata | 187 // WasmIndirectFunctionTableMetadata |
192 kModuleBytes, // maybe String | 188 kModuleBytes, // maybe String |
193 kFunctionNameTable, // maybe ByteArray | 189 kFunctionNameTable, // maybe ByteArray |
194 kMinRequiredMemory, // Smi. an uint32_t | 190 kMinRequiredMemory, // Smi. an uint32_t |
195 // The following 2 are either together present or absent: | 191 // The following 2 are either together present or absent: |
196 kDataSegmentsInfo, // maybe FixedArray of FixedArray respecting the | 192 kDataSegmentsInfo, // maybe FixedArray of FixedArray respecting the |
197 // WasmSegmentInfo structure | 193 // WasmSegmentInfo structure |
198 kDataSegments, // maybe ByteArray. | 194 kDataSegments, // maybe ByteArray. |
199 | 195 |
200 kGlobalsSize, // Smi. an uint32_t | 196 kGlobalsSize, // Smi. an uint32_t |
201 kMemSize, // Smi.an uint32_t | |
202 kMemStart, // MaybeHandle<ArrayBuffer> | |
203 kExportMem, // Smi. bool | 197 kExportMem, // Smi. bool |
204 kOrigin, // Smi. ModuleOrigin | 198 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. | 199 kCompiledWasmObjectTableSize // Sentinel value. |
210 }; | 200 }; |
211 | 201 |
212 enum WasmImportMetadata { | 202 enum WasmImportMetadata { |
213 kModuleName, // String | 203 kModuleName, // String |
214 kFunctionName, // maybe String | 204 kFunctionName, // maybe String |
215 kOutputCount, // Smi. an uint32_t | 205 kOutputCount, // Smi. an uint32_t |
216 kSignature, // ByteArray. A copy of the data in FunctionSig | 206 kSignature, // ByteArray. A copy of the data in FunctionSig |
217 kWasmImportDataTableSize // Sentinel value. | 207 kWasmImportDataTableSize // Sentinel value. |
218 }; | 208 }; |
(...skipping 113 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
332 DCHECK_EQ(0, bytes[i]); | 322 DCHECK_EQ(0, bytes[i]); |
333 } | 323 } |
334 #endif | 324 #endif |
335 | 325 |
336 Handle<JSArrayBuffer> buffer = isolate->factory()->NewJSArrayBuffer(); | 326 Handle<JSArrayBuffer> buffer = isolate->factory()->NewJSArrayBuffer(); |
337 JSArrayBuffer::Setup(buffer, isolate, false, memory, static_cast<int>(size)); | 327 JSArrayBuffer::Setup(buffer, isolate, false, memory, static_cast<int>(size)); |
338 buffer->set_is_neuterable(false); | 328 buffer->set_is_neuterable(false); |
339 return buffer; | 329 return buffer; |
340 } | 330 } |
341 | 331 |
342 void RelocateInstanceCode(Handle<JSObject> instance, Address old_start, | 332 void RelocateInstanceCode(Handle<JSObject> instance, Address start, |
343 Address start, uint32_t prev_size, | 333 uint32_t prev_size, uint32_t new_size) { |
344 uint32_t new_size) { | |
345 Handle<FixedArray> functions = Handle<FixedArray>( | 334 Handle<FixedArray> functions = Handle<FixedArray>( |
346 FixedArray::cast(instance->GetInternalField(kWasmModuleCodeTable))); | 335 FixedArray::cast(instance->GetInternalField(kWasmModuleCodeTable))); |
347 for (int i = 0; i < functions->length(); ++i) { | 336 for (int i = 0; i < functions->length(); ++i) { |
348 Handle<Code> function = Handle<Code>(Code::cast(functions->get(i))); | 337 Handle<Code> function = Handle<Code>(Code::cast(functions->get(i))); |
349 AllowDeferredHandleDereference embedding_raw_address; | 338 AllowDeferredHandleDereference embedding_raw_address; |
350 int mask = (1 << RelocInfo::WASM_MEMORY_REFERENCE) | | 339 int mask = (1 << RelocInfo::WASM_MEMORY_REFERENCE) | |
351 (1 << RelocInfo::WASM_MEMORY_SIZE_REFERENCE); | 340 (1 << RelocInfo::WASM_MEMORY_SIZE_REFERENCE); |
352 for (RelocIterator it(*function, mask); !it.done(); it.next()) { | 341 for (RelocIterator it(*function, mask); !it.done(); it.next()) { |
353 it.rinfo()->update_wasm_memory_reference(old_start, start, prev_size, | 342 it.rinfo()->update_wasm_memory_reference(nullptr, start, prev_size, |
354 new_size); | 343 new_size); |
355 } | 344 } |
356 } | 345 } |
357 } | 346 } |
358 | 347 |
359 // Allocate memory for a module instance as a new JSArrayBuffer. | 348 // Allocate memory for a module instance as a new JSArrayBuffer. |
360 Handle<JSArrayBuffer> AllocateMemory(ErrorThrower* thrower, Isolate* isolate, | 349 Handle<JSArrayBuffer> AllocateMemory(ErrorThrower* thrower, Isolate* isolate, |
361 uint32_t min_mem_pages) { | 350 uint32_t min_mem_pages) { |
362 if (min_mem_pages > WasmModule::kMaxMemPages) { | 351 if (min_mem_pages > WasmModule::kMaxMemPages) { |
363 thrower->Error("Out of memory: wasm memory too large"); | 352 thrower->Error("Out of memory: wasm memory too large"); |
364 return Handle<JSArrayBuffer>::null(); | 353 return Handle<JSArrayBuffer>::null(); |
365 } | 354 } |
366 Handle<JSArrayBuffer> mem_buffer = | 355 Handle<JSArrayBuffer> mem_buffer = |
367 NewArrayBuffer(isolate, min_mem_pages * WasmModule::kPageSize); | 356 NewArrayBuffer(isolate, min_mem_pages * WasmModule::kPageSize); |
368 | 357 |
369 if (mem_buffer.is_null()) { | 358 if (mem_buffer.is_null()) { |
370 thrower->Error("Out of memory: wasm memory"); | 359 thrower->Error("Out of memory: wasm memory"); |
371 } | 360 } |
372 return mem_buffer; | 361 return mem_buffer; |
373 } | 362 } |
374 | 363 |
375 void RelocateGlobals(Handle<JSObject> instance, Address old_start, | 364 void RelocateGlobals(Handle<JSObject> instance, Address globals_start) { |
376 Address globals_start) { | |
377 Handle<FixedArray> functions = Handle<FixedArray>( | 365 Handle<FixedArray> functions = Handle<FixedArray>( |
378 FixedArray::cast(instance->GetInternalField(kWasmModuleCodeTable))); | 366 FixedArray::cast(instance->GetInternalField(kWasmModuleCodeTable))); |
379 uint32_t function_count = static_cast<uint32_t>(functions->length()); | 367 uint32_t function_count = static_cast<uint32_t>(functions->length()); |
380 for (uint32_t i = 0; i < function_count; ++i) { | 368 for (uint32_t i = 0; i < function_count; ++i) { |
381 Handle<Code> function = Handle<Code>(Code::cast(functions->get(i))); | 369 Handle<Code> function = Handle<Code>(Code::cast(functions->get(i))); |
382 AllowDeferredHandleDereference embedding_raw_address; | 370 AllowDeferredHandleDereference embedding_raw_address; |
383 int mask = 1 << RelocInfo::WASM_GLOBAL_REFERENCE; | 371 int mask = 1 << RelocInfo::WASM_GLOBAL_REFERENCE; |
384 for (RelocIterator it(*function, mask); !it.done(); it.next()) { | 372 for (RelocIterator it(*function, mask); !it.done(); it.next()) { |
385 it.rinfo()->update_wasm_global_reference(old_start, globals_start); | 373 it.rinfo()->update_wasm_global_reference(nullptr, globals_start); |
386 } | 374 } |
387 } | 375 } |
388 } | 376 } |
389 | 377 |
390 Handle<Code> CreatePlaceholder(Factory* factory, uint32_t index, | 378 Handle<Code> CreatePlaceholder(Factory* factory, uint32_t index, |
391 Code::Kind kind) { | 379 Code::Kind kind) { |
392 // Create a placeholder code object and encode the corresponding index in | 380 // Create a placeholder code object and encode the corresponding index in |
393 // the {constant_pool_offset} field of the code object. | 381 // the {constant_pool_offset} field of the code object. |
394 // TODO(titzer): placeholder code objects are somewhat dangerous. | 382 // TODO(titzer): placeholder code objects are somewhat dangerous. |
395 static byte buffer[] = {0, 0, 0, 0, 0, 0, 0, 0}; // fake instructions. | 383 static byte buffer[] = {0, 0, 0, 0, 0, 0, 0, 0}; // fake instructions. |
(...skipping 10 matching lines...) Expand all Loading... |
406 std::vector<Handle<Code>>* placeholders, | 394 std::vector<Handle<Code>>* placeholders, |
407 size_t size) { | 395 size_t size) { |
408 DCHECK(placeholders->empty()); | 396 DCHECK(placeholders->empty()); |
409 placeholders->reserve(size); | 397 placeholders->reserve(size); |
410 | 398 |
411 for (uint32_t i = 0; i < size; ++i) { | 399 for (uint32_t i = 0; i < size; ++i) { |
412 placeholders->push_back(CreatePlaceholder(factory, i, Code::WASM_FUNCTION)); | 400 placeholders->push_back(CreatePlaceholder(factory, i, Code::WASM_FUNCTION)); |
413 } | 401 } |
414 } | 402 } |
415 | 403 |
416 bool LinkFunction(Isolate* isolate, Handle<Code> unlinked, | 404 bool LinkFunction(Handle<Code> unlinked, |
417 Handle<FixedArray> code_targets, | 405 const std::vector<Handle<Code>>& code_targets, |
418 Code::Kind kind = Code::WASM_FUNCTION) { | 406 Code::Kind kind) { |
419 bool modified = false; | 407 bool modified = false; |
420 int mode_mask = RelocInfo::ModeMask(RelocInfo::CODE_TARGET); | 408 int mode_mask = RelocInfo::kCodeTargetMask; |
421 AllowDeferredHandleDereference embedding_raw_address; | 409 AllowDeferredHandleDereference embedding_raw_address; |
422 for (RelocIterator it(*unlinked, mode_mask); !it.done(); it.next()) { | 410 for (RelocIterator it(*unlinked, mode_mask); !it.done(); it.next()) { |
423 Code* target = Code::GetCodeFromTargetAddress(it.rinfo()->target_address()); | 411 RelocInfo::Mode mode = it.rinfo()->rmode(); |
424 if (target->kind() == kind && | 412 if (RelocInfo::IsCodeTarget(mode)) { |
425 target->constant_pool_offset() >= kPlaceholderMarker) { | 413 Code* target = |
426 // Patch direct calls to placeholder code objects. | 414 Code::GetCodeFromTargetAddress(it.rinfo()->target_address()); |
427 uint32_t index = target->constant_pool_offset() - kPlaceholderMarker; | 415 if (target->kind() == kind && |
428 CHECK(index < static_cast<uint32_t>(code_targets->length())); | 416 target->constant_pool_offset() >= kPlaceholderMarker) { |
429 Handle<Code> new_target = | 417 // Patch direct calls to placeholder code objects. |
430 code_targets->GetValueChecked<Code>(isolate, index); | 418 uint32_t index = target->constant_pool_offset() - kPlaceholderMarker; |
431 if (target != *new_target) { | 419 CHECK(index < code_targets.size()); |
432 it.rinfo()->set_target_address(new_target->instruction_start(), | 420 Handle<Code> new_target = code_targets[index]; |
433 UPDATE_WRITE_BARRIER, SKIP_ICACHE_FLUSH); | 421 if (target != *new_target) { |
434 modified = true; | 422 it.rinfo()->set_target_address(new_target->instruction_start(), |
| 423 UPDATE_WRITE_BARRIER, |
| 424 SKIP_ICACHE_FLUSH); |
| 425 modified = true; |
| 426 } |
435 } | 427 } |
436 } | 428 } |
437 } | 429 } |
438 return modified; | 430 return modified; |
439 } | 431 } |
440 | 432 |
441 void LinkModuleFunctions(Isolate* isolate, Handle<FixedArray> functions) { | 433 void LinkModuleFunctions(Isolate* isolate, |
442 for (int i = 0; i < functions->length(); ++i) { | 434 std::vector<Handle<Code>>& functions) { |
443 Handle<Code> code = functions->GetValueChecked<Code>(isolate, i); | 435 for (size_t i = 0; i < functions.size(); ++i) { |
444 LinkFunction(isolate, code, functions); | 436 Handle<Code> code = functions[i]; |
| 437 LinkFunction(code, functions, Code::WASM_FUNCTION); |
445 } | 438 } |
446 } | 439 } |
447 | 440 |
448 void FlushAssemblyCache(Isolate* isolate, Handle<FixedArray> functions) { | 441 void FlushAssemblyCache(Isolate* isolate, Handle<FixedArray> functions) { |
449 for (int i = 0; i < functions->length(); ++i) { | 442 for (int i = 0; i < functions->length(); ++i) { |
450 Handle<Code> code = functions->GetValueChecked<Code>(isolate, i); | 443 Handle<Code> code = functions->GetValueChecked<Code>(isolate, i); |
451 Assembler::FlushICache(isolate, code->instruction_start(), | 444 Assembler::FlushICache(isolate, code->instruction_start(), |
452 code->instruction_size()); | 445 code->instruction_size()); |
453 } | 446 } |
454 } | 447 } |
455 | 448 |
456 void SetRuntimeSupport(Isolate* isolate, Handle<JSObject> js_object) { | 449 void SetRuntimeSupport(Isolate* isolate, Handle<JSObject> js_object) { |
457 Handle<FixedArray> functions = Handle<FixedArray>( | 450 Handle<FixedArray> functions = Handle<FixedArray>( |
458 FixedArray::cast(js_object->GetInternalField(kWasmModuleCodeTable))); | 451 FixedArray::cast(js_object->GetInternalField(kWasmModuleCodeTable))); |
459 Handle<WeakCell> weak_link = isolate->factory()->NewWeakCell(js_object); | 452 Handle<WeakCell> weak_link = isolate->factory()->NewWeakCell(js_object); |
460 | 453 |
461 for (int i = FLAG_skip_compiling_wasm_funcs; i < functions->length(); ++i) { | 454 for (int i = FLAG_skip_compiling_wasm_funcs; i < functions->length(); ++i) { |
462 Handle<Code> code = functions->GetValueChecked<Code>(isolate, i); | 455 Handle<Code> code = functions->GetValueChecked<Code>(isolate, i); |
| 456 DCHECK(code->deoptimization_data() == nullptr || |
| 457 code->deoptimization_data()->length() == 0); |
463 Handle<FixedArray> deopt_data = | 458 Handle<FixedArray> deopt_data = |
464 isolate->factory()->NewFixedArray(2, TENURED); | 459 isolate->factory()->NewFixedArray(2, TENURED); |
465 deopt_data->set(0, *weak_link); | 460 deopt_data->set(0, *weak_link); |
466 deopt_data->set(1, Smi::FromInt(static_cast<int>(i))); | 461 deopt_data->set(1, Smi::FromInt(static_cast<int>(i))); |
467 deopt_data->set_length(2); | 462 deopt_data->set_length(2); |
468 code->set_deoptimization_data(*deopt_data); | 463 code->set_deoptimization_data(*deopt_data); |
469 } | 464 } |
470 } | 465 } |
471 | 466 |
472 } // namespace | 467 } // namespace |
(...skipping 146 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
619 for (Handle<Code> c : functions) RecordStats(isolate, *c); | 614 for (Handle<Code> c : functions) RecordStats(isolate, *c); |
620 } | 615 } |
621 | 616 |
622 static void RecordStats(Isolate* isolate, Handle<FixedArray> functions) { | 617 static void RecordStats(Isolate* isolate, Handle<FixedArray> functions) { |
623 DisallowHeapAllocation no_gc; | 618 DisallowHeapAllocation no_gc; |
624 for (int i = 0; i < functions->length(); ++i) { | 619 for (int i = 0; i < functions->length(); ++i) { |
625 RecordStats(isolate, Code::cast(functions->get(i))); | 620 RecordStats(isolate, Code::cast(functions->get(i))); |
626 } | 621 } |
627 } | 622 } |
628 | 623 |
629 Address GetGlobalStartAddressFromCodeTemplate(Object* undefined, | |
630 JSObject* owner) { | |
631 Address old_address = nullptr; | |
632 Object* stored_value = owner->GetInternalField(kWasmGlobalsArrayBuffer); | |
633 if (stored_value != undefined) { | |
634 old_address = static_cast<Address>( | |
635 JSArrayBuffer::cast(stored_value)->backing_store()); | |
636 } | |
637 return old_address; | |
638 } | |
639 | |
640 Handle<FixedArray> GetImportsMetadata(Factory* factory, | 624 Handle<FixedArray> GetImportsMetadata(Factory* factory, |
641 const WasmModule* module) { | 625 const WasmModule* module) { |
642 Handle<FixedArray> ret = factory->NewFixedArray( | 626 Handle<FixedArray> ret = factory->NewFixedArray( |
643 static_cast<int>(module->import_table.size()), TENURED); | 627 static_cast<int>(module->import_table.size()), TENURED); |
644 for (size_t i = 0; i < module->import_table.size(); ++i) { | 628 for (size_t i = 0; i < module->import_table.size(); ++i) { |
645 const WasmImport& import = module->import_table[i]; | 629 const WasmImport& import = module->import_table[i]; |
646 WasmName module_name = module->GetNameOrNull(import.module_name_offset, | 630 WasmName module_name = module->GetNameOrNull(import.module_name_offset, |
647 import.module_name_length); | 631 import.module_name_length); |
648 WasmName function_name = module->GetNameOrNull(import.function_name_offset, | 632 WasmName function_name = module->GetNameOrNull(import.function_name_offset, |
649 import.function_name_length); | 633 import.function_name_length); |
(...skipping 271 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
921 } | 905 } |
922 | 906 |
923 MaybeHandle<ByteArray> function_name_table = | 907 MaybeHandle<ByteArray> function_name_table = |
924 compiled_module->GetValue<ByteArray>(isolate, kFunctionNameTable); | 908 compiled_module->GetValue<ByteArray>(isolate, kFunctionNameTable); |
925 if (!function_name_table.is_null()) { | 909 if (!function_name_table.is_null()) { |
926 js_object->SetInternalField(kWasmFunctionNamesArray, | 910 js_object->SetInternalField(kWasmFunctionNamesArray, |
927 *function_name_table.ToHandleChecked()); | 911 *function_name_table.ToHandleChecked()); |
928 } | 912 } |
929 } | 913 } |
930 | 914 |
931 bool SetupGlobals(Isolate* isolate, MaybeHandle<JSObject> template_owner, | 915 bool SetupGlobals(Isolate* isolate, Handle<FixedArray> compiled_module, |
932 Handle<FixedArray> compiled_module, Handle<JSObject> instance, | 916 Handle<JSObject> instance, ErrorThrower* thrower) { |
933 ErrorThrower* thrower) { | |
934 uint32_t globals_size = static_cast<uint32_t>( | 917 uint32_t globals_size = static_cast<uint32_t>( |
935 Smi::cast(compiled_module->get(kGlobalsSize))->value()); | 918 Smi::cast(compiled_module->get(kGlobalsSize))->value()); |
936 if (globals_size > 0) { | 919 if (globals_size > 0) { |
937 Handle<JSArrayBuffer> globals_buffer = | 920 Handle<JSArrayBuffer> globals_buffer = |
938 NewArrayBuffer(isolate, globals_size); | 921 NewArrayBuffer(isolate, globals_size); |
939 if (globals_buffer.is_null()) { | 922 if (globals_buffer.is_null()) { |
940 thrower->Error("Out of memory: wasm globals"); | 923 thrower->Error("Out of memory: wasm globals"); |
941 return false; | 924 return false; |
942 } | 925 } |
943 Address old_address = | 926 RelocateGlobals(instance, |
944 template_owner.is_null() | |
945 ? nullptr | |
946 : GetGlobalStartAddressFromCodeTemplate( | |
947 *isolate->factory()->undefined_value(), | |
948 JSObject::cast(*template_owner.ToHandleChecked())); | |
949 RelocateGlobals(instance, old_address, | |
950 static_cast<Address>(globals_buffer->backing_store())); | 927 static_cast<Address>(globals_buffer->backing_store())); |
951 instance->SetInternalField(kWasmGlobalsArrayBuffer, *globals_buffer); | 928 instance->SetInternalField(kWasmGlobalsArrayBuffer, *globals_buffer); |
952 } | 929 } |
953 return true; | 930 return true; |
954 } | 931 } |
955 | 932 |
956 bool SetupInstanceHeap(Isolate* isolate, Handle<FixedArray> compiled_module, | 933 bool SetupInstanceHeap(Isolate* isolate, Handle<FixedArray> compiled_module, |
957 Handle<JSObject> instance, Handle<JSArrayBuffer> memory, | 934 Handle<JSObject> instance, Handle<JSArrayBuffer> memory, |
958 ErrorThrower* thrower) { | 935 ErrorThrower* thrower) { |
959 uint32_t min_mem_pages = static_cast<uint32_t>( | 936 uint32_t min_mem_pages = static_cast<uint32_t>( |
960 Smi::cast(compiled_module->get(kMinRequiredMemory))->value()); | 937 Smi::cast(compiled_module->get(kMinRequiredMemory))->value()); |
961 isolate->counters()->wasm_min_mem_pages_count()->AddSample(min_mem_pages); | 938 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. | 939 // TODO(wasm): re-enable counter for max_mem_pages when we use that field. |
963 | 940 |
964 if (memory.is_null() && min_mem_pages > 0) { | 941 if (memory.is_null() && min_mem_pages > 0) { |
965 memory = AllocateMemory(thrower, isolate, min_mem_pages); | 942 memory = AllocateMemory(thrower, isolate, min_mem_pages); |
966 if (memory.is_null()) { | 943 if (memory.is_null()) { |
967 return false; | 944 return false; |
968 } | 945 } |
969 } | 946 } |
970 | 947 |
971 if (!memory.is_null()) { | 948 if (!memory.is_null()) { |
972 instance->SetInternalField(kWasmMemArrayBuffer, *memory); | 949 instance->SetInternalField(kWasmMemArrayBuffer, *memory); |
973 Address mem_start = static_cast<Address>(memory->backing_store()); | 950 Address mem_start = static_cast<Address>(memory->backing_store()); |
974 uint32_t mem_size = static_cast<uint32_t>(memory->byte_length()->Number()); | 951 uint32_t mem_size = static_cast<uint32_t>(memory->byte_length()->Number()); |
975 uint32_t old_mem_size = static_cast<uint32_t>( | 952 RelocateInstanceCode(instance, mem_start, |
976 compiled_module->GetValueChecked<HeapNumber>(isolate, kMemSize) | 953 WasmModule::kPageSize * min_mem_pages, mem_size); |
977 ->value()); | |
978 MaybeHandle<JSArrayBuffer> old_mem = | |
979 compiled_module->GetValue<JSArrayBuffer>(isolate, kMemStart); | |
980 Address old_mem_start = | |
981 old_mem.is_null() | |
982 ? nullptr | |
983 : static_cast<Address>(old_mem.ToHandleChecked()->backing_store()); | |
984 RelocateInstanceCode(instance, old_mem_start, mem_start, old_mem_size, | |
985 mem_size); | |
986 LoadDataSegments(compiled_module, mem_start, mem_size); | 954 LoadDataSegments(compiled_module, mem_start, mem_size); |
987 compiled_module->GetValueChecked<HeapNumber>(isolate, kMemSize) | |
988 ->set_value(static_cast<double>(mem_size)); | |
989 compiled_module->set(kMemStart, *memory); | |
990 } | 955 } |
991 return true; | 956 return true; |
992 } | 957 } |
993 | 958 |
994 void FixupFunctionsAndImports(Handle<FixedArray> old_functions, | |
995 Handle<FixedArray> new_functions, | |
996 MaybeHandle<FixedArray> maybe_old_imports, | |
997 MaybeHandle<FixedArray> maybe_new_imports) { | |
998 DCHECK_EQ(new_functions->length(), old_functions->length()); | |
999 | |
1000 DisallowHeapAllocation no_gc; | |
1001 std::map<Code*, Code*> old_to_new_code; | |
1002 for (int i = 0; i < new_functions->length(); ++i) { | |
1003 old_to_new_code.insert(std::make_pair(Code::cast(old_functions->get(i)), | |
1004 Code::cast(new_functions->get(i)))); | |
1005 } | |
1006 DCHECK_EQ(maybe_old_imports.is_null(), maybe_new_imports.is_null()); | |
1007 if (!maybe_old_imports.is_null()) { | |
1008 Handle<FixedArray> old_imports = maybe_old_imports.ToHandleChecked(); | |
1009 Handle<FixedArray> new_imports = maybe_new_imports.ToHandleChecked(); | |
1010 DCHECK_EQ(new_imports->length(), old_imports->length()); | |
1011 for (int i = 0; i < new_imports->length(); ++i) { | |
1012 old_to_new_code.insert(std::make_pair(Code::cast(old_imports->get(i)), | |
1013 Code::cast(new_imports->get(i)))); | |
1014 } | |
1015 } | |
1016 int mode_mask = RelocInfo::ModeMask(RelocInfo::CODE_TARGET); | |
1017 AllowDeferredHandleDereference embedding_raw_address; | |
1018 for (int i = 0; i < new_functions->length(); ++i) { | |
1019 Code* wasm_function = Code::cast(new_functions->get(i)); | |
1020 for (RelocIterator it(wasm_function, mode_mask); !it.done(); it.next()) { | |
1021 Code* old_code = | |
1022 Code::GetCodeFromTargetAddress(it.rinfo()->target_address()); | |
1023 if (old_code->kind() == Code::WASM_TO_JS_FUNCTION || | |
1024 old_code->kind() == Code::WASM_FUNCTION) { | |
1025 auto found = old_to_new_code.find(old_code); | |
1026 DCHECK(found != old_to_new_code.end()); | |
1027 Code* new_code = found->second; | |
1028 // Avoid redundant updates, expected for wasm functions, if we're at the | |
1029 // first instance. | |
1030 if (new_code == old_code) { | |
1031 DCHECK(new_code->kind() == Code::WASM_FUNCTION); | |
1032 continue; | |
1033 } | |
1034 it.rinfo()->set_target_address(new_code->instruction_start(), | |
1035 UPDATE_WRITE_BARRIER, SKIP_ICACHE_FLUSH); | |
1036 } | |
1037 } | |
1038 } | |
1039 } | |
1040 | |
1041 bool SetupImports(Isolate* isolate, Handle<FixedArray> compiled_module, | 959 bool SetupImports(Isolate* isolate, Handle<FixedArray> compiled_module, |
1042 Handle<JSObject> instance, ErrorThrower* thrower, | 960 Handle<JSObject> instance, ErrorThrower* thrower, |
1043 Handle<JSReceiver> ffi) { | 961 Handle<JSReceiver> ffi) { |
1044 //------------------------------------------------------------------------- | 962 //------------------------------------------------------------------------- |
1045 // Compile wrappers to imported functions. | 963 // Compile wrappers to imported functions. |
1046 //------------------------------------------------------------------------- | 964 //------------------------------------------------------------------------- |
1047 std::vector<Handle<Code>> import_code; | 965 std::vector<Handle<Code>> import_code; |
1048 MaybeHandle<FixedArray> maybe_import_data = | 966 MaybeHandle<FixedArray> maybe_import_data = |
1049 compiled_module->GetValue<FixedArray>(isolate, kImportData); | 967 compiled_module->GetValue<FixedArray>(isolate, kImportData); |
1050 Handle<FixedArray> import_data; | 968 Handle<FixedArray> import_data; |
1051 if (maybe_import_data.ToHandle(&import_data)) { | 969 if (maybe_import_data.ToHandle(&import_data)) { |
1052 if (!CompileWrappersToImportedFunctions(isolate, ffi, import_code, | 970 if (!CompileWrappersToImportedFunctions(isolate, ffi, import_code, |
1053 import_data, thrower)) { | 971 import_data, thrower)) { |
1054 return false; | 972 return false; |
1055 } | 973 } |
1056 } | 974 } |
1057 | 975 |
1058 RecordStats(isolate, import_code); | 976 RecordStats(isolate, import_code); |
| 977 |
1059 if (import_code.empty()) return true; | 978 if (import_code.empty()) return true; |
1060 | 979 |
1061 Handle<FixedArray> new_imports = | 980 { |
| 981 DisallowHeapAllocation no_gc; |
| 982 std::map<Code*, int> import_to_index; |
| 983 Handle<FixedArray> mapping = |
| 984 compiled_module->GetValueChecked<FixedArray>(isolate, kImportMap); |
| 985 for (int i = 0; i < mapping->length(); ++i) { |
| 986 import_to_index.insert(std::make_pair(Code::cast(mapping->get(i)), i)); |
| 987 } |
| 988 |
| 989 Handle<FixedArray> code_table = Handle<FixedArray>( |
| 990 FixedArray::cast(instance->GetInternalField(kWasmModuleCodeTable))); |
| 991 |
| 992 int mode_mask = RelocInfo::ModeMask(RelocInfo::CODE_TARGET); |
| 993 AllowDeferredHandleDereference embedding_raw_address; |
| 994 for (int i = 0; i < code_table->length(); ++i) { |
| 995 Handle<Code> wasm_function = |
| 996 code_table->GetValueChecked<Code>(isolate, i); |
| 997 for (RelocIterator it(*wasm_function, mode_mask); !it.done(); it.next()) { |
| 998 Code* target = |
| 999 Code::GetCodeFromTargetAddress(it.rinfo()->target_address()); |
| 1000 if (target->kind() == Code::WASM_TO_JS_FUNCTION) { |
| 1001 auto found_index = import_to_index.find(target); |
| 1002 CHECK(found_index != import_to_index.end()); |
| 1003 int index = found_index->second; |
| 1004 CHECK(index < static_cast<int>(import_code.size())); |
| 1005 Handle<Code> new_target = import_code[index]; |
| 1006 it.rinfo()->set_target_address(new_target->instruction_start(), |
| 1007 UPDATE_WRITE_BARRIER, |
| 1008 SKIP_ICACHE_FLUSH); |
| 1009 } |
| 1010 } |
| 1011 } |
| 1012 } |
| 1013 Handle<FixedArray> new_mapping = |
1062 isolate->factory()->NewFixedArray(static_cast<int>(import_code.size())); | 1014 isolate->factory()->NewFixedArray(static_cast<int>(import_code.size())); |
1063 for (int i = 0; i < new_imports->length(); ++i) { | 1015 for (int i = 0; i < new_mapping->length(); ++i) { |
1064 new_imports->set(i, *import_code[i]); | 1016 new_mapping->set(i, *import_code[i]); |
1065 } | 1017 } |
1066 compiled_module->set(kImportMap, *new_imports); | 1018 compiled_module->set(kImportMap, *new_mapping); |
| 1019 |
1067 return true; | 1020 return true; |
1068 } | 1021 } |
1069 | 1022 |
1070 bool SetupExportsObject(Handle<FixedArray> compiled_module, Isolate* isolate, | 1023 bool SetupExportsObject(Handle<FixedArray> compiled_module, Isolate* isolate, |
1071 Handle<JSObject> instance, ErrorThrower* thrower) { | 1024 Handle<JSObject> instance, ErrorThrower* thrower) { |
1072 Factory* factory = isolate->factory(); | 1025 Factory* factory = isolate->factory(); |
1073 bool mem_export = | 1026 bool mem_export = |
1074 static_cast<bool>(Smi::cast(compiled_module->get(kExportMem))->value()); | 1027 static_cast<bool>(Smi::cast(compiled_module->get(kExportMem))->value()); |
1075 ModuleOrigin origin = static_cast<ModuleOrigin>( | 1028 ModuleOrigin origin = static_cast<ModuleOrigin>( |
1076 Smi::cast(compiled_module->get(kOrigin))->value()); | 1029 Smi::cast(compiled_module->get(kOrigin))->value()); |
(...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1121 // Export the memory as a named property. | 1074 // Export the memory as a named property. |
1122 Handle<String> name = factory->InternalizeUtf8String("memory"); | 1075 Handle<String> name = factory->InternalizeUtf8String("memory"); |
1123 Handle<JSArrayBuffer> memory = Handle<JSArrayBuffer>( | 1076 Handle<JSArrayBuffer> memory = Handle<JSArrayBuffer>( |
1124 JSArrayBuffer::cast(instance->GetInternalField(kWasmMemArrayBuffer))); | 1077 JSArrayBuffer::cast(instance->GetInternalField(kWasmMemArrayBuffer))); |
1125 JSObject::AddProperty(exports_object, name, memory, READ_ONLY); | 1078 JSObject::AddProperty(exports_object, name, memory, READ_ONLY); |
1126 } | 1079 } |
1127 } | 1080 } |
1128 return true; | 1081 return true; |
1129 } | 1082 } |
1130 | 1083 |
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, | |
1148 FixedArray* compiled_module) { | |
1149 Object* undefined = *isolate->factory()->undefined_value(); | |
1150 Object* mem_size_obj = compiled_module->get(kMemSize); | |
1151 DCHECK(mem_size_obj->IsMutableHeapNumber()); | |
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; | |
1156 Address globals_start = | |
1157 GetGlobalStartAddressFromCodeTemplate(undefined, owner); | |
1158 | |
1159 if (old_mem_size > 0) { | |
1160 CHECK_NE(mem_start, undefined); | |
1161 old_mem_address = | |
1162 static_cast<Address>(JSArrayBuffer::cast(mem_start)->backing_store()); | |
1163 } | |
1164 int mode_mask = RelocInfo::ModeMask(RelocInfo::WASM_MEMORY_REFERENCE) | | |
1165 RelocInfo::ModeMask(RelocInfo::WASM_MEMORY_SIZE_REFERENCE) | | |
1166 RelocInfo::ModeMask(RelocInfo::WASM_GLOBAL_REFERENCE); | |
1167 | |
1168 Object* fct_obj = compiled_module->get(kFunctions); | |
1169 if (fct_obj != nullptr && fct_obj != undefined && | |
1170 (old_mem_size > 0 || globals_start != nullptr)) { | |
1171 FixedArray* functions = FixedArray::cast(fct_obj); | |
1172 for (int i = 0; i < functions->length(); ++i) { | |
1173 Code* code = Code::cast(functions->get(i)); | |
1174 bool changed = false; | |
1175 for (RelocIterator it(code, mode_mask); !it.done(); it.next()) { | |
1176 RelocInfo::Mode mode = it.rinfo()->rmode(); | |
1177 if (RelocInfo::IsWasmMemoryReference(mode) || | |
1178 RelocInfo::IsWasmMemorySizeReference(mode)) { | |
1179 it.rinfo()->update_wasm_memory_reference(old_mem_address, nullptr, | |
1180 old_mem_size, old_mem_size); | |
1181 changed = true; | |
1182 } else { | |
1183 CHECK(RelocInfo::IsWasmGlobalReference(mode)); | |
1184 it.rinfo()->update_wasm_global_reference(globals_start, nullptr); | |
1185 changed = true; | |
1186 } | |
1187 } | |
1188 if (changed) { | |
1189 Assembler::FlushICache(isolate, code->instruction_start(), | |
1190 code->instruction_size()); | |
1191 } | |
1192 } | |
1193 } | |
1194 compiled_module->set(kOwningInstance, undefined); | |
1195 compiled_module->set(kMemStart, undefined); | |
1196 } | |
1197 | |
1198 static void InstanceFinalizer(const v8::WeakCallbackInfo<void>& data) { | |
1199 JSObject** p = reinterpret_cast<JSObject**>(data.GetParameter()); | |
1200 JSObject* owner = *p; | |
1201 FixedArray* compiled_module = | |
1202 FixedArray::cast(owner->GetInternalField(kWasmCompiledModule)); | |
1203 Isolate* isolate = reinterpret_cast<Isolate*>(data.GetIsolate()); | |
1204 Object* undefined = *isolate->factory()->undefined_value(); | |
1205 WeakCell* weak_module_obj = GetModuleObject(compiled_module); | |
1206 DCHECK_NOT_NULL(weak_module_obj); | |
1207 // 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, | |
1209 // and we don't need to maintain the links between instances. | |
1210 if (!weak_module_obj->cleared()) { | |
1211 JSObject* module_obj = JSObject::cast(weak_module_obj->value()); | |
1212 FixedArray* current_template = | |
1213 FixedArray::cast(module_obj->GetInternalField(0)); | |
1214 DCHECK_NULL(GetPrevInstance(current_template)); | |
1215 WeakCell* next = GetNextInstance(compiled_module); | |
1216 WeakCell* prev = GetPrevInstance(compiled_module); | |
1217 | |
1218 if (current_template == compiled_module) { | |
1219 if (next == nullptr) { | |
1220 ResetCompiledModule(isolate, owner, compiled_module); | |
1221 } else { | |
1222 DCHECK(next->value()->IsFixedArray()); | |
1223 module_obj->SetInternalField(0, next->value()); | |
1224 DCHECK_NULL(prev); | |
1225 FixedArray::cast(next->value())->set(kPrevInstance, undefined); | |
1226 } | |
1227 } else { | |
1228 DCHECK(!(prev == nullptr && next == nullptr)); | |
1229 // the only reason prev or next would be cleared is if the | |
1230 // respective objects got collected, but if that happened, | |
1231 // we would have relinked the list. | |
1232 if (prev != nullptr) { | |
1233 DCHECK(!prev->cleared()); | |
1234 FixedArray::cast(prev->value()) | |
1235 ->set(kNextInstance, next == nullptr ? undefined : next); | |
1236 } | |
1237 if (next != nullptr) { | |
1238 DCHECK(!next->cleared()); | |
1239 FixedArray::cast(next->value()) | |
1240 ->set(kPrevInstance, prev == nullptr ? undefined : prev); | |
1241 } | |
1242 } | |
1243 } | |
1244 GlobalHandles::Destroy(reinterpret_cast<Object**>(p)); | |
1245 } | |
1246 | |
1247 } // namespace | 1084 } // namespace |
1248 | 1085 |
1249 MaybeHandle<FixedArray> WasmModule::CompileFunctions( | 1086 MaybeHandle<FixedArray> WasmModule::CompileFunctions( |
1250 Isolate* isolate, ErrorThrower* thrower) const { | 1087 Isolate* isolate, ErrorThrower* thrower) const { |
1251 Factory* factory = isolate->factory(); | 1088 Factory* factory = isolate->factory(); |
1252 | 1089 |
1253 MaybeHandle<FixedArray> nothing; | 1090 MaybeHandle<FixedArray> nothing; |
1254 | 1091 |
1255 WasmModuleInstance temp_instance_for_compilation(this); | 1092 WasmModuleInstance temp_instance_for_compilation(this); |
1256 temp_instance_for_compilation.context = isolate->native_context(); | 1093 temp_instance_for_compilation.context = isolate->native_context(); |
(...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1312 } | 1149 } |
1313 if (thrower->error()) return nothing; | 1150 if (thrower->error()) return nothing; |
1314 | 1151 |
1315 // At this point, compilation has completed. Update the code table. | 1152 // At this point, compilation has completed. Update the code table. |
1316 for (size_t i = FLAG_skip_compiling_wasm_funcs; | 1153 for (size_t i = FLAG_skip_compiling_wasm_funcs; |
1317 i < temp_instance_for_compilation.function_code.size(); ++i) { | 1154 i < temp_instance_for_compilation.function_code.size(); ++i) { |
1318 Code* code = *temp_instance_for_compilation.function_code[i]; | 1155 Code* code = *temp_instance_for_compilation.function_code[i]; |
1319 compiled_functions->set(static_cast<int>(i), code); | 1156 compiled_functions->set(static_cast<int>(i), code); |
1320 } | 1157 } |
1321 | 1158 |
1322 LinkModuleFunctions(isolate, compiled_functions); | |
1323 | |
1324 // TODO(mtrofin): do we need to flush the cache here? | |
1325 FlushAssemblyCache(isolate, compiled_functions); | |
1326 | |
1327 // Create the compiled module object, and populate with compiled functions | 1159 // Create the compiled module object, and populate with compiled functions |
1328 // and information needed at instantiation time. This object needs to be | 1160 // and information needed at instantiation time. This object needs to be |
1329 // serializable. Instantiation may occur off a deserialized version of this | 1161 // serializable. Instantiation may occur off a deserialized version of this |
1330 // object. | 1162 // object. |
1331 Handle<FixedArray> ret = | 1163 Handle<FixedArray> ret = |
1332 factory->NewFixedArray(kCompiledWasmObjectTableSize, TENURED); | 1164 factory->NewFixedArray(kCompiledWasmObjectTableSize, TENURED); |
1333 ret->set(kFunctions, *compiled_functions); | 1165 ret->set(kFunctions, *compiled_functions); |
1334 if (!indirect_table.is_null()) { | 1166 if (!indirect_table.is_null()) { |
1335 ret->set(kTableOfIndirectFunctionTables, *indirect_table.ToHandleChecked()); | 1167 ret->set(kTableOfIndirectFunctionTables, *indirect_table.ToHandleChecked()); |
1336 } | 1168 } |
(...skipping 75 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1412 } | 1244 } |
1413 | 1245 |
1414 Handle<ByteArray> function_name_table = | 1246 Handle<ByteArray> function_name_table = |
1415 BuildFunctionNamesTable(isolate, module_env.module); | 1247 BuildFunctionNamesTable(isolate, module_env.module); |
1416 ret->set(kFunctionNameTable, *function_name_table); | 1248 ret->set(kFunctionNameTable, *function_name_table); |
1417 ret->set(kMinRequiredMemory, Smi::FromInt(min_mem_pages)); | 1249 ret->set(kMinRequiredMemory, Smi::FromInt(min_mem_pages)); |
1418 if (data_segments.size() > 0) SaveDataSegmentInfo(factory, this, ret); | 1250 if (data_segments.size() > 0) SaveDataSegmentInfo(factory, this, ret); |
1419 ret->set(kGlobalsSize, Smi::FromInt(globals_size)); | 1251 ret->set(kGlobalsSize, Smi::FromInt(globals_size)); |
1420 ret->set(kExportMem, Smi::FromInt(mem_export)); | 1252 ret->set(kExportMem, Smi::FromInt(mem_export)); |
1421 ret->set(kOrigin, Smi::FromInt(origin)); | 1253 ret->set(kOrigin, Smi::FromInt(origin)); |
1422 Handle<HeapNumber> size_as_object = factory->NewHeapNumber( | |
1423 static_cast<double>(temp_instance_for_compilation.mem_size), MUTABLE, | |
1424 TENURED); | |
1425 ret->set(kMemSize, *size_as_object); | |
1426 return ret; | 1254 return ret; |
1427 } | 1255 } |
1428 | 1256 |
1429 void PatchJSWrapper(Isolate* isolate, Handle<Code> wrapper, | 1257 void PatchJSWrapper(Isolate* isolate, Handle<Code> wrapper, |
1430 Handle<Code> new_target) { | 1258 Handle<Code> new_target) { |
1431 AllowDeferredHandleDereference embedding_raw_address; | 1259 AllowDeferredHandleDereference embedding_raw_address; |
1432 bool seen = false; | 1260 bool seen = false; |
1433 for (RelocIterator it(*wrapper, 1 << RelocInfo::CODE_TARGET); !it.done(); | 1261 for (RelocIterator it(*wrapper, 1 << RelocInfo::CODE_TARGET); !it.done(); |
1434 it.next()) { | 1262 it.next()) { |
1435 Code* target = Code::GetCodeFromTargetAddress(it.rinfo()->target_address()); | 1263 Code* target = Code::GetCodeFromTargetAddress(it.rinfo()->target_address()); |
1436 if (target->kind() == Code::WASM_FUNCTION) { | 1264 if (target->kind() == Code::WASM_FUNCTION) { |
1437 DCHECK(!seen); | 1265 DCHECK(!seen); |
1438 seen = true; | 1266 seen = true; |
1439 it.rinfo()->set_target_address(new_target->instruction_start(), | 1267 it.rinfo()->set_target_address(new_target->instruction_start(), |
1440 UPDATE_WRITE_BARRIER, SKIP_ICACHE_FLUSH); | 1268 UPDATE_WRITE_BARRIER, SKIP_ICACHE_FLUSH); |
1441 } | 1269 } |
1442 } | 1270 } |
1443 CHECK(seen); | 1271 CHECK(seen); |
1444 Assembler::FlushICache(isolate, wrapper->instruction_start(), | 1272 Assembler::FlushICache(isolate, wrapper->instruction_start(), |
1445 wrapper->instruction_size()); | 1273 wrapper->instruction_size()); |
1446 } | 1274 } |
1447 | 1275 |
1448 Handle<FixedArray> SetupIndirectFunctionTable( | 1276 Handle<FixedArray> SetupIndirectFunctionTable( |
1449 Isolate* isolate, Handle<FixedArray> wasm_functions, | 1277 Isolate* isolate, Handle<FixedArray> wasm_functions, |
1450 Handle<FixedArray> indirect_table_template, | 1278 Handle<FixedArray> indirect_table_template) { |
1451 Handle<FixedArray> tables_to_replace) { | |
1452 Factory* factory = isolate->factory(); | 1279 Factory* factory = isolate->factory(); |
1453 Handle<FixedArray> cloned_indirect_tables = | 1280 Handle<FixedArray> cloned_indirect_tables = |
1454 factory->CopyFixedArray(indirect_table_template); | 1281 factory->CopyFixedArray(indirect_table_template); |
1455 for (int i = 0; i < cloned_indirect_tables->length(); ++i) { | 1282 for (int i = 0; i < cloned_indirect_tables->length(); ++i) { |
1456 Handle<FixedArray> orig_metadata = | 1283 Handle<FixedArray> orig_metadata = |
1457 cloned_indirect_tables->GetValueChecked<FixedArray>(isolate, i); | 1284 cloned_indirect_tables->GetValueChecked<FixedArray>(isolate, i); |
1458 Handle<FixedArray> cloned_metadata = factory->CopyFixedArray(orig_metadata); | 1285 Handle<FixedArray> cloned_metadata = factory->CopyFixedArray(orig_metadata); |
1459 cloned_indirect_tables->set(i, *cloned_metadata); | 1286 cloned_indirect_tables->set(i, *cloned_metadata); |
1460 | 1287 |
1461 Handle<FixedArray> orig_table = | 1288 Handle<FixedArray> orig_table = |
1462 cloned_metadata->GetValueChecked<FixedArray>(isolate, kTable); | 1289 cloned_metadata->GetValueChecked<FixedArray>(isolate, kTable); |
1463 Handle<FixedArray> cloned_table = factory->CopyFixedArray(orig_table); | 1290 Handle<FixedArray> cloned_table = factory->CopyFixedArray(orig_table); |
1464 cloned_metadata->set(kTable, *cloned_table); | 1291 cloned_metadata->set(kTable, *cloned_table); |
1465 // Patch the cloned code to refer to the cloned kTable. | 1292 // Patch the cloned code to refer to the cloned kTable. |
1466 Handle<FixedArray> table_to_replace = | 1293 for (int i = 0; i < wasm_functions->length(); ++i) { |
1467 tables_to_replace->GetValueChecked<FixedArray>(isolate, i) | |
1468 ->GetValueChecked<FixedArray>(isolate, kTable); | |
1469 for (int fct_index = 0; fct_index < wasm_functions->length(); ++fct_index) { | |
1470 Handle<Code> wasm_function = | 1294 Handle<Code> wasm_function = |
1471 wasm_functions->GetValueChecked<Code>(isolate, fct_index); | 1295 wasm_functions->GetValueChecked<Code>(isolate, i); |
1472 PatchFunctionTable(wasm_function, table_to_replace, cloned_table); | 1296 PatchFunctionTable(wasm_function, orig_table, cloned_table); |
1473 } | 1297 } |
1474 } | 1298 } |
1475 return cloned_indirect_tables; | 1299 return cloned_indirect_tables; |
1476 } | 1300 } |
1477 | 1301 |
1478 Handle<FixedArray> CloneModuleForInstance(Isolate* isolate, | 1302 Handle<FixedArray> CloneModuleForInstance(Isolate* isolate, |
1479 Handle<FixedArray> original) { | 1303 Handle<FixedArray> original) { |
1480 Factory* factory = isolate->factory(); | 1304 Factory* factory = isolate->factory(); |
1481 bool is_first = | |
1482 original->GetValue<WeakCell>(isolate, kOwningInstance).is_null(); | |
1483 | |
1484 if (is_first) { | |
1485 return original; | |
1486 } | |
1487 | |
1488 // We insert the latest clone in front. | |
1489 Handle<FixedArray> clone = factory->CopyFixedArray(original); | 1305 Handle<FixedArray> clone = factory->CopyFixedArray(original); |
1490 Handle<WeakCell> weak_link_to_wasm_obj = | |
1491 original->GetValueChecked<WeakCell>(isolate, kModuleObject); | |
1492 | |
1493 clone->set(kModuleObject, *weak_link_to_wasm_obj); | |
1494 Handle<WeakCell> link_to_original = factory->NewWeakCell(original); | |
1495 clone->set(kNextInstance, *link_to_original); | |
1496 Handle<WeakCell> link_to_clone = factory->NewWeakCell(clone); | |
1497 original->set(kPrevInstance, *link_to_clone); | |
1498 JSObject::cast(weak_link_to_wasm_obj->value())->SetInternalField(0, *clone); | |
1499 | 1306 |
1500 // Clone each wasm code object. | 1307 // Clone each wasm code object. |
1501 Handle<FixedArray> orig_wasm_functions = | 1308 Handle<FixedArray> orig_wasm_functions = |
1502 original->GetValueChecked<FixedArray>(isolate, kFunctions); | 1309 original->GetValueChecked<FixedArray>(isolate, kFunctions); |
1503 Handle<FixedArray> clone_wasm_functions = | 1310 Handle<FixedArray> clone_wasm_functions = |
1504 factory->CopyFixedArray(orig_wasm_functions); | 1311 factory->CopyFixedArray(orig_wasm_functions); |
1505 clone->set(kFunctions, *clone_wasm_functions); | 1312 clone->set(kFunctions, *clone_wasm_functions); |
1506 for (int i = 0; i < clone_wasm_functions->length(); ++i) { | 1313 for (int i = 0; i < clone_wasm_functions->length(); ++i) { |
1507 Handle<Code> orig_code = | 1314 Handle<Code> orig_code = |
1508 clone_wasm_functions->GetValueChecked<Code>(isolate, i); | 1315 clone_wasm_functions->GetValueChecked<Code>(isolate, i); |
(...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1549 clone->set(kStartupFunction, *startup_metadata); | 1356 clone->set(kStartupFunction, *startup_metadata); |
1550 // TODO(wasm): see todo above about int vs size_t indexing in FixedArray. | 1357 // TODO(wasm): see todo above about int vs size_t indexing in FixedArray. |
1551 int startup_fct_index = | 1358 int startup_fct_index = |
1552 Smi::cast(startup_metadata->get(kExportedFunctionIndex))->value(); | 1359 Smi::cast(startup_metadata->get(kExportedFunctionIndex))->value(); |
1553 CHECK_GE(startup_fct_index, 0); | 1360 CHECK_GE(startup_fct_index, 0); |
1554 CHECK_LT(startup_fct_index, clone_wasm_functions->length()); | 1361 CHECK_LT(startup_fct_index, clone_wasm_functions->length()); |
1555 Handle<Code> new_target = | 1362 Handle<Code> new_target = |
1556 clone_wasm_functions->GetValueChecked<Code>(isolate, startup_fct_index); | 1363 clone_wasm_functions->GetValueChecked<Code>(isolate, startup_fct_index); |
1557 PatchJSWrapper(isolate, startup_fct_clone, new_target); | 1364 PatchJSWrapper(isolate, startup_fct_clone, new_target); |
1558 } | 1365 } |
1559 clone->set(kImportMap, *isolate->factory()->undefined_value()); | |
1560 return clone; | 1366 return clone; |
1561 } | 1367 } |
1562 | 1368 |
1563 // Instantiates a wasm module as a JSObject. | 1369 // Instantiates a wasm module as a JSObject. |
1564 // * allocates a backing store of {mem_size} bytes. | 1370 // * allocates a backing store of {mem_size} bytes. |
1565 // * installs a named property "memory" for that buffer if exported | 1371 // * installs a named property "memory" for that buffer if exported |
1566 // * installs named properties on the object for exported functions | 1372 // * installs named properties on the object for exported functions |
1567 // * compiles wasm code to machine code | 1373 // * compiles wasm code to machine code |
1568 MaybeHandle<JSObject> WasmModule::Instantiate( | 1374 MaybeHandle<JSObject> WasmModule::Instantiate( |
1569 Isolate* isolate, Handle<FixedArray> compiled_module_template, | 1375 Isolate* isolate, Handle<FixedArray> compiled_module, |
1570 Handle<JSReceiver> ffi, Handle<JSArrayBuffer> memory) { | 1376 Handle<JSReceiver> ffi, Handle<JSArrayBuffer> memory) { |
1571 HistogramTimerScope wasm_instantiate_module_time_scope( | 1377 HistogramTimerScope wasm_instantiate_module_time_scope( |
1572 isolate->counters()->wasm_instantiate_module_time()); | 1378 isolate->counters()->wasm_instantiate_module_time()); |
1573 ErrorThrower thrower(isolate, "WasmModule::Instantiate()"); | 1379 ErrorThrower thrower(isolate, "WasmModule::Instantiate()"); |
1574 Factory* factory = isolate->factory(); | 1380 Factory* factory = isolate->factory(); |
1575 | 1381 |
1576 Handle<FixedArray> compiled_module = | 1382 compiled_module = CloneModuleForInstance(isolate, compiled_module); |
1577 CloneModuleForInstance(isolate, compiled_module_template); | |
1578 | 1383 |
1579 bool template_is_owned = | |
1580 GetOwningInstance(*compiled_module_template) != nullptr; | |
1581 | |
1582 MaybeHandle<JSObject> template_owner; | |
1583 if (template_is_owned) { | |
1584 Handle<WeakCell> weak_owner = | |
1585 compiled_module_template->GetValueChecked<WeakCell>(isolate, | |
1586 kOwningInstance); | |
1587 template_owner = handle(JSObject::cast(weak_owner->value())); | |
1588 } | |
1589 // These fields are compulsory. | 1384 // These fields are compulsory. |
1590 Handle<FixedArray> code_table = | 1385 Handle<FixedArray> code_table = |
1591 compiled_module->GetValueChecked<FixedArray>(isolate, kFunctions); | 1386 compiled_module->GetValueChecked<FixedArray>(isolate, kFunctions); |
1592 | 1387 |
| 1388 std::vector<Handle<Code>> functions( |
| 1389 static_cast<size_t>(code_table->length())); |
| 1390 for (int i = 0; i < code_table->length(); ++i) { |
| 1391 functions[static_cast<size_t>(i)] = |
| 1392 code_table->GetValueChecked<Code>(isolate, i); |
| 1393 } |
| 1394 LinkModuleFunctions(isolate, functions); |
| 1395 |
1593 RecordStats(isolate, code_table); | 1396 RecordStats(isolate, code_table); |
1594 | 1397 |
1595 MaybeHandle<JSObject> nothing; | 1398 MaybeHandle<JSObject> nothing; |
1596 | 1399 |
1597 Handle<Map> map = factory->NewMap( | 1400 Handle<Map> map = factory->NewMap( |
1598 JS_OBJECT_TYPE, | 1401 JS_OBJECT_TYPE, |
1599 JSObject::kHeaderSize + kWasmModuleInternalFieldCount * kPointerSize); | 1402 JSObject::kHeaderSize + kWasmModuleInternalFieldCount * kPointerSize); |
1600 Handle<JSObject> js_object = factory->NewJSObjectFromMap(map, TENURED); | 1403 Handle<JSObject> js_object = factory->NewJSObjectFromMap(map, TENURED); |
1601 js_object->SetInternalField(kWasmModuleCodeTable, *code_table); | 1404 js_object->SetInternalField(kWasmModuleCodeTable, *code_table); |
1602 | 1405 |
1603 // Remember the old imports, for the case when we are at the first instance - | |
1604 // they will be replaced with the instance's actual imports in SetupImports. | |
1605 MaybeHandle<FixedArray> old_imports = | |
1606 compiled_module_template->GetValue<FixedArray>(isolate, kImportMap); | |
1607 if (!(SetupInstanceHeap(isolate, compiled_module, js_object, memory, | 1406 if (!(SetupInstanceHeap(isolate, compiled_module, js_object, memory, |
1608 &thrower) && | 1407 &thrower) && |
1609 SetupGlobals(isolate, template_owner, compiled_module, js_object, | 1408 SetupGlobals(isolate, compiled_module, js_object, &thrower) && |
1610 &thrower) && | |
1611 SetupImports(isolate, compiled_module, js_object, &thrower, ffi) && | 1409 SetupImports(isolate, compiled_module, js_object, &thrower, ffi) && |
1612 SetupExportsObject(compiled_module, isolate, js_object, &thrower))) { | 1410 SetupExportsObject(compiled_module, isolate, js_object, &thrower))) { |
1613 return nothing; | 1411 return nothing; |
1614 } | 1412 } |
1615 | 1413 |
1616 FixupFunctionsAndImports( | |
1617 compiled_module_template->GetValueChecked<FixedArray>(isolate, | |
1618 kFunctions), | |
1619 code_table, old_imports, | |
1620 compiled_module->GetValue<FixedArray>(isolate, kImportMap)); | |
1621 | |
1622 SetDebugSupport(factory, compiled_module, js_object); | 1414 SetDebugSupport(factory, compiled_module, js_object); |
1623 SetRuntimeSupport(isolate, js_object); | 1415 SetRuntimeSupport(isolate, js_object); |
1624 | 1416 |
1625 FlushAssemblyCache(isolate, code_table); | 1417 FlushAssemblyCache(isolate, code_table); |
1626 | 1418 |
1627 { | 1419 MaybeHandle<FixedArray> maybe_indirect_tables = |
1628 std::vector<Handle<Code>> functions( | 1420 compiled_module->GetValue<FixedArray>(isolate, |
1629 static_cast<size_t>(code_table->length())); | 1421 kTableOfIndirectFunctionTables); |
1630 for (int i = 0; i < code_table->length(); ++i) { | 1422 Handle<FixedArray> indirect_tables_template; |
1631 functions[static_cast<size_t>(i)] = | 1423 if (maybe_indirect_tables.ToHandle(&indirect_tables_template)) { |
1632 code_table->GetValueChecked<Code>(isolate, i); | 1424 Handle<FixedArray> indirect_tables = SetupIndirectFunctionTable( |
| 1425 isolate, code_table, indirect_tables_template); |
| 1426 for (int i = 0; i < indirect_tables->length(); ++i) { |
| 1427 Handle<FixedArray> metadata = |
| 1428 indirect_tables->GetValueChecked<FixedArray>(isolate, i); |
| 1429 uint32_t size = Smi::cast(metadata->get(kSize))->value(); |
| 1430 Handle<FixedArray> table = |
| 1431 metadata->GetValueChecked<FixedArray>(isolate, kTable); |
| 1432 wasm::PopulateFunctionTable(table, size, &functions); |
1633 } | 1433 } |
1634 | 1434 js_object->SetInternalField(kWasmModuleFunctionTable, *indirect_tables); |
1635 MaybeHandle<FixedArray> maybe_indirect_tables = | |
1636 compiled_module->GetValue<FixedArray>(isolate, | |
1637 kTableOfIndirectFunctionTables); | |
1638 Handle<FixedArray> indirect_tables_template; | |
1639 if (maybe_indirect_tables.ToHandle(&indirect_tables_template)) { | |
1640 Handle<FixedArray> to_replace = | |
1641 template_owner.is_null() | |
1642 ? indirect_tables_template | |
1643 : handle(FixedArray::cast( | |
1644 template_owner.ToHandleChecked()->GetInternalField( | |
1645 kWasmModuleFunctionTable))); | |
1646 Handle<FixedArray> indirect_tables = SetupIndirectFunctionTable( | |
1647 isolate, code_table, indirect_tables_template, to_replace); | |
1648 for (int i = 0; i < indirect_tables->length(); ++i) { | |
1649 Handle<FixedArray> metadata = | |
1650 indirect_tables->GetValueChecked<FixedArray>(isolate, i); | |
1651 uint32_t size = Smi::cast(metadata->get(kSize))->value(); | |
1652 Handle<FixedArray> table = | |
1653 metadata->GetValueChecked<FixedArray>(isolate, kTable); | |
1654 wasm::PopulateFunctionTable(table, size, &functions); | |
1655 } | |
1656 js_object->SetInternalField(kWasmModuleFunctionTable, *indirect_tables); | |
1657 } | |
1658 } | 1435 } |
1659 | 1436 |
1660 // Run the start function if one was specified. | 1437 // Run the start function if one was specified. |
1661 MaybeHandle<FixedArray> maybe_startup_fct = | 1438 MaybeHandle<FixedArray> maybe_startup_fct = |
1662 compiled_module->GetValue<FixedArray>(isolate, kStartupFunction); | 1439 compiled_module->GetValue<FixedArray>(isolate, kStartupFunction); |
1663 Handle<FixedArray> metadata; | 1440 Handle<FixedArray> metadata; |
1664 if (maybe_startup_fct.ToHandle(&metadata)) { | 1441 if (maybe_startup_fct.ToHandle(&metadata)) { |
1665 HandleScope scope(isolate); | 1442 HandleScope scope(isolate); |
1666 Handle<Code> startup_code = | 1443 Handle<Code> startup_code = |
1667 metadata->GetValueChecked<Code>(isolate, kExportCode); | 1444 metadata->GetValueChecked<Code>(isolate, kExportCode); |
1668 int arity = Smi::cast(metadata->get(kExportArity))->value(); | 1445 int arity = Smi::cast(metadata->get(kExportArity))->value(); |
1669 MaybeHandle<ByteArray> startup_signature = | 1446 MaybeHandle<ByteArray> startup_signature = |
1670 metadata->GetValue<ByteArray>(isolate, kExportedSignature); | 1447 metadata->GetValue<ByteArray>(isolate, kExportedSignature); |
1671 Handle<JSFunction> startup_fct = WrapExportCodeAsJSFunction( | 1448 Handle<JSFunction> startup_fct = WrapExportCodeAsJSFunction( |
1672 isolate, startup_code, factory->InternalizeUtf8String("start"), arity, | 1449 isolate, startup_code, factory->InternalizeUtf8String("start"), arity, |
1673 startup_signature, js_object); | 1450 startup_signature, js_object); |
1674 RecordStats(isolate, *startup_code); | 1451 RecordStats(isolate, *startup_code); |
1675 // Call the JS function. | 1452 // Call the JS function. |
1676 Handle<Object> undefined = isolate->factory()->undefined_value(); | 1453 Handle<Object> undefined = isolate->factory()->undefined_value(); |
1677 MaybeHandle<Object> retval = | 1454 MaybeHandle<Object> retval = |
1678 Execution::Call(isolate, startup_fct, undefined, 0, nullptr); | 1455 Execution::Call(isolate, startup_fct, undefined, 0, nullptr); |
1679 | 1456 |
1680 if (retval.is_null()) { | 1457 if (retval.is_null()) { |
1681 thrower.Error("WASM.instantiateModule(): start function failed"); | 1458 thrower.Error("WASM.instantiateModule(): start function failed"); |
1682 return nothing; | 1459 return nothing; |
1683 } | 1460 } |
1684 } | 1461 } |
1685 | 1462 |
1686 DCHECK(wasm::IsWasmObject(*js_object)); | 1463 DCHECK(wasm::IsWasmObject(*js_object)); |
1687 | |
1688 if (!compiled_module->GetValue<WeakCell>(isolate, kModuleObject).is_null()) { | |
1689 js_object->SetInternalField(kWasmCompiledModule, *compiled_module); | |
1690 Handle<WeakCell> link_to_owner = factory->NewWeakCell(js_object); | |
1691 compiled_module->set(kOwningInstance, *link_to_owner); | |
1692 | |
1693 Handle<Object> global_handle = | |
1694 isolate->global_handles()->Create(*js_object); | |
1695 GlobalHandles::MakeWeak(global_handle.location(), global_handle.location(), | |
1696 &InstanceFinalizer, | |
1697 v8::WeakCallbackType::kFinalizer); | |
1698 } | |
1699 | |
1700 return js_object; | 1464 return js_object; |
1701 } | 1465 } |
1702 | 1466 |
1703 // TODO(mtrofin): remove this once we move to WASM_DIRECT_CALL | 1467 // TODO(mtrofin): remove this once we move to WASM_DIRECT_CALL |
1704 Handle<Code> ModuleEnv::GetCodeOrPlaceholder(uint32_t index) const { | 1468 Handle<Code> ModuleEnv::GetCodeOrPlaceholder(uint32_t index) const { |
1705 DCHECK(IsValidFunction(index)); | 1469 DCHECK(IsValidFunction(index)); |
1706 if (!placeholders.empty()) return placeholders[index]; | 1470 if (!placeholders.empty()) return placeholders[index]; |
1707 DCHECK_NOT_NULL(instance); | 1471 DCHECK_NOT_NULL(instance); |
1708 return instance->function_code[index]; | 1472 return instance->function_code[index]; |
1709 } | 1473 } |
(...skipping 167 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1877 DCHECK(origin == ModuleOrigin::kAsmJsOrigin); | 1641 DCHECK(origin == ModuleOrigin::kAsmJsOrigin); |
1878 Handle<Map> map = isolate->factory()->NewMap( | 1642 Handle<Map> map = isolate->factory()->NewMap( |
1879 JS_OBJECT_TYPE, JSObject::kHeaderSize + kPointerSize); | 1643 JS_OBJECT_TYPE, JSObject::kHeaderSize + kPointerSize); |
1880 module_obj = isolate->factory()->NewJSObjectFromMap(map, TENURED); | 1644 module_obj = isolate->factory()->NewJSObjectFromMap(map, TENURED); |
1881 } | 1645 } |
1882 module_obj->SetInternalField(0, *compiled_module); | 1646 module_obj->SetInternalField(0, *compiled_module); |
1883 if (origin == ModuleOrigin::kWasmOrigin) { | 1647 if (origin == ModuleOrigin::kWasmOrigin) { |
1884 Handle<Symbol> module_sym(isolate->native_context()->wasm_module_sym()); | 1648 Handle<Symbol> module_sym(isolate->native_context()->wasm_module_sym()); |
1885 Object::SetProperty(module_obj, module_sym, module_obj, STRICT).Check(); | 1649 Object::SetProperty(module_obj, module_sym, module_obj, STRICT).Check(); |
1886 } | 1650 } |
1887 Handle<WeakCell> link_to_module = isolate->factory()->NewWeakCell(module_obj); | |
1888 compiled_module->set(kModuleObject, *link_to_module); | |
1889 return module_obj; | 1651 return module_obj; |
1890 } | 1652 } |
1891 | 1653 |
1892 MaybeHandle<JSObject> CreateModuleObjectFromBytes(Isolate* isolate, | 1654 MaybeHandle<JSObject> CreateModuleObjectFromBytes(Isolate* isolate, |
1893 const byte* start, | 1655 const byte* start, |
1894 const byte* end, | 1656 const byte* end, |
1895 ErrorThrower* thrower, | 1657 ErrorThrower* thrower, |
1896 ModuleOrigin origin) { | 1658 ModuleOrigin origin) { |
1897 MaybeHandle<JSObject> nothing; | 1659 MaybeHandle<JSObject> nothing; |
1898 Zone zone(isolate->allocator()); | 1660 Zone zone(isolate->allocator()); |
1899 ModuleResult result = | 1661 ModuleResult result = |
1900 DecodeWasmModule(isolate, &zone, start, end, false, origin); | 1662 DecodeWasmModule(isolate, &zone, start, end, false, origin); |
1901 std::unique_ptr<const WasmModule> decoded_module(result.val); | 1663 std::unique_ptr<const WasmModule> decoded_module(result.val); |
1902 if (result.failed()) { | 1664 if (result.failed()) { |
1903 thrower->Failed("Wasm decoding failed", result); | 1665 thrower->Failed("Wasm decoding failed", result); |
1904 return nothing; | 1666 return nothing; |
1905 } | 1667 } |
1906 MaybeHandle<FixedArray> compiled_module = | 1668 MaybeHandle<FixedArray> compiled_module = |
1907 decoded_module->CompileFunctions(isolate, thrower); | 1669 decoded_module->CompileFunctions(isolate, thrower); |
1908 if (compiled_module.is_null()) return nothing; | 1670 if (compiled_module.is_null()) return nothing; |
1909 | 1671 |
1910 return CreateCompiledModuleObject(isolate, compiled_module.ToHandleChecked(), | 1672 return CreateCompiledModuleObject(isolate, compiled_module.ToHandleChecked(), |
1911 origin); | 1673 origin); |
1912 } | 1674 } |
1913 | 1675 |
1914 MaybeHandle<JSArrayBuffer> GetInstanceMemory(Isolate* isolate, | |
1915 Handle<JSObject> instance) { | |
1916 Object* mem = instance->GetInternalField(kWasmMemArrayBuffer); | |
1917 DCHECK(IsWasmObject(*instance)); | |
1918 if (mem->IsUndefined(isolate)) return MaybeHandle<JSArrayBuffer>(); | |
1919 return Handle<JSArrayBuffer>(JSArrayBuffer::cast(mem)); | |
1920 } | |
1921 | |
1922 void SetInstanceMemory(Handle<JSObject> instance, JSArrayBuffer* buffer) { | |
1923 DisallowHeapAllocation no_gc; | |
1924 DCHECK(IsWasmObject(*instance)); | |
1925 instance->SetInternalField(kWasmMemArrayBuffer, buffer); | |
1926 Object* module = instance->GetInternalField(kWasmCompiledModule); | |
1927 if (module->IsFixedArray()) { | |
1928 HeapNumber::cast(FixedArray::cast(module)->get(kMemSize)) | |
1929 ->set_value(buffer->byte_length()->Number()); | |
1930 } | |
1931 } | |
1932 | |
1933 namespace testing { | 1676 namespace testing { |
1934 | 1677 |
1935 int32_t CompileAndRunWasmModule(Isolate* isolate, const byte* module_start, | 1678 int32_t CompileAndRunWasmModule(Isolate* isolate, const byte* module_start, |
1936 const byte* module_end, bool asm_js) { | 1679 const byte* module_end, bool asm_js) { |
1937 HandleScope scope(isolate); | 1680 HandleScope scope(isolate); |
1938 Zone zone(isolate->allocator()); | 1681 Zone zone(isolate->allocator()); |
1939 ErrorThrower thrower(isolate, "CompileAndRunWasmModule"); | 1682 ErrorThrower thrower(isolate, "CompileAndRunWasmModule"); |
1940 | 1683 |
1941 // Decode the module, but don't verify function bodies, since we'll | 1684 // Decode the module, but don't verify function bodies, since we'll |
1942 // be compiling them anyway. | 1685 // be compiling them anyway. |
(...skipping 64 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2007 if (result->IsSmi()) { | 1750 if (result->IsSmi()) { |
2008 return Smi::cast(*result)->value(); | 1751 return Smi::cast(*result)->value(); |
2009 } | 1752 } |
2010 if (result->IsHeapNumber()) { | 1753 if (result->IsHeapNumber()) { |
2011 return static_cast<int32_t>(HeapNumber::cast(*result)->value()); | 1754 return static_cast<int32_t>(HeapNumber::cast(*result)->value()); |
2012 } | 1755 } |
2013 thrower->Error("WASM.compileRun() failed: Return value should be number"); | 1756 thrower->Error("WASM.compileRun() failed: Return value should be number"); |
2014 return -1; | 1757 return -1; |
2015 } | 1758 } |
2016 | 1759 |
2017 void ValidateInstancesChain(Isolate* isolate, Handle<JSObject> module_obj, | |
2018 int instance_count) { | |
2019 CHECK_GE(instance_count, 0); | |
2020 DisallowHeapAllocation no_gc; | |
2021 FixedArray* compiled_module = | |
2022 FixedArray::cast(module_obj->GetInternalField(0)); | |
2023 CHECK_EQ(JSObject::cast(GetModuleObject(compiled_module)->value()), | |
2024 *module_obj); | |
2025 Object* prev = nullptr; | |
2026 int found_instances = GetOwningInstance(compiled_module) == nullptr ? 0 : 1; | |
2027 FixedArray* current_instance = compiled_module; | |
2028 while (GetNextInstance(current_instance) != nullptr) { | |
2029 CHECK((prev == nullptr && GetPrevInstance(current_instance) == nullptr) || | |
2030 GetPrevInstance(current_instance)->value() == prev); | |
2031 CHECK_EQ(GetModuleObject(current_instance)->value(), *module_obj); | |
2032 CHECK(IsWasmObject(GetOwningInstance(current_instance)->value())); | |
2033 prev = current_instance; | |
2034 current_instance = | |
2035 FixedArray::cast(GetNextInstance(current_instance)->value()); | |
2036 ++found_instances; | |
2037 CHECK_LE(found_instances, instance_count); | |
2038 } | |
2039 CHECK_EQ(found_instances, instance_count); | |
2040 } | |
2041 | |
2042 void ValidateModuleState(Isolate* isolate, Handle<JSObject> module_obj) { | |
2043 DisallowHeapAllocation no_gc; | |
2044 FixedArray* compiled_module = | |
2045 FixedArray::cast(module_obj->GetInternalField(0)); | |
2046 CHECK_NOT_NULL(GetModuleObject(compiled_module)); | |
2047 CHECK_EQ(GetModuleObject(compiled_module)->value(), *module_obj); | |
2048 CHECK_NULL(GetPrevInstance(compiled_module)); | |
2049 CHECK_NULL(GetNextInstance(compiled_module)); | |
2050 CHECK_NULL(GetOwningInstance(compiled_module)); | |
2051 } | |
2052 | |
2053 void ValidateOrphanedInstance(Isolate* isolate, Handle<JSObject> instance) { | |
2054 DisallowHeapAllocation no_gc; | |
2055 CHECK(IsWasmObject(*instance)); | |
2056 FixedArray* compiled_module = | |
2057 FixedArray::cast(instance->GetInternalField(kWasmCompiledModule)); | |
2058 CHECK_NOT_NULL(GetModuleObject(compiled_module)); | |
2059 CHECK(GetModuleObject(compiled_module)->cleared()); | |
2060 } | |
2061 | |
2062 } // namespace testing | 1760 } // namespace testing |
2063 } // namespace wasm | 1761 } // namespace wasm |
2064 } // namespace internal | 1762 } // namespace internal |
2065 } // namespace v8 | 1763 } // namespace v8 |
OLD | NEW |