mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-12-01 08:42:13 +00:00
7ae6aea145
Differential Revision: https://phabricator.services.mozilla.com/D100484
190 lines
7.9 KiB
C++
190 lines
7.9 KiB
C++
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
|
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
|
|
/* This Source Code Form is subject to the terms of the Mozilla Public
|
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
|
|
|
#include "mozilla/Assertions.h"
|
|
#include "mozilla/AtomicBitfields.h"
|
|
|
|
// This is a big macro mess, so let's summarize what's in here right up front:
|
|
//
|
|
// |TestDocumentationExample| is intended to be a copy-paste of the example
|
|
// in the macro's documentation, to make sure it's correct.
|
|
//
|
|
//
|
|
// |TestJammedWithFlags| tests using every bit of the type for bool flags.
|
|
// 64-bit isn't tested due to macro limitations.
|
|
//
|
|
//
|
|
// |TestLopsided| tests an instance with the following configuration:
|
|
//
|
|
// * a 1-bit boolean
|
|
// * an (N-1)-bit uintN_t
|
|
//
|
|
// It tests both orderings of these fields.
|
|
//
|
|
// Hopefully these are enough to cover all the nasty boundary conditions
|
|
// (that still compile).
|
|
|
|
// ==================== TestDocumentationExample ========================
|
|
|
|
struct MyType {
|
|
MOZ_ATOMIC_BITFIELDS(mAtomicFields, 8,
|
|
((bool, IsDownloaded, 1), (uint32_t, SomeData, 2),
|
|
(uint8_t, OtherData, 5)))
|
|
|
|
int32_t aNormalInteger;
|
|
|
|
explicit MyType(uint32_t aSomeData) : aNormalInteger(7) {
|
|
StoreSomeData(aSomeData);
|
|
// Other bitfields were already default initialized to 0/false
|
|
}
|
|
};
|
|
|
|
void TestDocumentationExample() {
|
|
MyType val(3);
|
|
|
|
if (!val.LoadIsDownloaded()) {
|
|
val.StoreOtherData(2);
|
|
val.StoreIsDownloaded(true);
|
|
}
|
|
}
|
|
|
|
// ====================== TestJammedWithFlags =========================
|
|
|
|
#define TIMES_8(aFunc, aSeparator, aArgs) \
|
|
MOZ_FOR_EACH_SEPARATED(aFunc, aSeparator, aArgs, (1, 2, 3, 4, 5, 6, 7, 8))
|
|
#define TIMES_16(aFunc, aSeparator, aArgs) \
|
|
MOZ_FOR_EACH_SEPARATED( \
|
|
aFunc, aSeparator, aArgs, \
|
|
(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16))
|
|
#define TIMES_32(aFunc, aSeparator, aArgs) \
|
|
MOZ_FOR_EACH_SEPARATED( \
|
|
aFunc, aSeparator, aArgs, \
|
|
(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, \
|
|
21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32))
|
|
|
|
#define CHECK_BOOL(aIndex) \
|
|
MOZ_ASSERT(val.LoadFlag##aIndex() == false); \
|
|
val.StoreFlag##aIndex(true); \
|
|
MOZ_ASSERT(val.LoadFlag##aIndex() == true); \
|
|
val.StoreFlag##aIndex(false); \
|
|
MOZ_ASSERT(val.LoadFlag##aIndex() == false);
|
|
|
|
#define GENERATE_TEST_JAMMED_WITH_FLAGS(aSize) \
|
|
void TestJammedWithFlags##aSize() { \
|
|
JammedWithFlags##aSize val; \
|
|
TIMES_##aSize(CHECK_BOOL, (;), ()); \
|
|
}
|
|
|
|
#define TEST_JAMMED_WITH_FLAGS(aSize) TestJammedWithFlags##aSize();
|
|
|
|
// ========================= TestLopsided ===========================
|
|
|
|
#define GENERATE_TEST_LOPSIDED_FUNC(aSide, aSize) \
|
|
void TestLopsided##aSide##aSize() { \
|
|
Lopsided##aSide##aSize val; \
|
|
MOZ_ASSERT(val.LoadHappyLittleBit() == false); \
|
|
MOZ_ASSERT(val.LoadLargeAndInCharge() == 0); \
|
|
val.StoreHappyLittleBit(true); \
|
|
MOZ_ASSERT(val.LoadHappyLittleBit() == true); \
|
|
MOZ_ASSERT(val.LoadLargeAndInCharge() == 0); \
|
|
val.StoreLargeAndInCharge(1); \
|
|
MOZ_ASSERT(val.LoadHappyLittleBit() == true); \
|
|
MOZ_ASSERT(val.LoadLargeAndInCharge() == 1); \
|
|
val.StoreLargeAndInCharge(0); \
|
|
MOZ_ASSERT(val.LoadHappyLittleBit() == true); \
|
|
MOZ_ASSERT(val.LoadLargeAndInCharge() == 0); \
|
|
uint##aSize##_t size = aSize; \
|
|
uint##aSize##_t int_max = (~(1ull << (size - 1))) - 1; \
|
|
val.StoreLargeAndInCharge(int_max); \
|
|
MOZ_ASSERT(val.LoadHappyLittleBit() == true); \
|
|
MOZ_ASSERT(val.LoadLargeAndInCharge() == int_max); \
|
|
val.StoreHappyLittleBit(false); \
|
|
MOZ_ASSERT(val.LoadHappyLittleBit() == false); \
|
|
MOZ_ASSERT(val.LoadLargeAndInCharge() == int_max); \
|
|
val.StoreLargeAndInCharge(int_max); \
|
|
MOZ_ASSERT(val.LoadHappyLittleBit() == false); \
|
|
MOZ_ASSERT(val.LoadLargeAndInCharge() == int_max); \
|
|
}
|
|
|
|
#define GENERATE_TEST_LOPSIDED(aSize) \
|
|
struct LopsidedA##aSize { \
|
|
MOZ_ATOMIC_BITFIELDS(mAtomicFields, aSize, \
|
|
((bool, HappyLittleBit, 1), \
|
|
(uint##aSize##_t, LargeAndInCharge, ((aSize)-1)))) \
|
|
}; \
|
|
struct LopsidedB##aSize { \
|
|
MOZ_ATOMIC_BITFIELDS(mAtomicFields, aSize, \
|
|
((uint##aSize##_t, LargeAndInCharge, ((aSize)-1)), \
|
|
(bool, HappyLittleBit, 1))) \
|
|
}; \
|
|
GENERATE_TEST_LOPSIDED_FUNC(A, aSize); \
|
|
GENERATE_TEST_LOPSIDED_FUNC(B, aSize);
|
|
|
|
#define TEST_LOPSIDED(aSize) \
|
|
TestLopsidedA##aSize(); \
|
|
TestLopsidedB##aSize();
|
|
|
|
// ==================== generate and run the tests ======================
|
|
|
|
// There's an unknown bug in clang-cl-9 (used for win64-ccov) that makes
|
|
// generating these with the TIMES_N macro not work. So these are written out
|
|
// explicitly to unbork CI.
|
|
struct JammedWithFlags8 {
|
|
MOZ_ATOMIC_BITFIELDS(mAtomicFields, 8,
|
|
((bool, Flag1, 1), (bool, Flag2, 1), (bool, Flag3, 1),
|
|
(bool, Flag4, 1), (bool, Flag5, 1), (bool, Flag6, 1),
|
|
(bool, Flag7, 1), (bool, Flag8, 1)))
|
|
};
|
|
|
|
struct JammedWithFlags16 {
|
|
MOZ_ATOMIC_BITFIELDS(mAtomicFields, 16,
|
|
((bool, Flag1, 1), (bool, Flag2, 1), (bool, Flag3, 1),
|
|
(bool, Flag4, 1), (bool, Flag5, 1), (bool, Flag6, 1),
|
|
(bool, Flag7, 1), (bool, Flag8, 1), (bool, Flag9, 1),
|
|
(bool, Flag10, 1), (bool, Flag11, 1), (bool, Flag12, 1),
|
|
(bool, Flag13, 1), (bool, Flag14, 1), (bool, Flag15, 1),
|
|
(bool, Flag16, 1)))
|
|
};
|
|
|
|
struct JammedWithFlags32 {
|
|
MOZ_ATOMIC_BITFIELDS(mAtomicFields, 32,
|
|
((bool, Flag1, 1), (bool, Flag2, 1), (bool, Flag3, 1),
|
|
(bool, Flag4, 1), (bool, Flag5, 1), (bool, Flag6, 1),
|
|
(bool, Flag7, 1), (bool, Flag8, 1), (bool, Flag9, 1),
|
|
(bool, Flag10, 1), (bool, Flag11, 1), (bool, Flag12, 1),
|
|
(bool, Flag13, 1), (bool, Flag14, 1), (bool, Flag15, 1),
|
|
(bool, Flag16, 1), (bool, Flag17, 1), (bool, Flag18, 1),
|
|
(bool, Flag19, 1), (bool, Flag20, 1), (bool, Flag21, 1),
|
|
(bool, Flag22, 1), (bool, Flag23, 1), (bool, Flag24, 1),
|
|
(bool, Flag25, 1), (bool, Flag26, 1), (bool, Flag27, 1),
|
|
(bool, Flag28, 1), (bool, Flag29, 1), (bool, Flag30, 1),
|
|
(bool, Flag31, 1), (bool, Flag32, 1)))
|
|
};
|
|
|
|
GENERATE_TEST_JAMMED_WITH_FLAGS(8)
|
|
GENERATE_TEST_JAMMED_WITH_FLAGS(16)
|
|
GENERATE_TEST_JAMMED_WITH_FLAGS(32)
|
|
// MOZ_FOR_EACH_64 doesn't exist :(
|
|
|
|
GENERATE_TEST_LOPSIDED(8)
|
|
GENERATE_TEST_LOPSIDED(16)
|
|
GENERATE_TEST_LOPSIDED(32)
|
|
GENERATE_TEST_LOPSIDED(64)
|
|
|
|
int main() {
|
|
TestDocumentationExample();
|
|
|
|
TEST_JAMMED_WITH_FLAGS(8);
|
|
TEST_JAMMED_WITH_FLAGS(16);
|
|
TEST_JAMMED_WITH_FLAGS(32);
|
|
|
|
TEST_LOPSIDED(8);
|
|
TEST_LOPSIDED(16);
|
|
TEST_LOPSIDED(32);
|
|
TEST_LOPSIDED(64);
|
|
return 0;
|
|
}
|