gecko-dev/mozglue/misc/AutoProfilerLabel.cpp
Aaron Klotz a69086ea54 Bug 1573273: Add ProfilerLabelBegin and ProfilerLabelEnd to mozglue; r=gerald
While mozglue continues to be the correct location for calling the affected
code in this patch, the calls requiring profiler labels will soon be
originating from firefox.exe via the launcher process.

mozglue will be supplying the launcher process with an interface that consists
of what are effectively "OnBeginDllLoad" and "OnEndDllLoad" callback
notifications; obviously an RAII class is not going to be useful for that case.

We still want to keep the RAII stuff around, however, since we still need it
for cases where we need to fall back to using the legacy DLL blocklist.

Differential Revision: https://phabricator.services.mozilla.com/D41807

--HG--
extra : moz-landing-system : lando
2019-08-14 03:46:41 +00:00

114 lines
3.7 KiB
C++

/* -*- Mode: C++; tab-width: 2; 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/AutoProfilerLabel.h"
#include "mozilla/PlatformMutex.h"
namespace mozilla {
// RAII class that encapsulates all shared static data, and enforces locking
// when accessing this data.
class MOZ_RAII AutoProfilerLabelData {
public:
AutoProfilerLabelData() { sAPLMutex.Lock(); }
~AutoProfilerLabelData() { sAPLMutex.Unlock(); }
AutoProfilerLabelData(const AutoProfilerLabelData&) = delete;
void operator=(const AutoProfilerLabelData&) = delete;
const ProfilerLabelEnter& EnterCRef() const { return sEnter; }
ProfilerLabelEnter& EnterRef() { return sEnter; }
const ProfilerLabelExit& ExitCRef() const { return sExit; }
ProfilerLabelExit& ExitRef() { return sExit; }
const uint32_t& GenerationCRef() const { return sGeneration; }
uint32_t& GenerationRef() { return sGeneration; }
static bool RacyIsProfilerPresent() { return !!sGeneration; }
private:
// Thin shell around mozglue PlatformMutex, for local internal use.
// Does not preserve behavior in JS record/replay.
class Mutex : private mozilla::detail::MutexImpl {
public:
Mutex()
: mozilla::detail::MutexImpl(
mozilla::recordreplay::Behavior::DontPreserve) {}
void Lock() { mozilla::detail::MutexImpl::lock(); }
void Unlock() { mozilla::detail::MutexImpl::unlock(); }
};
// Mutex protecting access to the following static members.
static Mutex sAPLMutex;
static ProfilerLabelEnter sEnter;
static ProfilerLabelExit sExit;
// Current "generation" of RegisterProfilerLabelEnterExit calls.
static uint32_t sGeneration;
};
/* static */ AutoProfilerLabelData::Mutex AutoProfilerLabelData::sAPLMutex;
/* static */ ProfilerLabelEnter AutoProfilerLabelData::sEnter = nullptr;
/* static */ ProfilerLabelExit AutoProfilerLabelData::sExit = nullptr;
/* static */ uint32_t AutoProfilerLabelData::sGeneration = 0;
void RegisterProfilerLabelEnterExit(ProfilerLabelEnter aEnter,
ProfilerLabelExit aExit) {
MOZ_ASSERT(!aEnter == !aExit, "Must provide both null or both non-null");
AutoProfilerLabelData data;
MOZ_ASSERT(!aEnter != !data.EnterRef(),
"Must go from null to non-null, or from non-null to null");
data.EnterRef() = aEnter;
data.ExitRef() = aExit;
++data.GenerationRef();
}
bool IsProfilerPresent() {
return AutoProfilerLabelData::RacyIsProfilerPresent();
}
ProfilerLabel ProfilerLabelBegin(const char* aLabelName,
const char* aDynamicString, void* aSp) {
const AutoProfilerLabelData data;
void* entryContext = (data.EnterCRef())
? data.EnterCRef()(aLabelName, aDynamicString, aSp)
: nullptr;
uint32_t generation = data.GenerationCRef();
return MakeTuple(entryContext, generation);
}
void ProfilerLabelEnd(const ProfilerLabel& aLabel) {
if (!IsValidProfilerLabel(aLabel)) {
return;
}
const AutoProfilerLabelData data;
if (data.ExitCRef() && (Get<1>(aLabel) == data.GenerationCRef())) {
data.ExitCRef()(Get<0>(aLabel));
}
}
AutoProfilerLabel::AutoProfilerLabel(
const char* aLabel,
const char* aDynamicString MOZ_GUARD_OBJECT_NOTIFIER_PARAM_IN_IMPL) {
MOZ_GUARD_OBJECT_NOTIFIER_INIT;
Tie(mEntryContext, mGeneration) =
ProfilerLabelBegin(aLabel, aDynamicString, this);
}
AutoProfilerLabel::~AutoProfilerLabel() {
ProfilerLabelEnd(MakeTuple(mEntryContext, mGeneration));
}
} // namespace mozilla