summaryrefslogtreecommitdiff
path: root/Source/Core
diff options
context:
space:
mode:
authorPierre Bourdon <delroth@gmail.com>2014-05-18 14:10:47 +0200
committerPierre Bourdon <delroth@gmail.com>2014-05-18 17:37:33 +0200
commit826a9e0152f6ae1422f2e4e69f9dd5dc8a2b7822 (patch)
treeba3eeba744ac76e409d1272104339fe0fb24f526 /Source/Core
parent6950f533aee33cbdce7ecfd5f59e3aba3836e730 (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.cpp26
-rw-r--r--Source/Core/Core/HW/MMIO.h12
-rw-r--r--Source/Core/Core/HW/MMIOHandlers.h34
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;
};