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/wasm/function-body-decoder.h" | 19 #include "src/wasm/function-body-decoder.h" |
20 #include "src/wasm/leb-helper.h" | |
20 #include "src/wasm/module-decoder.h" | 21 #include "src/wasm/module-decoder.h" |
21 #include "src/wasm/wasm-js.h" | 22 #include "src/wasm/wasm-js.h" |
22 #include "src/wasm/wasm-limits.h" | 23 #include "src/wasm/wasm-limits.h" |
23 #include "src/wasm/wasm-module.h" | 24 #include "src/wasm/wasm-module.h" |
24 #include "src/wasm/wasm-objects.h" | 25 #include "src/wasm/wasm-objects.h" |
25 #include "src/wasm/wasm-result.h" | 26 #include "src/wasm/wasm-result.h" |
26 | 27 |
27 using namespace v8::internal; | 28 using namespace v8::internal; |
28 using namespace v8::internal::wasm; | 29 using namespace v8::internal::wasm; |
29 namespace base = v8::base; | 30 namespace base = v8::base; |
(...skipping 408 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
438 WasmName str = module_env->GetName(&func); | 439 WasmName str = module_env->GetName(&func); |
439 thrower->CompileError("Compilation of #%d:%.*s failed.", i, str.length(), | 440 thrower->CompileError("Compilation of #%d:%.*s failed.", i, str.length(), |
440 str.start()); | 441 str.start()); |
441 break; | 442 break; |
442 } | 443 } |
443 // Install the code into the linker table. | 444 // Install the code into the linker table. |
444 functions[i] = code; | 445 functions[i] = code; |
445 } | 446 } |
446 } | 447 } |
447 | 448 |
448 void PatchDirectCalls(Handle<FixedArray> old_functions, | 449 int ExtractDirectCallIndex(const byte* pc) { |
titzer
2017/01/11 18:02:48
Can you use a decoder for this? That way we don't
Clemens Hammacher
2017/01/11 18:28:43
Done.
FYI: I have to write it as wasm::Decoder, b
| |
449 Handle<FixedArray> new_functions, int start) { | 450 DCHECK_EQ(static_cast<int>(kExprCallFunction), static_cast<int>(*pc)); |
450 DCHECK_EQ(new_functions->length(), old_functions->length()); | 451 uint32_t call_idx = LEBHelper::read_u32v(pc + 1); |
452 DCHECK_GE(kMaxInt, call_idx); | |
453 return static_cast<int>(call_idx); | |
454 } | |
451 | 455 |
456 void PatchDirectCalls(Handle<FixedArray> new_functions, | |
457 Handle<WasmCompiledModule> compiled_module, | |
458 WasmModule* module, int start) { | |
452 DisallowHeapAllocation no_gc; | 459 DisallowHeapAllocation no_gc; |
453 std::map<Code*, Code*> old_to_new_code; | |
454 for (int i = 0; i < new_functions->length(); ++i) { | |
455 old_to_new_code.insert(std::make_pair(Code::cast(old_functions->get(i)), | |
456 Code::cast(new_functions->get(i)))); | |
457 } | |
458 int mode_mask = RelocInfo::ModeMask(RelocInfo::CODE_TARGET); | |
459 AllowDeferredHandleDereference embedding_raw_address; | 460 AllowDeferredHandleDereference embedding_raw_address; |
460 for (int i = start; i < new_functions->length(); ++i) { | 461 SeqOneByteString* module_bytes = compiled_module->module_bytes(); |
462 std::vector<WasmFunction>* wasm_functions = | |
463 &compiled_module->module()->functions; | |
464 DCHECK_EQ(wasm_functions->size() + | |
465 compiled_module->module()->num_exported_functions, | |
466 new_functions->length()); | |
467 DCHECK_EQ(start, compiled_module->module()->num_imported_functions); | |
468 | |
469 int num_wasm_functions = static_cast<int>(wasm_functions->size()); | |
470 for (int i = start; i < num_wasm_functions; ++i) { | |
461 Code* wasm_function = Code::cast(new_functions->get(i)); | 471 Code* wasm_function = Code::cast(new_functions->get(i)); |
462 for (RelocIterator it(wasm_function, mode_mask); !it.done(); it.next()) { | 472 DCHECK(wasm_function->kind() == Code::WASM_FUNCTION); |
463 Code* old_code = | 473 SourcePositionTableIterator source_pos_iterator( |
464 Code::GetCodeFromTargetAddress(it.rinfo()->target_address()); | 474 wasm_function->source_position_table()); |
465 if (old_code->kind() == Code::WASM_TO_JS_FUNCTION || | 475 const byte* func_bytes = |
466 old_code->kind() == Code::WASM_FUNCTION) { | 476 module_bytes->GetChars() + |
467 auto found = old_to_new_code.find(old_code); | 477 compiled_module->module()->functions[i].code_start_offset; |
468 DCHECK(found != old_to_new_code.end()); | 478 for (RelocIterator it(wasm_function, RelocInfo::kCodeTargetMask); |
469 Code* new_code = found->second; | 479 !it.done(); it.next()) { |
470 if (new_code != old_code) { | 480 Code::Kind kind = |
471 it.rinfo()->set_target_address(new_code->instruction_start(), | 481 Code::GetCodeFromTargetAddress(it.rinfo()->target_address())->kind(); |
472 UPDATE_WRITE_BARRIER, | 482 if (kind != Code::WASM_FUNCTION && kind != Code::WASM_TO_JS_FUNCTION) |
473 SKIP_ICACHE_FLUSH); | 483 continue; |
474 } | 484 size_t offset_l = it.rinfo()->pc() - wasm_function->instruction_start(); |
475 } | 485 DCHECK_GE(kMaxInt, offset_l); |
486 int offset = static_cast<int>(offset_l); | |
487 DCHECK(!source_pos_iterator.done()); | |
488 int byte_pos; | |
489 do { | |
490 byte_pos = source_pos_iterator.source_position().ScriptOffset(); | |
491 source_pos_iterator.Advance(); | |
492 } while (!source_pos_iterator.done() && | |
493 source_pos_iterator.code_offset() <= offset); | |
494 int called_func_index = ExtractDirectCallIndex(func_bytes + byte_pos); | |
495 Code* new_code = Code::cast(new_functions->get(called_func_index)); | |
496 it.rinfo()->set_target_address(new_code->instruction_start(), | |
497 UPDATE_WRITE_BARRIER, SKIP_ICACHE_FLUSH); | |
476 } | 498 } |
477 } | 499 } |
500 int func_index = num_wasm_functions; | |
501 for (auto exp : module->export_table) { | |
502 if (exp.kind != kExternalFunction) continue; | |
503 Code* export_wrapper = Code::cast(new_functions->get(func_index)); | |
504 DCHECK_EQ(Code::JS_TO_WASM_FUNCTION, export_wrapper->kind()); | |
505 // There must be exactly one call to WASM_FUNCTION or WASM_TO_JS_FUNCTION. | |
506 int num_wasm_calls = 0; | |
507 for (RelocIterator it(export_wrapper, RelocInfo::kCodeTargetMask); | |
508 !it.done(); it.next()) { | |
509 Code::Kind kind = | |
510 Code::GetCodeFromTargetAddress(it.rinfo()->target_address())->kind(); | |
511 if (kind != Code::WASM_FUNCTION && kind != Code::WASM_TO_JS_FUNCTION) | |
512 continue; | |
513 ++num_wasm_calls; | |
514 Code* new_code = Code::cast(new_functions->get(exp.index)); | |
515 DCHECK_EQ(kind, new_code->kind()); | |
516 it.rinfo()->set_target_address(new_code->instruction_start(), | |
517 UPDATE_WRITE_BARRIER, SKIP_ICACHE_FLUSH); | |
518 } | |
519 DCHECK_EQ(1, num_wasm_calls); | |
520 func_index++; | |
521 } | |
522 DCHECK_EQ(new_functions->length(), func_index); | |
478 } | 523 } |
479 | 524 |
480 static void ResetCompiledModule(Isolate* isolate, WasmInstanceObject* owner, | 525 static void ResetCompiledModule(Isolate* isolate, WasmInstanceObject* owner, |
481 WasmCompiledModule* compiled_module) { | 526 WasmCompiledModule* compiled_module) { |
482 TRACE("Resetting %d\n", compiled_module->instance_id()); | 527 TRACE("Resetting %d\n", compiled_module->instance_id()); |
483 Object* undefined = *isolate->factory()->undefined_value(); | 528 Object* undefined = *isolate->factory()->undefined_value(); |
484 uint32_t old_mem_size = compiled_module->mem_size(); | 529 uint32_t old_mem_size = compiled_module->mem_size(); |
485 uint32_t default_mem_size = compiled_module->default_mem_size(); | 530 uint32_t default_mem_size = compiled_module->default_mem_size(); |
486 Object* mem_start = compiled_module->maybe_ptr_to_memory(); | 531 Object* mem_start = compiled_module->maybe_ptr_to_memory(); |
487 Address old_mem_address = nullptr; | 532 Address old_mem_address = nullptr; |
(...skipping 804 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1292 instance->memory_object()->AddInstance(isolate_, instance); | 1337 instance->memory_object()->AddInstance(isolate_, instance); |
1293 } | 1338 } |
1294 | 1339 |
1295 //-------------------------------------------------------------------------- | 1340 //-------------------------------------------------------------------------- |
1296 // Set up the indirect function tables for the new instance. | 1341 // Set up the indirect function tables for the new instance. |
1297 //-------------------------------------------------------------------------- | 1342 //-------------------------------------------------------------------------- |
1298 if (function_table_count > 0) InitializeTables(code_table, instance); | 1343 if (function_table_count > 0) InitializeTables(code_table, instance); |
1299 | 1344 |
1300 if (num_imported_functions > 0 || !owner.is_null()) { | 1345 if (num_imported_functions > 0 || !owner.is_null()) { |
1301 // If the code was cloned, or new imports were compiled, patch. | 1346 // If the code was cloned, or new imports were compiled, patch. |
1302 PatchDirectCalls(old_code_table, code_table, num_imported_functions); | 1347 PatchDirectCalls(code_table, compiled_module_, module_, |
1348 num_imported_functions); | |
1303 } | 1349 } |
1304 | 1350 |
1305 FlushICache(isolate_, code_table); | 1351 FlushICache(isolate_, code_table); |
1306 | 1352 |
1307 //-------------------------------------------------------------------------- | 1353 //-------------------------------------------------------------------------- |
1308 // Unpack and notify signal handler of protected instructions. | 1354 // Unpack and notify signal handler of protected instructions. |
1309 //-------------------------------------------------------------------------- | 1355 //-------------------------------------------------------------------------- |
1310 { | 1356 { |
1311 for (int i = 0; i < code_table->length(); ++i) { | 1357 for (int i = 0; i < code_table->length(); ++i) { |
1312 Handle<Code> code = code_table->GetValueChecked<Code>(isolate_, i); | 1358 Handle<Code> code = code_table->GetValueChecked<Code>(isolate_, i); |
(...skipping 985 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
2298 CHECK(!compiled_module->has_weak_owning_instance()); | 2344 CHECK(!compiled_module->has_weak_owning_instance()); |
2299 } | 2345 } |
2300 | 2346 |
2301 void testing::ValidateOrphanedInstance(Isolate* isolate, | 2347 void testing::ValidateOrphanedInstance(Isolate* isolate, |
2302 Handle<WasmInstanceObject> instance) { | 2348 Handle<WasmInstanceObject> instance) { |
2303 DisallowHeapAllocation no_gc; | 2349 DisallowHeapAllocation no_gc; |
2304 WasmCompiledModule* compiled_module = instance->compiled_module(); | 2350 WasmCompiledModule* compiled_module = instance->compiled_module(); |
2305 CHECK(compiled_module->has_weak_wasm_module()); | 2351 CHECK(compiled_module->has_weak_wasm_module()); |
2306 CHECK(compiled_module->ptr_to_weak_wasm_module()->cleared()); | 2352 CHECK(compiled_module->ptr_to_weak_wasm_module()->cleared()); |
2307 } | 2353 } |
OLD | NEW |