mirror of
https://repo.dactyloidae.xyz/Dactyloidae/UXP.git
synced 2026-10-04 06:17:30 +09:00
Issue #2148 - Make Vector not use AlignedStorage for its inline element storage
See Bug 1338374 1/2
This commit is contained in:
parent
cdd91edd79
commit
0365f940fe
5 changed files with 108 additions and 48 deletions
|
|
@ -46,7 +46,8 @@ struct LoopIterationBound : public TempObject
|
||||||
// of the loop header. This will use loop invariant terms and header phis.
|
// of the loop header. This will use loop invariant terms and header phis.
|
||||||
LinearSum currentSum;
|
LinearSum currentSum;
|
||||||
|
|
||||||
LoopIterationBound(MBasicBlock* header, MTest* test, LinearSum boundSum, LinearSum currentSum)
|
LoopIterationBound(MBasicBlock* header, MTest* test,
|
||||||
|
const LinearSum& boundSum, const LinearSum& currentSum)
|
||||||
: header(header), test(test),
|
: header(header), test(test),
|
||||||
boundSum(boundSum), currentSum(currentSum)
|
boundSum(boundSum), currentSum(currentSum)
|
||||||
{
|
{
|
||||||
|
|
@ -59,7 +60,7 @@ typedef Vector<LoopIterationBound*, 0, SystemAllocPolicy> LoopIterationBoundVect
|
||||||
struct SymbolicBound : public TempObject
|
struct SymbolicBound : public TempObject
|
||||||
{
|
{
|
||||||
private:
|
private:
|
||||||
SymbolicBound(LoopIterationBound* loop, LinearSum sum)
|
SymbolicBound(LoopIterationBound* loop, const LinearSum& sum)
|
||||||
: loop(loop), sum(sum)
|
: loop(loop), sum(sum)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
@ -73,7 +74,8 @@ struct SymbolicBound : public TempObject
|
||||||
// If nullptr, then 'sum' is always valid.
|
// If nullptr, then 'sum' is always valid.
|
||||||
LoopIterationBound* loop;
|
LoopIterationBound* loop;
|
||||||
|
|
||||||
static SymbolicBound* New(TempAllocator& alloc, LoopIterationBound* loop, LinearSum sum) {
|
static SymbolicBound*
|
||||||
|
New(TempAllocator& alloc, LoopIterationBound* loop, const LinearSum& sum) {
|
||||||
return new(alloc) SymbolicBound(loop, sum);
|
return new(alloc) SymbolicBound(loop, sum);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -23,6 +23,7 @@
|
||||||
/* Note: Aborts on OOM. */
|
/* Note: Aborts on OOM. */
|
||||||
class JSAPITestString {
|
class JSAPITestString {
|
||||||
js::Vector<char, 0, js::SystemAllocPolicy> chars;
|
js::Vector<char, 0, js::SystemAllocPolicy> chars;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
JSAPITestString() {}
|
JSAPITestString() {}
|
||||||
explicit JSAPITestString(const char* s) { *this += s; }
|
explicit JSAPITestString(const char* s) { *this += s; }
|
||||||
|
|
@ -32,21 +33,34 @@ class JSAPITestString {
|
||||||
const char* end() const { return chars.end(); }
|
const char* end() const { return chars.end(); }
|
||||||
size_t length() const { return chars.length(); }
|
size_t length() const { return chars.length(); }
|
||||||
|
|
||||||
JSAPITestString & operator +=(const char* s) {
|
JSAPITestString& operator +=(const char* s) {
|
||||||
if (!chars.append(s, strlen(s)))
|
if (!chars.append(s, strlen(s)))
|
||||||
abort();
|
abort();
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
JSAPITestString & operator +=(const JSAPITestString& s) {
|
JSAPITestString& operator +=(const JSAPITestString& s) {
|
||||||
if (!chars.append(s.begin(), s.length()))
|
if (!chars.append(s.begin(), s.length()))
|
||||||
abort();
|
abort();
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
inline JSAPITestString operator+(JSAPITestString a, const char* b) { return a += b; }
|
inline JSAPITestString
|
||||||
inline JSAPITestString operator+(JSAPITestString a, const JSAPITestString& b) { return a += b; }
|
operator+(const JSAPITestString& a, const char* b)
|
||||||
|
{
|
||||||
|
JSAPITestString result = a;
|
||||||
|
result += b;
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline JSAPITestString
|
||||||
|
operator+(const JSAPITestString& a, const JSAPITestString& b)
|
||||||
|
{
|
||||||
|
JSAPITestString result = a;
|
||||||
|
result += b;
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
class JSAPITest
|
class JSAPITest
|
||||||
{
|
{
|
||||||
|
|
@ -205,7 +219,11 @@ class JSAPITest
|
||||||
return fail(JSAPITestString("CHECK failed: " #expr), __FILE__, __LINE__); \
|
return fail(JSAPITestString("CHECK failed: " #expr), __FILE__, __LINE__); \
|
||||||
} while (false)
|
} while (false)
|
||||||
|
|
||||||
bool fail(JSAPITestString msg = JSAPITestString(), const char* filename = "-", int lineno = 0) {
|
bool fail(const JSAPITestString& msg = JSAPITestString(),
|
||||||
|
const char* filename = "-",
|
||||||
|
int lineno = 0)
|
||||||
|
{
|
||||||
|
JSAPITestString message = msg;
|
||||||
if (JS_IsExceptionPending(cx)) {
|
if (JS_IsExceptionPending(cx)) {
|
||||||
js::gc::AutoSuppressGC gcoff(cx);
|
js::gc::AutoSuppressGC gcoff(cx);
|
||||||
JS::RootedValue v(cx);
|
JS::RootedValue v(cx);
|
||||||
|
|
@ -215,11 +233,12 @@ class JSAPITest
|
||||||
if (s) {
|
if (s) {
|
||||||
JSAutoByteString bytes(cx, s);
|
JSAutoByteString bytes(cx, s);
|
||||||
if (!!bytes)
|
if (!!bytes)
|
||||||
msg += bytes.ptr();
|
message += bytes.ptr();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
fprintf(stderr, "%s:%d:%.*s\n", filename, lineno, (int) msg.length(), msg.begin());
|
fprintf(stderr, "%s:%d:%.*s\n",
|
||||||
msgs += msg;
|
filename, lineno, int(message.length()), message.begin());
|
||||||
|
msgs += message;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
101
mfbt/Vector.h
101
mfbt/Vector.h
|
|
@ -277,7 +277,7 @@ struct VectorTesting;
|
||||||
template<typename T,
|
template<typename T,
|
||||||
size_t MinInlineCapacity = 0,
|
size_t MinInlineCapacity = 0,
|
||||||
class AllocPolicy = MallocAllocPolicy>
|
class AllocPolicy = MallocAllocPolicy>
|
||||||
class Vector final : private AllocPolicy
|
class MOZ_NON_PARAM Vector final : private AllocPolicy
|
||||||
{
|
{
|
||||||
/* utilities */
|
/* utilities */
|
||||||
|
|
||||||
|
|
@ -293,36 +293,39 @@ class Vector final : private AllocPolicy
|
||||||
|
|
||||||
/* magic constants */
|
/* magic constants */
|
||||||
|
|
||||||
static const int kMaxInlineBytes = 1024;
|
/**
|
||||||
|
* The maximum space allocated for inline element storage.
|
||||||
/* compute constants */
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Consider element size to be 1 for buffer sizing if there are 0 inline
|
|
||||||
* elements. This allows us to compile when the definition of the element
|
|
||||||
* type is not visible here.
|
|
||||||
*
|
*
|
||||||
* Explicit specialization is only allowed at namespace scope, so in order
|
* We reduce space by what the AllocPolicy base class and prior Vector member
|
||||||
* to keep everything here, we use a dummy template parameter with partial
|
* fields likely consume to attempt to play well with binary size classes.
|
||||||
* specialization.
|
|
||||||
*/
|
*/
|
||||||
template<int M, int Dummy>
|
static constexpr size_t kMaxInlineBytes =
|
||||||
struct ElemSize
|
1024 -
|
||||||
{
|
(sizeof(AllocPolicy) + sizeof(T*) + sizeof(size_t) + sizeof(size_t));
|
||||||
static const size_t value = sizeof(T);
|
|
||||||
};
|
/**
|
||||||
template<int Dummy>
|
* The number of T elements of inline capacity built into this Vector. This
|
||||||
struct ElemSize<0, Dummy>
|
* is usually |MinInlineCapacity|, but it may be less (or zero!) for large T.
|
||||||
{
|
*
|
||||||
static const size_t value = 1;
|
* We use a partially-specialized template (not explicit specialization, which
|
||||||
|
* is only allowed at namespace scope) to compute this value. The benefit is
|
||||||
|
* that |sizeof(T)| need not be computed, and |T| doesn't have to be fully
|
||||||
|
* defined at the time |Vector<T>| appears, if no inline storage is requested.
|
||||||
|
*/
|
||||||
|
template <size_t MinimumInlineCapacity, size_t Dummy>
|
||||||
|
struct ComputeCapacity {
|
||||||
|
static constexpr size_t value =
|
||||||
|
tl::Min<MinimumInlineCapacity, kMaxInlineBytes / sizeof(T)>::value;
|
||||||
};
|
};
|
||||||
|
|
||||||
static const size_t kInlineCapacity =
|
template <size_t Dummy>
|
||||||
tl::Min<MinInlineCapacity, kMaxInlineBytes / ElemSize<MinInlineCapacity, 0>::value>::value;
|
struct ComputeCapacity<0, Dummy> {
|
||||||
|
static constexpr size_t value = 0;
|
||||||
|
};
|
||||||
|
|
||||||
/* Calculate inline buffer size; avoid 0-sized array. */
|
/** The actual inline capacity in number of elements T. This may be zero! */
|
||||||
static const size_t kInlineBytes =
|
static constexpr size_t kInlineCapacity =
|
||||||
tl::Max<1, kInlineCapacity * ElemSize<MinInlineCapacity, 0>::value>::value;
|
ComputeCapacity<MinInlineCapacity, 0>::value;
|
||||||
|
|
||||||
/* member data */
|
/* member data */
|
||||||
|
|
||||||
|
|
@ -346,8 +349,34 @@ class Vector final : private AllocPolicy
|
||||||
size_t mReserved;
|
size_t mReserved;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* Memory used for inline storage. */
|
/*
|
||||||
AlignedStorage<kInlineBytes> mStorage;
|
* Memory used for inline storage. We want basically this:
|
||||||
|
*
|
||||||
|
* alignas(T) unsigned char storage[kInlineCapacity * sizeof(T)];
|
||||||
|
*
|
||||||
|
* but C++ forbids zero-sized arrays that might result if we did this. We fix
|
||||||
|
* this by (again) using partial specialization, defining an array only if
|
||||||
|
* contains at least one element.
|
||||||
|
*/
|
||||||
|
template<size_t Capacity, size_t Dummy>
|
||||||
|
struct InlineStorage
|
||||||
|
{
|
||||||
|
alignas(T) unsigned char mBytes[Capacity * sizeof(T)];
|
||||||
|
|
||||||
|
// GCC fails due to -Werror=strict-aliasing if |mBytes| is directly cast to
|
||||||
|
// T*. Indirecting through this function addresses the problem.
|
||||||
|
void* data() { return mBytes; }
|
||||||
|
|
||||||
|
T* addr() { return static_cast<T*>(data()); }
|
||||||
|
};
|
||||||
|
|
||||||
|
template<size_t Dummy>
|
||||||
|
struct InlineStorage<0, Dummy>
|
||||||
|
{
|
||||||
|
T* addr() { return nullptr; }
|
||||||
|
};
|
||||||
|
|
||||||
|
InlineStorage<kInlineCapacity, 0> mStorage;
|
||||||
|
|
||||||
#ifdef DEBUG
|
#ifdef DEBUG
|
||||||
friend class ReentrancyGuard;
|
friend class ReentrancyGuard;
|
||||||
|
|
@ -363,7 +392,7 @@ class Vector final : private AllocPolicy
|
||||||
|
|
||||||
T* inlineStorage()
|
T* inlineStorage()
|
||||||
{
|
{
|
||||||
return static_cast<T*>(mStorage.addr());
|
return mStorage.addr();
|
||||||
}
|
}
|
||||||
|
|
||||||
T* beginNoCheck() const
|
T* beginNoCheck() const
|
||||||
|
|
@ -771,7 +800,7 @@ Vector<T, N, AP>::Vector(AP aAP)
|
||||||
, mEntered(false)
|
, mEntered(false)
|
||||||
#endif
|
#endif
|
||||||
{
|
{
|
||||||
mBegin = static_cast<T*>(mStorage.addr());
|
mBegin = inlineStorage();
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Move constructor. */
|
/* Move constructor. */
|
||||||
|
|
@ -791,7 +820,7 @@ Vector<T, N, AllocPolicy>::Vector(Vector&& aRhs)
|
||||||
|
|
||||||
if (aRhs.usingInlineStorage()) {
|
if (aRhs.usingInlineStorage()) {
|
||||||
/* We can't move the buffer over in this case, so copy elements. */
|
/* We can't move the buffer over in this case, so copy elements. */
|
||||||
mBegin = static_cast<T*>(mStorage.addr());
|
mBegin = inlineStorage();
|
||||||
Impl::moveConstruct(mBegin, aRhs.beginNoCheck(), aRhs.endNoCheck());
|
Impl::moveConstruct(mBegin, aRhs.beginNoCheck(), aRhs.endNoCheck());
|
||||||
/*
|
/*
|
||||||
* Leave aRhs's mLength, mBegin, mCapacity, and mReserved as they are.
|
* Leave aRhs's mLength, mBegin, mCapacity, and mReserved as they are.
|
||||||
|
|
@ -803,7 +832,7 @@ Vector<T, N, AllocPolicy>::Vector(Vector&& aRhs)
|
||||||
* in-line storage.
|
* in-line storage.
|
||||||
*/
|
*/
|
||||||
mBegin = aRhs.mBegin;
|
mBegin = aRhs.mBegin;
|
||||||
aRhs.mBegin = static_cast<T*>(aRhs.mStorage.addr());
|
aRhs.mBegin = aRhs.inlineStorage();
|
||||||
aRhs.mCapacity = kInlineCapacity;
|
aRhs.mCapacity = kInlineCapacity;
|
||||||
aRhs.mLength = 0;
|
aRhs.mLength = 0;
|
||||||
#ifdef DEBUG
|
#ifdef DEBUG
|
||||||
|
|
@ -1142,7 +1171,7 @@ Vector<T, N, AP>::clearAndFree()
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
this->free_(beginNoCheck());
|
this->free_(beginNoCheck());
|
||||||
mBegin = static_cast<T*>(mStorage.addr());
|
mBegin = inlineStorage();
|
||||||
mCapacity = kInlineCapacity;
|
mCapacity = kInlineCapacity;
|
||||||
#ifdef DEBUG
|
#ifdef DEBUG
|
||||||
mReserved = 0;
|
mReserved = 0;
|
||||||
|
|
@ -1370,7 +1399,7 @@ Vector<T, N, AP>::extractRawBuffer()
|
||||||
}
|
}
|
||||||
|
|
||||||
T* ret = mBegin;
|
T* ret = mBegin;
|
||||||
mBegin = static_cast<T*>(mStorage.addr());
|
mBegin = inlineStorage();
|
||||||
mLength = 0;
|
mLength = 0;
|
||||||
mCapacity = kInlineCapacity;
|
mCapacity = kInlineCapacity;
|
||||||
#ifdef DEBUG
|
#ifdef DEBUG
|
||||||
|
|
@ -1396,7 +1425,7 @@ Vector<T, N, AP>::extractOrCopyRawBuffer()
|
||||||
|
|
||||||
Impl::moveConstruct(copy, beginNoCheck(), endNoCheck());
|
Impl::moveConstruct(copy, beginNoCheck(), endNoCheck());
|
||||||
Impl::destroy(beginNoCheck(), endNoCheck());
|
Impl::destroy(beginNoCheck(), endNoCheck());
|
||||||
mBegin = static_cast<T*>(mStorage.addr());
|
mBegin = inlineStorage();
|
||||||
mLength = 0;
|
mLength = 0;
|
||||||
mCapacity = kInlineCapacity;
|
mCapacity = kInlineCapacity;
|
||||||
#ifdef DEBUG
|
#ifdef DEBUG
|
||||||
|
|
@ -1424,7 +1453,7 @@ Vector<T, N, AP>::replaceRawBuffer(T* aP, size_t aLength)
|
||||||
* otherwise be acceptable. Maybe this behaviour should be
|
* otherwise be acceptable. Maybe this behaviour should be
|
||||||
* specifiable with an argument to this function.
|
* specifiable with an argument to this function.
|
||||||
*/
|
*/
|
||||||
mBegin = static_cast<T*>(mStorage.addr());
|
mBegin = inlineStorage();
|
||||||
mLength = aLength;
|
mLength = aLength;
|
||||||
mCapacity = kInlineCapacity;
|
mCapacity = kInlineCapacity;
|
||||||
Impl::moveConstruct(mBegin, aP, aP + aLength);
|
Impl::moveConstruct(mBegin, aP, aP + aLength);
|
||||||
|
|
|
||||||
|
|
@ -172,10 +172,17 @@ CTLogVerifier::Verify(const LogEntry& entry,
|
||||||
if (rv != Success) {
|
if (rv != Success) {
|
||||||
return rv;
|
return rv;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// sct.extensions may be empty. If it is, sctExtensionsInput will remain in
|
||||||
|
// its default state, which is valid but of length 0.
|
||||||
Input sctExtensionsInput;
|
Input sctExtensionsInput;
|
||||||
rv = BufferToInput(sct.extensions, sctExtensionsInput);
|
rv = BufferToInput(sct.extensions, sctExtensionsInput);
|
||||||
if (rv != Success) {
|
if (sct.extensions.length() > 0) {
|
||||||
return rv;
|
rv = sctExtensionsInput.Init(sct.extensions.begin(),
|
||||||
|
sct.extensions.length());
|
||||||
|
if (rv != Success) {
|
||||||
|
return rv;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Buffer serializedData;
|
Buffer serializedData;
|
||||||
|
|
|
||||||
|
|
@ -115,6 +115,9 @@ struct SignedCertificateTimestamp
|
||||||
|
|
||||||
inline pkix::Result BufferToInput(const Buffer& buffer, pkix::Input& input)
|
inline pkix::Result BufferToInput(const Buffer& buffer, pkix::Input& input)
|
||||||
{
|
{
|
||||||
|
if (buffer.length() == 0) {
|
||||||
|
return pkix::Result::FATAL_ERROR_LIBRARY_FAILURE;
|
||||||
|
}
|
||||||
return input.Init(buffer.begin(), buffer.length());
|
return input.Init(buffer.begin(), buffer.length());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue