Chromium Code Reviews| 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 |