| 858 | } |
| 859 | |
| 860 | static void InvalidateGuestThreadCodeRange(FEXCore::Core::InternalThreadState* Thread, InvalidatedEntryAccumulator& Accumulator, |
| 861 | uint64_t Start, uint64_t Length) { |
| 862 | // Ensures now-modified mappings aren't cached as being in their previous non-executable state. |
| 863 | // Accessing FrontendDecoder is safe as the thread's code invalidation mutex must be locked here. |
| 864 | Thread->FrontendDecoder->ResetExecutableRangeCache(); |
| 865 | |
| 866 | auto lk = Thread->LookupCache->AcquireLock(); |
| 867 | auto& CodePages = Thread->LookupCache->Shared->CodePages; |
| 868 | |
| 869 | auto lower = CodePages.lower_bound(Start >> 12); |
| 870 | auto upper = CodePages.upper_bound((Start + Length - 1) >> 12); |
| 871 | |
| 872 | for (auto it = lower; it != upper; it++) { |
| 873 | Accumulator.emplace_back(std::move(it->second)); |
| 874 | } |
| 875 | |
| 876 | bool InvalidatedAnyEntries = false; |
| 877 | for (const auto& PageEntries : Accumulator) { |
| 878 | for (const auto& Entry : PageEntries) { |
| 879 | if (ContextImpl::ThreadRemoveCodeEntry(Thread, Entry)) { |
| 880 | InvalidatedAnyEntries = true; |
| 881 | } |
| 882 | } |
| 883 | } |
| 884 | |
| 885 | if (InvalidatedAnyEntries) { |
| 886 | // This may cause access violations in the thread on Windows as zeroing is not atomic, this is handled by the frontend |
| 887 | Allocator::VirtualDontNeed(Thread->CallRetStackBase, FEXCore::Core::InternalThreadState::CALLRET_STACK_SIZE); |
| 888 | } |
| 889 | } |
| 890 | |
| 891 | void ContextImpl::InvalidateGuestCodeRange(FEXCore::Core::InternalThreadState* Thread, InvalidatedEntryAccumulator& Accumulator, |
| 892 | uint64_t Start, uint64_t Length) { |
no test coverage detected