mirror of
https://github.com/dolphin-emu/dolphin.git
synced 2026-10-19 17:18:59 +02:00
JitCache has been using a class called ValidBlockBitSet. This commit replaces it with a new class called LazyMemoryRegionBitSet, which works similarly but is backed by a LazyMemoryRegion, letting us skip allocating memory for parts of the bit set that correspond to emulated memory regions where the game isn't storing any code. I have also added optimized functions for setting or clearing long runs of bits. Additionally, this commit replaces JitBase's three std::unordered_sets that are keeping track of instructions with LazyMemoryRegionBitSets. Here the benefit is more speed than memory usage. This improves NBA Live 2005's menu performance by 1% or so in SuperSamus's testing.
77 lines
1.7 KiB
C++
77 lines
1.7 KiB
C++
// Copyright 2026 Dolphin Emulator Project
|
|
// SPDX-License-Identifier: GPL-2.0-or-later
|
|
|
|
#pragma once
|
|
|
|
#include <cstddef>
|
|
|
|
#include "Common/Assert.h"
|
|
#include "Common/MemArena.h"
|
|
|
|
namespace Common
|
|
{
|
|
// A bit set backed by a LazyMemoryRegion.
|
|
class LazyMemoryRegionBitSet final
|
|
{
|
|
public:
|
|
// Allocates backing memory and creates a bit set.
|
|
// Allocating backing memory may fail; use IsValid to check for success.
|
|
LazyMemoryRegionBitSet(size_t bits);
|
|
|
|
bool IsValid() const { return m_valid; }
|
|
|
|
void Clear();
|
|
|
|
bool TestBit(size_t bit) const
|
|
{
|
|
CheckBitIndexReadable(bit);
|
|
return (m_pointer[bit / 32] & (1 << (bit % 32))) != 0;
|
|
}
|
|
|
|
void SetBit(size_t bit)
|
|
{
|
|
CheckBitIndexWriteable(bit);
|
|
m_region.EnsureMemoryPageWritable(bit / 8);
|
|
m_pointer[bit / 32] |= (1 << (bit % 32));
|
|
}
|
|
|
|
void ClearBit(size_t bit)
|
|
{
|
|
CheckBitIndexWriteable(bit);
|
|
m_region.EnsureMemoryPageWritable(bit / 8);
|
|
m_pointer[bit / 32] &= ~(1 << (bit % 32));
|
|
}
|
|
|
|
void SetBits(size_t bits_start, size_t bits_end);
|
|
|
|
void ClearBits(size_t bits_start, size_t bits_end);
|
|
|
|
const u32* GetRawMemory() const { return m_pointer; }
|
|
|
|
private:
|
|
LazyMemoryRegion m_region;
|
|
u32* m_pointer;
|
|
size_t m_bits;
|
|
bool m_valid;
|
|
|
|
bool Create(size_t bits);
|
|
|
|
void CheckBitIndexReadable(size_t bit) const
|
|
{
|
|
DEBUG_ASSERT_MSG(COMMON, m_valid, "LazyMemoryRegionBitSet isn't valid");
|
|
DEBUG_ASSERT_MSG(COMMON, bit < m_bits,
|
|
"Tried to access bit {} in a LazyMemoryRegionBitSet with only {} bits", bit,
|
|
m_bits);
|
|
}
|
|
|
|
void CheckBitIndexWriteable(size_t bit)
|
|
{
|
|
CheckBitIndexReadable(bit);
|
|
m_region.EnsureMemoryPageWritable(bit / 8);
|
|
}
|
|
|
|
void CheckBitIndicesWriteable(size_t bits_start, size_t bits_end);
|
|
};
|
|
|
|
} // namespace Common
|