mirror of
https://github.com/RGBCube/serenity
synced 2025-07-27 00:47:45 +00:00
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. :^)
This commit is contained in:
parent
a4a389156d
commit
59b4874443
2 changed files with 16 additions and 5 deletions
|
@ -37,24 +37,33 @@ SoftMMU::Region* SoftMMU::find_region(X86::LogicalAddress address)
|
||||||
if (address.selector() == 0x28)
|
if (address.selector() == 0x28)
|
||||||
return m_tls_region.ptr();
|
return m_tls_region.ptr();
|
||||||
|
|
||||||
for (auto& region : m_regions) {
|
size_t page_index = (address.offset() & ~(PAGE_SIZE - 1)) / PAGE_SIZE;
|
||||||
if (region.contains(address.offset()))
|
return m_page_to_region_map[page_index];
|
||||||
return ®ion;
|
|
||||||
}
|
|
||||||
return nullptr;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void SoftMMU::add_region(NonnullOwnPtr<Region> region)
|
void SoftMMU::add_region(NonnullOwnPtr<Region> region)
|
||||||
{
|
{
|
||||||
ASSERT(!find_region({ 0x20, region->base() }));
|
ASSERT(!find_region({ 0x20, region->base() }));
|
||||||
|
|
||||||
// FIXME: More sanity checks pls
|
// FIXME: More sanity checks pls
|
||||||
if (region->is_shared_buffer())
|
if (region->is_shared_buffer())
|
||||||
m_shbuf_regions.set(static_cast<SharedBufferRegion*>(region.ptr())->shbuf_id(), region.ptr());
|
m_shbuf_regions.set(static_cast<SharedBufferRegion*>(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));
|
m_regions.append(move(region));
|
||||||
}
|
}
|
||||||
|
|
||||||
void SoftMMU::remove_region(Region& 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())
|
if (region.is_shared_buffer())
|
||||||
m_shbuf_regions.remove(static_cast<SharedBufferRegion&>(region).shbuf_id());
|
m_shbuf_regions.remove(static_cast<SharedBufferRegion&>(region).shbuf_id());
|
||||||
m_regions.remove_first_matching([&](auto& entry) { return entry.ptr() == ®ion; });
|
m_regions.remove_first_matching([&](auto& entry) { return entry.ptr() == ®ion; });
|
||||||
|
|
|
@ -125,6 +125,8 @@ public:
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
Region* m_page_to_region_map[786432];
|
||||||
|
|
||||||
OwnPtr<Region> m_tls_region;
|
OwnPtr<Region> m_tls_region;
|
||||||
NonnullOwnPtrVector<Region> m_regions;
|
NonnullOwnPtrVector<Region> m_regions;
|
||||||
HashMap<int, Region*> m_shbuf_regions;
|
HashMap<int, Region*> m_shbuf_regions;
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue