Chromium Code Reviews

Side by Side Diff: src/wasm/wasm-module.cc

Issue 2696143006: [wasm] Refactor code specialization / patching (Closed)
Patch Set: Remove unused variables and add documentation Created 3 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments.
Jump to:
View unified diff |
OLDNEW
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...)
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...)
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...)
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 CodeSpecialization code_specialization;
551 if (compiled_module->has_function_tables()) {
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 367
557 if (old_mem_size > 0) { 368 if (old_mem_size > 0) {
558 CHECK_NE(mem_start, undefined); 369 CHECK_NE(mem_start, undefined);
559 old_mem_address = 370 Address old_mem_address =
560 static_cast<Address>(JSArrayBuffer::cast(mem_start)->backing_store()); 371 static_cast<Address>(JSArrayBuffer::cast(mem_start)->backing_store());
561 } 372 code_specialization.RelocateMemoryReferences(
562 int mode_mask = RelocInfo::ModeMask(RelocInfo::WASM_MEMORY_REFERENCE) | 373 old_mem_address, old_mem_size, nullptr, default_mem_size);
563 RelocInfo::ModeMask(RelocInfo::WASM_MEMORY_SIZE_REFERENCE) | 374 }
564 RelocInfo::ModeMask(RelocInfo::WASM_GLOBAL_REFERENCE) |
565 RelocInfo::ModeMask(RelocInfo::EMBEDDED_OBJECT);
566 375
567 // Patch code to update memory references, global references, and function 376 if (owner->has_globals_buffer()) {
568 // table references. 377 Address globals_start =
569 Object* fct_obj = compiled_module->ptr_to_code_table(); 378 static_cast<Address>(owner->globals_buffer()->backing_store());
570 if (fct_obj != nullptr && fct_obj != undefined && 379 code_specialization.RelocateGlobals(globals_start, nullptr);
571 (old_mem_size > 0 || globals_start != nullptr || function_tables)) { 380 }
381
382 // Reset function tables.
383 if (compiled_module->has_function_tables()) {
384 FixedArray* function_tables = compiled_module->ptr_to_function_tables();
385 FixedArray* empty_function_tables =
386 compiled_module->ptr_to_empty_function_tables();
387 DCHECK_EQ(function_tables->length(), empty_function_tables->length());
388 for (int i = 0, e = function_tables->length(); i < e; ++i) {
389 code_specialization.RelocateObject(function_tables->get(i),
390 empty_function_tables->get(i));
391 }
392 compiled_module->set_ptr_to_function_tables(empty_function_tables);
393 }
394
572 FixedArray* functions = FixedArray::cast(fct_obj); 395 FixedArray* functions = FixedArray::cast(fct_obj);
573 for (int i = compiled_module->num_imported_functions(); 396 for (int i = compiled_module->num_imported_functions(),
574 i < functions->length(); ++i) { 397 end = functions->length();
398 i < end; ++i) {
575 Code* code = Code::cast(functions->get(i)); 399 Code* code = Code::cast(functions->get(i));
576 bool changed = false; 400 if (code->kind() != Code::WASM_FUNCTION) {
577 for (RelocIterator it(code, mode_mask); !it.done(); it.next()) { 401 // From here on, there should only be wrappers for exported functions.
578 RelocInfo::Mode mode = it.rinfo()->rmode(); 402 for (; i < end; ++i) {
579 if (RelocInfo::IsWasmMemoryReference(mode) || 403 DCHECK_EQ(Code::JS_TO_WASM_FUNCTION,
580 RelocInfo::IsWasmMemorySizeReference(mode)) { 404 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 } 405 }
406 break;
596 } 407 }
408 bool changed =
409 code_specialization.ApplyToWasmCode(code, SKIP_ICACHE_FLUSH);
410 // TODO(wasm): Check if this is faster than passing FLUSH_ICACHE_IF_NEEDED
411 // above.
597 if (changed) { 412 if (changed) {
598 Assembler::FlushICache(isolate, code->instruction_start(), 413 Assembler::FlushICache(isolate, code->instruction_start(),
599 code->instruction_size()); 414 code->instruction_size());
600 } 415 }
601 } 416 }
602 } 417 }
603 compiled_module->reset_memory(); 418 compiled_module->reset_memory();
604 } 419 }
605 420
606 static void MemoryInstanceFinalizer(Isolate* isolate, 421 static void MemoryInstanceFinalizer(Isolate* isolate,
(...skipping 144 matching lines...)
751 566
752 int name_chars = SNPrintF(ArrayVector(buffer), "wasm-%08x", hash); 567 int name_chars = SNPrintF(ArrayVector(buffer), "wasm-%08x", hash);
753 DCHECK(name_chars >= 0 && name_chars < kBufferSize); 568 DCHECK(name_chars >= 0 && name_chars < kBufferSize);
754 MaybeHandle<String> name_str = isolate->factory()->NewStringFromOneByte( 569 MaybeHandle<String> name_str = isolate->factory()->NewStringFromOneByte(
755 Vector<const uint8_t>(reinterpret_cast<uint8_t*>(buffer), name_chars), 570 Vector<const uint8_t>(reinterpret_cast<uint8_t*>(buffer), name_chars),
756 TENURED); 571 TENURED);
757 script->set_name(*name_str.ToHandleChecked()); 572 script->set_name(*name_str.ToHandleChecked());
758 573
759 return script; 574 return script;
760 } 575 }
576
577 // Information collected during instantiation, needed for the final code
578 // specialization phase.
579 struct RelocationInfo {
580 uint32_t old_mem_size = 0;
581 Address old_mem_start = nullptr;
582 Address old_globals_start = nullptr;
583 // TODO(wasm): Prepare this for more than one indirect function table.
584 uint32_t old_function_table_size = 0;
585 uint32_t new_function_table_size = 0;
586
587 // Relocate all objects in old_table to the corresponding one in new_table.
588 struct TableToRelocate {
589 Handle<FixedArray> old_table;
590 Handle<FixedArray> new_table;
591 TableToRelocate(Handle<FixedArray> o, Handle<FixedArray> n)
592 : old_table(o), new_table(n) {}
593 };
594 std::vector<TableToRelocate> tables_to_relocate;
595 };
596
761 } // namespace 597 } // namespace
762 598
763 Handle<JSArrayBuffer> SetupArrayBuffer(Isolate* isolate, void* backing_store, 599 Handle<JSArrayBuffer> SetupArrayBuffer(Isolate* isolate, void* backing_store,
764 size_t size, bool is_external, 600 size_t size, bool is_external,
765 bool enable_guard_regions) { 601 bool enable_guard_regions) {
766 Handle<JSArrayBuffer> buffer = isolate->factory()->NewJSArrayBuffer(); 602 Handle<JSArrayBuffer> buffer = isolate->factory()->NewJSArrayBuffer();
767 JSArrayBuffer::Setup(buffer, isolate, is_external, backing_store, 603 JSArrayBuffer::Setup(buffer, isolate, is_external, backing_store,
768 static_cast<int>(size)); 604 static_cast<int>(size));
769 buffer->set_is_neuterable(false); 605 buffer->set_is_neuterable(false);
770 buffer->set_has_guard_region(enable_guard_regions); 606 buffer->set_has_guard_region(enable_guard_regions);
(...skipping 462 matching lines...)
1233 TRACE("Reusing existing instance %d\n", 1069 TRACE("Reusing existing instance %d\n",
1234 compiled_module_->instance_id()); 1070 compiled_module_->instance_id());
1235 } 1071 }
1236 compiled_module_->set_code_table(code_table); 1072 compiled_module_->set_code_table(code_table);
1237 compiled_module_->set_native_context(isolate_->native_context()); 1073 compiled_module_->set_native_context(isolate_->native_context());
1238 } 1074 }
1239 1075
1240 //-------------------------------------------------------------------------- 1076 //--------------------------------------------------------------------------
1241 // Allocate the instance object. 1077 // Allocate the instance object.
1242 //-------------------------------------------------------------------------- 1078 //--------------------------------------------------------------------------
1079 RelocationInfo reloc_info;
1243 Handle<WasmInstanceObject> instance = 1080 Handle<WasmInstanceObject> instance =
1244 WasmInstanceObject::New(isolate_, compiled_module_); 1081 WasmInstanceObject::New(isolate_, compiled_module_);
1245 1082
1246 //-------------------------------------------------------------------------- 1083 //--------------------------------------------------------------------------
1247 // Set up the globals for the new instance. 1084 // Set up the globals for the new instance.
1248 //-------------------------------------------------------------------------- 1085 //--------------------------------------------------------------------------
1249 MaybeHandle<JSArrayBuffer> old_globals; 1086 MaybeHandle<JSArrayBuffer> old_globals;
1250 uint32_t globals_size = module_->globals_size; 1087 uint32_t globals_size = module_->globals_size;
1251 if (globals_size > 0) { 1088 if (globals_size > 0) {
1252 const bool enable_guard_regions = false; 1089 const bool enable_guard_regions = false;
1253 Handle<JSArrayBuffer> global_buffer = 1090 Handle<JSArrayBuffer> global_buffer =
1254 NewArrayBuffer(isolate_, globals_size, enable_guard_regions); 1091 NewArrayBuffer(isolate_, globals_size, enable_guard_regions);
1255 globals_ = global_buffer; 1092 globals_ = global_buffer;
1256 if (globals_.is_null()) { 1093 if (globals_.is_null()) {
1257 thrower_->RangeError("Out of memory: wasm globals"); 1094 thrower_->RangeError("Out of memory: wasm globals");
1258 return nothing; 1095 return nothing;
1259 } 1096 }
1260 Address old_address = 1097 if (!owner.is_null() && owner.ToHandleChecked()->has_globals_buffer()) {
1261 owner.is_null() ? nullptr : GetGlobalStartAddressFromCodeTemplate( 1098 reloc_info.old_globals_start = static_cast<Address>(
1262 isolate_->heap()->undefined_value(), 1099 owner.ToHandleChecked()->globals_buffer()->backing_store());
1263 *owner.ToHandleChecked()); 1100 }
1264 RelocateGlobals(code_table, old_address,
1265 static_cast<Address>(global_buffer->backing_store()));
1266 instance->set_globals_buffer(*global_buffer); 1101 instance->set_globals_buffer(*global_buffer);
1267 } 1102 }
1268 1103
1269 //-------------------------------------------------------------------------- 1104 //--------------------------------------------------------------------------
1270 // Prepare for initialization of function tables. 1105 // Prepare for initialization of function tables.
1271 //-------------------------------------------------------------------------- 1106 //--------------------------------------------------------------------------
1272 int function_table_count = 1107 int function_table_count =
1273 static_cast<int>(module_->function_tables.size()); 1108 static_cast<int>(module_->function_tables.size());
1274 table_instances_.reserve(module_->function_tables.size()); 1109 table_instances_.reserve(module_->function_tables.size());
1275 for (int index = 0; index < function_table_count; ++index) { 1110 for (int index = 0; index < function_table_count; ++index) {
1276 table_instances_.push_back( 1111 table_instances_.push_back(
1277 {Handle<WasmTableObject>::null(), Handle<FixedArray>::null(), 1112 {Handle<WasmTableObject>::null(), Handle<FixedArray>::null(),
1278 Handle<FixedArray>::null(), Handle<FixedArray>::null()}); 1113 Handle<FixedArray>::null(), Handle<FixedArray>::null()});
1279 } 1114 }
1280 1115
1281 //-------------------------------------------------------------------------- 1116 //--------------------------------------------------------------------------
1282 // Process the imports for the module. 1117 // Process the imports for the module.
1283 //-------------------------------------------------------------------------- 1118 //--------------------------------------------------------------------------
1284 int num_imported_functions = ProcessImports(code_table, instance); 1119 int num_imported_functions = ProcessImports(code_table, instance);
1285 if (num_imported_functions < 0) return nothing; 1120 if (num_imported_functions < 0) return nothing;
1286 1121
1287 //-------------------------------------------------------------------------- 1122 //--------------------------------------------------------------------------
1288 // Process the initialization for the module's globals. 1123 // Process the initialization for the module's globals.
1289 //-------------------------------------------------------------------------- 1124 //--------------------------------------------------------------------------
1290 InitGlobals(); 1125 InitGlobals();
1291 1126
1292 //-------------------------------------------------------------------------- 1127 //--------------------------------------------------------------------------
1293 // Set up the indirect function tables for the new instance. 1128 // Set up the indirect function tables for the new instance.
1294 //-------------------------------------------------------------------------- 1129 //--------------------------------------------------------------------------
1295 if (function_table_count > 0) InitializeTables(code_table, instance); 1130 if (function_table_count > 0)
1131 InitializeTables(code_table, instance, &reloc_info);
1296 1132
1297 //-------------------------------------------------------------------------- 1133 //--------------------------------------------------------------------------
1298 // Set up the memory for the new instance. 1134 // Set up the memory for the new instance.
1299 //-------------------------------------------------------------------------- 1135 //--------------------------------------------------------------------------
1300 MaybeHandle<JSArrayBuffer> old_memory; 1136 MaybeHandle<JSArrayBuffer> old_memory;
1301 1137
1302 uint32_t min_mem_pages = module_->min_mem_pages; 1138 uint32_t min_mem_pages = module_->min_mem_pages;
1303 isolate_->counters()->wasm_min_mem_pages_count()->AddSample(min_mem_pages); 1139 isolate_->counters()->wasm_min_mem_pages_count()->AddSample(min_mem_pages);
1304 1140
1305 if (!memory_.is_null()) { 1141 if (!memory_.is_null()) {
(...skipping 31 matching lines...)
1337 ? 0 : static_cast<uint32_t>(memory_->byte_length()->Number()); 1173 ? 0 : static_cast<uint32_t>(memory_->byte_length()->Number());
1338 if (!in_bounds(base, seg.source_size, mem_size)) { 1174 if (!in_bounds(base, seg.source_size, mem_size)) {
1339 thrower_->LinkError("data segment is out of bounds"); 1175 thrower_->LinkError("data segment is out of bounds");
1340 return nothing; 1176 return nothing;
1341 } 1177 }
1342 } 1178 }
1343 1179
1344 //-------------------------------------------------------------------------- 1180 //--------------------------------------------------------------------------
1345 // Initialize memory. 1181 // Initialize memory.
1346 //-------------------------------------------------------------------------- 1182 //--------------------------------------------------------------------------
1183 reloc_info.old_mem_size = compiled_module_->mem_size();
1347 if (!memory_.is_null()) { 1184 if (!memory_.is_null()) {
1348 instance->set_memory_buffer(*memory_); 1185 instance->set_memory_buffer(*memory_);
1349 Address mem_start = static_cast<Address>(memory_->backing_store()); 1186 Address mem_start = static_cast<Address>(memory_->backing_store());
1350 uint32_t mem_size = 1187 uint32_t mem_size =
1351 static_cast<uint32_t>(memory_->byte_length()->Number()); 1188 static_cast<uint32_t>(memory_->byte_length()->Number());
1352 LoadDataSegments(mem_start, mem_size); 1189 LoadDataSegments(mem_start, mem_size);
1353 1190
1354 uint32_t old_mem_size = compiled_module_->mem_size(); 1191 if (compiled_module_->has_memory()) {
1355 Address old_mem_start = 1192 reloc_info.old_mem_start =
1356 compiled_module_->has_memory() 1193 static_cast<Address>(compiled_module_->memory()->backing_store());
1357 ? static_cast<Address>( 1194 }
1358 compiled_module_->memory()->backing_store())
1359 : nullptr;
1360 RelocateMemoryReferencesInCode(
1361 code_table, module_->num_imported_functions, old_mem_start, mem_start,
1362 old_mem_size, mem_size);
1363 compiled_module_->set_memory(memory_); 1195 compiled_module_->set_memory(memory_);
1364 } 1196 }
1365 1197
1366 //-------------------------------------------------------------------------- 1198 //--------------------------------------------------------------------------
1367 // Set up the runtime support for the new instance. 1199 // Set up the runtime support for the new instance.
1368 //-------------------------------------------------------------------------- 1200 //--------------------------------------------------------------------------
1369 Handle<WeakCell> weak_link = factory->NewWeakCell(instance); 1201 Handle<WeakCell> weak_link = factory->NewWeakCell(instance);
1370 1202
1371 for (int i = num_imported_functions + FLAG_skip_compiling_wasm_funcs; 1203 for (int i = num_imported_functions + FLAG_skip_compiling_wasm_funcs;
1372 i < code_table->length(); ++i) { 1204 i < code_table->length(); ++i) {
(...skipping 18 matching lines...)
1391 DCHECK(wasm::IsWasmInstance(*instance)); 1223 DCHECK(wasm::IsWasmInstance(*instance));
1392 if (instance->has_memory_object()) { 1224 if (instance->has_memory_object()) {
1393 instance->memory_object()->AddInstance(isolate_, instance); 1225 instance->memory_object()->AddInstance(isolate_, instance);
1394 } 1226 }
1395 1227
1396 //-------------------------------------------------------------------------- 1228 //--------------------------------------------------------------------------
1397 // Initialize the indirect function tables. 1229 // Initialize the indirect function tables.
1398 //-------------------------------------------------------------------------- 1230 //--------------------------------------------------------------------------
1399 if (function_table_count > 0) LoadTableSegments(code_table, instance); 1231 if (function_table_count > 0) LoadTableSegments(code_table, instance);
1400 1232
1401 // Patch new call sites and the context. 1233 // Now patch the new code.
1402 PatchDirectCallsAndContext(code_table, compiled_module_, module_, 1234 {
1403 num_imported_functions); 1235 CodeSpecialization code_specialization;
1236 // Direct calls:
1237 code_specialization.RelocateDirectCalls(*instance);
1238 // Globals:
1239 if (instance->has_globals_buffer()) {
1240 code_specialization.RelocateGlobals(
1241 reloc_info.old_globals_start,
1242 static_cast<Address>(instance->globals_buffer()->backing_store()));
1243 }
1244 // Memory:
1245 if (compiled_module_->has_memory()) {
1246 Address mem_start =
1247 static_cast<Address>(compiled_module_->memory()->backing_store());
1248 uint32_t mem_size = compiled_module_->mem_size();
1249 code_specialization.RelocateMemoryReferences(reloc_info.old_mem_start,
1250 reloc_info.old_mem_size,
1251 mem_start, mem_size);
1252 }
1253 // Tables:
1254 for (auto& e : reloc_info.tables_to_relocate) {
1255 DCHECK_EQ(e.old_table->length(), e.new_table->length());
1256 for (int i = 0, l = e.old_table->length(); i < l; ++i) {
1257 code_specialization.RelocateObject(e.old_table->get(i),
1258 e.new_table->get(i));
1259 }
1260 }
1261 if (reloc_info.old_function_table_size !=
1262 reloc_info.new_function_table_size) {
1263 code_specialization.PatchTableSize(reloc_info.old_function_table_size,
1264 reloc_info.new_function_table_size);
1265 }
1266
1267 // Now run the specialization.
1268 code_specialization.ApplyToWholeInstance(*instance, SKIP_ICACHE_FLUSH);
1269 }
1404 1270
1405 FlushICache(isolate_, code_table); 1271 FlushICache(isolate_, code_table);
1406 1272
1407 //-------------------------------------------------------------------------- 1273 //--------------------------------------------------------------------------
1408 // Unpack and notify signal handler of protected instructions. 1274 // Unpack and notify signal handler of protected instructions.
1409 //-------------------------------------------------------------------------- 1275 //--------------------------------------------------------------------------
1410 if (FLAG_wasm_trap_handler) { 1276 if (FLAG_wasm_trap_handler) {
1411 for (int i = 0; i < code_table->length(); ++i) { 1277 for (int i = 0; i < code_table->length(); ++i) {
1412 Handle<Code> code = code_table->GetValueChecked<Code>(isolate_, i); 1278 Handle<Code> code = code_table->GetValueChecked<Code>(isolate_, i);
1413 1279
(...skipping 674 matching lines...)
2088 1954
2089 if (module_->origin == kWasmOrigin) { 1955 if (module_->origin == kWasmOrigin) {
2090 v8::Maybe<bool> success = JSReceiver::SetIntegrityLevel( 1956 v8::Maybe<bool> success = JSReceiver::SetIntegrityLevel(
2091 exports_object, FROZEN, Object::DONT_THROW); 1957 exports_object, FROZEN, Object::DONT_THROW);
2092 DCHECK(success.FromMaybe(false)); 1958 DCHECK(success.FromMaybe(false));
2093 USE(success); 1959 USE(success);
2094 } 1960 }
2095 } 1961 }
2096 1962
2097 void InitializeTables(Handle<FixedArray> code_table, 1963 void InitializeTables(Handle<FixedArray> code_table,
2098 Handle<WasmInstanceObject> instance) { 1964 Handle<WasmInstanceObject> instance,
1965 RelocationInfo* reloc_info) {
2099 int function_table_count = 1966 int function_table_count =
2100 static_cast<int>(module_->function_tables.size()); 1967 static_cast<int>(module_->function_tables.size());
2101 Handle<FixedArray> new_function_tables = 1968 Handle<FixedArray> new_function_tables =
2102 isolate_->factory()->NewFixedArray(function_table_count); 1969 isolate_->factory()->NewFixedArray(function_table_count);
2103 Handle<FixedArray> new_signature_tables = 1970 Handle<FixedArray> new_signature_tables =
2104 isolate_->factory()->NewFixedArray(function_table_count); 1971 isolate_->factory()->NewFixedArray(function_table_count);
2105 for (int index = 0; index < function_table_count; ++index) { 1972 for (int index = 0; index < function_table_count; ++index) {
2106 WasmIndirectFunctionTable& table = module_->function_tables[index]; 1973 WasmIndirectFunctionTable& table = module_->function_tables[index];
2107 TableInstance& table_instance = table_instances_[index]; 1974 TableInstance& table_instance = table_instances_[index];
2108 int table_size = static_cast<int>(table.min_size); 1975 int table_size = static_cast<int>(table.min_size);
2109 1976
2110 if (table_instance.function_table.is_null()) { 1977 if (table_instance.function_table.is_null()) {
2111 // Create a new dispatch table if necessary. 1978 // Create a new dispatch table if necessary.
2112 table_instance.function_table = 1979 table_instance.function_table =
2113 isolate_->factory()->NewFixedArray(table_size); 1980 isolate_->factory()->NewFixedArray(table_size);
2114 table_instance.signature_table = 1981 table_instance.signature_table =
2115 isolate_->factory()->NewFixedArray(table_size); 1982 isolate_->factory()->NewFixedArray(table_size);
2116 for (int i = 0; i < table_size; ++i) { 1983 for (int i = 0; i < table_size; ++i) {
2117 // Fill the table with invalid signature indexes so that 1984 // Fill the table with invalid signature indexes so that
2118 // uninitialized entries will always fail the signature check. 1985 // uninitialized entries will always fail the signature check.
2119 table_instance.signature_table->set(i, 1986 table_instance.signature_table->set(i,
2120 Smi::FromInt(kInvalidSigIndex)); 1987 Smi::FromInt(kInvalidSigIndex));
2121 } 1988 }
2122 } else { 1989 } else {
2123 // Table is imported, patch table bounds check 1990 // Table is imported, patch table bounds check
2124 DCHECK(table_size <= table_instance.function_table->length()); 1991 DCHECK(table_size <= table_instance.function_table->length());
2125 if (table_size < table_instance.function_table->length()) { 1992 if (table_size < table_instance.function_table->length()) {
2126 RelocateTableSizeReferences(code_table, table_size, 1993 reloc_info->old_function_table_size = table_size;
2127 table_instance.function_table->length()); 1994 reloc_info->new_function_table_size =
1995 table_instance.function_table->length();
2128 } 1996 }
2129 } 1997 }
2130 1998
2131 new_function_tables->set(static_cast<int>(index), 1999 new_function_tables->set(static_cast<int>(index),
2132 *table_instance.function_table); 2000 *table_instance.function_table);
2133 new_signature_tables->set(static_cast<int>(index), 2001 new_signature_tables->set(static_cast<int>(index),
2134 *table_instance.signature_table); 2002 *table_instance.signature_table);
2135 } 2003 }
2136 2004
2137 // Patch all code that has references to the old indirect tables. 2005 reloc_info->tables_to_relocate.emplace_back(
2138 Handle<FixedArray> old_function_tables = 2006 compiled_module_->function_tables(), new_function_tables);
2139 compiled_module_->function_tables(); 2007 reloc_info->tables_to_relocate.emplace_back(
2140 Handle<FixedArray> old_signature_tables = 2008 compiled_module_->signature_tables(), new_signature_tables);
2141 compiled_module_->signature_tables(); 2009
2142 for (int i = 0; i < code_table->length(); ++i) {
2143 if (!code_table->get(i)->IsCode()) continue;
2144 Handle<Code> code(Code::cast(code_table->get(i)), isolate_);
2145 for (int j = 0; j < function_table_count; ++j) {
2146 ReplaceReferenceInCode(
2147 code, Handle<Object>(old_function_tables->get(j), isolate_),
2148 Handle<Object>(new_function_tables->get(j), isolate_));
2149 ReplaceReferenceInCode(
2150 code, Handle<Object>(old_signature_tables->get(j), isolate_),
2151 Handle<Object>(new_signature_tables->get(j), isolate_));
2152 }
2153 }
2154 compiled_module_->set_function_tables(new_function_tables); 2010 compiled_module_->set_function_tables(new_function_tables);
2155 compiled_module_->set_signature_tables(new_signature_tables); 2011 compiled_module_->set_signature_tables(new_signature_tables);
2156 } 2012 }
2157 2013
2158 void LoadTableSegments(Handle<FixedArray> code_table, 2014 void LoadTableSegments(Handle<FixedArray> code_table,
2159 Handle<WasmInstanceObject> instance) { 2015 Handle<WasmInstanceObject> instance) {
2160 int function_table_count = 2016 int function_table_count =
2161 static_cast<int>(module_->function_tables.size()); 2017 static_cast<int>(module_->function_tables.size());
2162 for (int index = 0; index < function_table_count; ++index) { 2018 for (int index = 0; index < function_table_count; ++index) {
2163 WasmIndirectFunctionTable& table = module_->function_tables[index]; 2019 WasmIndirectFunctionTable& table = module_->function_tables[index];
(...skipping 230 matching lines...)
2394 if (old_size != 0) { 2250 if (old_size != 0) {
2395 memcpy(new_mem_start, old_mem_start, old_size); 2251 memcpy(new_mem_start, old_mem_start, old_size);
2396 } 2252 }
2397 return new_buffer; 2253 return new_buffer;
2398 } 2254 }
2399 2255
2400 void UncheckedUpdateInstanceMemory(Isolate* isolate, 2256 void UncheckedUpdateInstanceMemory(Isolate* isolate,
2401 Handle<WasmInstanceObject> instance, 2257 Handle<WasmInstanceObject> instance,
2402 Address old_mem_start, uint32_t old_size) { 2258 Address old_mem_start, uint32_t old_size) {
2403 DCHECK(instance->has_memory_buffer()); 2259 DCHECK(instance->has_memory_buffer());
2404 Handle<JSArrayBuffer> new_buffer(instance->memory_buffer()); 2260 Handle<JSArrayBuffer> mem_buffer(instance->memory_buffer());
2405 uint32_t new_size = new_buffer->byte_length()->Number(); 2261 uint32_t new_size = mem_buffer->byte_length()->Number();
2406 DCHECK(new_size <= std::numeric_limits<uint32_t>::max()); 2262 Address new_mem_start = static_cast<Address>(mem_buffer->backing_store());
2407 Address new_mem_start = static_cast<Address>(new_buffer->backing_store());
2408 DCHECK_NOT_NULL(new_mem_start); 2263 DCHECK_NOT_NULL(new_mem_start);
2409 Handle<FixedArray> code_table = instance->compiled_module()->code_table(); 2264 CodeSpecialization code_specialization;
2410 RelocateMemoryReferencesInCode( 2265 code_specialization.RelocateMemoryReferences(old_mem_start, old_size,
2411 code_table, instance->compiled_module()->module()->num_imported_functions, 2266 new_mem_start, new_size);
2412 old_mem_start, new_mem_start, old_size, new_size); 2267 code_specialization.ApplyToWholeInstance(*instance);
2413 } 2268 }
2414 2269
2415 void DetachArrayBuffer(Isolate* isolate, Handle<JSArrayBuffer> buffer) { 2270 void DetachArrayBuffer(Isolate* isolate, Handle<JSArrayBuffer> buffer) {
2416 const bool has_guard_regions = 2271 const bool has_guard_regions =
2417 (!buffer.is_null() && buffer->has_guard_region()); 2272 (!buffer.is_null() && buffer->has_guard_region());
2418 void* backing_store = buffer->backing_store(); 2273 void* backing_store = buffer->backing_store();
2419 if (backing_store != nullptr) { 2274 if (backing_store != nullptr) {
2420 DCHECK(!buffer->is_neuterable()); 2275 DCHECK(!buffer->is_neuterable());
2421 int64_t byte_length = NumberToSize(buffer->byte_length()); 2276 int64_t byte_length = NumberToSize(buffer->byte_length());
2422 buffer->set_is_neuterable(true); 2277 buffer->set_is_neuterable(true);
(...skipping 117 matching lines...)
2540 } else { 2395 } else {
2541 return GrowWebAssemblyMemory(isolate, handle(instance_obj->memory_object()), 2396 return GrowWebAssemblyMemory(isolate, handle(instance_obj->memory_object()),
2542 pages); 2397 pages);
2543 } 2398 }
2544 } 2399 }
2545 2400
2546 void wasm::GrowDispatchTables(Isolate* isolate, 2401 void wasm::GrowDispatchTables(Isolate* isolate,
2547 Handle<FixedArray> dispatch_tables, 2402 Handle<FixedArray> dispatch_tables,
2548 uint32_t old_size, uint32_t count) { 2403 uint32_t old_size, uint32_t count) {
2549 DCHECK_EQ(0, dispatch_tables->length() % 4); 2404 DCHECK_EQ(0, dispatch_tables->length() % 4);
2405
2550 for (int i = 0; i < dispatch_tables->length(); i += 4) { 2406 for (int i = 0; i < dispatch_tables->length(); i += 4) {
2551 Handle<FixedArray> old_function_table( 2407 Handle<FixedArray> old_function_table(
2552 FixedArray::cast(dispatch_tables->get(i + 2))); 2408 FixedArray::cast(dispatch_tables->get(i + 2)));
2553 Handle<FixedArray> old_signature_table( 2409 Handle<FixedArray> old_signature_table(
2554 FixedArray::cast(dispatch_tables->get(i + 3))); 2410 FixedArray::cast(dispatch_tables->get(i + 3)));
2555 Handle<FixedArray> new_function_table = 2411 Handle<FixedArray> new_function_table =
2556 isolate->factory()->CopyFixedArrayAndGrow(old_function_table, count); 2412 isolate->factory()->CopyFixedArrayAndGrow(old_function_table, count);
2557 Handle<FixedArray> new_signature_table = 2413 Handle<FixedArray> new_signature_table =
2558 isolate->factory()->CopyFixedArrayAndGrow(old_signature_table, count); 2414 isolate->factory()->CopyFixedArrayAndGrow(old_signature_table, count);
2559 2415
2560 // Get code table for the instance
2561 Handle<WasmInstanceObject> instance(
2562 WasmInstanceObject::cast(dispatch_tables->get(i)));
2563 Handle<FixedArray> code_table(instance->compiled_module()->code_table());
2564
2565 // Relocate size references
2566 RelocateTableSizeReferences(code_table, old_size, old_size + count);
2567
2568 // Replace references of old tables with new tables.
2569 for (int j = 0; j < code_table->length(); ++j) {
2570 if (!code_table->get(j)->IsCode()) continue;
2571 Handle<Code> code = Handle<Code>(Code::cast(code_table->get(j)));
2572 ReplaceReferenceInCode(code, old_function_table, new_function_table);
2573 ReplaceReferenceInCode(code, old_signature_table, new_signature_table);
2574 }
2575
2576 // Update dispatch tables with new function/signature tables 2416 // Update dispatch tables with new function/signature tables
2577 dispatch_tables->set(i + 2, *new_function_table); 2417 dispatch_tables->set(i + 2, *new_function_table);
2578 dispatch_tables->set(i + 3, *new_signature_table); 2418 dispatch_tables->set(i + 3, *new_signature_table);
2419
2420 // Patch the code of the respective instance.
2421 CodeSpecialization code_specialization;
2422 code_specialization.PatchTableSize(old_size, old_size + count);
2423 code_specialization.RelocateObject(*old_function_table,
2424 *new_function_table);
2425 code_specialization.RelocateObject(*old_signature_table,
2426 *new_signature_table);
2427 code_specialization.ApplyToWholeInstance(
2428 WasmInstanceObject::cast(dispatch_tables->get(i)));
2579 } 2429 }
2580 } 2430 }
2581 2431
2582 void testing::ValidateInstancesChain(Isolate* isolate, 2432 void testing::ValidateInstancesChain(Isolate* isolate,
2583 Handle<WasmModuleObject> module_obj, 2433 Handle<WasmModuleObject> module_obj,
2584 int instance_count) { 2434 int instance_count) {
2585 CHECK_GE(instance_count, 0); 2435 CHECK_GE(instance_count, 0);
2586 DisallowHeapAllocation no_gc; 2436 DisallowHeapAllocation no_gc;
2587 WasmCompiledModule* compiled_module = module_obj->compiled_module(); 2437 WasmCompiledModule* compiled_module = module_obj->compiled_module();
2588 CHECK_EQ(JSObject::cast(compiled_module->ptr_to_weak_wasm_module()->value()), 2438 CHECK_EQ(JSObject::cast(compiled_module->ptr_to_weak_wasm_module()->value()),
(...skipping 229 matching lines...)
2818 Handle<FixedArray> storage = factory->NewFixedArray(num_custom_sections); 2668 Handle<FixedArray> storage = factory->NewFixedArray(num_custom_sections);
2819 JSArray::SetContent(array_object, storage); 2669 JSArray::SetContent(array_object, storage);
2820 array_object->set_length(Smi::FromInt(num_custom_sections)); 2670 array_object->set_length(Smi::FromInt(num_custom_sections));
2821 2671
2822 for (int i = 0; i < num_custom_sections; i++) { 2672 for (int i = 0; i < num_custom_sections; i++) {
2823 storage->set(i, *matching_sections[i]); 2673 storage->set(i, *matching_sections[i]);
2824 } 2674 }
2825 2675
2826 return array_object; 2676 return array_object;
2827 } 2677 }
OLDNEW
« src/wasm/wasm-code-specialization.h ('K') | « src/wasm/wasm-code-specialization.cc ('k') | no next file » | no next file with comments »

Powered by Google App Engine