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...) 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...) 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...) 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 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...) Loading... |
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...) Loading... |
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...) Loading... |
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...) Loading... |
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...) Loading... |
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...) Loading... |
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...) Loading... |
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...) Loading... |
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 } |
OLD | NEW |