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" |
(...skipping 427 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
438 WasmName str = module_env->GetName(&func); | 438 WasmName str = module_env->GetName(&func); |
439 thrower->CompileError("Compilation of #%d:%.*s failed.", i, str.length(), | 439 thrower->CompileError("Compilation of #%d:%.*s failed.", i, str.length(), |
440 str.start()); | 440 str.start()); |
441 break; | 441 break; |
442 } | 442 } |
443 // Install the code into the linker table. | 443 // Install the code into the linker table. |
444 functions[i] = code; | 444 functions[i] = code; |
445 } | 445 } |
446 } | 446 } |
447 | 447 |
448 void PatchDirectCalls(Handle<FixedArray> old_functions, | 448 int ExtractDirectCallIndex(wasm::Decoder& decoder, const byte* pc) { |
449 Handle<FixedArray> new_functions, int start) { | 449 DCHECK_EQ(static_cast<int>(kExprCallFunction), static_cast<int>(*pc)); |
450 DCHECK_EQ(new_functions->length(), old_functions->length()); | 450 decoder.Reset(pc + 1, pc + 6); |
451 uint32_t call_idx = decoder.consume_u32v("call index"); | |
452 DCHECK(decoder.ok()); | |
453 DCHECK_GE(kMaxInt, call_idx); | |
454 return static_cast<int>(call_idx); | |
455 } | |
451 | 456 |
457 void PatchDirectCalls(Handle<FixedArray> new_functions, | |
458 Handle<WasmCompiledModule> compiled_module, | |
459 WasmModule* module, int start) { | |
452 DisallowHeapAllocation no_gc; | 460 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; | 461 AllowDeferredHandleDereference embedding_raw_address; |
460 for (int i = start; i < new_functions->length(); ++i) { | 462 SeqOneByteString* module_bytes = compiled_module->module_bytes(); |
463 std::vector<WasmFunction>* wasm_functions = | |
464 &compiled_module->module()->functions; | |
465 DCHECK_EQ(wasm_functions->size() + | |
466 compiled_module->module()->num_exported_functions, | |
467 new_functions->length()); | |
468 DCHECK_EQ(start, compiled_module->module()->num_imported_functions); | |
469 | |
470 // Allocate decoder outside of the loop and reuse it to decode all function | |
471 // indexes. | |
472 wasm::Decoder decoder(nullptr, nullptr); | |
473 int num_wasm_functions = static_cast<int>(wasm_functions->size()); | |
474 for (int i = start; i < num_wasm_functions; ++i) { | |
titzer
2017/01/11 18:34:04
Can you add a comment here about what we are doing
Clemens Hammacher
2017/01/12 09:03:12
Done.
| |
461 Code* wasm_function = Code::cast(new_functions->get(i)); | 475 Code* wasm_function = Code::cast(new_functions->get(i)); |
462 for (RelocIterator it(wasm_function, mode_mask); !it.done(); it.next()) { | 476 DCHECK(wasm_function->kind() == Code::WASM_FUNCTION); |
463 Code* old_code = | 477 SourcePositionTableIterator source_pos_iterator( |
464 Code::GetCodeFromTargetAddress(it.rinfo()->target_address()); | 478 wasm_function->source_position_table()); |
465 if (old_code->kind() == Code::WASM_TO_JS_FUNCTION || | 479 const byte* func_bytes = |
466 old_code->kind() == Code::WASM_FUNCTION) { | 480 module_bytes->GetChars() + |
467 auto found = old_to_new_code.find(old_code); | 481 compiled_module->module()->functions[i].code_start_offset; |
468 DCHECK(found != old_to_new_code.end()); | 482 for (RelocIterator it(wasm_function, RelocInfo::kCodeTargetMask); |
469 Code* new_code = found->second; | 483 !it.done(); it.next()) { |
470 if (new_code != old_code) { | 484 Code::Kind kind = |
471 it.rinfo()->set_target_address(new_code->instruction_start(), | 485 Code::GetCodeFromTargetAddress(it.rinfo()->target_address())->kind(); |
472 UPDATE_WRITE_BARRIER, | 486 if (kind != Code::WASM_FUNCTION && kind != Code::WASM_TO_JS_FUNCTION) |
473 SKIP_ICACHE_FLUSH); | 487 continue; |
474 } | 488 size_t offset_l = it.rinfo()->pc() - wasm_function->instruction_start(); |
475 } | 489 DCHECK_GE(kMaxInt, offset_l); |
490 int offset = static_cast<int>(offset_l); | |
491 DCHECK(!source_pos_iterator.done()); | |
492 int byte_pos; | |
493 do { | |
494 byte_pos = source_pos_iterator.source_position().ScriptOffset(); | |
495 source_pos_iterator.Advance(); | |
496 } while (!source_pos_iterator.done() && | |
497 source_pos_iterator.code_offset() <= offset); | |
498 int called_func_index = | |
499 ExtractDirectCallIndex(decoder, func_bytes + byte_pos); | |
500 Code* new_code = Code::cast(new_functions->get(called_func_index)); | |
501 it.rinfo()->set_target_address(new_code->instruction_start(), | |
502 UPDATE_WRITE_BARRIER, SKIP_ICACHE_FLUSH); | |
476 } | 503 } |
477 } | 504 } |
505 int func_index = num_wasm_functions; | |
506 for (auto exp : module->export_table) { | |
507 if (exp.kind != kExternalFunction) continue; | |
508 Code* export_wrapper = Code::cast(new_functions->get(func_index)); | |
509 DCHECK_EQ(Code::JS_TO_WASM_FUNCTION, export_wrapper->kind()); | |
510 // There must be exactly one call to WASM_FUNCTION or WASM_TO_JS_FUNCTION. | |
511 int num_wasm_calls = 0; | |
512 for (RelocIterator it(export_wrapper, RelocInfo::kCodeTargetMask); | |
513 !it.done(); it.next()) { | |
514 Code::Kind kind = | |
515 Code::GetCodeFromTargetAddress(it.rinfo()->target_address())->kind(); | |
516 if (kind != Code::WASM_FUNCTION && kind != Code::WASM_TO_JS_FUNCTION) | |
517 continue; | |
518 ++num_wasm_calls; | |
519 Code* new_code = Code::cast(new_functions->get(exp.index)); | |
520 DCHECK_EQ(kind, new_code->kind()); | |
521 it.rinfo()->set_target_address(new_code->instruction_start(), | |
522 UPDATE_WRITE_BARRIER, SKIP_ICACHE_FLUSH); | |
523 } | |
524 DCHECK_EQ(1, num_wasm_calls); | |
525 func_index++; | |
526 } | |
527 DCHECK_EQ(new_functions->length(), func_index); | |
478 } | 528 } |
479 | 529 |
480 static void ResetCompiledModule(Isolate* isolate, WasmInstanceObject* owner, | 530 static void ResetCompiledModule(Isolate* isolate, WasmInstanceObject* owner, |
481 WasmCompiledModule* compiled_module) { | 531 WasmCompiledModule* compiled_module) { |
482 TRACE("Resetting %d\n", compiled_module->instance_id()); | 532 TRACE("Resetting %d\n", compiled_module->instance_id()); |
483 Object* undefined = *isolate->factory()->undefined_value(); | 533 Object* undefined = *isolate->factory()->undefined_value(); |
484 uint32_t old_mem_size = compiled_module->mem_size(); | 534 uint32_t old_mem_size = compiled_module->mem_size(); |
485 uint32_t default_mem_size = compiled_module->default_mem_size(); | 535 uint32_t default_mem_size = compiled_module->default_mem_size(); |
486 Object* mem_start = compiled_module->maybe_ptr_to_memory(); | 536 Object* mem_start = compiled_module->maybe_ptr_to_memory(); |
487 Address old_mem_address = nullptr; | 537 Address old_mem_address = nullptr; |
(...skipping 810 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1298 instance->memory_object()->AddInstance(isolate_, instance); | 1348 instance->memory_object()->AddInstance(isolate_, instance); |
1299 } | 1349 } |
1300 | 1350 |
1301 //-------------------------------------------------------------------------- | 1351 //-------------------------------------------------------------------------- |
1302 // Set up the indirect function tables for the new instance. | 1352 // Set up the indirect function tables for the new instance. |
1303 //-------------------------------------------------------------------------- | 1353 //-------------------------------------------------------------------------- |
1304 if (function_table_count > 0) InitializeTables(code_table, instance); | 1354 if (function_table_count > 0) InitializeTables(code_table, instance); |
1305 | 1355 |
1306 if (num_imported_functions > 0 || !owner.is_null()) { | 1356 if (num_imported_functions > 0 || !owner.is_null()) { |
1307 // If the code was cloned, or new imports were compiled, patch. | 1357 // If the code was cloned, or new imports were compiled, patch. |
1308 PatchDirectCalls(old_code_table, code_table, num_imported_functions); | 1358 PatchDirectCalls(code_table, compiled_module_, module_, |
1359 num_imported_functions); | |
1309 } | 1360 } |
1310 | 1361 |
1311 FlushICache(isolate_, code_table); | 1362 FlushICache(isolate_, code_table); |
1312 | 1363 |
1313 //-------------------------------------------------------------------------- | 1364 //-------------------------------------------------------------------------- |
1314 // Unpack and notify signal handler of protected instructions. | 1365 // Unpack and notify signal handler of protected instructions. |
1315 //-------------------------------------------------------------------------- | 1366 //-------------------------------------------------------------------------- |
1316 { | 1367 { |
1317 for (int i = 0; i < code_table->length(); ++i) { | 1368 for (int i = 0; i < code_table->length(); ++i) { |
1318 Handle<Code> code = code_table->GetValueChecked<Code>(isolate_, i); | 1369 Handle<Code> code = code_table->GetValueChecked<Code>(isolate_, i); |
(...skipping 1138 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
2457 | 2508 |
2458 JSObject::AddProperty(entry, name_string, export_name.ToHandleChecked(), | 2509 JSObject::AddProperty(entry, name_string, export_name.ToHandleChecked(), |
2459 NONE); | 2510 NONE); |
2460 JSObject::AddProperty(entry, kind_string, export_kind, NONE); | 2511 JSObject::AddProperty(entry, kind_string, export_kind, NONE); |
2461 | 2512 |
2462 storage->set(index, *entry); | 2513 storage->set(index, *entry); |
2463 } | 2514 } |
2464 | 2515 |
2465 return array_object; | 2516 return array_object; |
2466 } | 2517 } |
OLD | NEW |