| 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/assembler-inl.h" | 7 #include "src/assembler-inl.h" |
| 8 #include "src/base/adapters.h" | 8 #include "src/base/adapters.h" |
| 9 #include "src/base/atomic-utils.h" | 9 #include "src/base/atomic-utils.h" |
| 10 #include "src/code-stubs.h" | 10 #include "src/code-stubs.h" |
| 11 #include "src/compiler/wasm-compiler.h" | 11 #include "src/compiler/wasm-compiler.h" |
| 12 #include "src/debug/interface-types.h" | 12 #include "src/debug/interface-types.h" |
| 13 #include "src/objects.h" | 13 #include "src/objects.h" |
| 14 #include "src/property-descriptor.h" | 14 #include "src/property-descriptor.h" |
| 15 #include "src/simulator.h" | 15 #include "src/simulator.h" |
| 16 #include "src/snapshot/snapshot.h" | 16 #include "src/snapshot/snapshot.h" |
| 17 #include "src/v8.h" | 17 #include "src/v8.h" |
| 18 | 18 |
| 19 #include "src/asmjs/asm-wasm-builder.h" | 19 #include "src/asmjs/asm-wasm-builder.h" |
| 20 #include "src/wasm/function-body-decoder.h" | 20 #include "src/wasm/function-body-decoder.h" |
| 21 #include "src/wasm/module-decoder.h" | 21 #include "src/wasm/module-decoder.h" |
| 22 #include "src/wasm/wasm-code-specialization.h" |
| 22 #include "src/wasm/wasm-js.h" | 23 #include "src/wasm/wasm-js.h" |
| 23 #include "src/wasm/wasm-limits.h" | 24 #include "src/wasm/wasm-limits.h" |
| 24 #include "src/wasm/wasm-module.h" | 25 #include "src/wasm/wasm-module.h" |
| 25 #include "src/wasm/wasm-objects.h" | 26 #include "src/wasm/wasm-objects.h" |
| 26 #include "src/wasm/wasm-result.h" | 27 #include "src/wasm/wasm-result.h" |
| 27 | 28 |
| 28 using namespace v8::internal; | 29 using namespace v8::internal; |
| 29 using namespace v8::internal::wasm; | 30 using namespace v8::internal::wasm; |
| 30 namespace base = v8::base; | 31 namespace base = v8::base; |
| 31 | 32 |
| 32 #define TRACE(...) \ | 33 #define TRACE(...) \ |
| 33 do { \ | 34 do { \ |
| 34 if (FLAG_trace_wasm_instances) PrintF(__VA_ARGS__); \ | 35 if (FLAG_trace_wasm_instances) PrintF(__VA_ARGS__); \ |
| 35 } while (false) | 36 } while (false) |
| 36 | 37 |
| 37 #define TRACE_CHAIN(instance) \ | 38 #define TRACE_CHAIN(instance) \ |
| 38 do { \ | 39 do { \ |
| 39 instance->PrintInstancesChain(); \ | 40 instance->PrintInstancesChain(); \ |
| 40 } while (false) | 41 } while (false) |
| 41 | 42 |
| 42 namespace { | 43 namespace { |
| 43 | 44 |
| 44 static const int kInvalidSigIndex = -1; | 45 static const int kInvalidSigIndex = -1; |
| 45 | 46 |
| 46 byte* raw_buffer_ptr(MaybeHandle<JSArrayBuffer> buffer, int offset) { | 47 byte* raw_buffer_ptr(MaybeHandle<JSArrayBuffer> buffer, int offset) { |
| 47 return static_cast<byte*>(buffer.ToHandleChecked()->backing_store()) + offset; | 48 return static_cast<byte*>(buffer.ToHandleChecked()->backing_store()) + offset; |
| 48 } | 49 } |
| 49 | 50 |
| 50 void ReplaceReferenceInCode(Handle<Code> code, Handle<Object> old_ref, | |
| 51 Handle<Object> new_ref) { | |
| 52 for (RelocIterator it(*code, 1 << RelocInfo::EMBEDDED_OBJECT); !it.done(); | |
| 53 it.next()) { | |
| 54 if (it.rinfo()->target_object() == *old_ref) { | |
| 55 it.rinfo()->set_target_object(*new_ref); | |
| 56 } | |
| 57 } | |
| 58 } | |
| 59 | |
| 60 static void MemoryFinalizer(const v8::WeakCallbackInfo<void>& data) { | 51 static void MemoryFinalizer(const v8::WeakCallbackInfo<void>& data) { |
| 61 DisallowHeapAllocation no_gc; | 52 DisallowHeapAllocation no_gc; |
| 62 JSArrayBuffer** p = reinterpret_cast<JSArrayBuffer**>(data.GetParameter()); | 53 JSArrayBuffer** p = reinterpret_cast<JSArrayBuffer**>(data.GetParameter()); |
| 63 JSArrayBuffer* buffer = *p; | 54 JSArrayBuffer* buffer = *p; |
| 64 | 55 |
| 65 if (!buffer->was_neutered()) { | 56 if (!buffer->was_neutered()) { |
| 66 void* memory = buffer->backing_store(); | 57 void* memory = buffer->backing_store(); |
| 67 DCHECK(memory != nullptr); | 58 DCHECK(memory != nullptr); |
| 68 base::OS::Free(memory, | 59 base::OS::Free(memory, |
| 69 RoundUp(kWasmMaxHeapOffset, base::OS::CommitPageSize())); | 60 RoundUp(kWasmMaxHeapOffset, base::OS::CommitPageSize())); |
| (...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 115 ->AdjustAmountOfExternalAllocatedMemory(size); | 106 ->AdjustAmountOfExternalAllocatedMemory(size); |
| 116 | 107 |
| 117 is_external = true; | 108 is_external = true; |
| 118 return memory; | 109 return memory; |
| 119 } else { | 110 } else { |
| 120 void* memory = isolate->array_buffer_allocator()->Allocate(size); | 111 void* memory = isolate->array_buffer_allocator()->Allocate(size); |
| 121 return memory; | 112 return memory; |
| 122 } | 113 } |
| 123 } | 114 } |
| 124 | 115 |
| 125 void RelocateMemoryReferencesInCode(Handle<FixedArray> code_table, | |
| 126 uint32_t num_imported_functions, | |
| 127 Address old_start, Address start, | |
| 128 uint32_t prev_size, uint32_t new_size) { | |
| 129 for (int i = static_cast<int>(num_imported_functions); | |
| 130 i < code_table->length(); ++i) { | |
| 131 DCHECK(code_table->get(i)->IsCode()); | |
| 132 Handle<Code> code = Handle<Code>(Code::cast(code_table->get(i))); | |
| 133 AllowDeferredHandleDereference embedding_raw_address; | |
| 134 int mask = (1 << RelocInfo::WASM_MEMORY_REFERENCE) | | |
| 135 (1 << RelocInfo::WASM_MEMORY_SIZE_REFERENCE); | |
| 136 for (RelocIterator it(*code, mask); !it.done(); it.next()) { | |
| 137 it.rinfo()->update_wasm_memory_reference(old_start, start, prev_size, | |
| 138 new_size); | |
| 139 } | |
| 140 } | |
| 141 } | |
| 142 | |
| 143 void RelocateGlobals(Handle<FixedArray> code_table, Address old_start, | |
| 144 Address globals_start) { | |
| 145 for (int i = 0; i < code_table->length(); ++i) { | |
| 146 DCHECK(code_table->get(i)->IsCode()); | |
| 147 Handle<Code> code = Handle<Code>(Code::cast(code_table->get(i))); | |
| 148 AllowDeferredHandleDereference embedding_raw_address; | |
| 149 int mask = 1 << RelocInfo::WASM_GLOBAL_REFERENCE; | |
| 150 for (RelocIterator it(*code, mask); !it.done(); it.next()) { | |
| 151 it.rinfo()->update_wasm_global_reference(old_start, globals_start); | |
| 152 } | |
| 153 } | |
| 154 } | |
| 155 | |
| 156 void RelocateTableSizeReferences(Handle<FixedArray> code_table, | |
| 157 uint32_t old_size, uint32_t new_size) { | |
| 158 for (int i = 0; i < code_table->length(); ++i) { | |
| 159 DCHECK(code_table->get(i)->IsCode()); | |
| 160 Handle<Code> code = Handle<Code>(Code::cast(code_table->get(i))); | |
| 161 AllowDeferredHandleDereference embedding_raw_address; | |
| 162 int mask = 1 << RelocInfo::WASM_FUNCTION_TABLE_SIZE_REFERENCE; | |
| 163 for (RelocIterator it(*code, mask); !it.done(); it.next()) { | |
| 164 it.rinfo()->update_wasm_function_table_size_reference(old_size, new_size); | |
| 165 } | |
| 166 } | |
| 167 } | |
| 168 | |
| 169 void FlushICache(Isolate* isolate, Handle<FixedArray> code_table) { | 116 void FlushICache(Isolate* isolate, Handle<FixedArray> code_table) { |
| 170 for (int i = 0; i < code_table->length(); ++i) { | 117 for (int i = 0; i < code_table->length(); ++i) { |
| 171 Handle<Code> code = code_table->GetValueChecked<Code>(isolate, i); | 118 Handle<Code> code = code_table->GetValueChecked<Code>(isolate, i); |
| 172 Assembler::FlushICache(isolate, code->instruction_start(), | 119 Assembler::FlushICache(isolate, code->instruction_start(), |
| 173 code->instruction_size()); | 120 code->instruction_size()); |
| 174 } | 121 } |
| 175 } | 122 } |
| 176 | 123 |
| 177 // Fetches the compilation unit of a wasm function and executes its parallel | 124 // Fetches the compilation unit of a wasm function and executes its parallel |
| 178 // phase. | 125 // phase. |
| (...skipping 60 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 239 code->relocation_info()->length()); | 186 code->relocation_info()->length()); |
| 240 } | 187 } |
| 241 | 188 |
| 242 static void RecordStats(Isolate* isolate, Handle<FixedArray> functions) { | 189 static void RecordStats(Isolate* isolate, Handle<FixedArray> functions) { |
| 243 DisallowHeapAllocation no_gc; | 190 DisallowHeapAllocation no_gc; |
| 244 for (int i = 0; i < functions->length(); ++i) { | 191 for (int i = 0; i < functions->length(); ++i) { |
| 245 RecordStats(isolate, Code::cast(functions->get(i))); | 192 RecordStats(isolate, Code::cast(functions->get(i))); |
| 246 } | 193 } |
| 247 } | 194 } |
| 248 | 195 |
| 249 Address GetGlobalStartAddressFromCodeTemplate(Object* undefined, | |
| 250 JSObject* object) { | |
| 251 auto instance = WasmInstanceObject::cast(object); | |
| 252 Address old_address = nullptr; | |
| 253 if (instance->has_globals_buffer()) { | |
| 254 old_address = | |
| 255 static_cast<Address>(instance->globals_buffer()->backing_store()); | |
| 256 } | |
| 257 return old_address; | |
| 258 } | |
| 259 | |
| 260 void InitializeParallelCompilation( | 196 void InitializeParallelCompilation( |
| 261 Isolate* isolate, const std::vector<WasmFunction>& functions, | 197 Isolate* isolate, const std::vector<WasmFunction>& functions, |
| 262 std::vector<compiler::WasmCompilationUnit*>& compilation_units, | 198 std::vector<compiler::WasmCompilationUnit*>& compilation_units, |
| 263 ModuleBytesEnv& module_env, ErrorThrower* thrower) { | 199 ModuleBytesEnv& module_env, ErrorThrower* thrower) { |
| 264 for (uint32_t i = FLAG_skip_compiling_wasm_funcs; i < functions.size(); ++i) { | 200 for (uint32_t i = FLAG_skip_compiling_wasm_funcs; i < functions.size(); ++i) { |
| 265 const WasmFunction* func = &functions[i]; | 201 const WasmFunction* func = &functions[i]; |
| 266 compilation_units[i] = | 202 compilation_units[i] = |
| 267 func->imported ? nullptr : new compiler::WasmCompilationUnit( | 203 func->imported ? nullptr : new compiler::WasmCompilationUnit( |
| 268 thrower, isolate, &module_env, func, i); | 204 thrower, isolate, &module_env, func, i); |
| 269 } | 205 } |
| (...skipping 138 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 408 WasmName str = module_env->wire_bytes.GetName(&func); | 344 WasmName str = module_env->wire_bytes.GetName(&func); |
| 409 thrower->CompileError("Compilation of #%d:%.*s failed.", i, str.length(), | 345 thrower->CompileError("Compilation of #%d:%.*s failed.", i, str.length(), |
| 410 str.start()); | 346 str.start()); |
| 411 break; | 347 break; |
| 412 } | 348 } |
| 413 // Install the code into the linker table. | 349 // Install the code into the linker table. |
| 414 functions[i] = code; | 350 functions[i] = code; |
| 415 } | 351 } |
| 416 } | 352 } |
| 417 | 353 |
| 418 int ExtractDirectCallIndex(wasm::Decoder& decoder, const byte* pc) { | |
| 419 DCHECK_EQ(static_cast<int>(kExprCallFunction), static_cast<int>(*pc)); | |
| 420 decoder.Reset(pc + 1, pc + 6); | |
| 421 uint32_t call_idx = decoder.consume_u32v("call index"); | |
| 422 DCHECK(decoder.ok()); | |
| 423 DCHECK_GE(kMaxInt, call_idx); | |
| 424 return static_cast<int>(call_idx); | |
| 425 } | |
| 426 | |
| 427 int AdvanceSourcePositionTableIterator(SourcePositionTableIterator& iterator, | |
| 428 size_t offset_l) { | |
| 429 DCHECK_GE(kMaxInt, offset_l); | |
| 430 int offset = static_cast<int>(offset_l); | |
| 431 DCHECK(!iterator.done()); | |
| 432 int byte_pos; | |
| 433 do { | |
| 434 byte_pos = iterator.source_position().ScriptOffset(); | |
| 435 iterator.Advance(); | |
| 436 } while (!iterator.done() && iterator.code_offset() <= offset); | |
| 437 return byte_pos; | |
| 438 } | |
| 439 | |
| 440 void PatchContext(RelocIterator& it, Context* context) { | |
| 441 Object* old = it.rinfo()->target_object(); | |
| 442 // The only context we use is the native context. | |
| 443 DCHECK_IMPLIES(old->IsContext(), old->IsNativeContext()); | |
| 444 if (!old->IsNativeContext()) return; | |
| 445 it.rinfo()->set_target_object(context, UPDATE_WRITE_BARRIER, | |
| 446 SKIP_ICACHE_FLUSH); | |
| 447 } | |
| 448 | |
| 449 void PatchDirectCallsAndContext(Handle<FixedArray> new_functions, | |
| 450 Handle<WasmCompiledModule> compiled_module, | |
| 451 WasmModule* module, int start) { | |
| 452 DisallowHeapAllocation no_gc; | |
| 453 AllowDeferredHandleDereference embedding_raw_address; | |
| 454 SeqOneByteString* module_bytes = compiled_module->module_bytes(); | |
| 455 std::vector<WasmFunction>* wasm_functions = | |
| 456 &compiled_module->module()->functions; | |
| 457 DCHECK_EQ(wasm_functions->size() + | |
| 458 compiled_module->module()->num_exported_functions, | |
| 459 new_functions->length()); | |
| 460 DCHECK_EQ(start, compiled_module->module()->num_imported_functions); | |
| 461 Context* context = compiled_module->ptr_to_native_context(); | |
| 462 int mode_mask = RelocInfo::ModeMask(RelocInfo::CODE_TARGET) | | |
| 463 RelocInfo::ModeMask(RelocInfo::EMBEDDED_OBJECT); | |
| 464 | |
| 465 // Allocate decoder outside of the loop and reuse it to decode all function | |
| 466 // indexes. | |
| 467 wasm::Decoder decoder(nullptr, nullptr); | |
| 468 int num_wasm_functions = static_cast<int>(wasm_functions->size()); | |
| 469 int func_index = start; | |
| 470 // We patch WASM_FUNCTION and WASM_TO_JS_FUNCTION during re-instantiation, | |
| 471 // and illegal builtins initially and after deserialization. | |
| 472 auto is_at_wasm_call = [](RelocIterator& it) { | |
| 473 Code* code = Code::GetCodeFromTargetAddress(it.rinfo()->target_address()); | |
| 474 return code->kind() == Code::WASM_FUNCTION || | |
| 475 code->kind() == Code::WASM_TO_JS_FUNCTION || | |
| 476 code->builtin_index() == Builtins::kIllegal; | |
| 477 }; | |
| 478 | |
| 479 // Patch all wasm functions. | |
| 480 for (; func_index < num_wasm_functions; ++func_index) { | |
| 481 Code* wasm_function = Code::cast(new_functions->get(func_index)); | |
| 482 DCHECK(wasm_function->kind() == Code::WASM_FUNCTION); | |
| 483 // Iterate simultaneously over the relocation information and the source | |
| 484 // position table. For each call in the reloc info, move the source position | |
| 485 // iterator forward to that position to find the byte offset of the | |
| 486 // respective call. Then extract the call index from the module wire bytes | |
| 487 // to find the new compiled function. | |
| 488 SourcePositionTableIterator source_pos_iterator( | |
| 489 wasm_function->source_position_table()); | |
| 490 const byte* func_bytes = | |
| 491 module_bytes->GetChars() + | |
| 492 compiled_module->module()->functions[func_index].code_start_offset; | |
| 493 for (RelocIterator it(wasm_function, mode_mask); !it.done(); it.next()) { | |
| 494 if (RelocInfo::IsEmbeddedObject(it.rinfo()->rmode())) { | |
| 495 PatchContext(it, context); | |
| 496 continue; | |
| 497 } | |
| 498 DCHECK(RelocInfo::IsCodeTarget(it.rinfo()->rmode())); | |
| 499 if (!is_at_wasm_call(it)) continue; | |
| 500 size_t offset = it.rinfo()->pc() - wasm_function->instruction_start(); | |
| 501 int byte_pos = | |
| 502 AdvanceSourcePositionTableIterator(source_pos_iterator, offset); | |
| 503 int called_func_index = | |
| 504 ExtractDirectCallIndex(decoder, func_bytes + byte_pos); | |
| 505 Code* new_code = Code::cast(new_functions->get(called_func_index)); | |
| 506 it.rinfo()->set_target_address(new_code->instruction_start(), | |
| 507 UPDATE_WRITE_BARRIER, SKIP_ICACHE_FLUSH); | |
| 508 } | |
| 509 } | |
| 510 // Patch all exported functions. | |
| 511 for (auto exp : module->export_table) { | |
| 512 if (exp.kind != kExternalFunction) continue; | |
| 513 Code* export_wrapper = Code::cast(new_functions->get(func_index)); | |
| 514 DCHECK_EQ(Code::JS_TO_WASM_FUNCTION, export_wrapper->kind()); | |
| 515 // There must be exactly one call to WASM_FUNCTION or WASM_TO_JS_FUNCTION. | |
| 516 int num_wasm_calls = 0; | |
| 517 for (RelocIterator it(export_wrapper, mode_mask); !it.done(); it.next()) { | |
| 518 if (RelocInfo::IsEmbeddedObject(it.rinfo()->rmode())) { | |
| 519 PatchContext(it, context); | |
| 520 continue; | |
| 521 } | |
| 522 DCHECK(RelocInfo::IsCodeTarget(it.rinfo()->rmode())); | |
| 523 if (!is_at_wasm_call(it)) continue; | |
| 524 ++num_wasm_calls; | |
| 525 Code* new_code = Code::cast(new_functions->get(exp.index)); | |
| 526 DCHECK(new_code->kind() == Code::WASM_FUNCTION || | |
| 527 new_code->kind() == Code::WASM_TO_JS_FUNCTION); | |
| 528 it.rinfo()->set_target_address(new_code->instruction_start(), | |
| 529 UPDATE_WRITE_BARRIER, SKIP_ICACHE_FLUSH); | |
| 530 } | |
| 531 DCHECK_EQ(1, num_wasm_calls); | |
| 532 func_index++; | |
| 533 } | |
| 534 DCHECK_EQ(new_functions->length(), func_index); | |
| 535 } | |
| 536 | |
| 537 static void ResetCompiledModule(Isolate* isolate, WasmInstanceObject* owner, | 354 static void ResetCompiledModule(Isolate* isolate, WasmInstanceObject* owner, |
| 538 WasmCompiledModule* compiled_module) { | 355 WasmCompiledModule* compiled_module) { |
| 539 TRACE("Resetting %d\n", compiled_module->instance_id()); | 356 TRACE("Resetting %d\n", compiled_module->instance_id()); |
| 540 Object* undefined = *isolate->factory()->undefined_value(); | 357 Object* undefined = *isolate->factory()->undefined_value(); |
| 541 uint32_t old_mem_size = compiled_module->mem_size(); | 358 Object* fct_obj = compiled_module->ptr_to_code_table(); |
| 542 uint32_t default_mem_size = compiled_module->default_mem_size(); | 359 if (fct_obj != nullptr && fct_obj != undefined) { |
| 543 Object* mem_start = compiled_module->maybe_ptr_to_memory(); | 360 uint32_t old_mem_size = compiled_module->mem_size(); |
| 544 Address old_mem_address = nullptr; | 361 uint32_t default_mem_size = compiled_module->default_mem_size(); |
| 545 Address globals_start = | 362 Object* mem_start = compiled_module->maybe_ptr_to_memory(); |
| 546 GetGlobalStartAddressFromCodeTemplate(undefined, owner); | |
| 547 | 363 |
| 548 // Reset function tables. | 364 // Patch code to update memory references, global references, and function |
| 549 FixedArray* function_tables = nullptr; | 365 // table references. |
| 550 FixedArray* empty_function_tables = nullptr; | 366 Zone specialization_zone(isolate->allocator(), ZONE_NAME); |
| 551 if (compiled_module->has_function_tables()) { | 367 CodeSpecialization code_specialization(isolate, &specialization_zone); |
| 552 function_tables = compiled_module->ptr_to_function_tables(); | |
| 553 empty_function_tables = compiled_module->ptr_to_empty_function_tables(); | |
| 554 compiled_module->set_ptr_to_function_tables(empty_function_tables); | |
| 555 } | |
| 556 | 368 |
| 557 if (old_mem_size > 0) { | 369 if (old_mem_size > 0) { |
| 558 CHECK_NE(mem_start, undefined); | 370 CHECK_NE(mem_start, undefined); |
| 559 old_mem_address = | 371 Address old_mem_address = |
| 560 static_cast<Address>(JSArrayBuffer::cast(mem_start)->backing_store()); | 372 static_cast<Address>(JSArrayBuffer::cast(mem_start)->backing_store()); |
| 561 } | 373 code_specialization.RelocateMemoryReferences( |
| 562 int mode_mask = RelocInfo::ModeMask(RelocInfo::WASM_MEMORY_REFERENCE) | | 374 old_mem_address, old_mem_size, nullptr, default_mem_size); |
| 563 RelocInfo::ModeMask(RelocInfo::WASM_MEMORY_SIZE_REFERENCE) | | 375 } |
| 564 RelocInfo::ModeMask(RelocInfo::WASM_GLOBAL_REFERENCE) | | |
| 565 RelocInfo::ModeMask(RelocInfo::EMBEDDED_OBJECT); | |
| 566 | 376 |
| 567 // Patch code to update memory references, global references, and function | 377 if (owner->has_globals_buffer()) { |
| 568 // table references. | 378 Address globals_start = |
| 569 Object* fct_obj = compiled_module->ptr_to_code_table(); | 379 static_cast<Address>(owner->globals_buffer()->backing_store()); |
| 570 if (fct_obj != nullptr && fct_obj != undefined && | 380 code_specialization.RelocateGlobals(globals_start, nullptr); |
| 571 (old_mem_size > 0 || globals_start != nullptr || function_tables)) { | 381 } |
| 382 |
| 383 // Reset function tables. |
| 384 if (compiled_module->has_function_tables()) { |
| 385 FixedArray* function_tables = compiled_module->ptr_to_function_tables(); |
| 386 FixedArray* empty_function_tables = |
| 387 compiled_module->ptr_to_empty_function_tables(); |
| 388 DCHECK_EQ(function_tables->length(), empty_function_tables->length()); |
| 389 for (int i = 0, e = function_tables->length(); i < e; ++i) { |
| 390 code_specialization.RelocateObject( |
| 391 handle(function_tables->get(i), isolate), |
| 392 handle(empty_function_tables->get(i), isolate)); |
| 393 } |
| 394 compiled_module->set_ptr_to_function_tables(empty_function_tables); |
| 395 } |
| 396 |
| 572 FixedArray* functions = FixedArray::cast(fct_obj); | 397 FixedArray* functions = FixedArray::cast(fct_obj); |
| 573 for (int i = compiled_module->num_imported_functions(); | 398 for (int i = compiled_module->num_imported_functions(), |
| 574 i < functions->length(); ++i) { | 399 end = functions->length(); |
| 400 i < end; ++i) { |
| 575 Code* code = Code::cast(functions->get(i)); | 401 Code* code = Code::cast(functions->get(i)); |
| 576 bool changed = false; | 402 if (code->kind() != Code::WASM_FUNCTION) { |
| 577 for (RelocIterator it(code, mode_mask); !it.done(); it.next()) { | 403 // From here on, there should only be wrappers for exported functions. |
| 578 RelocInfo::Mode mode = it.rinfo()->rmode(); | 404 for (; i < end; ++i) { |
| 579 if (RelocInfo::IsWasmMemoryReference(mode) || | 405 DCHECK_EQ(Code::JS_TO_WASM_FUNCTION, |
| 580 RelocInfo::IsWasmMemorySizeReference(mode)) { | 406 Code::cast(functions->get(i))->kind()); |
| 581 it.rinfo()->update_wasm_memory_reference( | |
| 582 old_mem_address, nullptr, old_mem_size, default_mem_size); | |
| 583 changed = true; | |
| 584 } else if (RelocInfo::IsWasmGlobalReference(mode)) { | |
| 585 it.rinfo()->update_wasm_global_reference(globals_start, nullptr); | |
| 586 changed = true; | |
| 587 } else if (RelocInfo::IsEmbeddedObject(mode) && function_tables) { | |
| 588 Object* old = it.rinfo()->target_object(); | |
| 589 for (int j = 0; j < function_tables->length(); ++j) { | |
| 590 if (function_tables->get(j) == old) { | |
| 591 it.rinfo()->set_target_object(empty_function_tables->get(j)); | |
| 592 changed = true; | |
| 593 } | |
| 594 } | |
| 595 } | 407 } |
| 408 break; |
| 596 } | 409 } |
| 410 bool changed = |
| 411 code_specialization.ApplyToWasmCode(code, SKIP_ICACHE_FLUSH); |
| 412 // TODO(wasm): Check if this is faster than passing FLUSH_ICACHE_IF_NEEDED |
| 413 // above. |
| 597 if (changed) { | 414 if (changed) { |
| 598 Assembler::FlushICache(isolate, code->instruction_start(), | 415 Assembler::FlushICache(isolate, code->instruction_start(), |
| 599 code->instruction_size()); | 416 code->instruction_size()); |
| 600 } | 417 } |
| 601 } | 418 } |
| 602 } | 419 } |
| 603 compiled_module->reset_memory(); | 420 compiled_module->reset_memory(); |
| 604 } | 421 } |
| 605 | 422 |
| 606 static void MemoryInstanceFinalizer(Isolate* isolate, | 423 static void MemoryInstanceFinalizer(Isolate* isolate, |
| (...skipping 144 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 751 | 568 |
| 752 int name_chars = SNPrintF(ArrayVector(buffer), "wasm-%08x", hash); | 569 int name_chars = SNPrintF(ArrayVector(buffer), "wasm-%08x", hash); |
| 753 DCHECK(name_chars >= 0 && name_chars < kBufferSize); | 570 DCHECK(name_chars >= 0 && name_chars < kBufferSize); |
| 754 MaybeHandle<String> name_str = isolate->factory()->NewStringFromOneByte( | 571 MaybeHandle<String> name_str = isolate->factory()->NewStringFromOneByte( |
| 755 Vector<const uint8_t>(reinterpret_cast<uint8_t*>(buffer), name_chars), | 572 Vector<const uint8_t>(reinterpret_cast<uint8_t*>(buffer), name_chars), |
| 756 TENURED); | 573 TENURED); |
| 757 script->set_name(*name_str.ToHandleChecked()); | 574 script->set_name(*name_str.ToHandleChecked()); |
| 758 | 575 |
| 759 return script; | 576 return script; |
| 760 } | 577 } |
| 578 |
| 761 } // namespace | 579 } // namespace |
| 762 | 580 |
| 763 Handle<JSArrayBuffer> SetupArrayBuffer(Isolate* isolate, void* backing_store, | 581 Handle<JSArrayBuffer> SetupArrayBuffer(Isolate* isolate, void* backing_store, |
| 764 size_t size, bool is_external, | 582 size_t size, bool is_external, |
| 765 bool enable_guard_regions) { | 583 bool enable_guard_regions) { |
| 766 Handle<JSArrayBuffer> buffer = isolate->factory()->NewJSArrayBuffer(); | 584 Handle<JSArrayBuffer> buffer = isolate->factory()->NewJSArrayBuffer(); |
| 767 JSArrayBuffer::Setup(buffer, isolate, is_external, backing_store, | 585 JSArrayBuffer::Setup(buffer, isolate, is_external, backing_store, |
| 768 static_cast<int>(size)); | 586 static_cast<int>(size)); |
| 769 buffer->set_is_neuterable(false); | 587 buffer->set_is_neuterable(false); |
| 770 buffer->set_has_guard_region(enable_guard_regions); | 588 buffer->set_has_guard_region(enable_guard_regions); |
| (...skipping 466 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1237 TRACE("Reusing existing instance %d\n", | 1055 TRACE("Reusing existing instance %d\n", |
| 1238 compiled_module_->instance_id()); | 1056 compiled_module_->instance_id()); |
| 1239 } | 1057 } |
| 1240 compiled_module_->set_code_table(code_table); | 1058 compiled_module_->set_code_table(code_table); |
| 1241 compiled_module_->set_native_context(isolate_->native_context()); | 1059 compiled_module_->set_native_context(isolate_->native_context()); |
| 1242 } | 1060 } |
| 1243 | 1061 |
| 1244 //-------------------------------------------------------------------------- | 1062 //-------------------------------------------------------------------------- |
| 1245 // Allocate the instance object. | 1063 // Allocate the instance object. |
| 1246 //-------------------------------------------------------------------------- | 1064 //-------------------------------------------------------------------------- |
| 1065 Zone instantiation_zone(isolate_->allocator(), ZONE_NAME); |
| 1066 CodeSpecialization code_specialization(isolate_, &instantiation_zone); |
| 1247 Handle<WasmInstanceObject> instance = | 1067 Handle<WasmInstanceObject> instance = |
| 1248 WasmInstanceObject::New(isolate_, compiled_module_); | 1068 WasmInstanceObject::New(isolate_, compiled_module_); |
| 1249 | 1069 |
| 1250 //-------------------------------------------------------------------------- | 1070 //-------------------------------------------------------------------------- |
| 1251 // Set up the globals for the new instance. | 1071 // Set up the globals for the new instance. |
| 1252 //-------------------------------------------------------------------------- | 1072 //-------------------------------------------------------------------------- |
| 1253 MaybeHandle<JSArrayBuffer> old_globals; | 1073 MaybeHandle<JSArrayBuffer> old_globals; |
| 1254 uint32_t globals_size = module_->globals_size; | 1074 uint32_t globals_size = module_->globals_size; |
| 1255 if (globals_size > 0) { | 1075 if (globals_size > 0) { |
| 1256 const bool enable_guard_regions = false; | 1076 const bool enable_guard_regions = false; |
| 1257 Handle<JSArrayBuffer> global_buffer = | 1077 Handle<JSArrayBuffer> global_buffer = |
| 1258 NewArrayBuffer(isolate_, globals_size, enable_guard_regions); | 1078 NewArrayBuffer(isolate_, globals_size, enable_guard_regions); |
| 1259 globals_ = global_buffer; | 1079 globals_ = global_buffer; |
| 1260 if (globals_.is_null()) { | 1080 if (globals_.is_null()) { |
| 1261 thrower_->RangeError("Out of memory: wasm globals"); | 1081 thrower_->RangeError("Out of memory: wasm globals"); |
| 1262 return nothing; | 1082 return nothing; |
| 1263 } | 1083 } |
| 1264 Address old_address = | 1084 Address old_globals_start = nullptr; |
| 1265 owner.is_null() ? nullptr : GetGlobalStartAddressFromCodeTemplate( | 1085 if (!owner.is_null()) { |
| 1266 isolate_->heap()->undefined_value(), | 1086 DCHECK(owner.ToHandleChecked()->has_globals_buffer()); |
| 1267 *owner.ToHandleChecked()); | 1087 old_globals_start = static_cast<Address>( |
| 1268 RelocateGlobals(code_table, old_address, | 1088 owner.ToHandleChecked()->globals_buffer()->backing_store()); |
| 1269 static_cast<Address>(global_buffer->backing_store())); | 1089 } |
| 1090 Address new_globals_start = |
| 1091 static_cast<Address>(global_buffer->backing_store()); |
| 1092 code_specialization.RelocateGlobals(old_globals_start, new_globals_start); |
| 1270 instance->set_globals_buffer(*global_buffer); | 1093 instance->set_globals_buffer(*global_buffer); |
| 1271 } | 1094 } |
| 1272 | 1095 |
| 1273 //-------------------------------------------------------------------------- | 1096 //-------------------------------------------------------------------------- |
| 1274 // Prepare for initialization of function tables. | 1097 // Prepare for initialization of function tables. |
| 1275 //-------------------------------------------------------------------------- | 1098 //-------------------------------------------------------------------------- |
| 1276 int function_table_count = | 1099 int function_table_count = |
| 1277 static_cast<int>(module_->function_tables.size()); | 1100 static_cast<int>(module_->function_tables.size()); |
| 1278 table_instances_.reserve(module_->function_tables.size()); | 1101 table_instances_.reserve(module_->function_tables.size()); |
| 1279 for (int index = 0; index < function_table_count; ++index) { | 1102 for (int index = 0; index < function_table_count; ++index) { |
| 1280 table_instances_.push_back( | 1103 table_instances_.push_back( |
| 1281 {Handle<WasmTableObject>::null(), Handle<FixedArray>::null(), | 1104 {Handle<WasmTableObject>::null(), Handle<FixedArray>::null(), |
| 1282 Handle<FixedArray>::null(), Handle<FixedArray>::null()}); | 1105 Handle<FixedArray>::null(), Handle<FixedArray>::null()}); |
| 1283 } | 1106 } |
| 1284 | 1107 |
| 1285 //-------------------------------------------------------------------------- | 1108 //-------------------------------------------------------------------------- |
| 1286 // Process the imports for the module. | 1109 // Process the imports for the module. |
| 1287 //-------------------------------------------------------------------------- | 1110 //-------------------------------------------------------------------------- |
| 1288 int num_imported_functions = ProcessImports(code_table, instance); | 1111 int num_imported_functions = ProcessImports(code_table, instance); |
| 1289 if (num_imported_functions < 0) return nothing; | 1112 if (num_imported_functions < 0) return nothing; |
| 1290 | 1113 |
| 1291 //-------------------------------------------------------------------------- | 1114 //-------------------------------------------------------------------------- |
| 1292 // Process the initialization for the module's globals. | 1115 // Process the initialization for the module's globals. |
| 1293 //-------------------------------------------------------------------------- | 1116 //-------------------------------------------------------------------------- |
| 1294 InitGlobals(); | 1117 InitGlobals(); |
| 1295 | 1118 |
| 1296 //-------------------------------------------------------------------------- | 1119 //-------------------------------------------------------------------------- |
| 1297 // Set up the indirect function tables for the new instance. | 1120 // Set up the indirect function tables for the new instance. |
| 1298 //-------------------------------------------------------------------------- | 1121 //-------------------------------------------------------------------------- |
| 1299 if (function_table_count > 0) InitializeTables(code_table, instance); | 1122 if (function_table_count > 0) |
| 1123 InitializeTables(code_table, instance, &code_specialization); |
| 1300 | 1124 |
| 1301 //-------------------------------------------------------------------------- | 1125 //-------------------------------------------------------------------------- |
| 1302 // Set up the memory for the new instance. | 1126 // Set up the memory for the new instance. |
| 1303 //-------------------------------------------------------------------------- | 1127 //-------------------------------------------------------------------------- |
| 1304 MaybeHandle<JSArrayBuffer> old_memory; | 1128 MaybeHandle<JSArrayBuffer> old_memory; |
| 1305 | 1129 |
| 1306 uint32_t min_mem_pages = module_->min_mem_pages; | 1130 uint32_t min_mem_pages = module_->min_mem_pages; |
| 1307 isolate_->counters()->wasm_min_mem_pages_count()->AddSample(min_mem_pages); | 1131 isolate_->counters()->wasm_min_mem_pages_count()->AddSample(min_mem_pages); |
| 1308 | 1132 |
| 1309 if (!memory_.is_null()) { | 1133 if (!memory_.is_null()) { |
| (...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1354 uint32_t mem_size = | 1178 uint32_t mem_size = |
| 1355 static_cast<uint32_t>(memory_->byte_length()->Number()); | 1179 static_cast<uint32_t>(memory_->byte_length()->Number()); |
| 1356 LoadDataSegments(mem_start, mem_size); | 1180 LoadDataSegments(mem_start, mem_size); |
| 1357 | 1181 |
| 1358 uint32_t old_mem_size = compiled_module_->mem_size(); | 1182 uint32_t old_mem_size = compiled_module_->mem_size(); |
| 1359 Address old_mem_start = | 1183 Address old_mem_start = |
| 1360 compiled_module_->has_memory() | 1184 compiled_module_->has_memory() |
| 1361 ? static_cast<Address>( | 1185 ? static_cast<Address>( |
| 1362 compiled_module_->memory()->backing_store()) | 1186 compiled_module_->memory()->backing_store()) |
| 1363 : nullptr; | 1187 : nullptr; |
| 1364 RelocateMemoryReferencesInCode( | 1188 code_specialization.RelocateMemoryReferences(old_mem_start, old_mem_size, |
| 1365 code_table, module_->num_imported_functions, old_mem_start, mem_start, | 1189 mem_start, mem_size); |
| 1366 old_mem_size, mem_size); | |
| 1367 compiled_module_->set_memory(memory_); | 1190 compiled_module_->set_memory(memory_); |
| 1368 } | 1191 } |
| 1369 | 1192 |
| 1370 //-------------------------------------------------------------------------- | 1193 //-------------------------------------------------------------------------- |
| 1371 // Set up the runtime support for the new instance. | 1194 // Set up the runtime support for the new instance. |
| 1372 //-------------------------------------------------------------------------- | 1195 //-------------------------------------------------------------------------- |
| 1373 Handle<WeakCell> weak_link = factory->NewWeakCell(instance); | 1196 Handle<WeakCell> weak_link = factory->NewWeakCell(instance); |
| 1374 | 1197 |
| 1375 for (int i = num_imported_functions + FLAG_skip_compiling_wasm_funcs; | 1198 for (int i = num_imported_functions + FLAG_skip_compiling_wasm_funcs; |
| 1376 i < code_table->length(); ++i) { | 1199 i < code_table->length(); ++i) { |
| (...skipping 18 matching lines...) Expand all Loading... |
| 1395 DCHECK(wasm::IsWasmInstance(*instance)); | 1218 DCHECK(wasm::IsWasmInstance(*instance)); |
| 1396 if (instance->has_memory_object()) { | 1219 if (instance->has_memory_object()) { |
| 1397 instance->memory_object()->AddInstance(isolate_, instance); | 1220 instance->memory_object()->AddInstance(isolate_, instance); |
| 1398 } | 1221 } |
| 1399 | 1222 |
| 1400 //-------------------------------------------------------------------------- | 1223 //-------------------------------------------------------------------------- |
| 1401 // Initialize the indirect function tables. | 1224 // Initialize the indirect function tables. |
| 1402 //-------------------------------------------------------------------------- | 1225 //-------------------------------------------------------------------------- |
| 1403 if (function_table_count > 0) LoadTableSegments(code_table, instance); | 1226 if (function_table_count > 0) LoadTableSegments(code_table, instance); |
| 1404 | 1227 |
| 1405 // Patch new call sites and the context. | 1228 // Patch all code with the relocations registered in code_specialization. |
| 1406 PatchDirectCallsAndContext(code_table, compiled_module_, module_, | 1229 { |
| 1407 num_imported_functions); | 1230 code_specialization.RelocateDirectCalls(instance); |
| 1231 code_specialization.ApplyToWholeInstance(*instance, SKIP_ICACHE_FLUSH); |
| 1232 } |
| 1408 | 1233 |
| 1409 FlushICache(isolate_, code_table); | 1234 FlushICache(isolate_, code_table); |
| 1410 | 1235 |
| 1411 //-------------------------------------------------------------------------- | 1236 //-------------------------------------------------------------------------- |
| 1412 // Unpack and notify signal handler of protected instructions. | 1237 // Unpack and notify signal handler of protected instructions. |
| 1413 //-------------------------------------------------------------------------- | 1238 //-------------------------------------------------------------------------- |
| 1414 if (FLAG_wasm_trap_handler) { | 1239 if (FLAG_wasm_trap_handler) { |
| 1415 for (int i = 0; i < code_table->length(); ++i) { | 1240 for (int i = 0; i < code_table->length(); ++i) { |
| 1416 Handle<Code> code = code_table->GetValueChecked<Code>(isolate_, i); | 1241 Handle<Code> code = code_table->GetValueChecked<Code>(isolate_, i); |
| 1417 | 1242 |
| (...skipping 674 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2092 | 1917 |
| 2093 if (module_->origin == kWasmOrigin) { | 1918 if (module_->origin == kWasmOrigin) { |
| 2094 v8::Maybe<bool> success = JSReceiver::SetIntegrityLevel( | 1919 v8::Maybe<bool> success = JSReceiver::SetIntegrityLevel( |
| 2095 exports_object, FROZEN, Object::DONT_THROW); | 1920 exports_object, FROZEN, Object::DONT_THROW); |
| 2096 DCHECK(success.FromMaybe(false)); | 1921 DCHECK(success.FromMaybe(false)); |
| 2097 USE(success); | 1922 USE(success); |
| 2098 } | 1923 } |
| 2099 } | 1924 } |
| 2100 | 1925 |
| 2101 void InitializeTables(Handle<FixedArray> code_table, | 1926 void InitializeTables(Handle<FixedArray> code_table, |
| 2102 Handle<WasmInstanceObject> instance) { | 1927 Handle<WasmInstanceObject> instance, |
| 1928 CodeSpecialization* code_specialization) { |
| 2103 int function_table_count = | 1929 int function_table_count = |
| 2104 static_cast<int>(module_->function_tables.size()); | 1930 static_cast<int>(module_->function_tables.size()); |
| 2105 Handle<FixedArray> new_function_tables = | 1931 Handle<FixedArray> new_function_tables = |
| 2106 isolate_->factory()->NewFixedArray(function_table_count); | 1932 isolate_->factory()->NewFixedArray(function_table_count); |
| 2107 Handle<FixedArray> new_signature_tables = | 1933 Handle<FixedArray> new_signature_tables = |
| 2108 isolate_->factory()->NewFixedArray(function_table_count); | 1934 isolate_->factory()->NewFixedArray(function_table_count); |
| 2109 for (int index = 0; index < function_table_count; ++index) { | 1935 for (int index = 0; index < function_table_count; ++index) { |
| 2110 WasmIndirectFunctionTable& table = module_->function_tables[index]; | 1936 WasmIndirectFunctionTable& table = module_->function_tables[index]; |
| 2111 TableInstance& table_instance = table_instances_[index]; | 1937 TableInstance& table_instance = table_instances_[index]; |
| 2112 int table_size = static_cast<int>(table.min_size); | 1938 int table_size = static_cast<int>(table.min_size); |
| 2113 | 1939 |
| 2114 if (table_instance.function_table.is_null()) { | 1940 if (table_instance.function_table.is_null()) { |
| 2115 // Create a new dispatch table if necessary. | 1941 // Create a new dispatch table if necessary. |
| 2116 table_instance.function_table = | 1942 table_instance.function_table = |
| 2117 isolate_->factory()->NewFixedArray(table_size); | 1943 isolate_->factory()->NewFixedArray(table_size); |
| 2118 table_instance.signature_table = | 1944 table_instance.signature_table = |
| 2119 isolate_->factory()->NewFixedArray(table_size); | 1945 isolate_->factory()->NewFixedArray(table_size); |
| 2120 for (int i = 0; i < table_size; ++i) { | 1946 for (int i = 0; i < table_size; ++i) { |
| 2121 // Fill the table with invalid signature indexes so that | 1947 // Fill the table with invalid signature indexes so that |
| 2122 // uninitialized entries will always fail the signature check. | 1948 // uninitialized entries will always fail the signature check. |
| 2123 table_instance.signature_table->set(i, | 1949 table_instance.signature_table->set(i, |
| 2124 Smi::FromInt(kInvalidSigIndex)); | 1950 Smi::FromInt(kInvalidSigIndex)); |
| 2125 } | 1951 } |
| 2126 } else { | 1952 } else { |
| 2127 // Table is imported, patch table bounds check | 1953 // Table is imported, patch table bounds check |
| 2128 DCHECK(table_size <= table_instance.function_table->length()); | 1954 DCHECK(table_size <= table_instance.function_table->length()); |
| 2129 if (table_size < table_instance.function_table->length()) { | 1955 if (table_size < table_instance.function_table->length()) { |
| 2130 RelocateTableSizeReferences(code_table, table_size, | 1956 code_specialization->PatchTableSize( |
| 2131 table_instance.function_table->length()); | 1957 table_size, table_instance.function_table->length()); |
| 2132 } | 1958 } |
| 2133 } | 1959 } |
| 2134 | 1960 |
| 2135 new_function_tables->set(static_cast<int>(index), | 1961 new_function_tables->set(static_cast<int>(index), |
| 2136 *table_instance.function_table); | 1962 *table_instance.function_table); |
| 2137 new_signature_tables->set(static_cast<int>(index), | 1963 new_signature_tables->set(static_cast<int>(index), |
| 2138 *table_instance.signature_table); | 1964 *table_instance.signature_table); |
| 2139 } | 1965 } |
| 2140 | 1966 |
| 2141 // Patch all code that has references to the old indirect tables. | 1967 FixedArray* old_function_tables = |
| 2142 Handle<FixedArray> old_function_tables = | 1968 compiled_module_->ptr_to_function_tables(); |
| 2143 compiled_module_->function_tables(); | 1969 DCHECK_EQ(old_function_tables->length(), new_function_tables->length()); |
| 2144 Handle<FixedArray> old_signature_tables = | 1970 for (int i = 0, e = new_function_tables->length(); i < e; ++i) { |
| 2145 compiled_module_->signature_tables(); | 1971 code_specialization->RelocateObject( |
| 2146 for (int i = 0; i < code_table->length(); ++i) { | 1972 handle(old_function_tables->get(i), isolate_), |
| 2147 if (!code_table->get(i)->IsCode()) continue; | 1973 handle(new_function_tables->get(i), isolate_)); |
| 2148 Handle<Code> code(Code::cast(code_table->get(i)), isolate_); | |
| 2149 for (int j = 0; j < function_table_count; ++j) { | |
| 2150 ReplaceReferenceInCode( | |
| 2151 code, Handle<Object>(old_function_tables->get(j), isolate_), | |
| 2152 Handle<Object>(new_function_tables->get(j), isolate_)); | |
| 2153 ReplaceReferenceInCode( | |
| 2154 code, Handle<Object>(old_signature_tables->get(j), isolate_), | |
| 2155 Handle<Object>(new_signature_tables->get(j), isolate_)); | |
| 2156 } | |
| 2157 } | 1974 } |
| 1975 FixedArray* old_signature_tables = |
| 1976 compiled_module_->ptr_to_signature_tables(); |
| 1977 DCHECK_EQ(old_signature_tables->length(), new_signature_tables->length()); |
| 1978 for (int i = 0, e = new_signature_tables->length(); i < e; ++i) { |
| 1979 code_specialization->RelocateObject( |
| 1980 handle(old_signature_tables->get(i), isolate_), |
| 1981 handle(new_signature_tables->get(i), isolate_)); |
| 1982 } |
| 1983 |
| 2158 compiled_module_->set_function_tables(new_function_tables); | 1984 compiled_module_->set_function_tables(new_function_tables); |
| 2159 compiled_module_->set_signature_tables(new_signature_tables); | 1985 compiled_module_->set_signature_tables(new_signature_tables); |
| 2160 } | 1986 } |
| 2161 | 1987 |
| 2162 void LoadTableSegments(Handle<FixedArray> code_table, | 1988 void LoadTableSegments(Handle<FixedArray> code_table, |
| 2163 Handle<WasmInstanceObject> instance) { | 1989 Handle<WasmInstanceObject> instance) { |
| 2164 int function_table_count = | 1990 int function_table_count = |
| 2165 static_cast<int>(module_->function_tables.size()); | 1991 static_cast<int>(module_->function_tables.size()); |
| 2166 for (int index = 0; index < function_table_count; ++index) { | 1992 for (int index = 0; index < function_table_count; ++index) { |
| 2167 WasmIndirectFunctionTable& table = module_->function_tables[index]; | 1993 WasmIndirectFunctionTable& table = module_->function_tables[index]; |
| (...skipping 169 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2337 if (old_size != 0) { | 2163 if (old_size != 0) { |
| 2338 memcpy(new_mem_start, old_mem_start, old_size); | 2164 memcpy(new_mem_start, old_mem_start, old_size); |
| 2339 } | 2165 } |
| 2340 return new_buffer; | 2166 return new_buffer; |
| 2341 } | 2167 } |
| 2342 | 2168 |
| 2343 void UncheckedUpdateInstanceMemory(Isolate* isolate, | 2169 void UncheckedUpdateInstanceMemory(Isolate* isolate, |
| 2344 Handle<WasmInstanceObject> instance, | 2170 Handle<WasmInstanceObject> instance, |
| 2345 Address old_mem_start, uint32_t old_size) { | 2171 Address old_mem_start, uint32_t old_size) { |
| 2346 DCHECK(instance->has_memory_buffer()); | 2172 DCHECK(instance->has_memory_buffer()); |
| 2347 Handle<JSArrayBuffer> new_buffer(instance->memory_buffer()); | 2173 Handle<JSArrayBuffer> mem_buffer(instance->memory_buffer()); |
| 2348 uint32_t new_size = new_buffer->byte_length()->Number(); | 2174 uint32_t new_size = mem_buffer->byte_length()->Number(); |
| 2349 DCHECK(new_size <= std::numeric_limits<uint32_t>::max()); | 2175 Address new_mem_start = static_cast<Address>(mem_buffer->backing_store()); |
| 2350 Address new_mem_start = static_cast<Address>(new_buffer->backing_store()); | |
| 2351 DCHECK_NOT_NULL(new_mem_start); | 2176 DCHECK_NOT_NULL(new_mem_start); |
| 2352 Handle<FixedArray> code_table = instance->compiled_module()->code_table(); | 2177 Zone specialization_zone(isolate->allocator(), ZONE_NAME); |
| 2353 RelocateMemoryReferencesInCode( | 2178 CodeSpecialization code_specialization(isolate, &specialization_zone); |
| 2354 code_table, instance->compiled_module()->module()->num_imported_functions, | 2179 code_specialization.RelocateMemoryReferences(old_mem_start, old_size, |
| 2355 old_mem_start, new_mem_start, old_size, new_size); | 2180 new_mem_start, new_size); |
| 2181 code_specialization.ApplyToWholeInstance(*instance); |
| 2356 } | 2182 } |
| 2357 | 2183 |
| 2358 void DetachArrayBuffer(Isolate* isolate, Handle<JSArrayBuffer> buffer) { | 2184 void DetachArrayBuffer(Isolate* isolate, Handle<JSArrayBuffer> buffer) { |
| 2359 const bool has_guard_regions = | 2185 const bool has_guard_regions = |
| 2360 (!buffer.is_null() && buffer->has_guard_region()); | 2186 (!buffer.is_null() && buffer->has_guard_region()); |
| 2361 void* backing_store = buffer->backing_store(); | 2187 void* backing_store = buffer->backing_store(); |
| 2362 if (backing_store != nullptr) { | 2188 if (backing_store != nullptr) { |
| 2363 DCHECK(!buffer->is_neuterable()); | 2189 DCHECK(!buffer->is_neuterable()); |
| 2364 int64_t byte_length = NumberToSize(buffer->byte_length()); | 2190 int64_t byte_length = NumberToSize(buffer->byte_length()); |
| 2365 buffer->set_is_neuterable(true); | 2191 buffer->set_is_neuterable(true); |
| (...skipping 117 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2483 } else { | 2309 } else { |
| 2484 return GrowWebAssemblyMemory(isolate, handle(instance_obj->memory_object()), | 2310 return GrowWebAssemblyMemory(isolate, handle(instance_obj->memory_object()), |
| 2485 pages); | 2311 pages); |
| 2486 } | 2312 } |
| 2487 } | 2313 } |
| 2488 | 2314 |
| 2489 void wasm::GrowDispatchTables(Isolate* isolate, | 2315 void wasm::GrowDispatchTables(Isolate* isolate, |
| 2490 Handle<FixedArray> dispatch_tables, | 2316 Handle<FixedArray> dispatch_tables, |
| 2491 uint32_t old_size, uint32_t count) { | 2317 uint32_t old_size, uint32_t count) { |
| 2492 DCHECK_EQ(0, dispatch_tables->length() % 4); | 2318 DCHECK_EQ(0, dispatch_tables->length() % 4); |
| 2319 |
| 2320 Zone specialization_zone(isolate->allocator(), ZONE_NAME); |
| 2493 for (int i = 0; i < dispatch_tables->length(); i += 4) { | 2321 for (int i = 0; i < dispatch_tables->length(); i += 4) { |
| 2494 Handle<FixedArray> old_function_table( | 2322 Handle<FixedArray> old_function_table( |
| 2495 FixedArray::cast(dispatch_tables->get(i + 2))); | 2323 FixedArray::cast(dispatch_tables->get(i + 2))); |
| 2496 Handle<FixedArray> old_signature_table( | 2324 Handle<FixedArray> old_signature_table( |
| 2497 FixedArray::cast(dispatch_tables->get(i + 3))); | 2325 FixedArray::cast(dispatch_tables->get(i + 3))); |
| 2498 Handle<FixedArray> new_function_table = | 2326 Handle<FixedArray> new_function_table = |
| 2499 isolate->factory()->CopyFixedArrayAndGrow(old_function_table, count); | 2327 isolate->factory()->CopyFixedArrayAndGrow(old_function_table, count); |
| 2500 Handle<FixedArray> new_signature_table = | 2328 Handle<FixedArray> new_signature_table = |
| 2501 isolate->factory()->CopyFixedArrayAndGrow(old_signature_table, count); | 2329 isolate->factory()->CopyFixedArrayAndGrow(old_signature_table, count); |
| 2502 | 2330 |
| 2503 // Get code table for the instance | |
| 2504 Handle<WasmInstanceObject> instance( | |
| 2505 WasmInstanceObject::cast(dispatch_tables->get(i))); | |
| 2506 Handle<FixedArray> code_table(instance->compiled_module()->code_table()); | |
| 2507 | |
| 2508 // Relocate size references | |
| 2509 RelocateTableSizeReferences(code_table, old_size, old_size + count); | |
| 2510 | |
| 2511 // Replace references of old tables with new tables. | |
| 2512 for (int j = 0; j < code_table->length(); ++j) { | |
| 2513 if (!code_table->get(j)->IsCode()) continue; | |
| 2514 Handle<Code> code = Handle<Code>(Code::cast(code_table->get(j))); | |
| 2515 ReplaceReferenceInCode(code, old_function_table, new_function_table); | |
| 2516 ReplaceReferenceInCode(code, old_signature_table, new_signature_table); | |
| 2517 } | |
| 2518 | |
| 2519 // Update dispatch tables with new function/signature tables | 2331 // Update dispatch tables with new function/signature tables |
| 2520 dispatch_tables->set(i + 2, *new_function_table); | 2332 dispatch_tables->set(i + 2, *new_function_table); |
| 2521 dispatch_tables->set(i + 3, *new_signature_table); | 2333 dispatch_tables->set(i + 3, *new_signature_table); |
| 2334 |
| 2335 // Patch the code of the respective instance. |
| 2336 CodeSpecialization code_specialization(isolate, &specialization_zone); |
| 2337 code_specialization.PatchTableSize(old_size, old_size + count); |
| 2338 code_specialization.RelocateObject(old_function_table, new_function_table); |
| 2339 code_specialization.RelocateObject(old_signature_table, |
| 2340 new_signature_table); |
| 2341 code_specialization.ApplyToWholeInstance( |
| 2342 WasmInstanceObject::cast(dispatch_tables->get(i))); |
| 2522 } | 2343 } |
| 2523 } | 2344 } |
| 2524 | 2345 |
| 2525 void testing::ValidateInstancesChain(Isolate* isolate, | 2346 void testing::ValidateInstancesChain(Isolate* isolate, |
| 2526 Handle<WasmModuleObject> module_obj, | 2347 Handle<WasmModuleObject> module_obj, |
| 2527 int instance_count) { | 2348 int instance_count) { |
| 2528 CHECK_GE(instance_count, 0); | 2349 CHECK_GE(instance_count, 0); |
| 2529 DisallowHeapAllocation no_gc; | 2350 DisallowHeapAllocation no_gc; |
| 2530 WasmCompiledModule* compiled_module = module_obj->compiled_module(); | 2351 WasmCompiledModule* compiled_module = module_obj->compiled_module(); |
| 2531 CHECK_EQ(JSObject::cast(compiled_module->ptr_to_weak_wasm_module()->value()), | 2352 CHECK_EQ(JSObject::cast(compiled_module->ptr_to_weak_wasm_module()->value()), |
| (...skipping 369 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2901 Handle<String> module_property_name = | 2722 Handle<String> module_property_name = |
| 2902 isolate->factory()->InternalizeUtf8String("module"); | 2723 isolate->factory()->InternalizeUtf8String("module"); |
| 2903 Handle<String> instance_property_name = | 2724 Handle<String> instance_property_name = |
| 2904 isolate->factory()->InternalizeUtf8String("instance"); | 2725 isolate->factory()->InternalizeUtf8String("instance"); |
| 2905 JSObject::AddProperty(ret, module_property_name, module, NONE); | 2726 JSObject::AddProperty(ret, module_property_name, module, NONE); |
| 2906 JSObject::AddProperty(ret, instance_property_name, | 2727 JSObject::AddProperty(ret, instance_property_name, |
| 2907 instance_object.ToHandleChecked(), NONE); | 2728 instance_object.ToHandleChecked(), NONE); |
| 2908 | 2729 |
| 2909 ResolvePromise(isolate, promise, ret); | 2730 ResolvePromise(isolate, promise, ret); |
| 2910 } | 2731 } |
| OLD | NEW |