Bug 1814798 - pt 1. Add bool to enable/disable PHC at runtime r=glandium

Add the ability to enable and disable PHC at runtime through the malloc
bridge.

Differential Revision: https://phabricator.services.mozilla.com/D178753
This commit is contained in:
Paul Bone 2023-09-18 06:48:06 +00:00
parent 9e5ceff322
commit accac535a0
2 changed files with 54 additions and 2 deletions

View File

@ -116,6 +116,19 @@ struct DMDFuncs;
} // namespace dmd
namespace phc {
// PHC has three different states:
// * Not compiled in
// * OnlyFree - The memory allocator is hooked but new allocations
// requests will be forwarded to mozjemalloc, free() will
// correctly free any PHC allocations and realloc() will
// "move" PHC allocations to mozjemalloc allocations.
// * Enabled - Full use.
enum PHCState {
OnlyFree,
Enabled,
};
class AddrInfo;
struct MemoryUsage {
@ -139,7 +152,7 @@ struct DebugFdRegistry {
} // namespace mozilla
struct ReplaceMallocBridge {
ReplaceMallocBridge() : mVersion(5) {}
ReplaceMallocBridge() : mVersion(6) {}
// This method was added in version 1 of the bridge.
virtual mozilla::dmd::DMDFuncs* GetDMDFuncs() { return nullptr; }
@ -195,6 +208,11 @@ struct ReplaceMallocBridge {
// This method was added in version 5 of the bridge.
virtual void PHCMemoryUsage(mozilla::phc::MemoryUsage& aMemoryUsage) {}
// Set PHC's state. See the comments above on `PHCState` for the meaning of
// each state.
// This method was added in version 6 of the bridge.
virtual void SetPHCState(mozilla::phc::PHCState aState) {}
# ifndef REPLACE_MALLOC_IMPL
// Returns the replace-malloc bridge if its version is at least the
// requested one.
@ -269,6 +287,13 @@ struct ReplaceMalloc {
singleton->PHCMemoryUsage(aMemoryUsage);
}
}
static void SetPHCState(mozilla::phc::PHCState aPHCState) {
auto singleton = ReplaceMallocBridge::Get(/* minimumVersion */ 6);
if (singleton) {
singleton->SetPHCState(aPHCState);
}
}
};
# endif

View File

@ -323,6 +323,9 @@ static const size_t kAllPagesSize = kNumAllPages * kPageSize;
// AllocAllPages() for more information.
static const size_t kAllPagesJemallocSize = kAllPagesSize - kPageSize;
// The default state for PHC. Either Enabled or OnlyFree.
#define DEFAULT_STATE mozilla::phc::Enabled
// The junk value used to fill new allocation in debug builds. It's same value
// as the one used by mozjemalloc. PHC applies it unconditionally in debug
// builds. Unlike mozjemalloc, PHC doesn't consult the MALLOC_OPTIONS
@ -874,6 +877,14 @@ class GMut {
}
#endif
// Should we make new PHC allocations?
bool ShouldMakeNewAllocations() const {
return mPhcState == mozilla::phc::Enabled;
}
using PHCState = mozilla::phc::PHCState;
void SetState(PHCState aState) { mPhcState = aState; }
private:
template <int N>
uint64_t RandomSeed() {
@ -933,6 +944,11 @@ class GMut {
size_t mPageAllocHits = 0;
size_t mPageAllocMisses = 0;
#endif
// This will only ever be updated from one thread. The other threads should
// eventually get the update.
Atomic<PHCState, Relaxed> mPhcState =
Atomic<PHCState, Relaxed>(DEFAULT_STATE);
};
Mutex GMut::sMutex;
@ -1074,6 +1090,11 @@ static void* MaybePageAlloc(const Maybe<arena_id_t>& aArenaId, size_t aReqSize,
return nullptr;
}
MOZ_ASSERT(gMut);
if (!gMut->ShouldMakeNewAllocations()) {
return nullptr;
}
GAtomic::IncrementNow();
// Decrement the delay. If it's zero, we do a page allocation and reset the
@ -1344,7 +1365,7 @@ MOZ_ALWAYS_INLINE static void* PageRealloc(const Maybe<arena_id_t>& aArenaId,
// Check for realloc() of a freed block.
gMut->EnsureValidAndInUse(lock, aOldPtr, index);
if (aNewSize <= kPageSize) {
if (aNewSize <= kPageSize && gMut->ShouldMakeNewAllocations()) {
// A page-to-page transition. Just keep using the page allocation. We do
// this even if the thread is disabled, because it doesn't create a new
// page allocation. Note that ResizePageInUse() checks aArenaId.
@ -1687,6 +1708,12 @@ class PHCBridge : public ReplaceMallocBridge {
aMemoryUsage.mFragmentationBytes = 0;
}
}
// Enable or Disable PHC at runtime. If PHC is disabled it will still trap
// bad uses of previous allocations, but won't track any new allocations.
virtual void SetPHCState(mozilla::phc::PHCState aState) override {
gMut->SetState(aState);
}
};
// WARNING: this function runs *very* early -- before all static initializers