diff options
| author | Pierre Bourdon <delroth@gmail.com> | 2014-05-18 14:10:47 +0200 |
|---|---|---|
| committer | Pierre Bourdon <delroth@gmail.com> | 2014-05-18 17:37:33 +0200 |
| commit | 826a9e0152f6ae1422f2e4e69f9dd5dc8a2b7822 (patch) | |
| tree | ba3eeba744ac76e409d1272104339fe0fb24f526 /Source/Core | |
| parent | 6950f533aee33cbdce7ecfd5f59e3aba3836e730 (diff) | |
MMIO: Lazy-initialize read/write handlers since most are not actually used
Diffstat (limited to 'Source/Core')
| -rw-r--r-- | Source/Core/Core/HW/MMIO.cpp | 26 | ||||
| -rw-r--r-- | Source/Core/Core/HW/MMIO.h | 12 | ||||
| -rw-r--r-- | Source/Core/Core/HW/MMIOHandlers.h | 34 |
3 files changed, 51 insertions, 21 deletions
diff --git a/Source/Core/Core/HW/MMIO.cpp b/Source/Core/Core/HW/MMIO.cpp index f8cbe9ee18..d1b37e5c54 100644 --- a/Source/Core/Core/HW/MMIO.cpp +++ b/Source/Core/Core/HW/MMIO.cpp @@ -224,8 +224,8 @@ ReadHandlingMethod<T>* ReadToSmaller(Mapping* mmio, u32 high_part_addr, u32 low_ { typedef typename SmallerAccessSize<T>::value ST; - const ReadHandler<ST>* high_part; - const ReadHandler<ST>* low_part; + ReadHandler<ST>* high_part; + ReadHandler<ST>* low_part; mmio->GetHandlerForRead(high_part_addr, &high_part); mmio->GetHandlerForRead(low_part_addr, &low_part); @@ -241,8 +241,8 @@ WriteHandlingMethod<T>* WriteToSmaller(Mapping* mmio, u32 high_part_addr, u32 lo { typedef typename SmallerAccessSize<T>::value ST; - const WriteHandler<ST>* high_part; - const WriteHandler<ST>* low_part; + WriteHandler<ST>* high_part; + WriteHandler<ST>* low_part; mmio->GetHandlerForWrite(high_part_addr, &high_part); mmio->GetHandlerForWrite(low_part_addr, &low_part); @@ -258,7 +258,7 @@ ReadHandlingMethod<T>* ReadToLarger(Mapping* mmio, u32 larger_addr, u32 shift) { typedef typename LargerAccessSize<T>::value LT; - const ReadHandler<LT>* large; + ReadHandler<LT>* large; mmio->GetHandlerForRead(larger_addr, &large); // TODO(delroth): optimize @@ -271,9 +271,8 @@ ReadHandlingMethod<T>* ReadToLarger(Mapping* mmio, u32 larger_addr, u32 shift) // redundant code between these two classes but trying to abstract it away // brings more trouble than it fixes. template <typename T> -ReadHandler<T>::ReadHandler() : m_Method(nullptr) +ReadHandler<T>::ReadHandler() { - ResetMethod(InvalidRead<T>()); } template <typename T> @@ -289,8 +288,11 @@ ReadHandler<T>::~ReadHandler() } template <typename T> -void ReadHandler<T>::Visit(ReadHandlingMethodVisitor<T>& visitor) const +void ReadHandler<T>::Visit(ReadHandlingMethodVisitor<T>& visitor) { + if (!m_Method) + InitializeInvalid(); + m_Method->AcceptReadVisitor(visitor); } @@ -325,9 +327,8 @@ void ReadHandler<T>::ResetMethod(ReadHandlingMethod<T>* method) } template <typename T> -WriteHandler<T>::WriteHandler() : m_Method(nullptr) +WriteHandler<T>::WriteHandler() { - ResetMethod(InvalidWrite<T>()); } template <typename T> @@ -343,8 +344,11 @@ WriteHandler<T>::~WriteHandler() } template <typename T> -void WriteHandler<T>::Visit(WriteHandlingMethodVisitor<T>& visitor) const +void WriteHandler<T>::Visit(WriteHandlingMethodVisitor<T>& visitor) { + if (!m_Method) + InitializeInvalid(); + m_Method->AcceptWriteVisitor(visitor); } diff --git a/Source/Core/Core/HW/MMIO.h b/Source/Core/Core/HW/MMIO.h index 28fe19ba5a..721689fb54 100644 --- a/Source/Core/Core/HW/MMIO.h +++ b/Source/Core/Core/HW/MMIO.h @@ -105,7 +105,7 @@ public: // Note that for reads we cannot simply return the read value because C++ // allows overloading only with parameter types, not return types. #define READ_FUNC(Size) \ - void Read(u32 addr, u##Size* val) const \ + void Read(u32 addr, u##Size* val) \ { \ u32 id = UniqueID(addr) / sizeof (u##Size); \ *val = m_Read##Size##Handlers[id].Read(addr); \ @@ -114,7 +114,7 @@ public: #undef READ_FUNC #define WRITE_FUNC(Size) \ - void Write(u32 addr, u##Size val) const \ + void Write(u32 addr, u##Size val) \ { \ u32 id = UniqueID(addr) / sizeof (u##Size); \ m_Write##Size##Handlers[id].Write(addr, val); \ @@ -133,11 +133,11 @@ public: // value. This second variant is needed because C++ doesn't do overloads // based on return type but only based on argument types. #define GET_HANDLERS_FUNC(Type, Size) \ - const Type##Handler<u##Size>& GetHandlerFor##Type##Size(u32 addr) const \ + Type##Handler<u##Size>& GetHandlerFor##Type##Size(u32 addr) \ { \ return m_##Type##Size##Handlers[UniqueID(addr) / sizeof (u##Size)]; \ } \ - void GetHandlerFor##Type(u32 addr, const Type##Handler<u##Size>** h) const \ + void GetHandlerFor##Type(u32 addr, Type##Handler<u##Size>** h) \ { \ *h = &GetHandlerFor##Type##Size(addr); \ } @@ -147,8 +147,8 @@ public: // Dummy 64 bits variants of these functions. While 64 bits MMIO access is // not supported, we need these in order to make the code compile. - void Read(u32 addr, u64* val) const { _dbg_assert_(MEMMAP, 0); } - void Write(u32 addr, u64 val) const { _dbg_assert_(MEMMAP, 0); } + void Read(u32 addr, u64* val) { _dbg_assert_(MEMMAP, 0); } + void Write(u32 addr, u64 val) { _dbg_assert_(MEMMAP, 0); } private: // These arrays contain the handlers for each MMIO access type: read/write diff --git a/Source/Core/Core/HW/MMIOHandlers.h b/Source/Core/Core/HW/MMIOHandlers.h index 7afe9f60b5..8fc3c25e6d 100644 --- a/Source/Core/Core/HW/MMIOHandlers.h +++ b/Source/Core/Core/HW/MMIOHandlers.h @@ -115,10 +115,16 @@ public: ~ReadHandler(); // Entry point for read handling method visitors. - void Visit(ReadHandlingMethodVisitor<T>& visitor) const; + void Visit(ReadHandlingMethodVisitor<T>& visitor); - T Read(u32 addr) const + T Read(u32 addr) { + // Check if the handler has already been initialized. For real + // handlers, this will always be the case, so this branch should be + // easily predictable. + if (!m_Method) + InitializeInvalid(); + return m_ReadFunc(addr); } @@ -127,6 +133,13 @@ public: void ResetMethod(ReadHandlingMethod<T>* method); private: + // Initialize this handler to an invalid handler. Done lazily to avoid + // useless initialization of thousands of unused handler objects. + void InitializeInvalid() + { + ResetMethod(InvalidRead<T>()); + } + std::unique_ptr<ReadHandlingMethod<T>> m_Method; std::function<T(u32)> m_ReadFunc; }; @@ -142,10 +155,16 @@ public: ~WriteHandler(); // Entry point for write handling method visitors. - void Visit(WriteHandlingMethodVisitor<T>& visitor) const; + void Visit(WriteHandlingMethodVisitor<T>& visitor); - void Write(u32 addr, T val) const + void Write(u32 addr, T val) { + // Check if the handler has already been initialized. For real + // handlers, this will always be the case, so this branch should be + // easily predictable. + if (!m_Method) + InitializeInvalid(); + m_WriteFunc(addr, val); } @@ -155,6 +174,13 @@ public: void ResetMethod(WriteHandlingMethod<T>* method); private: + // Initialize this handler to an invalid handler. Done lazily to avoid + // useless initialization of thousands of unused handler objects. + void InitializeInvalid() + { + ResetMethod(InvalidWrite<T>()); + } + std::unique_ptr<WriteHandlingMethod<T>> m_Method; std::function<void(u32, T)> m_WriteFunc; }; |
