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 449 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
460 int offset = static_cast<int>(offset_l); | 460 int offset = static_cast<int>(offset_l); |
461 DCHECK(!iterator.done()); | 461 DCHECK(!iterator.done()); |
462 int byte_pos; | 462 int byte_pos; |
463 do { | 463 do { |
464 byte_pos = iterator.source_position().ScriptOffset(); | 464 byte_pos = iterator.source_position().ScriptOffset(); |
465 iterator.Advance(); | 465 iterator.Advance(); |
466 } while (!iterator.done() && iterator.code_offset() <= offset); | 466 } while (!iterator.done() && iterator.code_offset() <= offset); |
467 return byte_pos; | 467 return byte_pos; |
468 } | 468 } |
469 | 469 |
470 void PatchDirectCalls(Handle<FixedArray> new_functions, | 470 void PatchContext(RelocIterator& it, Context* context) { |
471 Handle<WasmCompiledModule> compiled_module, | 471 Object* old = it.rinfo()->target_object(); |
472 WasmModule* module, int start) { | 472 // The only context we use is the native context. |
| 473 DCHECK_IMPLIES(old->IsContext(), old->IsNativeContext()); |
| 474 if (!old->IsNativeContext()) return; |
| 475 it.rinfo()->set_target_object(context, UPDATE_WRITE_BARRIER, |
| 476 SKIP_ICACHE_FLUSH); |
| 477 } |
| 478 |
| 479 void PatchDirectCallsAndContext(Handle<FixedArray> new_functions, |
| 480 Handle<WasmCompiledModule> compiled_module, |
| 481 WasmModule* module, int start) { |
473 DisallowHeapAllocation no_gc; | 482 DisallowHeapAllocation no_gc; |
474 AllowDeferredHandleDereference embedding_raw_address; | 483 AllowDeferredHandleDereference embedding_raw_address; |
475 SeqOneByteString* module_bytes = compiled_module->module_bytes(); | 484 SeqOneByteString* module_bytes = compiled_module->module_bytes(); |
476 std::vector<WasmFunction>* wasm_functions = | 485 std::vector<WasmFunction>* wasm_functions = |
477 &compiled_module->module()->functions; | 486 &compiled_module->module()->functions; |
478 DCHECK_EQ(wasm_functions->size() + | 487 DCHECK_EQ(wasm_functions->size() + |
479 compiled_module->module()->num_exported_functions, | 488 compiled_module->module()->num_exported_functions, |
480 new_functions->length()); | 489 new_functions->length()); |
481 DCHECK_EQ(start, compiled_module->module()->num_imported_functions); | 490 DCHECK_EQ(start, compiled_module->module()->num_imported_functions); |
| 491 Context* context = compiled_module->ptr_to_native_context(); |
| 492 int mode_mask = RelocInfo::ModeMask(RelocInfo::CODE_TARGET) | |
| 493 RelocInfo::ModeMask(RelocInfo::EMBEDDED_OBJECT); |
482 | 494 |
483 // Allocate decoder outside of the loop and reuse it to decode all function | 495 // Allocate decoder outside of the loop and reuse it to decode all function |
484 // indexes. | 496 // indexes. |
485 wasm::Decoder decoder(nullptr, nullptr); | 497 wasm::Decoder decoder(nullptr, nullptr); |
486 int num_wasm_functions = static_cast<int>(wasm_functions->size()); | 498 int num_wasm_functions = static_cast<int>(wasm_functions->size()); |
487 int func_index = start; | 499 int func_index = start; |
488 // Patch all wasm functions. | 500 // Patch all wasm functions. |
489 for (; func_index < num_wasm_functions; ++func_index) { | 501 for (; func_index < num_wasm_functions; ++func_index) { |
490 Code* wasm_function = Code::cast(new_functions->get(func_index)); | 502 Code* wasm_function = Code::cast(new_functions->get(func_index)); |
491 DCHECK(wasm_function->kind() == Code::WASM_FUNCTION); | 503 DCHECK(wasm_function->kind() == Code::WASM_FUNCTION); |
492 // Iterate simultaneously over the relocation information and the source | 504 // Iterate simultaneously over the relocation information and the source |
493 // position table. For each call in the reloc info, move the source position | 505 // position table. For each call in the reloc info, move the source position |
494 // iterator forward to that position to find the byte offset of the | 506 // iterator forward to that position to find the byte offset of the |
495 // respective call. Then extract the call index from the module wire bytes | 507 // respective call. Then extract the call index from the module wire bytes |
496 // to find the new compiled function. | 508 // to find the new compiled function. |
497 SourcePositionTableIterator source_pos_iterator( | 509 SourcePositionTableIterator source_pos_iterator( |
498 wasm_function->source_position_table()); | 510 wasm_function->source_position_table()); |
499 const byte* func_bytes = | 511 const byte* func_bytes = |
500 module_bytes->GetChars() + | 512 module_bytes->GetChars() + |
501 compiled_module->module()->functions[func_index].code_start_offset; | 513 compiled_module->module()->functions[func_index].code_start_offset; |
502 for (RelocIterator it(wasm_function, RelocInfo::kCodeTargetMask); | 514 for (RelocIterator it(wasm_function, mode_mask); !it.done(); it.next()) { |
503 !it.done(); it.next()) { | 515 if (RelocInfo::IsEmbeddedObject(it.rinfo()->rmode())) { |
| 516 PatchContext(it, context); |
| 517 continue; |
| 518 } |
| 519 DCHECK(RelocInfo::IsCodeTarget(it.rinfo()->rmode())); |
504 Code::Kind kind = | 520 Code::Kind kind = |
505 Code::GetCodeFromTargetAddress(it.rinfo()->target_address())->kind(); | 521 Code::GetCodeFromTargetAddress(it.rinfo()->target_address())->kind(); |
506 if (kind != Code::WASM_FUNCTION && kind != Code::WASM_TO_JS_FUNCTION) | 522 if (kind != Code::WASM_FUNCTION && kind != Code::WASM_TO_JS_FUNCTION) |
507 continue; | 523 continue; |
508 size_t offset = it.rinfo()->pc() - wasm_function->instruction_start(); | 524 size_t offset = it.rinfo()->pc() - wasm_function->instruction_start(); |
509 int byte_pos = | 525 int byte_pos = |
510 AdvanceSourcePositionTableIterator(source_pos_iterator, offset); | 526 AdvanceSourcePositionTableIterator(source_pos_iterator, offset); |
511 int called_func_index = | 527 int called_func_index = |
512 ExtractDirectCallIndex(decoder, func_bytes + byte_pos); | 528 ExtractDirectCallIndex(decoder, func_bytes + byte_pos); |
513 Code* new_code = Code::cast(new_functions->get(called_func_index)); | 529 Code* new_code = Code::cast(new_functions->get(called_func_index)); |
514 it.rinfo()->set_target_address(new_code->instruction_start(), | 530 it.rinfo()->set_target_address(new_code->instruction_start(), |
515 UPDATE_WRITE_BARRIER, SKIP_ICACHE_FLUSH); | 531 UPDATE_WRITE_BARRIER, SKIP_ICACHE_FLUSH); |
516 } | 532 } |
517 } | 533 } |
518 // Patch all exported functions. | 534 // Patch all exported functions. |
519 for (auto exp : module->export_table) { | 535 for (auto exp : module->export_table) { |
520 if (exp.kind != kExternalFunction) continue; | 536 if (exp.kind != kExternalFunction) continue; |
521 Code* export_wrapper = Code::cast(new_functions->get(func_index)); | 537 Code* export_wrapper = Code::cast(new_functions->get(func_index)); |
522 DCHECK_EQ(Code::JS_TO_WASM_FUNCTION, export_wrapper->kind()); | 538 DCHECK_EQ(Code::JS_TO_WASM_FUNCTION, export_wrapper->kind()); |
523 // There must be exactly one call to WASM_FUNCTION or WASM_TO_JS_FUNCTION. | 539 // There must be exactly one call to WASM_FUNCTION or WASM_TO_JS_FUNCTION. |
524 int num_wasm_calls = 0; | 540 int num_wasm_calls = 0; |
525 for (RelocIterator it(export_wrapper, RelocInfo::kCodeTargetMask); | 541 for (RelocIterator it(export_wrapper, mode_mask); !it.done(); it.next()) { |
526 !it.done(); it.next()) { | 542 if (RelocInfo::IsEmbeddedObject(it.rinfo()->rmode())) { |
| 543 PatchContext(it, context); |
| 544 continue; |
| 545 } |
| 546 DCHECK(RelocInfo::IsCodeTarget(it.rinfo()->rmode())); |
527 Code::Kind kind = | 547 Code::Kind kind = |
528 Code::GetCodeFromTargetAddress(it.rinfo()->target_address())->kind(); | 548 Code::GetCodeFromTargetAddress(it.rinfo()->target_address())->kind(); |
529 if (kind != Code::WASM_FUNCTION && kind != Code::WASM_TO_JS_FUNCTION) | 549 if (kind != Code::WASM_FUNCTION && kind != Code::WASM_TO_JS_FUNCTION) |
530 continue; | 550 continue; |
531 ++num_wasm_calls; | 551 ++num_wasm_calls; |
532 Code* new_code = Code::cast(new_functions->get(exp.index)); | 552 Code* new_code = Code::cast(new_functions->get(exp.index)); |
533 DCHECK_EQ(kind, new_code->kind()); | 553 DCHECK_EQ(kind, new_code->kind()); |
534 it.rinfo()->set_target_address(new_code->instruction_start(), | 554 it.rinfo()->set_target_address(new_code->instruction_start(), |
535 UPDATE_WRITE_BARRIER, SKIP_ICACHE_FLUSH); | 555 UPDATE_WRITE_BARRIER, SKIP_ICACHE_FLUSH); |
536 } | 556 } |
(...skipping 693 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1230 } | 1250 } |
1231 } | 1251 } |
1232 RecordStats(isolate_, code_table); | 1252 RecordStats(isolate_, code_table); |
1233 } else { | 1253 } else { |
1234 // There was no owner, so we can reuse the original. | 1254 // There was no owner, so we can reuse the original. |
1235 compiled_module_ = original; | 1255 compiled_module_ = original; |
1236 TRACE("Reusing existing instance %d\n", | 1256 TRACE("Reusing existing instance %d\n", |
1237 compiled_module_->instance_id()); | 1257 compiled_module_->instance_id()); |
1238 } | 1258 } |
1239 compiled_module_->set_code_table(code_table); | 1259 compiled_module_->set_code_table(code_table); |
| 1260 compiled_module_->set_native_context(isolate_->native_context()); |
1240 } | 1261 } |
1241 module_ = compiled_module_->module(); | 1262 module_ = compiled_module_->module(); |
1242 | 1263 |
1243 //-------------------------------------------------------------------------- | 1264 //-------------------------------------------------------------------------- |
1244 // Allocate the instance object. | 1265 // Allocate the instance object. |
1245 //-------------------------------------------------------------------------- | 1266 //-------------------------------------------------------------------------- |
1246 Handle<WasmInstanceObject> instance = | 1267 Handle<WasmInstanceObject> instance = |
1247 WasmInstanceObject::New(isolate_, compiled_module_); | 1268 WasmInstanceObject::New(isolate_, compiled_module_); |
1248 | 1269 |
1249 //-------------------------------------------------------------------------- | 1270 //-------------------------------------------------------------------------- |
(...skipping 109 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1359 DCHECK(wasm::IsWasmInstance(*instance)); | 1380 DCHECK(wasm::IsWasmInstance(*instance)); |
1360 if (instance->has_memory_object()) { | 1381 if (instance->has_memory_object()) { |
1361 instance->memory_object()->AddInstance(isolate_, instance); | 1382 instance->memory_object()->AddInstance(isolate_, instance); |
1362 } | 1383 } |
1363 | 1384 |
1364 //-------------------------------------------------------------------------- | 1385 //-------------------------------------------------------------------------- |
1365 // Set up the indirect function tables for the new instance. | 1386 // Set up the indirect function tables for the new instance. |
1366 //-------------------------------------------------------------------------- | 1387 //-------------------------------------------------------------------------- |
1367 if (function_table_count > 0) InitializeTables(code_table, instance); | 1388 if (function_table_count > 0) InitializeTables(code_table, instance); |
1368 | 1389 |
1369 if (num_imported_functions > 0 || !owner.is_null()) { | 1390 // Patch new call sites and the context. |
1370 // If the code was cloned, or new imports were compiled, patch. | 1391 PatchDirectCallsAndContext(code_table, compiled_module_, module_, |
1371 PatchDirectCalls(code_table, compiled_module_, module_, | 1392 num_imported_functions); |
1372 num_imported_functions); | |
1373 } | |
1374 | 1393 |
1375 FlushICache(isolate_, code_table); | 1394 FlushICache(isolate_, code_table); |
1376 | 1395 |
1377 //-------------------------------------------------------------------------- | 1396 //-------------------------------------------------------------------------- |
1378 // Unpack and notify signal handler of protected instructions. | 1397 // Unpack and notify signal handler of protected instructions. |
1379 //-------------------------------------------------------------------------- | 1398 //-------------------------------------------------------------------------- |
1380 { | 1399 { |
1381 for (int i = 0; i < code_table->length(); ++i) { | 1400 for (int i = 0; i < code_table->length(); ++i) { |
1382 Handle<Code> code = code_table->GetValueChecked<Code>(isolate_, i); | 1401 Handle<Code> code = code_table->GetValueChecked<Code>(isolate_, i); |
1383 | 1402 |
(...skipping 1137 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2521 | 2540 |
2522 JSObject::AddProperty(entry, name_string, export_name.ToHandleChecked(), | 2541 JSObject::AddProperty(entry, name_string, export_name.ToHandleChecked(), |
2523 NONE); | 2542 NONE); |
2524 JSObject::AddProperty(entry, kind_string, export_kind, NONE); | 2543 JSObject::AddProperty(entry, kind_string, export_kind, NONE); |
2525 | 2544 |
2526 storage->set(index, *entry); | 2545 storage->set(index, *entry); |
2527 } | 2546 } |
2528 | 2547 |
2529 return array_object; | 2548 return array_object; |
2530 } | 2549 } |
OLD | NEW |