| 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 |