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 const int kWasmModuleFunctionTable = 0; | 161 enum WasmInstanceFields { |
162 const int kWasmModuleCodeTable = 1; | 162 kWasmCompiledModule = 0, |
163 const int kWasmMemArrayBuffer = 2; | 163 kWasmModuleFunctionTable, |
164 const int kWasmGlobalsArrayBuffer = 3; | 164 kWasmModuleCodeTable, |
165 // TODO(clemensh): Remove function name array, extract names from module bytes. | 165 kWasmMemArrayBuffer, |
166 const int kWasmFunctionNamesArray = 4; | 166 kWasmGlobalsArrayBuffer, |
167 const int kWasmModuleBytesString = 5; | 167 // TODO(clemensh): Remove function name array, extract names from module |
168 const int kWasmDebugInfo = 6; | 168 // bytes. |
169 const int kWasmModuleInternalFieldCount = 7; | 169 kWasmFunctionNamesArray, |
| 170 kWasmModuleBytesString, |
| 171 kWasmDebugInfo, |
| 172 kWasmModuleInternalFieldCount |
| 173 }; |
170 | 174 |
171 // 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. |
172 // 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. |
173 // The elements typed as "maybe" are optional. The others are mandatory. Since | 177 // The elements typed as "maybe" are optional. The others are mandatory. Since |
174 // the compiled module is either obtained from the current v8 instance, or from | 178 // the compiled module is either obtained from the current v8 instance, or from |
175 // a snapshot produced by a compatible (==identical) v8 instance, we simply | 179 // a snapshot produced by a compatible (==identical) v8 instance, we simply |
176 // fail at instantiation time, in the face of invalid data. | 180 // fail at instantiation time, in the face of invalid data. |
177 enum CompiledWasmObjectFields { | 181 enum CompiledWasmObjectFields { |
178 kFunctions, // FixedArray of Code | 182 kFunctions, // FixedArray of Code |
179 kImportData, // maybe FixedArray of FixedArray respecting the | 183 kImportData, // maybe FixedArray of FixedArray respecting the |
180 // WasmImportMetadata structure. | 184 // WasmImportMetadata structure. |
181 kImportMap, // FixedArray. The i-th element is the Code object used for | 185 kImportMap, // FixedArray. The i-th element is the Code object used for |
182 // import i | 186 // import i |
183 kExports, // maybe FixedArray of FixedArray of WasmExportMetadata | 187 kExports, // maybe FixedArray of FixedArray of WasmExportMetadata |
184 // structure | 188 // structure |
185 kStartupFunction, // maybe FixedArray of WasmExportMetadata structure | 189 kStartupFunction, // maybe FixedArray of WasmExportMetadata structure |
186 kTableOfIndirectFunctionTables, // maybe FixedArray of FixedArray of | 190 kTableOfIndirectFunctionTables, // maybe FixedArray of FixedArray of |
187 // WasmIndirectFunctionTableMetadata | 191 // WasmIndirectFunctionTableMetadata |
188 kModuleBytes, // maybe String | 192 kModuleBytes, // maybe String |
189 kFunctionNameTable, // maybe ByteArray | 193 kFunctionNameTable, // maybe ByteArray |
190 kMinRequiredMemory, // Smi. an uint32_t | 194 kMinRequiredMemory, // Smi. an uint32_t |
191 // The following 2 are either together present or absent: | 195 // The following 2 are either together present or absent: |
192 kDataSegmentsInfo, // maybe FixedArray of FixedArray respecting the | 196 kDataSegmentsInfo, // maybe FixedArray of FixedArray respecting the |
193 // WasmSegmentInfo structure | 197 // WasmSegmentInfo structure |
194 kDataSegments, // maybe ByteArray. | 198 kDataSegments, // maybe ByteArray. |
195 | 199 |
196 kGlobalsSize, // Smi. an uint32_t | 200 kGlobalsSize, // Smi. an uint32_t |
| 201 kMemSize, // Smi.an uint32_t |
| 202 kMemStart, // MaybeHandle<ArrayBuffer> |
197 kExportMem, // Smi. bool | 203 kExportMem, // Smi. bool |
198 kOrigin, // Smi. ModuleOrigin | 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. |
199 kCompiledWasmObjectTableSize // Sentinel value. | 209 kCompiledWasmObjectTableSize // Sentinel value. |
200 }; | 210 }; |
201 | 211 |
202 enum WasmImportMetadata { | 212 enum WasmImportMetadata { |
203 kModuleName, // String | 213 kModuleName, // String |
204 kFunctionName, // maybe String | 214 kFunctionName, // maybe String |
205 kOutputCount, // Smi. an uint32_t | 215 kOutputCount, // Smi. an uint32_t |
206 kSignature, // ByteArray. A copy of the data in FunctionSig | 216 kSignature, // ByteArray. A copy of the data in FunctionSig |
207 kWasmImportDataTableSize // Sentinel value. | 217 kWasmImportDataTableSize // Sentinel value. |
208 }; | 218 }; |
(...skipping 113 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
322 DCHECK_EQ(0, bytes[i]); | 332 DCHECK_EQ(0, bytes[i]); |
323 } | 333 } |
324 #endif | 334 #endif |
325 | 335 |
326 Handle<JSArrayBuffer> buffer = isolate->factory()->NewJSArrayBuffer(); | 336 Handle<JSArrayBuffer> buffer = isolate->factory()->NewJSArrayBuffer(); |
327 JSArrayBuffer::Setup(buffer, isolate, false, memory, static_cast<int>(size)); | 337 JSArrayBuffer::Setup(buffer, isolate, false, memory, static_cast<int>(size)); |
328 buffer->set_is_neuterable(false); | 338 buffer->set_is_neuterable(false); |
329 return buffer; | 339 return buffer; |
330 } | 340 } |
331 | 341 |
332 void RelocateInstanceCode(Handle<JSObject> instance, Address start, | 342 void RelocateInstanceCode(Handle<JSObject> instance, Address old_start, |
333 uint32_t prev_size, uint32_t new_size) { | 343 Address start, uint32_t prev_size, |
| 344 uint32_t new_size) { |
334 Handle<FixedArray> functions = Handle<FixedArray>( | 345 Handle<FixedArray> functions = Handle<FixedArray>( |
335 FixedArray::cast(instance->GetInternalField(kWasmModuleCodeTable))); | 346 FixedArray::cast(instance->GetInternalField(kWasmModuleCodeTable))); |
336 for (int i = 0; i < functions->length(); ++i) { | 347 for (int i = 0; i < functions->length(); ++i) { |
337 Handle<Code> function = Handle<Code>(Code::cast(functions->get(i))); | 348 Handle<Code> function = Handle<Code>(Code::cast(functions->get(i))); |
338 AllowDeferredHandleDereference embedding_raw_address; | 349 AllowDeferredHandleDereference embedding_raw_address; |
339 int mask = (1 << RelocInfo::WASM_MEMORY_REFERENCE) | | 350 int mask = (1 << RelocInfo::WASM_MEMORY_REFERENCE) | |
340 (1 << RelocInfo::WASM_MEMORY_SIZE_REFERENCE); | 351 (1 << RelocInfo::WASM_MEMORY_SIZE_REFERENCE); |
341 for (RelocIterator it(*function, mask); !it.done(); it.next()) { | 352 for (RelocIterator it(*function, mask); !it.done(); it.next()) { |
342 it.rinfo()->update_wasm_memory_reference(nullptr, start, prev_size, | 353 it.rinfo()->update_wasm_memory_reference(old_start, start, prev_size, |
343 new_size); | 354 new_size); |
344 } | 355 } |
345 } | 356 } |
346 } | 357 } |
347 | 358 |
348 // Allocate memory for a module instance as a new JSArrayBuffer. | 359 // Allocate memory for a module instance as a new JSArrayBuffer. |
349 Handle<JSArrayBuffer> AllocateMemory(ErrorThrower* thrower, Isolate* isolate, | 360 Handle<JSArrayBuffer> AllocateMemory(ErrorThrower* thrower, Isolate* isolate, |
350 uint32_t min_mem_pages) { | 361 uint32_t min_mem_pages) { |
351 if (min_mem_pages > WasmModule::kMaxMemPages) { | 362 if (min_mem_pages > WasmModule::kMaxMemPages) { |
352 thrower->Error("Out of memory: wasm memory too large"); | 363 thrower->Error("Out of memory: wasm memory too large"); |
353 return Handle<JSArrayBuffer>::null(); | 364 return Handle<JSArrayBuffer>::null(); |
354 } | 365 } |
355 Handle<JSArrayBuffer> mem_buffer = | 366 Handle<JSArrayBuffer> mem_buffer = |
356 NewArrayBuffer(isolate, min_mem_pages * WasmModule::kPageSize); | 367 NewArrayBuffer(isolate, min_mem_pages * WasmModule::kPageSize); |
357 | 368 |
358 if (mem_buffer.is_null()) { | 369 if (mem_buffer.is_null()) { |
359 thrower->Error("Out of memory: wasm memory"); | 370 thrower->Error("Out of memory: wasm memory"); |
360 } | 371 } |
361 return mem_buffer; | 372 return mem_buffer; |
362 } | 373 } |
363 | 374 |
364 void RelocateGlobals(Handle<JSObject> instance, Address globals_start) { | 375 void RelocateGlobals(Handle<JSObject> instance, Address old_start, |
| 376 Address globals_start) { |
365 Handle<FixedArray> functions = Handle<FixedArray>( | 377 Handle<FixedArray> functions = Handle<FixedArray>( |
366 FixedArray::cast(instance->GetInternalField(kWasmModuleCodeTable))); | 378 FixedArray::cast(instance->GetInternalField(kWasmModuleCodeTable))); |
367 uint32_t function_count = static_cast<uint32_t>(functions->length()); | 379 uint32_t function_count = static_cast<uint32_t>(functions->length()); |
368 for (uint32_t i = 0; i < function_count; ++i) { | 380 for (uint32_t i = 0; i < function_count; ++i) { |
369 Handle<Code> function = Handle<Code>(Code::cast(functions->get(i))); | 381 Handle<Code> function = Handle<Code>(Code::cast(functions->get(i))); |
370 AllowDeferredHandleDereference embedding_raw_address; | 382 AllowDeferredHandleDereference embedding_raw_address; |
371 int mask = 1 << RelocInfo::WASM_GLOBAL_REFERENCE; | 383 int mask = 1 << RelocInfo::WASM_GLOBAL_REFERENCE; |
372 for (RelocIterator it(*function, mask); !it.done(); it.next()) { | 384 for (RelocIterator it(*function, mask); !it.done(); it.next()) { |
373 it.rinfo()->update_wasm_global_reference(nullptr, globals_start); | 385 it.rinfo()->update_wasm_global_reference(old_start, globals_start); |
374 } | 386 } |
375 } | 387 } |
376 } | 388 } |
377 | 389 |
378 Handle<Code> CreatePlaceholder(Factory* factory, uint32_t index, | 390 Handle<Code> CreatePlaceholder(Factory* factory, uint32_t index, |
379 Code::Kind kind) { | 391 Code::Kind kind) { |
380 // Create a placeholder code object and encode the corresponding index in | 392 // Create a placeholder code object and encode the corresponding index in |
381 // the {constant_pool_offset} field of the code object. | 393 // the {constant_pool_offset} field of the code object. |
382 // TODO(titzer): placeholder code objects are somewhat dangerous. | 394 // TODO(titzer): placeholder code objects are somewhat dangerous. |
383 static byte buffer[] = {0, 0, 0, 0, 0, 0, 0, 0}; // fake instructions. | 395 static byte buffer[] = {0, 0, 0, 0, 0, 0, 0, 0}; // fake instructions. |
(...skipping 10 matching lines...) Expand all Loading... |
394 std::vector<Handle<Code>>* placeholders, | 406 std::vector<Handle<Code>>* placeholders, |
395 size_t size) { | 407 size_t size) { |
396 DCHECK(placeholders->empty()); | 408 DCHECK(placeholders->empty()); |
397 placeholders->reserve(size); | 409 placeholders->reserve(size); |
398 | 410 |
399 for (uint32_t i = 0; i < size; ++i) { | 411 for (uint32_t i = 0; i < size; ++i) { |
400 placeholders->push_back(CreatePlaceholder(factory, i, Code::WASM_FUNCTION)); | 412 placeholders->push_back(CreatePlaceholder(factory, i, Code::WASM_FUNCTION)); |
401 } | 413 } |
402 } | 414 } |
403 | 415 |
404 bool LinkFunction(Handle<Code> unlinked, | 416 bool LinkFunction(Isolate* isolate, Handle<Code> unlinked, |
405 const std::vector<Handle<Code>>& code_targets, | 417 Handle<FixedArray> code_targets, |
406 Code::Kind kind) { | 418 Code::Kind kind = Code::WASM_FUNCTION) { |
407 bool modified = false; | 419 bool modified = false; |
408 int mode_mask = RelocInfo::kCodeTargetMask; | 420 int mode_mask = RelocInfo::ModeMask(RelocInfo::CODE_TARGET); |
409 AllowDeferredHandleDereference embedding_raw_address; | 421 AllowDeferredHandleDereference embedding_raw_address; |
410 for (RelocIterator it(*unlinked, mode_mask); !it.done(); it.next()) { | 422 for (RelocIterator it(*unlinked, mode_mask); !it.done(); it.next()) { |
411 RelocInfo::Mode mode = it.rinfo()->rmode(); | 423 Code* target = Code::GetCodeFromTargetAddress(it.rinfo()->target_address()); |
412 if (RelocInfo::IsCodeTarget(mode)) { | 424 if (target->kind() == kind && |
413 Code* target = | 425 target->constant_pool_offset() >= kPlaceholderMarker) { |
414 Code::GetCodeFromTargetAddress(it.rinfo()->target_address()); | 426 // Patch direct calls to placeholder code objects. |
415 if (target->kind() == kind && | 427 uint32_t index = target->constant_pool_offset() - kPlaceholderMarker; |
416 target->constant_pool_offset() >= kPlaceholderMarker) { | 428 CHECK(index < static_cast<uint32_t>(code_targets->length())); |
417 // Patch direct calls to placeholder code objects. | 429 Handle<Code> new_target = |
418 uint32_t index = target->constant_pool_offset() - kPlaceholderMarker; | 430 code_targets->GetValueChecked<Code>(isolate, index); |
419 CHECK(index < code_targets.size()); | 431 if (target != *new_target) { |
420 Handle<Code> new_target = code_targets[index]; | 432 it.rinfo()->set_target_address(new_target->instruction_start(), |
421 if (target != *new_target) { | 433 UPDATE_WRITE_BARRIER, SKIP_ICACHE_FLUSH); |
422 it.rinfo()->set_target_address(new_target->instruction_start(), | 434 modified = true; |
423 UPDATE_WRITE_BARRIER, | |
424 SKIP_ICACHE_FLUSH); | |
425 modified = true; | |
426 } | |
427 } | 435 } |
428 } | 436 } |
429 } | 437 } |
430 return modified; | 438 return modified; |
431 } | 439 } |
432 | 440 |
433 void LinkModuleFunctions(Isolate* isolate, | 441 void LinkModuleFunctions(Isolate* isolate, Handle<FixedArray> functions) { |
434 std::vector<Handle<Code>>& functions) { | 442 for (int i = 0; i < functions->length(); ++i) { |
435 for (size_t i = 0; i < functions.size(); ++i) { | 443 Handle<Code> code = functions->GetValueChecked<Code>(isolate, i); |
436 Handle<Code> code = functions[i]; | 444 LinkFunction(isolate, code, functions); |
437 LinkFunction(code, functions, Code::WASM_FUNCTION); | |
438 } | 445 } |
439 } | 446 } |
440 | 447 |
441 void FlushAssemblyCache(Isolate* isolate, Handle<FixedArray> functions) { | 448 void FlushAssemblyCache(Isolate* isolate, Handle<FixedArray> functions) { |
442 for (int i = 0; i < functions->length(); ++i) { | 449 for (int i = 0; i < functions->length(); ++i) { |
443 Handle<Code> code = functions->GetValueChecked<Code>(isolate, i); | 450 Handle<Code> code = functions->GetValueChecked<Code>(isolate, i); |
444 Assembler::FlushICache(isolate, code->instruction_start(), | 451 Assembler::FlushICache(isolate, code->instruction_start(), |
445 code->instruction_size()); | 452 code->instruction_size()); |
446 } | 453 } |
447 } | 454 } |
448 | 455 |
449 void SetRuntimeSupport(Isolate* isolate, Handle<JSObject> js_object) { | 456 void SetRuntimeSupport(Isolate* isolate, Handle<JSObject> js_object) { |
450 Handle<FixedArray> functions = Handle<FixedArray>( | 457 Handle<FixedArray> functions = Handle<FixedArray>( |
451 FixedArray::cast(js_object->GetInternalField(kWasmModuleCodeTable))); | 458 FixedArray::cast(js_object->GetInternalField(kWasmModuleCodeTable))); |
452 Handle<WeakCell> weak_link = isolate->factory()->NewWeakCell(js_object); | 459 Handle<WeakCell> weak_link = isolate->factory()->NewWeakCell(js_object); |
453 | 460 |
454 for (int i = FLAG_skip_compiling_wasm_funcs; i < functions->length(); ++i) { | 461 for (int i = FLAG_skip_compiling_wasm_funcs; i < functions->length(); ++i) { |
455 Handle<Code> code = functions->GetValueChecked<Code>(isolate, i); | 462 Handle<Code> code = functions->GetValueChecked<Code>(isolate, i); |
456 DCHECK(code->deoptimization_data() == nullptr || | |
457 code->deoptimization_data()->length() == 0); | |
458 Handle<FixedArray> deopt_data = | 463 Handle<FixedArray> deopt_data = |
459 isolate->factory()->NewFixedArray(2, TENURED); | 464 isolate->factory()->NewFixedArray(2, TENURED); |
460 deopt_data->set(0, *weak_link); | 465 deopt_data->set(0, *weak_link); |
461 deopt_data->set(1, Smi::FromInt(static_cast<int>(i))); | 466 deopt_data->set(1, Smi::FromInt(static_cast<int>(i))); |
462 deopt_data->set_length(2); | 467 deopt_data->set_length(2); |
463 code->set_deoptimization_data(*deopt_data); | 468 code->set_deoptimization_data(*deopt_data); |
464 } | 469 } |
465 } | 470 } |
466 | 471 |
467 } // namespace | 472 } // namespace |
(...skipping 146 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
614 for (Handle<Code> c : functions) RecordStats(isolate, *c); | 619 for (Handle<Code> c : functions) RecordStats(isolate, *c); |
615 } | 620 } |
616 | 621 |
617 static void RecordStats(Isolate* isolate, Handle<FixedArray> functions) { | 622 static void RecordStats(Isolate* isolate, Handle<FixedArray> functions) { |
618 DisallowHeapAllocation no_gc; | 623 DisallowHeapAllocation no_gc; |
619 for (int i = 0; i < functions->length(); ++i) { | 624 for (int i = 0; i < functions->length(); ++i) { |
620 RecordStats(isolate, Code::cast(functions->get(i))); | 625 RecordStats(isolate, Code::cast(functions->get(i))); |
621 } | 626 } |
622 } | 627 } |
623 | 628 |
| 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 |
624 Handle<FixedArray> GetImportsMetadata(Factory* factory, | 640 Handle<FixedArray> GetImportsMetadata(Factory* factory, |
625 const WasmModule* module) { | 641 const WasmModule* module) { |
626 Handle<FixedArray> ret = factory->NewFixedArray( | 642 Handle<FixedArray> ret = factory->NewFixedArray( |
627 static_cast<int>(module->import_table.size()), TENURED); | 643 static_cast<int>(module->import_table.size()), TENURED); |
628 for (size_t i = 0; i < module->import_table.size(); ++i) { | 644 for (size_t i = 0; i < module->import_table.size(); ++i) { |
629 const WasmImport& import = module->import_table[i]; | 645 const WasmImport& import = module->import_table[i]; |
630 WasmName module_name = module->GetNameOrNull(import.module_name_offset, | 646 WasmName module_name = module->GetNameOrNull(import.module_name_offset, |
631 import.module_name_length); | 647 import.module_name_length); |
632 WasmName function_name = module->GetNameOrNull(import.function_name_offset, | 648 WasmName function_name = module->GetNameOrNull(import.function_name_offset, |
633 import.function_name_length); | 649 import.function_name_length); |
(...skipping 271 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
905 } | 921 } |
906 | 922 |
907 MaybeHandle<ByteArray> function_name_table = | 923 MaybeHandle<ByteArray> function_name_table = |
908 compiled_module->GetValue<ByteArray>(isolate, kFunctionNameTable); | 924 compiled_module->GetValue<ByteArray>(isolate, kFunctionNameTable); |
909 if (!function_name_table.is_null()) { | 925 if (!function_name_table.is_null()) { |
910 js_object->SetInternalField(kWasmFunctionNamesArray, | 926 js_object->SetInternalField(kWasmFunctionNamesArray, |
911 *function_name_table.ToHandleChecked()); | 927 *function_name_table.ToHandleChecked()); |
912 } | 928 } |
913 } | 929 } |
914 | 930 |
915 bool SetupGlobals(Isolate* isolate, Handle<FixedArray> compiled_module, | 931 bool SetupGlobals(Isolate* isolate, MaybeHandle<JSObject> template_owner, |
916 Handle<JSObject> instance, ErrorThrower* thrower) { | 932 Handle<FixedArray> compiled_module, Handle<JSObject> instance, |
| 933 ErrorThrower* thrower) { |
917 uint32_t globals_size = static_cast<uint32_t>( | 934 uint32_t globals_size = static_cast<uint32_t>( |
918 Smi::cast(compiled_module->get(kGlobalsSize))->value()); | 935 Smi::cast(compiled_module->get(kGlobalsSize))->value()); |
919 if (globals_size > 0) { | 936 if (globals_size > 0) { |
920 Handle<JSArrayBuffer> globals_buffer = | 937 Handle<JSArrayBuffer> globals_buffer = |
921 NewArrayBuffer(isolate, globals_size); | 938 NewArrayBuffer(isolate, globals_size); |
922 if (globals_buffer.is_null()) { | 939 if (globals_buffer.is_null()) { |
923 thrower->Error("Out of memory: wasm globals"); | 940 thrower->Error("Out of memory: wasm globals"); |
924 return false; | 941 return false; |
925 } | 942 } |
926 RelocateGlobals(instance, | 943 Address old_address = |
| 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, |
927 static_cast<Address>(globals_buffer->backing_store())); | 950 static_cast<Address>(globals_buffer->backing_store())); |
928 instance->SetInternalField(kWasmGlobalsArrayBuffer, *globals_buffer); | 951 instance->SetInternalField(kWasmGlobalsArrayBuffer, *globals_buffer); |
929 } | 952 } |
930 return true; | 953 return true; |
931 } | 954 } |
932 | 955 |
933 bool SetupInstanceHeap(Isolate* isolate, Handle<FixedArray> compiled_module, | 956 bool SetupInstanceHeap(Isolate* isolate, Handle<FixedArray> compiled_module, |
934 Handle<JSObject> instance, Handle<JSArrayBuffer> memory, | 957 Handle<JSObject> instance, Handle<JSArrayBuffer> memory, |
935 ErrorThrower* thrower) { | 958 ErrorThrower* thrower) { |
936 uint32_t min_mem_pages = static_cast<uint32_t>( | 959 uint32_t min_mem_pages = static_cast<uint32_t>( |
937 Smi::cast(compiled_module->get(kMinRequiredMemory))->value()); | 960 Smi::cast(compiled_module->get(kMinRequiredMemory))->value()); |
938 isolate->counters()->wasm_min_mem_pages_count()->AddSample(min_mem_pages); | 961 isolate->counters()->wasm_min_mem_pages_count()->AddSample(min_mem_pages); |
939 // TODO(wasm): re-enable counter for max_mem_pages when we use that field. | 962 // TODO(wasm): re-enable counter for max_mem_pages when we use that field. |
940 | 963 |
941 if (memory.is_null() && min_mem_pages > 0) { | 964 if (memory.is_null() && min_mem_pages > 0) { |
942 memory = AllocateMemory(thrower, isolate, min_mem_pages); | 965 memory = AllocateMemory(thrower, isolate, min_mem_pages); |
943 if (memory.is_null()) { | 966 if (memory.is_null()) { |
944 return false; | 967 return false; |
945 } | 968 } |
946 } | 969 } |
947 | 970 |
948 if (!memory.is_null()) { | 971 if (!memory.is_null()) { |
949 instance->SetInternalField(kWasmMemArrayBuffer, *memory); | 972 instance->SetInternalField(kWasmMemArrayBuffer, *memory); |
950 Address mem_start = static_cast<Address>(memory->backing_store()); | 973 Address mem_start = static_cast<Address>(memory->backing_store()); |
951 uint32_t mem_size = static_cast<uint32_t>(memory->byte_length()->Number()); | 974 uint32_t mem_size = static_cast<uint32_t>(memory->byte_length()->Number()); |
952 RelocateInstanceCode(instance, mem_start, | 975 uint32_t old_mem_size = static_cast<uint32_t>( |
953 WasmModule::kPageSize * min_mem_pages, 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 = |
| 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); |
954 LoadDataSegments(compiled_module, mem_start, mem_size); | 986 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); |
955 } | 990 } |
956 return true; | 991 return true; |
957 } | 992 } |
958 | 993 |
| 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 |
959 bool SetupImports(Isolate* isolate, Handle<FixedArray> compiled_module, | 1041 bool SetupImports(Isolate* isolate, Handle<FixedArray> compiled_module, |
960 Handle<JSObject> instance, ErrorThrower* thrower, | 1042 Handle<JSObject> instance, ErrorThrower* thrower, |
961 Handle<JSReceiver> ffi) { | 1043 Handle<JSReceiver> ffi) { |
962 //------------------------------------------------------------------------- | 1044 //------------------------------------------------------------------------- |
963 // Compile wrappers to imported functions. | 1045 // Compile wrappers to imported functions. |
964 //------------------------------------------------------------------------- | 1046 //------------------------------------------------------------------------- |
965 std::vector<Handle<Code>> import_code; | 1047 std::vector<Handle<Code>> import_code; |
966 MaybeHandle<FixedArray> maybe_import_data = | 1048 MaybeHandle<FixedArray> maybe_import_data = |
967 compiled_module->GetValue<FixedArray>(isolate, kImportData); | 1049 compiled_module->GetValue<FixedArray>(isolate, kImportData); |
968 Handle<FixedArray> import_data; | 1050 Handle<FixedArray> import_data; |
969 if (maybe_import_data.ToHandle(&import_data)) { | 1051 if (maybe_import_data.ToHandle(&import_data)) { |
970 if (!CompileWrappersToImportedFunctions(isolate, ffi, import_code, | 1052 if (!CompileWrappersToImportedFunctions(isolate, ffi, import_code, |
971 import_data, thrower)) { | 1053 import_data, thrower)) { |
972 return false; | 1054 return false; |
973 } | 1055 } |
974 } | 1056 } |
975 | 1057 |
976 RecordStats(isolate, import_code); | 1058 RecordStats(isolate, import_code); |
977 | |
978 if (import_code.empty()) return true; | 1059 if (import_code.empty()) return true; |
979 | 1060 |
980 { | 1061 Handle<FixedArray> new_imports = |
981 DisallowHeapAllocation no_gc; | 1062 isolate->factory()->NewFixedArray(static_cast<int>(import_code.size())); |
982 std::map<Code*, int> import_to_index; | 1063 for (int i = 0; i < new_imports->length(); ++i) { |
983 Handle<FixedArray> mapping = | 1064 new_imports->set(i, *import_code[i]); |
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 } | 1065 } |
1013 Handle<FixedArray> new_mapping = | 1066 compiled_module->set(kImportMap, *new_imports); |
1014 isolate->factory()->NewFixedArray(static_cast<int>(import_code.size())); | |
1015 for (int i = 0; i < new_mapping->length(); ++i) { | |
1016 new_mapping->set(i, *import_code[i]); | |
1017 } | |
1018 compiled_module->set(kImportMap, *new_mapping); | |
1019 | |
1020 return true; | 1067 return true; |
1021 } | 1068 } |
1022 | 1069 |
1023 bool SetupExportsObject(Handle<FixedArray> compiled_module, Isolate* isolate, | 1070 bool SetupExportsObject(Handle<FixedArray> compiled_module, Isolate* isolate, |
1024 Handle<JSObject> instance, ErrorThrower* thrower) { | 1071 Handle<JSObject> instance, ErrorThrower* thrower) { |
1025 Factory* factory = isolate->factory(); | 1072 Factory* factory = isolate->factory(); |
1026 bool mem_export = | 1073 bool mem_export = |
1027 static_cast<bool>(Smi::cast(compiled_module->get(kExportMem))->value()); | 1074 static_cast<bool>(Smi::cast(compiled_module->get(kExportMem))->value()); |
1028 ModuleOrigin origin = static_cast<ModuleOrigin>( | 1075 ModuleOrigin origin = static_cast<ModuleOrigin>( |
1029 Smi::cast(compiled_module->get(kOrigin))->value()); | 1076 Smi::cast(compiled_module->get(kOrigin))->value()); |
(...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1074 // Export the memory as a named property. | 1121 // Export the memory as a named property. |
1075 Handle<String> name = factory->InternalizeUtf8String("memory"); | 1122 Handle<String> name = factory->InternalizeUtf8String("memory"); |
1076 Handle<JSArrayBuffer> memory = Handle<JSArrayBuffer>( | 1123 Handle<JSArrayBuffer> memory = Handle<JSArrayBuffer>( |
1077 JSArrayBuffer::cast(instance->GetInternalField(kWasmMemArrayBuffer))); | 1124 JSArrayBuffer::cast(instance->GetInternalField(kWasmMemArrayBuffer))); |
1078 JSObject::AddProperty(exports_object, name, memory, READ_ONLY); | 1125 JSObject::AddProperty(exports_object, name, memory, READ_ONLY); |
1079 } | 1126 } |
1080 } | 1127 } |
1081 return true; | 1128 return true; |
1082 } | 1129 } |
1083 | 1130 |
| 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 |
1084 } // namespace | 1247 } // namespace |
1085 | 1248 |
1086 MaybeHandle<FixedArray> WasmModule::CompileFunctions( | 1249 MaybeHandle<FixedArray> WasmModule::CompileFunctions( |
1087 Isolate* isolate, ErrorThrower* thrower) const { | 1250 Isolate* isolate, ErrorThrower* thrower) const { |
1088 Factory* factory = isolate->factory(); | 1251 Factory* factory = isolate->factory(); |
1089 | 1252 |
1090 MaybeHandle<FixedArray> nothing; | 1253 MaybeHandle<FixedArray> nothing; |
1091 | 1254 |
1092 WasmModuleInstance temp_instance_for_compilation(this); | 1255 WasmModuleInstance temp_instance_for_compilation(this); |
1093 temp_instance_for_compilation.context = isolate->native_context(); | 1256 temp_instance_for_compilation.context = isolate->native_context(); |
(...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1149 } | 1312 } |
1150 if (thrower->error()) return nothing; | 1313 if (thrower->error()) return nothing; |
1151 | 1314 |
1152 // At this point, compilation has completed. Update the code table. | 1315 // At this point, compilation has completed. Update the code table. |
1153 for (size_t i = FLAG_skip_compiling_wasm_funcs; | 1316 for (size_t i = FLAG_skip_compiling_wasm_funcs; |
1154 i < temp_instance_for_compilation.function_code.size(); ++i) { | 1317 i < temp_instance_for_compilation.function_code.size(); ++i) { |
1155 Code* code = *temp_instance_for_compilation.function_code[i]; | 1318 Code* code = *temp_instance_for_compilation.function_code[i]; |
1156 compiled_functions->set(static_cast<int>(i), code); | 1319 compiled_functions->set(static_cast<int>(i), code); |
1157 } | 1320 } |
1158 | 1321 |
| 1322 LinkModuleFunctions(isolate, compiled_functions); |
| 1323 |
| 1324 // TODO(mtrofin): do we need to flush the cache here? |
| 1325 FlushAssemblyCache(isolate, compiled_functions); |
| 1326 |
1159 // Create the compiled module object, and populate with compiled functions | 1327 // Create the compiled module object, and populate with compiled functions |
1160 // and information needed at instantiation time. This object needs to be | 1328 // and information needed at instantiation time. This object needs to be |
1161 // serializable. Instantiation may occur off a deserialized version of this | 1329 // serializable. Instantiation may occur off a deserialized version of this |
1162 // object. | 1330 // object. |
1163 Handle<FixedArray> ret = | 1331 Handle<FixedArray> ret = |
1164 factory->NewFixedArray(kCompiledWasmObjectTableSize, TENURED); | 1332 factory->NewFixedArray(kCompiledWasmObjectTableSize, TENURED); |
1165 ret->set(kFunctions, *compiled_functions); | 1333 ret->set(kFunctions, *compiled_functions); |
1166 if (!indirect_table.is_null()) { | 1334 if (!indirect_table.is_null()) { |
1167 ret->set(kTableOfIndirectFunctionTables, *indirect_table.ToHandleChecked()); | 1335 ret->set(kTableOfIndirectFunctionTables, *indirect_table.ToHandleChecked()); |
1168 } | 1336 } |
(...skipping 75 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1244 } | 1412 } |
1245 | 1413 |
1246 Handle<ByteArray> function_name_table = | 1414 Handle<ByteArray> function_name_table = |
1247 BuildFunctionNamesTable(isolate, module_env.module); | 1415 BuildFunctionNamesTable(isolate, module_env.module); |
1248 ret->set(kFunctionNameTable, *function_name_table); | 1416 ret->set(kFunctionNameTable, *function_name_table); |
1249 ret->set(kMinRequiredMemory, Smi::FromInt(min_mem_pages)); | 1417 ret->set(kMinRequiredMemory, Smi::FromInt(min_mem_pages)); |
1250 if (data_segments.size() > 0) SaveDataSegmentInfo(factory, this, ret); | 1418 if (data_segments.size() > 0) SaveDataSegmentInfo(factory, this, ret); |
1251 ret->set(kGlobalsSize, Smi::FromInt(globals_size)); | 1419 ret->set(kGlobalsSize, Smi::FromInt(globals_size)); |
1252 ret->set(kExportMem, Smi::FromInt(mem_export)); | 1420 ret->set(kExportMem, Smi::FromInt(mem_export)); |
1253 ret->set(kOrigin, Smi::FromInt(origin)); | 1421 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); |
1254 return ret; | 1426 return ret; |
1255 } | 1427 } |
1256 | 1428 |
1257 void PatchJSWrapper(Isolate* isolate, Handle<Code> wrapper, | 1429 void PatchJSWrapper(Isolate* isolate, Handle<Code> wrapper, |
1258 Handle<Code> new_target) { | 1430 Handle<Code> new_target) { |
1259 AllowDeferredHandleDereference embedding_raw_address; | 1431 AllowDeferredHandleDereference embedding_raw_address; |
1260 bool seen = false; | 1432 bool seen = false; |
1261 for (RelocIterator it(*wrapper, 1 << RelocInfo::CODE_TARGET); !it.done(); | 1433 for (RelocIterator it(*wrapper, 1 << RelocInfo::CODE_TARGET); !it.done(); |
1262 it.next()) { | 1434 it.next()) { |
1263 Code* target = Code::GetCodeFromTargetAddress(it.rinfo()->target_address()); | 1435 Code* target = Code::GetCodeFromTargetAddress(it.rinfo()->target_address()); |
1264 if (target->kind() == Code::WASM_FUNCTION) { | 1436 if (target->kind() == Code::WASM_FUNCTION) { |
1265 DCHECK(!seen); | 1437 DCHECK(!seen); |
1266 seen = true; | 1438 seen = true; |
1267 it.rinfo()->set_target_address(new_target->instruction_start(), | 1439 it.rinfo()->set_target_address(new_target->instruction_start(), |
1268 UPDATE_WRITE_BARRIER, SKIP_ICACHE_FLUSH); | 1440 UPDATE_WRITE_BARRIER, SKIP_ICACHE_FLUSH); |
1269 } | 1441 } |
1270 } | 1442 } |
1271 CHECK(seen); | 1443 CHECK(seen); |
1272 Assembler::FlushICache(isolate, wrapper->instruction_start(), | 1444 Assembler::FlushICache(isolate, wrapper->instruction_start(), |
1273 wrapper->instruction_size()); | 1445 wrapper->instruction_size()); |
1274 } | 1446 } |
1275 | 1447 |
1276 Handle<FixedArray> SetupIndirectFunctionTable( | 1448 Handle<FixedArray> SetupIndirectFunctionTable( |
1277 Isolate* isolate, Handle<FixedArray> wasm_functions, | 1449 Isolate* isolate, Handle<FixedArray> wasm_functions, |
1278 Handle<FixedArray> indirect_table_template) { | 1450 Handle<FixedArray> indirect_table_template, |
| 1451 Handle<FixedArray> tables_to_replace) { |
1279 Factory* factory = isolate->factory(); | 1452 Factory* factory = isolate->factory(); |
1280 Handle<FixedArray> cloned_indirect_tables = | 1453 Handle<FixedArray> cloned_indirect_tables = |
1281 factory->CopyFixedArray(indirect_table_template); | 1454 factory->CopyFixedArray(indirect_table_template); |
1282 for (int i = 0; i < cloned_indirect_tables->length(); ++i) { | 1455 for (int i = 0; i < cloned_indirect_tables->length(); ++i) { |
1283 Handle<FixedArray> orig_metadata = | 1456 Handle<FixedArray> orig_metadata = |
1284 cloned_indirect_tables->GetValueChecked<FixedArray>(isolate, i); | 1457 cloned_indirect_tables->GetValueChecked<FixedArray>(isolate, i); |
1285 Handle<FixedArray> cloned_metadata = factory->CopyFixedArray(orig_metadata); | 1458 Handle<FixedArray> cloned_metadata = factory->CopyFixedArray(orig_metadata); |
1286 cloned_indirect_tables->set(i, *cloned_metadata); | 1459 cloned_indirect_tables->set(i, *cloned_metadata); |
1287 | 1460 |
1288 Handle<FixedArray> orig_table = | 1461 Handle<FixedArray> orig_table = |
1289 cloned_metadata->GetValueChecked<FixedArray>(isolate, kTable); | 1462 cloned_metadata->GetValueChecked<FixedArray>(isolate, kTable); |
1290 Handle<FixedArray> cloned_table = factory->CopyFixedArray(orig_table); | 1463 Handle<FixedArray> cloned_table = factory->CopyFixedArray(orig_table); |
1291 cloned_metadata->set(kTable, *cloned_table); | 1464 cloned_metadata->set(kTable, *cloned_table); |
1292 // Patch the cloned code to refer to the cloned kTable. | 1465 // Patch the cloned code to refer to the cloned kTable. |
1293 for (int i = 0; i < wasm_functions->length(); ++i) { | 1466 Handle<FixedArray> table_to_replace = |
| 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) { |
1294 Handle<Code> wasm_function = | 1470 Handle<Code> wasm_function = |
1295 wasm_functions->GetValueChecked<Code>(isolate, i); | 1471 wasm_functions->GetValueChecked<Code>(isolate, fct_index); |
1296 PatchFunctionTable(wasm_function, orig_table, cloned_table); | 1472 PatchFunctionTable(wasm_function, table_to_replace, cloned_table); |
1297 } | 1473 } |
1298 } | 1474 } |
1299 return cloned_indirect_tables; | 1475 return cloned_indirect_tables; |
1300 } | 1476 } |
1301 | 1477 |
1302 Handle<FixedArray> CloneModuleForInstance(Isolate* isolate, | 1478 Handle<FixedArray> CloneModuleForInstance(Isolate* isolate, |
1303 Handle<FixedArray> original) { | 1479 Handle<FixedArray> original) { |
1304 Factory* factory = isolate->factory(); | 1480 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. |
1305 Handle<FixedArray> clone = factory->CopyFixedArray(original); | 1489 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); |
1306 | 1499 |
1307 // Clone each wasm code object. | 1500 // Clone each wasm code object. |
1308 Handle<FixedArray> orig_wasm_functions = | 1501 Handle<FixedArray> orig_wasm_functions = |
1309 original->GetValueChecked<FixedArray>(isolate, kFunctions); | 1502 original->GetValueChecked<FixedArray>(isolate, kFunctions); |
1310 Handle<FixedArray> clone_wasm_functions = | 1503 Handle<FixedArray> clone_wasm_functions = |
1311 factory->CopyFixedArray(orig_wasm_functions); | 1504 factory->CopyFixedArray(orig_wasm_functions); |
1312 clone->set(kFunctions, *clone_wasm_functions); | 1505 clone->set(kFunctions, *clone_wasm_functions); |
1313 for (int i = 0; i < clone_wasm_functions->length(); ++i) { | 1506 for (int i = 0; i < clone_wasm_functions->length(); ++i) { |
1314 Handle<Code> orig_code = | 1507 Handle<Code> orig_code = |
1315 clone_wasm_functions->GetValueChecked<Code>(isolate, i); | 1508 clone_wasm_functions->GetValueChecked<Code>(isolate, i); |
(...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1356 clone->set(kStartupFunction, *startup_metadata); | 1549 clone->set(kStartupFunction, *startup_metadata); |
1357 // TODO(wasm): see todo above about int vs size_t indexing in FixedArray. | 1550 // TODO(wasm): see todo above about int vs size_t indexing in FixedArray. |
1358 int startup_fct_index = | 1551 int startup_fct_index = |
1359 Smi::cast(startup_metadata->get(kExportedFunctionIndex))->value(); | 1552 Smi::cast(startup_metadata->get(kExportedFunctionIndex))->value(); |
1360 CHECK_GE(startup_fct_index, 0); | 1553 CHECK_GE(startup_fct_index, 0); |
1361 CHECK_LT(startup_fct_index, clone_wasm_functions->length()); | 1554 CHECK_LT(startup_fct_index, clone_wasm_functions->length()); |
1362 Handle<Code> new_target = | 1555 Handle<Code> new_target = |
1363 clone_wasm_functions->GetValueChecked<Code>(isolate, startup_fct_index); | 1556 clone_wasm_functions->GetValueChecked<Code>(isolate, startup_fct_index); |
1364 PatchJSWrapper(isolate, startup_fct_clone, new_target); | 1557 PatchJSWrapper(isolate, startup_fct_clone, new_target); |
1365 } | 1558 } |
| 1559 clone->set(kImportMap, *isolate->factory()->undefined_value()); |
1366 return clone; | 1560 return clone; |
1367 } | 1561 } |
1368 | 1562 |
1369 // Instantiates a wasm module as a JSObject. | 1563 // Instantiates a wasm module as a JSObject. |
1370 // * allocates a backing store of {mem_size} bytes. | 1564 // * allocates a backing store of {mem_size} bytes. |
1371 // * installs a named property "memory" for that buffer if exported | 1565 // * installs a named property "memory" for that buffer if exported |
1372 // * installs named properties on the object for exported functions | 1566 // * installs named properties on the object for exported functions |
1373 // * compiles wasm code to machine code | 1567 // * compiles wasm code to machine code |
1374 MaybeHandle<JSObject> WasmModule::Instantiate( | 1568 MaybeHandle<JSObject> WasmModule::Instantiate( |
1375 Isolate* isolate, Handle<FixedArray> compiled_module, | 1569 Isolate* isolate, Handle<FixedArray> compiled_module_template, |
1376 Handle<JSReceiver> ffi, Handle<JSArrayBuffer> memory) { | 1570 Handle<JSReceiver> ffi, Handle<JSArrayBuffer> memory) { |
1377 HistogramTimerScope wasm_instantiate_module_time_scope( | 1571 HistogramTimerScope wasm_instantiate_module_time_scope( |
1378 isolate->counters()->wasm_instantiate_module_time()); | 1572 isolate->counters()->wasm_instantiate_module_time()); |
1379 ErrorThrower thrower(isolate, "WasmModule::Instantiate()"); | 1573 ErrorThrower thrower(isolate, "WasmModule::Instantiate()"); |
1380 Factory* factory = isolate->factory(); | 1574 Factory* factory = isolate->factory(); |
1381 | 1575 |
1382 compiled_module = CloneModuleForInstance(isolate, compiled_module); | 1576 Handle<FixedArray> compiled_module = |
| 1577 CloneModuleForInstance(isolate, compiled_module_template); |
1383 | 1578 |
| 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 } |
1384 // These fields are compulsory. | 1589 // These fields are compulsory. |
1385 Handle<FixedArray> code_table = | 1590 Handle<FixedArray> code_table = |
1386 compiled_module->GetValueChecked<FixedArray>(isolate, kFunctions); | 1591 compiled_module->GetValueChecked<FixedArray>(isolate, kFunctions); |
1387 | 1592 |
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 | |
1396 RecordStats(isolate, code_table); | 1593 RecordStats(isolate, code_table); |
1397 | 1594 |
1398 MaybeHandle<JSObject> nothing; | 1595 MaybeHandle<JSObject> nothing; |
1399 | 1596 |
1400 Handle<Map> map = factory->NewMap( | 1597 Handle<Map> map = factory->NewMap( |
1401 JS_OBJECT_TYPE, | 1598 JS_OBJECT_TYPE, |
1402 JSObject::kHeaderSize + kWasmModuleInternalFieldCount * kPointerSize); | 1599 JSObject::kHeaderSize + kWasmModuleInternalFieldCount * kPointerSize); |
1403 Handle<JSObject> js_object = factory->NewJSObjectFromMap(map, TENURED); | 1600 Handle<JSObject> js_object = factory->NewJSObjectFromMap(map, TENURED); |
1404 js_object->SetInternalField(kWasmModuleCodeTable, *code_table); | 1601 js_object->SetInternalField(kWasmModuleCodeTable, *code_table); |
1405 | 1602 |
| 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); |
1406 if (!(SetupInstanceHeap(isolate, compiled_module, js_object, memory, | 1607 if (!(SetupInstanceHeap(isolate, compiled_module, js_object, memory, |
1407 &thrower) && | 1608 &thrower) && |
1408 SetupGlobals(isolate, compiled_module, js_object, &thrower) && | 1609 SetupGlobals(isolate, template_owner, compiled_module, js_object, |
| 1610 &thrower) && |
1409 SetupImports(isolate, compiled_module, js_object, &thrower, ffi) && | 1611 SetupImports(isolate, compiled_module, js_object, &thrower, ffi) && |
1410 SetupExportsObject(compiled_module, isolate, js_object, &thrower))) { | 1612 SetupExportsObject(compiled_module, isolate, js_object, &thrower))) { |
1411 return nothing; | 1613 return nothing; |
1412 } | 1614 } |
1413 | 1615 |
| 1616 FixupFunctionsAndImports( |
| 1617 compiled_module_template->GetValueChecked<FixedArray>(isolate, |
| 1618 kFunctions), |
| 1619 code_table, old_imports, |
| 1620 compiled_module->GetValue<FixedArray>(isolate, kImportMap)); |
| 1621 |
1414 SetDebugSupport(factory, compiled_module, js_object); | 1622 SetDebugSupport(factory, compiled_module, js_object); |
1415 SetRuntimeSupport(isolate, js_object); | 1623 SetRuntimeSupport(isolate, js_object); |
1416 | 1624 |
1417 FlushAssemblyCache(isolate, code_table); | 1625 FlushAssemblyCache(isolate, code_table); |
1418 | 1626 |
1419 MaybeHandle<FixedArray> maybe_indirect_tables = | 1627 { |
1420 compiled_module->GetValue<FixedArray>(isolate, | 1628 std::vector<Handle<Code>> functions( |
1421 kTableOfIndirectFunctionTables); | 1629 static_cast<size_t>(code_table->length())); |
1422 Handle<FixedArray> indirect_tables_template; | 1630 for (int i = 0; i < code_table->length(); ++i) { |
1423 if (maybe_indirect_tables.ToHandle(&indirect_tables_template)) { | 1631 functions[static_cast<size_t>(i)] = |
1424 Handle<FixedArray> indirect_tables = SetupIndirectFunctionTable( | 1632 code_table->GetValueChecked<Code>(isolate, i); |
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); | |
1433 } | 1633 } |
1434 js_object->SetInternalField(kWasmModuleFunctionTable, *indirect_tables); | 1634 |
| 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 } |
1435 } | 1658 } |
1436 | 1659 |
1437 // Run the start function if one was specified. | 1660 // Run the start function if one was specified. |
1438 MaybeHandle<FixedArray> maybe_startup_fct = | 1661 MaybeHandle<FixedArray> maybe_startup_fct = |
1439 compiled_module->GetValue<FixedArray>(isolate, kStartupFunction); | 1662 compiled_module->GetValue<FixedArray>(isolate, kStartupFunction); |
1440 Handle<FixedArray> metadata; | 1663 Handle<FixedArray> metadata; |
1441 if (maybe_startup_fct.ToHandle(&metadata)) { | 1664 if (maybe_startup_fct.ToHandle(&metadata)) { |
1442 HandleScope scope(isolate); | 1665 HandleScope scope(isolate); |
1443 Handle<Code> startup_code = | 1666 Handle<Code> startup_code = |
1444 metadata->GetValueChecked<Code>(isolate, kExportCode); | 1667 metadata->GetValueChecked<Code>(isolate, kExportCode); |
1445 int arity = Smi::cast(metadata->get(kExportArity))->value(); | 1668 int arity = Smi::cast(metadata->get(kExportArity))->value(); |
1446 MaybeHandle<ByteArray> startup_signature = | 1669 MaybeHandle<ByteArray> startup_signature = |
1447 metadata->GetValue<ByteArray>(isolate, kExportedSignature); | 1670 metadata->GetValue<ByteArray>(isolate, kExportedSignature); |
1448 Handle<JSFunction> startup_fct = WrapExportCodeAsJSFunction( | 1671 Handle<JSFunction> startup_fct = WrapExportCodeAsJSFunction( |
1449 isolate, startup_code, factory->InternalizeUtf8String("start"), arity, | 1672 isolate, startup_code, factory->InternalizeUtf8String("start"), arity, |
1450 startup_signature, js_object); | 1673 startup_signature, js_object); |
1451 RecordStats(isolate, *startup_code); | 1674 RecordStats(isolate, *startup_code); |
1452 // Call the JS function. | 1675 // Call the JS function. |
1453 Handle<Object> undefined = isolate->factory()->undefined_value(); | 1676 Handle<Object> undefined = isolate->factory()->undefined_value(); |
1454 MaybeHandle<Object> retval = | 1677 MaybeHandle<Object> retval = |
1455 Execution::Call(isolate, startup_fct, undefined, 0, nullptr); | 1678 Execution::Call(isolate, startup_fct, undefined, 0, nullptr); |
1456 | 1679 |
1457 if (retval.is_null()) { | 1680 if (retval.is_null()) { |
1458 thrower.Error("WASM.instantiateModule(): start function failed"); | 1681 thrower.Error("WASM.instantiateModule(): start function failed"); |
1459 return nothing; | 1682 return nothing; |
1460 } | 1683 } |
1461 } | 1684 } |
1462 | 1685 |
1463 DCHECK(wasm::IsWasmObject(*js_object)); | 1686 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 |
1464 return js_object; | 1700 return js_object; |
1465 } | 1701 } |
1466 | 1702 |
1467 // TODO(mtrofin): remove this once we move to WASM_DIRECT_CALL | 1703 // TODO(mtrofin): remove this once we move to WASM_DIRECT_CALL |
1468 Handle<Code> ModuleEnv::GetCodeOrPlaceholder(uint32_t index) const { | 1704 Handle<Code> ModuleEnv::GetCodeOrPlaceholder(uint32_t index) const { |
1469 DCHECK(IsValidFunction(index)); | 1705 DCHECK(IsValidFunction(index)); |
1470 if (!placeholders.empty()) return placeholders[index]; | 1706 if (!placeholders.empty()) return placeholders[index]; |
1471 DCHECK_NOT_NULL(instance); | 1707 DCHECK_NOT_NULL(instance); |
1472 return instance->function_code[index]; | 1708 return instance->function_code[index]; |
1473 } | 1709 } |
(...skipping 167 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1641 DCHECK(origin == ModuleOrigin::kAsmJsOrigin); | 1877 DCHECK(origin == ModuleOrigin::kAsmJsOrigin); |
1642 Handle<Map> map = isolate->factory()->NewMap( | 1878 Handle<Map> map = isolate->factory()->NewMap( |
1643 JS_OBJECT_TYPE, JSObject::kHeaderSize + kPointerSize); | 1879 JS_OBJECT_TYPE, JSObject::kHeaderSize + kPointerSize); |
1644 module_obj = isolate->factory()->NewJSObjectFromMap(map, TENURED); | 1880 module_obj = isolate->factory()->NewJSObjectFromMap(map, TENURED); |
1645 } | 1881 } |
1646 module_obj->SetInternalField(0, *compiled_module); | 1882 module_obj->SetInternalField(0, *compiled_module); |
1647 if (origin == ModuleOrigin::kWasmOrigin) { | 1883 if (origin == ModuleOrigin::kWasmOrigin) { |
1648 Handle<Symbol> module_sym(isolate->native_context()->wasm_module_sym()); | 1884 Handle<Symbol> module_sym(isolate->native_context()->wasm_module_sym()); |
1649 Object::SetProperty(module_obj, module_sym, module_obj, STRICT).Check(); | 1885 Object::SetProperty(module_obj, module_sym, module_obj, STRICT).Check(); |
1650 } | 1886 } |
| 1887 Handle<WeakCell> link_to_module = isolate->factory()->NewWeakCell(module_obj); |
| 1888 compiled_module->set(kModuleObject, *link_to_module); |
1651 return module_obj; | 1889 return module_obj; |
1652 } | 1890 } |
1653 | 1891 |
1654 MaybeHandle<JSObject> CreateModuleObjectFromBytes(Isolate* isolate, | 1892 MaybeHandle<JSObject> CreateModuleObjectFromBytes(Isolate* isolate, |
1655 const byte* start, | 1893 const byte* start, |
1656 const byte* end, | 1894 const byte* end, |
1657 ErrorThrower* thrower, | 1895 ErrorThrower* thrower, |
1658 ModuleOrigin origin) { | 1896 ModuleOrigin origin) { |
1659 MaybeHandle<JSObject> nothing; | 1897 MaybeHandle<JSObject> nothing; |
1660 Zone zone(isolate->allocator()); | 1898 Zone zone(isolate->allocator()); |
1661 ModuleResult result = | 1899 ModuleResult result = |
1662 DecodeWasmModule(isolate, &zone, start, end, false, origin); | 1900 DecodeWasmModule(isolate, &zone, start, end, false, origin); |
1663 std::unique_ptr<const WasmModule> decoded_module(result.val); | 1901 std::unique_ptr<const WasmModule> decoded_module(result.val); |
1664 if (result.failed()) { | 1902 if (result.failed()) { |
1665 thrower->Failed("Wasm decoding failed", result); | 1903 thrower->Failed("Wasm decoding failed", result); |
1666 return nothing; | 1904 return nothing; |
1667 } | 1905 } |
1668 MaybeHandle<FixedArray> compiled_module = | 1906 MaybeHandle<FixedArray> compiled_module = |
1669 decoded_module->CompileFunctions(isolate, thrower); | 1907 decoded_module->CompileFunctions(isolate, thrower); |
1670 if (compiled_module.is_null()) return nothing; | 1908 if (compiled_module.is_null()) return nothing; |
1671 | 1909 |
1672 return CreateCompiledModuleObject(isolate, compiled_module.ToHandleChecked(), | 1910 return CreateCompiledModuleObject(isolate, compiled_module.ToHandleChecked(), |
1673 origin); | 1911 origin); |
1674 } | 1912 } |
1675 | 1913 |
| 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 |
1676 namespace testing { | 1933 namespace testing { |
1677 | 1934 |
1678 int32_t CompileAndRunWasmModule(Isolate* isolate, const byte* module_start, | 1935 int32_t CompileAndRunWasmModule(Isolate* isolate, const byte* module_start, |
1679 const byte* module_end, bool asm_js) { | 1936 const byte* module_end, bool asm_js) { |
1680 HandleScope scope(isolate); | 1937 HandleScope scope(isolate); |
1681 Zone zone(isolate->allocator()); | 1938 Zone zone(isolate->allocator()); |
1682 ErrorThrower thrower(isolate, "CompileAndRunWasmModule"); | 1939 ErrorThrower thrower(isolate, "CompileAndRunWasmModule"); |
1683 | 1940 |
1684 // Decode the module, but don't verify function bodies, since we'll | 1941 // Decode the module, but don't verify function bodies, since we'll |
1685 // be compiling them anyway. | 1942 // be compiling them anyway. |
(...skipping 64 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1750 if (result->IsSmi()) { | 2007 if (result->IsSmi()) { |
1751 return Smi::cast(*result)->value(); | 2008 return Smi::cast(*result)->value(); |
1752 } | 2009 } |
1753 if (result->IsHeapNumber()) { | 2010 if (result->IsHeapNumber()) { |
1754 return static_cast<int32_t>(HeapNumber::cast(*result)->value()); | 2011 return static_cast<int32_t>(HeapNumber::cast(*result)->value()); |
1755 } | 2012 } |
1756 thrower->Error("WASM.compileRun() failed: Return value should be number"); | 2013 thrower->Error("WASM.compileRun() failed: Return value should be number"); |
1757 return -1; | 2014 return -1; |
1758 } | 2015 } |
1759 | 2016 |
| 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 |
1760 } // namespace testing | 2062 } // namespace testing |
1761 } // namespace wasm | 2063 } // namespace wasm |
1762 } // namespace internal | 2064 } // namespace internal |
1763 } // namespace v8 | 2065 } // namespace v8 |
OLD | NEW |