Bug 558410 - silence strict aliasing warnings (r=jorendorff)

--HG--
extra : rebase_source : c6cad8a5461e685f31f5959aa69635be57c807d4
This commit is contained in:
Luke Wagner 2010-04-19 13:08:19 -07:00
parent 04a7e441fc
commit ee07742078
2 changed files with 44 additions and 40 deletions

View File

@ -249,6 +249,28 @@ class SystemAllocPolicy
void reportAllocOverflow() const {}
};
/*
* This utility pales in comparison to Boost's aligned_storage. The utility
* simply assumes that uint64_t is enough alignment for anyone. This may need
* to be extended one day...
*
* As an important side effect, pulling the storage into this template is
* enough obfuscation to confuse gcc's strict-aliasing analysis into not giving
* false negatives when we cast from the char buffer to whatever type we've
* constructed using the bytes.
*/
template <size_t nbytes>
struct AlignedStorage
{
union U {
char bytes[nbytes];
uint64_t _;
} u;
const void *addr() const { return u.bytes; }
void *addr() { return u.bytes; }
};
/*
* Small utility for lazily constructing objects without using dynamic storage.
* When a LazilyConstructed<T> is constructed, it is |empty()|, i.e., no value
@ -260,45 +282,42 @@ class SystemAllocPolicy
template <class T>
class LazilyConstructed
{
union {
uint64 align;
char bytes[sizeof(T) + 1];
};
AlignedStorage<sizeof(T)> storage;
bool constructed;
T &asT() { return *reinterpret_cast<T *>(bytes); }
char & constructed() { return bytes[sizeof(T)]; }
T &asT() { return *reinterpret_cast<T *>(storage.addr()); }
public:
LazilyConstructed() { constructed() = false; }
~LazilyConstructed() { if (constructed()) asT().~T(); }
LazilyConstructed() { constructed = false; }
~LazilyConstructed() { if (constructed) asT().~T(); }
bool empty() const { return !constructed(); }
bool empty() const { return !constructed; }
void construct() {
JS_ASSERT(!constructed());
new(bytes) T();
constructed() = true;
JS_ASSERT(!constructed);
new(storage.addr()) T();
constructed = true;
}
template <class T1>
void construct(const T1 &t1) {
JS_ASSERT(!constructed());
new(bytes) T(t1);
constructed() = true;
JS_ASSERT(!constructed);
new(storage.addr()) T(t1);
constructed = true;
}
template <class T1, class T2>
void construct(const T1 &t1, const T2 &t2) {
JS_ASSERT(!constructed());
new(bytes) T(t1, t2);
constructed() = true;
JS_ASSERT(!constructed);
new(storage.addr()) T(t1, t2);
constructed = true;
}
template <class T1, class T2, class T3>
void construct(const T1 &t1, const T2 &t2, const T3 &t3) {
JS_ASSERT(!constructed());
new(bytes) T(t1, t2, t3);
constructed() = true;
JS_ASSERT(!constructed);
new(storage.addr()) T(t1, t2, t3);
constructed = true;
}
};

View File

@ -208,7 +208,7 @@ class Vector : AllocPolicy
/*
* Since a vector either stores elements inline or in a heap-allocated
* buffer, reuse the storage. mLengthOrCapacity serves as the union
* discriminator. In inline mode (when elements are stored in u.mBuf),
* discriminator. In inline mode (when elements are stored in u.storage),
* mLengthOrCapacity holds the vector's length. In heap mode (when elements
* are stored in [u.ptrs.mBegin, u.ptrs.mEnd)), mLengthOrCapacity holds the
* vector's capacity.
@ -228,22 +228,7 @@ class Vector : AllocPolicy
union {
BufferPtrs ptrs;
char mBuf[sInlineBytes];
#if __GNUC__
/*
* GCC thinks there is a strict aliasing warning since mBuf is a char
* array but we read and write to it as a T array. This is not an error
* since there are no reads and writes to the mBuf memory except those
* that treat it as a T array. Sadly,
* #pragma GCC diagnostic ignore "-Wstrict-aliasing"
* doesn't silence the warning. Type punning is allowed through a union
* of the involved types, so, for now, this error can be silenced by
* adding each offending T to this union. (This won't work for non-POD
* T's, but there don't seem to be any with warnings yet...)
*/
jschar unused1_;
#endif
AlignedStorage<sInlineBytes> storage;
} u;
/* Only valid when usingInlineStorage() */
@ -259,12 +244,12 @@ class Vector : AllocPolicy
T *inlineBegin() const {
JS_ASSERT(usingInlineStorage());
return (T *)u.mBuf;
return (T *)u.storage.addr();
}
T *inlineEnd() const {
JS_ASSERT(usingInlineStorage());
return (T *)u.mBuf + mLengthOrCapacity;
return (T *)u.storage.addr() + mLengthOrCapacity;
}
/* Only valid when !usingInlineStorage() */