Bug 1612799 - Make UniqueJSONStrings operations fallible - r=canaltinova

When something goes wrong, the most likely cause is running out of memory, so
we clear our data to try and free some memory ASAP, to hopefully reduce the
likelihood of a terminating OOM elsewhere.

Differential Revision: https://phabricator.services.mozilla.com/D155653
This commit is contained in:
Gerald Squelart 2022-09-05 01:19:29 +00:00
parent 7dc3f8d14e
commit 14f77ee12e
2 changed files with 50 additions and 11 deletions

View File

@ -11,6 +11,10 @@ namespace mozilla::baseprofiler {
UniqueJSONStrings::UniqueJSONStrings(FailureLatch& aFailureLatch)
: mStringTableWriter(aFailureLatch) {
mStringTableWriter.StartBareList();
if (const char* failure = mStringTableWriter.GetFailure(); failure) {
ClearAndSetFailure(failure);
return;
}
}
UniqueJSONStrings::UniqueJSONStrings(FailureLatch& aFailureLatch,
@ -24,14 +28,17 @@ UniqueJSONStrings::UniqueJSONStrings(FailureLatch& aFailureLatch,
}
if (const char* failure = aOther.GetFailure(); failure) {
mStringTableWriter.SetFailure(failure);
ClearAndSetFailure(failure);
return;
}
mStringTableWriter.StartBareList();
uint32_t count = aOther.mStringHashToIndexMap.count();
if (count != 0) {
MOZ_ALWAYS_TRUE(mStringHashToIndexMap.reserve(count));
if (!mStringHashToIndexMap.reserve(count)) {
ClearAndSetFailure("Cannot reserve UniqueJSONStrings map storage");
return;
}
auto iter = aOther.mStringHashToIndexMap.iter();
for (auto&& [unusedIndex, progressLogger] :
aProgressLogger.CreateLoopSubLoggersFromTo(
@ -47,6 +54,9 @@ UniqueJSONStrings::UniqueJSONStrings(FailureLatch& aFailureLatch,
aProgressLogger.SetLocalProgress(90_pc, "Copied unique strings");
mStringTableWriter.CopyAndSplice(
aOther.mStringTableWriter.ChunkedWriteFunc());
if (const char* failure = aOther.GetFailure(); failure) {
ClearAndSetFailure(failure);
}
aProgressLogger.SetLocalProgress(100_pc, "Spliced unique strings");
}
}
@ -58,18 +68,34 @@ void UniqueJSONStrings::SpliceStringTableElements(
aWriter.TakeAndSplice(mStringTableWriter.TakeChunkedWriteFunc());
}
uint32_t UniqueJSONStrings::GetOrAddIndex(const Span<const char>& aStr) {
void UniqueJSONStrings::ClearAndSetFailure(std::string aFailure) {
mStringTableWriter.SetFailure(std::move(aFailure));
mStringHashToIndexMap.clear();
}
Maybe<uint32_t> UniqueJSONStrings::GetOrAddIndex(const Span<const char>& aStr) {
if (Failed()) {
return Nothing{};
}
uint32_t count = mStringHashToIndexMap.count();
HashNumber hash = HashString(aStr.data(), aStr.size());
auto entry = mStringHashToIndexMap.lookupForAdd(hash);
if (entry) {
MOZ_ASSERT(entry->value() < count);
return entry->value();
return Some(entry->value());
}
MOZ_RELEASE_ASSERT(mStringHashToIndexMap.add(entry, hash, count));
if (!mStringHashToIndexMap.add(entry, hash, count)) {
ClearAndSetFailure("OOM in UniqueJSONStrings::GetOrAddIndex adding a map");
return Nothing{};
}
mStringTableWriter.StringElement(aStr);
return count;
if (const char* failure = mStringTableWriter.GetFailure(); failure) {
ClearAndSetFailure(failure);
return Nothing{};
}
return Some(count);
}
} // namespace mozilla::baseprofiler

View File

@ -10,6 +10,7 @@
#include "mozilla/HashFunctions.h"
#include "mozilla/HashTable.h"
#include "mozilla/JSONWriter.h"
#include "mozilla/Maybe.h"
#include "mozilla/NotNull.h"
#include "mozilla/ProgressLogger.h"
#include "mozilla/TimeStamp.h"
@ -538,15 +539,25 @@ class UniqueJSONStrings final : public FailureLatch {
// Add `aStr` to the list (if not already there), and write its index as a
// named object property.
void WriteProperty(JSONWriter& aWriter, const Span<const char>& aName,
void WriteProperty(SpliceableJSONWriter& aWriter,
const Span<const char>& aName,
const Span<const char>& aStr) {
aWriter.IntProperty(aName, GetOrAddIndex(aStr));
if (const Maybe<uint32_t> maybeIndex = GetOrAddIndex(aStr); maybeIndex) {
aWriter.IntProperty(aName, *maybeIndex);
} else {
aWriter.SetFailureFrom(*this);
}
}
// Add `aStr` to the list (if not already there), and write its index as an
// array element.
void WriteElement(JSONWriter& aWriter, const Span<const char>& aStr) {
aWriter.IntElement(GetOrAddIndex(aStr));
void WriteElement(SpliceableJSONWriter& aWriter,
const Span<const char>& aStr) {
if (const Maybe<uint32_t> maybeIndex = GetOrAddIndex(aStr); maybeIndex) {
aWriter.IntElement(*maybeIndex);
} else if (!aWriter.Failed()) {
aWriter.SetFailureFrom(*this);
}
}
// Splice all collected unique strings into an array. This should only be done
@ -560,9 +571,11 @@ class UniqueJSONStrings final : public FailureLatch {
}
private:
MFBT_API void ClearAndSetFailure(std::string aFailure);
// If `aStr` is already listed, return its index.
// Otherwise add it to the list and return the new index.
MFBT_API uint32_t GetOrAddIndex(const Span<const char>& aStr);
MFBT_API Maybe<uint32_t> GetOrAddIndex(const Span<const char>& aStr);
SpliceableChunkedJSONWriter mStringTableWriter;
HashMap<HashNumber, uint32_t> mStringHashToIndexMap;