PointerWrap currently checks its mode for every individual byte of everything it 'does', including all of RAM. Make it not do that.

Decreases total Wii state save time (not counting compression) from
~570ms to ~18ms.

The compiler can't remove this check because of potential aliasing; this
might be fixable (e.g. by making mode const), but there is no reason to
have the code work in such a braindead way in the first place.

- DoVoid now uses memcpy.
- DoArray now uses DoVoid on the whole rather than Doing each element
(would fail for an array of STL structures, but we don't have any of
those).
- Do also now uses DoVoid.  (In the previous version, it replicated
DoVoid's code in order to ensure each type gets its own implementation,
which for small types then becomes a simple load/store in any modern
compiler.  Now DoVoid is __forceinline, which addresses that issue and
shouldn't make a big difference otherwise - perhaps a few extra copies
of the code inlined into DoArray or whatever.)
This commit is contained in:
comex 2014-08-27 19:50:52 -04:00
parent 7d05ebbc9b
commit faa2666393

View file

@ -162,8 +162,8 @@ public:
template <typename T>
void DoArray(T* x, u32 count)
{
for (u32 i = 0; i != count; ++i)
Do(x[i]);
static_assert(IsTriviallyCopyable(T), "Only sane for trivially copyable types");
DoVoid(x, count * sizeof(T));
}
void Do(Common::Flag& flag)
@ -178,6 +178,10 @@ public:
void Do(T& x)
{
static_assert(IsTriviallyCopyable(T), "Only sane for trivially copyable types");
// Note:
// Usually we can just use x = **ptr, etc. However, this doesn't work
// for unions containing BitFields (long story, stupid language rules)
// or arrays. This will get optimized anyway.
DoVoid((void*)&x, sizeof(x));
}
@ -285,38 +289,30 @@ private:
Do(elem);
}
__forceinline void DoByte(u8& x)
__forceinline
void DoVoid(void *data, u32 size)
{
switch (mode)
{
case MODE_READ:
x = **ptr;
memcpy(data, *ptr, size);
break;
case MODE_WRITE:
**ptr = x;
memcpy(*ptr, data, size);
break;
case MODE_MEASURE:
break;
case MODE_VERIFY:
_dbg_assert_msg_(COMMON, (x == **ptr),
"Savestate verification failure: %d (0x%X) (at %p) != %d (0x%X) (at %p).\n",
x, x, &x, **ptr, **ptr, *ptr);
break;
default:
_dbg_assert_msg_(COMMON, !memcmp(data, *ptr, size),
"Savestate verification failure: buf %p != %p (size %u).\n",
data, *ptr, size);
break;
}
++(*ptr);
}
void DoVoid(void *data, u32 size)
{
for (u32 i = 0; i != size; ++i)
DoByte(reinterpret_cast<u8*>(data)[i]);
*ptr += size;
}
};