| 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 |