From 59b4874443184305274f671a7bbc94773ef3f9a9 Mon Sep 17 00:00:00 2001 From: Andreas Kling Date: Sun, 15 Nov 2020 17:30:32 +0100 Subject: [PATCH] UserspaceEmulator: Add a page-address-to-MMU-region lookup map To make SoftMMU::find_region() O(1), this patch invests 3MiB into a lookup table where we track each possible page base address and map them to the SoftMMU::Region corresponding to that address. This is another large improvement to general emulation performance. :^) --- DevTools/UserspaceEmulator/SoftMMU.cpp | 19 ++++++++++++++----- DevTools/UserspaceEmulator/SoftMMU.h | 2 ++ 2 files changed, 16 insertions(+), 5 deletions(-) diff --git a/DevTools/UserspaceEmulator/SoftMMU.cpp b/DevTools/UserspaceEmulator/SoftMMU.cpp index 9d330f2305c..58b7f724756 100644 --- a/DevTools/UserspaceEmulator/SoftMMU.cpp +++ b/DevTools/UserspaceEmulator/SoftMMU.cpp @@ -37,24 +37,33 @@ SoftMMU::Region* SoftMMU::find_region(X86::LogicalAddress address) if (address.selector() == 0x28) return m_tls_region.ptr(); - for (auto& region : m_regions) { - if (region.contains(address.offset())) - return ®ion; - } - return nullptr; + size_t page_index = (address.offset() & ~(PAGE_SIZE - 1)) / PAGE_SIZE; + return m_page_to_region_map[page_index]; } void SoftMMU::add_region(NonnullOwnPtr region) { ASSERT(!find_region({ 0x20, region->base() })); + // FIXME: More sanity checks pls if (region->is_shared_buffer()) m_shbuf_regions.set(static_cast(region.ptr())->shbuf_id(), region.ptr()); + + size_t first_page_in_region = region->base() / PAGE_SIZE; + for (size_t i = 0; i < ceil_div(region->size(), PAGE_SIZE); ++i) { + m_page_to_region_map[first_page_in_region + i] = region.ptr(); + } + m_regions.append(move(region)); } void SoftMMU::remove_region(Region& region) { + size_t first_page_in_region = region.base() / PAGE_SIZE; + for (size_t i = 0; i < ceil_div(region.size(), PAGE_SIZE); ++i) { + m_page_to_region_map[first_page_in_region + i] = nullptr; + } + if (region.is_shared_buffer()) m_shbuf_regions.remove(static_cast(region).shbuf_id()); m_regions.remove_first_matching([&](auto& entry) { return entry.ptr() == ®ion; }); diff --git a/DevTools/UserspaceEmulator/SoftMMU.h b/DevTools/UserspaceEmulator/SoftMMU.h index 52e9b2a2492..f09c7f97767 100644 --- a/DevTools/UserspaceEmulator/SoftMMU.h +++ b/DevTools/UserspaceEmulator/SoftMMU.h @@ -125,6 +125,8 @@ public: } private: + Region* m_page_to_region_map[786432]; + OwnPtr m_tls_region; NonnullOwnPtrVector m_regions; HashMap m_shbuf_regions;