Make pointer tracking array facility fail gracefully when it is full (#411)

This commit is contained in:
Jon Haslam 2023-11-15 16:13:54 +00:00 committed by GitHub
parent f9cb0115e1
commit 02306bf80e
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 48 additions and 7 deletions

View File

@ -327,6 +327,8 @@ void FuncGen::DefineTopLevelGetSizeRef(std::string& testCode,
uintptr_t& writtenSize = data[dataSegOffset++];
writtenSize = 0;
uintptr_t& timeTakenNs = data[dataSegOffset++];
size_t& pointersSize = data[dataSegOffset++];
size_t& pointersCapacity = data[dataSegOffset++];
dataSegOffset *= sizeof(uintptr_t);
JLOG("%1% @");
@ -336,6 +338,8 @@ void FuncGen::DefineTopLevelGetSizeRef(std::string& testCode,
OIInternal::StoreData((uintptr_t)123456789, dataSegOffset);
writtenSize = dataSegOffset;
dataBase += dataSegOffset;
pointersSize = pointers.size();
pointersCapacity = pointers.capacity();
)";
if (features[Feature::JitTiming]) {
func += R"(
@ -419,6 +423,8 @@ void FuncGen::DefineTopLevelGetSizeSmartPtr(std::string& testCode,
uintptr_t& writtenSize = data[dataSegOffset++];
writtenSize = 0;
uintptr_t& timeTakenNs = data[dataSegOffset++];
size_t& pointersSize = data[dataSegOffset++];
size_t& pointersCapacity = data[dataSegOffset++];
dataSegOffset *= sizeof(uintptr_t);
@ -427,6 +433,8 @@ void FuncGen::DefineTopLevelGetSizeSmartPtr(std::string& testCode,
OIInternal::StoreData((uintptr_t)123456789, dataSegOffset);
writtenSize = dataSegOffset;
dataBase += dataSegOffset;
pointersSize = pointers.size();
pointersCapacity = pointers.capacity();
)";
if (features[Feature::JitTiming]) {
func += R"(

View File

@ -2746,6 +2746,14 @@ bool OIDebugger::decodeTargetData(const DataHeader& dataHeader,
LOG(INFO) << "JIT Timing: " << dataHeader.timeTakenNs << "ns";
}
VLOG(1) << "Pointer tracking stats: " << dataHeader.pointersCapacity << "/"
<< dataHeader.pointersSize;
if (dataHeader.pointersCapacity == dataHeader.pointersSize) {
VLOG(1) << "Pointer tracking array is exhausted! Results may be"
" partial.";
}
/*
* Currently we use MAX_INT to indicate two things:
* - a single MAX_INT indicates the end of results for the current object

View File

@ -276,6 +276,8 @@ class OIDebugger {
uintptr_t cookie;
uintptr_t size;
uintptr_t timeTakenNs;
size_t pointersSize;
size_t pointersCapacity;
/*
* Flexible Array Member are not standard in C++, but this is

View File

@ -44,9 +44,12 @@ class {
private:
// 1 MiB of pointers
std::array<uintptr_t, (1 << 20) / sizeof(uintptr_t)> data;
size_t numEntries;
// twang_mix64 hash function, taken from Folly where it is used
// as the default hash function for 64-bit integers
/*
* twang_mix64 hash function, taken from Folly where it is used as the
* default hash function for 64-bit integers.
*/
constexpr static uint64_t twang_mix64(uint64_t key) noexcept {
key = (~key) + (key << 21); // key *= (1 << 21) - 1; key -= 1;
key = key ^ (key >> 24);
@ -61,26 +64,46 @@ class {
public:
void initialize() noexcept {
data.fill(0);
numEntries = 0;
}
// Adds the pointer to the set.
// Returns `true` if the value was newly added,
// or `false` if the value was already present.
/*
* Adds the pointer to the set.
* Returns `true` if the value was newly added. `false` may be returned if
* the value was already present, a null pointer was passed or if there are
* no entries left in the array.
*/
bool add(uintptr_t pointer) noexcept {
__builtin_assume(pointer > 0);
if (pointer == 0) {
return false;
}
uint64_t index = twang_mix64(pointer) % data.size();
while (true) {
uintptr_t entry = data[index];
if (entry == 0) {
data[index] = pointer;
++numEntries;
return true;
}
if (entry == pointer) {
if (entry == pointer || numEntries >= data.size()) {
return false;
}
index = (index + 1) % data.size();
}
}
size_t size(void) {
return numEntries;
}
size_t capacity(void) {
return data.size();
}
bool add(const auto* p) {
return add((uintptr_t)p);
}