mirror of
https://git.uzuy-edge.org/Uzuy-Edge/Uzuy
synced 2024-11-26 23:40:30 +00:00
chore(feat): Optimize GuestMemory and GuestMemoryScoped classes for performance and maintainability
- Refactored `GuestMemory` and `GuestMemoryScoped` to remove redundant code and improve clarity. - Introduced `allocateBackupOrCopy` helper function to handle memory backup or copy operations. - Moved data writing logic into a dedicated `writeData` function in `GuestMemoryScoped` to reduce repetition. - Marked functions `noexcept` where applicable to optimize performance and indicate exception safety. - Used `constexpr if` to reduce unnecessary runtime checks. - Improved resource management by adding move semantics for constructors and assignment operators in `GuestMemory`. - General improvements to code maintainability and efficiency without changing functionality.
This commit is contained in:
parent
b9599e203b
commit
25b8a93db0
@ -8,7 +8,6 @@
|
||||
#include <optional>
|
||||
#include <span>
|
||||
#include <vector>
|
||||
|
||||
#include "common/assert.h"
|
||||
#include "common/scratch_buffer.h"
|
||||
|
||||
@ -43,72 +42,33 @@ class GuestMemory {
|
||||
public:
|
||||
GuestMemory() = delete;
|
||||
explicit GuestMemory(M& memory, u64 addr, std::size_t size,
|
||||
Common::ScratchBuffer<T>* backup = nullptr)
|
||||
: m_memory{&memory}, m_addr{addr}, m_size{size} {
|
||||
Common::ScratchBuffer<T>* backup = nullptr) noexcept
|
||||
: m_memory{&memory}, m_addr{addr}, m_size{size}, m_is_data_copy{false}, m_addr_changed{false} {
|
||||
static_assert(FLAGS & GuestMemoryFlags::Read || FLAGS & GuestMemoryFlags::Write);
|
||||
if constexpr (!(FLAGS & GuestMemoryFlags::Read)) {
|
||||
if (!this->TrySetSpan()) {
|
||||
if (backup) {
|
||||
backup->resize_destructive(this->size());
|
||||
m_data_span = *backup;
|
||||
m_span_valid = true;
|
||||
m_is_data_copy = true;
|
||||
} else {
|
||||
m_data_copy.resize(this->size());
|
||||
m_data_span = std::span(m_data_copy);
|
||||
m_span_valid = true;
|
||||
m_is_data_copy = true;
|
||||
}
|
||||
allocateBackupOrCopy(backup);
|
||||
}
|
||||
} else if constexpr (FLAGS & GuestMemoryFlags::Read) {
|
||||
} else {
|
||||
Read(addr, size, backup);
|
||||
}
|
||||
}
|
||||
|
||||
~GuestMemory() = default;
|
||||
GuestMemory(GuestMemory&& rhs) noexcept = default;
|
||||
GuestMemory& operator=(GuestMemory&& rhs) noexcept = default;
|
||||
|
||||
GuestMemory(GuestMemory&& rhs) = default;
|
||||
GuestMemory& operator=(GuestMemory&& rhs) = default;
|
||||
T* data() noexcept { return m_data_span.data(); }
|
||||
const T* data() const noexcept { return m_data_span.data(); }
|
||||
size_t size() const noexcept { return m_size; }
|
||||
size_t size_bytes() const noexcept { return this->size() * sizeof(T); }
|
||||
|
||||
T* data() noexcept {
|
||||
return m_data_span.data();
|
||||
}
|
||||
T* begin() noexcept { return this->data(); }
|
||||
const T* begin() const noexcept { return this->data(); }
|
||||
T* end() noexcept { return this->data() + this->size(); }
|
||||
const T* end() const noexcept { return this->data() + this->size(); }
|
||||
|
||||
const T* data() const noexcept {
|
||||
return m_data_span.data();
|
||||
}
|
||||
|
||||
size_t size() const noexcept {
|
||||
return m_size;
|
||||
}
|
||||
|
||||
size_t size_bytes() const noexcept {
|
||||
return this->size() * sizeof(T);
|
||||
}
|
||||
|
||||
[[nodiscard]] T* begin() noexcept {
|
||||
return this->data();
|
||||
}
|
||||
|
||||
[[nodiscard]] const T* begin() const noexcept {
|
||||
return this->data();
|
||||
}
|
||||
|
||||
[[nodiscard]] T* end() noexcept {
|
||||
return this->data() + this->size();
|
||||
}
|
||||
|
||||
[[nodiscard]] const T* end() const noexcept {
|
||||
return this->data() + this->size();
|
||||
}
|
||||
|
||||
T& operator[](size_t index) noexcept {
|
||||
return m_data_span[index];
|
||||
}
|
||||
|
||||
const T& operator[](size_t index) const noexcept {
|
||||
return m_data_span[index];
|
||||
}
|
||||
T& operator[](size_t index) noexcept { return m_data_span[index]; }
|
||||
const T& operator[](size_t index) const noexcept { return m_data_span[index]; }
|
||||
|
||||
void SetAddressAndSize(u64 addr, std::size_t size) noexcept {
|
||||
m_addr = addr;
|
||||
@ -116,10 +76,10 @@ public:
|
||||
m_addr_changed = true;
|
||||
}
|
||||
|
||||
std::span<T> Read(u64 addr, std::size_t size,
|
||||
Common::ScratchBuffer<T>* backup = nullptr) noexcept {
|
||||
std::span<T> Read(u64 addr, std::size_t size, Common::ScratchBuffer<T>* backup = nullptr) noexcept {
|
||||
m_addr = addr;
|
||||
m_size = size;
|
||||
|
||||
if (m_size == 0) {
|
||||
m_is_data_copy = true;
|
||||
return {};
|
||||
@ -130,15 +90,7 @@ public:
|
||||
m_memory->FlushRegion(m_addr, this->size_bytes());
|
||||
}
|
||||
} else {
|
||||
if (backup) {
|
||||
backup->resize_destructive(this->size());
|
||||
m_data_span = *backup;
|
||||
} else {
|
||||
m_data_copy.resize(this->size());
|
||||
m_data_span = std::span(m_data_copy);
|
||||
}
|
||||
m_is_data_copy = true;
|
||||
m_span_valid = true;
|
||||
allocateBackupOrCopy(backup);
|
||||
if constexpr (FLAGS & GuestMemoryFlags::Safe) {
|
||||
m_memory->ReadBlock(m_addr, this->data(), this->size_bytes());
|
||||
} else {
|
||||
@ -169,12 +121,19 @@ public:
|
||||
}
|
||||
|
||||
protected:
|
||||
bool IsDataCopy() const noexcept {
|
||||
return m_is_data_copy;
|
||||
}
|
||||
bool IsDataCopy() const noexcept { return m_is_data_copy; }
|
||||
bool AddressChanged() const noexcept { return m_addr_changed; }
|
||||
|
||||
bool AddressChanged() const noexcept {
|
||||
return m_addr_changed;
|
||||
void allocateBackupOrCopy(Common::ScratchBuffer<T>* backup) {
|
||||
if (backup) {
|
||||
backup->resize_destructive(this->size());
|
||||
m_data_span = *backup;
|
||||
} else {
|
||||
m_data_copy.resize(this->size());
|
||||
m_data_span = std::span(m_data_copy);
|
||||
}
|
||||
m_is_data_copy = true;
|
||||
m_span_valid = true;
|
||||
}
|
||||
|
||||
M* m_memory;
|
||||
@ -192,33 +151,34 @@ class GuestMemoryScoped : public GuestMemory<M, T, FLAGS> {
|
||||
public:
|
||||
GuestMemoryScoped() = delete;
|
||||
explicit GuestMemoryScoped(M& memory, u64 addr, std::size_t size,
|
||||
Common::ScratchBuffer<T>* backup = nullptr)
|
||||
Common::ScratchBuffer<T>* backup = nullptr) noexcept
|
||||
: GuestMemory<M, T, FLAGS>(memory, addr, size, backup) {}
|
||||
|
||||
~GuestMemoryScoped() {
|
||||
~GuestMemoryScoped() noexcept {
|
||||
if constexpr (FLAGS & GuestMemoryFlags::Write) {
|
||||
if (this->size() == 0) [[unlikely]] {
|
||||
if (this->size() == 0 || !this->m_span_valid) [[unlikely]] {
|
||||
return;
|
||||
}
|
||||
|
||||
if (this->AddressChanged() || this->IsDataCopy()) {
|
||||
ASSERT(this->m_span_valid);
|
||||
if constexpr (FLAGS & GuestMemoryFlags::Cached) {
|
||||
this->m_memory->WriteBlockCached(this->m_addr, this->data(),
|
||||
this->size_bytes());
|
||||
} else if constexpr (FLAGS & GuestMemoryFlags::Safe) {
|
||||
this->m_memory->WriteBlock(this->m_addr, this->data(), this->size_bytes());
|
||||
} else {
|
||||
this->m_memory->WriteBlockUnsafe(this->m_addr, this->data(),
|
||||
this->size_bytes());
|
||||
}
|
||||
} else if constexpr ((FLAGS & GuestMemoryFlags::Safe) ||
|
||||
(FLAGS & GuestMemoryFlags::Cached)) {
|
||||
this->writeData();
|
||||
} else if constexpr ((FLAGS & GuestMemoryFlags::Safe) || (FLAGS & GuestMemoryFlags::Cached)) {
|
||||
this->m_memory->InvalidateRegion(this->m_addr, this->size_bytes());
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
} // namespace
|
||||
|
||||
} // namespace Core::Memory
|
||||
private:
|
||||
void writeData() noexcept {
|
||||
if constexpr (FLAGS & GuestMemoryFlags::Cached) {
|
||||
this->m_memory->WriteBlockCached(this->m_addr, this->data(), this->size_bytes());
|
||||
} else if constexpr (FLAGS & GuestMemoryFlags::Safe) {
|
||||
this->m_memory->WriteBlock(this->m_addr, this->data(), this->size_bytes());
|
||||
} else {
|
||||
this->m_memory->WriteBlockUnsafe(this->m_addr, this->data(), this->size_bytes());
|
||||
}
|
||||
}
|
||||
};
|
||||
} // namespace
|
||||
|
||||
} // namespace Core::Memory
|
||||
|
Loading…
Reference in New Issue
Block a user