--- a/memory/replace/logalloc/FdPrintf.cpp
+++ b/memory/replace/logalloc/FdPrintf.cpp
@@ -11,34 +11,36 @@
#else
#include <unistd.h>
#endif
#include <cstring>
#include "mozilla/Assertions.h"
#include "mozilla/Unused.h"
/* Template class allowing a limited number of increments on a value */
-template <typename T>
+template<typename T>
class CheckedIncrement
{
public:
CheckedIncrement(T aValue, size_t aMaxIncrement)
- : mValue(aValue), mMaxIncrement(aMaxIncrement)
- {}
+ : mValue(aValue)
+ , mMaxIncrement(aMaxIncrement)
+ {
+ }
- T operator ++(int)
+ T operator++(int)
{
if (!mMaxIncrement) {
MOZ_CRASH("overflow detected");
}
mMaxIncrement--;
return mValue++;
}
- T& operator ++()
+ T& operator++()
{
(*this)++;
return mValue;
}
operator T() { return mValue; }
private:
--- a/memory/replace/logalloc/FdPrintf.h
+++ b/memory/replace/logalloc/FdPrintf.h
@@ -12,15 +12,16 @@
* Only %p and %z are supported.
* /!\ This function used a fixed-size internal buffer. The caller is
* expected to not use a format string that may overflow.
* The aFd argument is a file descriptor on UNIX and a native win32 file
* handle on Windows (from CreateFile). We can't use the windows POSIX
* APIs is that they don't support O_APPEND in a multi-process-safe way,
* while CreateFile does.
*/
-extern void FdPrintf(intptr_t aFd, const char* aFormat, ...)
+extern void
+FdPrintf(intptr_t aFd, const char* aFormat, ...)
#ifdef __GNUC__
-__attribute__((format(printf, 2, 3)))
+ __attribute__((format(printf, 2, 3)))
#endif
-;
+ ;
#endif /* __FdPrintf_h__ */
--- a/memory/replace/logalloc/LogAlloc.cpp
+++ b/memory/replace/logalloc/LogAlloc.cpp
@@ -23,22 +23,24 @@
static malloc_table_t sFuncs;
static intptr_t sFd = 0;
static bool sStdoutOrStderr = false;
static Mutex sMutex;
static void
-prefork() {
+prefork()
+{
sMutex.Lock();
}
static void
-postfork() {
+postfork()
+{
sMutex.Unlock();
}
static size_t
GetPid()
{
return size_t(getpid());
}
@@ -50,27 +52,27 @@ GetTid()
return size_t(GetCurrentThreadId());
#else
return size_t(pthread_self());
#endif
}
#ifdef ANDROID
/* See mozglue/android/APKOpen.cpp */
-extern "C" MOZ_EXPORT __attribute__((weak))
-void* __dso_handle;
+extern "C" MOZ_EXPORT __attribute__((weak)) void* __dso_handle;
/* Android doesn't have pthread_atfork defined in pthread.h */
-extern "C" MOZ_EXPORT
-int pthread_atfork(void (*)(void), void (*)(void), void (*)(void));
+extern "C" MOZ_EXPORT int
+pthread_atfork(void (*)(void), void (*)(void), void (*)(void));
#endif
class LogAllocBridge : public ReplaceMallocBridge
{
- virtual void InitDebugFd(mozilla::DebugFdRegistry& aRegistry) override {
+ virtual void InitDebugFd(mozilla::DebugFdRegistry& aRegistry) override
+ {
if (!sStdoutOrStderr) {
aRegistry.RegisterHandle(sFd);
}
}
};
/* Do a simple, text-form, log of all calls to replace-malloc functions.
* Use locking to guarantee that an allocation that did happen is logged
@@ -86,66 +88,86 @@ replace_malloc(size_t aSize)
return ptr;
}
static int
replace_posix_memalign(void** aPtr, size_t aAlignment, size_t aSize)
{
MutexAutoLock lock(sMutex);
int ret = sFuncs.posix_memalign(aPtr, aAlignment, aSize);
- FdPrintf(sFd, "%zu %zu posix_memalign(%zu,%zu)=%p\n", GetPid(), GetTid(),
- aAlignment, aSize, (ret == 0) ? *aPtr : nullptr);
+ FdPrintf(sFd,
+ "%zu %zu posix_memalign(%zu,%zu)=%p\n",
+ GetPid(),
+ GetTid(),
+ aAlignment,
+ aSize,
+ (ret == 0) ? *aPtr : nullptr);
return ret;
}
static void*
replace_aligned_alloc(size_t aAlignment, size_t aSize)
{
MutexAutoLock lock(sMutex);
void* ptr = sFuncs.aligned_alloc(aAlignment, aSize);
- FdPrintf(sFd, "%zu %zu aligned_alloc(%zu,%zu)=%p\n", GetPid(), GetTid(),
- aAlignment, aSize, ptr);
+ FdPrintf(sFd,
+ "%zu %zu aligned_alloc(%zu,%zu)=%p\n",
+ GetPid(),
+ GetTid(),
+ aAlignment,
+ aSize,
+ ptr);
return ptr;
}
static void*
replace_calloc(size_t aNum, size_t aSize)
{
MutexAutoLock lock(sMutex);
void* ptr = sFuncs.calloc(aNum, aSize);
- FdPrintf(sFd, "%zu %zu calloc(%zu,%zu)=%p\n", GetPid(), GetTid(), aNum,
- aSize, ptr);
+ FdPrintf(
+ sFd, "%zu %zu calloc(%zu,%zu)=%p\n", GetPid(), GetTid(), aNum, aSize, ptr);
return ptr;
}
static void*
replace_realloc(void* aPtr, size_t aSize)
{
MutexAutoLock lock(sMutex);
void* new_ptr = sFuncs.realloc(aPtr, aSize);
- FdPrintf(sFd, "%zu %zu realloc(%p,%zu)=%p\n", GetPid(), GetTid(), aPtr,
- aSize, new_ptr);
+ FdPrintf(sFd,
+ "%zu %zu realloc(%p,%zu)=%p\n",
+ GetPid(),
+ GetTid(),
+ aPtr,
+ aSize,
+ new_ptr);
return new_ptr;
}
static void
replace_free(void* aPtr)
{
MutexAutoLock lock(sMutex);
FdPrintf(sFd, "%zu %zu free(%p)\n", GetPid(), GetTid(), aPtr);
sFuncs.free(aPtr);
}
static void*
replace_memalign(size_t aAlignment, size_t aSize)
{
MutexAutoLock lock(sMutex);
void* ptr = sFuncs.memalign(aAlignment, aSize);
- FdPrintf(sFd, "%zu %zu memalign(%zu,%zu)=%p\n", GetPid(), GetTid(),
- aAlignment, aSize, ptr);
+ FdPrintf(sFd,
+ "%zu %zu memalign(%zu,%zu)=%p\n",
+ GetPid(),
+ GetTid(),
+ aAlignment,
+ aSize,
+ ptr);
return ptr;
}
static void*
replace_valloc(size_t aSize)
{
MutexAutoLock lock(sMutex);
void* ptr = sFuncs.valloc(aSize);
@@ -165,17 +187,17 @@ void
replace_init(malloc_table_t* aTable, ReplaceMallocBridge** aBridge)
{
/* Initialize output file descriptor from the MALLOC_LOG environment
* variable. Numbers up to 9999 are considered as a preopened file
* descriptor number. Other values are considered as a file name. */
char* log = getenv("MALLOC_LOG");
if (log && *log) {
int fd = 0;
- const char *fd_num = log;
+ const char* fd_num = log;
while (*fd_num) {
/* Reject non digits. */
if (*fd_num < '0' || *fd_num > '9') {
fd = -1;
break;
}
fd = fd * 10 + (*fd_num - '0');
/* Reject values >= 10000. */
@@ -189,19 +211,23 @@ replace_init(malloc_table_t* aTable, Rep
sStdoutOrStderr = true;
}
#ifdef _WIN32
// See comment in FdPrintf.h as to why CreateFile is used.
HANDLE handle;
if (fd > 0) {
handle = reinterpret_cast<HANDLE>(_get_osfhandle(fd));
} else {
- handle = CreateFileA(log, FILE_APPEND_DATA, FILE_SHARE_READ |
- FILE_SHARE_WRITE, nullptr, OPEN_ALWAYS,
- FILE_ATTRIBUTE_NORMAL, nullptr);
+ handle = CreateFileA(log,
+ FILE_APPEND_DATA,
+ FILE_SHARE_READ | FILE_SHARE_WRITE,
+ nullptr,
+ OPEN_ALWAYS,
+ FILE_ATTRIBUTE_NORMAL,
+ nullptr);
}
if (handle != INVALID_HANDLE_VALUE) {
sFd = reinterpret_cast<intptr_t>(handle);
}
#else
if (fd == -1) {
fd = open(log, O_WRONLY | O_CREAT | O_APPEND, 0644);
}
@@ -215,17 +241,17 @@ replace_init(malloc_table_t* aTable, Rep
if (sFd == 0) {
return;
}
sMutex.Init();
static LogAllocBridge bridge;
sFuncs = *aTable;
#define MALLOC_FUNCS MALLOC_FUNCS_MALLOC_BASE
-#define MALLOC_DECL(name, ...) aTable->name = replace_ ## name;
+#define MALLOC_DECL(name, ...) aTable->name = replace_##name;
#include "malloc_decls.h"
aTable->jemalloc_stats = replace_jemalloc_stats;
if (!getenv("MALLOC_LOG_MINIMAL")) {
aTable->posix_memalign = replace_posix_memalign;
aTable->aligned_alloc = replace_aligned_alloc;
aTable->valloc = replace_valloc;
}
*aBridge = &bridge;
--- a/memory/replace/logalloc/replay/Replay.cpp
+++ b/memory/replace/logalloc/replay/Replay.cpp
@@ -28,48 +28,55 @@ die(const char* message)
/* Here, it doesn't matter that fprintf may allocate memory. */
fprintf(stderr, "%s\n", message);
exit(1);
}
/* We don't want to be using malloc() to allocate our internal tracking
* data, because that would change the parameters of what is being measured,
* so we want to use data types that directly use mmap/VirtualAlloc. */
-template <typename T, size_t Len>
+template<typename T, size_t Len>
class MappedArray
{
public:
- MappedArray(): mPtr(nullptr) {}
+ MappedArray()
+ : mPtr(nullptr)
+ {
+ }
~MappedArray()
{
if (mPtr) {
#ifdef _WIN32
VirtualFree(mPtr, sizeof(T) * Len, MEM_RELEASE);
#else
munmap(mPtr, sizeof(T) * Len);
#endif
}
}
- T& operator[] (size_t aIndex) const
+ T& operator[](size_t aIndex) const
{
if (mPtr) {
return mPtr[aIndex];
}
#ifdef _WIN32
- mPtr = reinterpret_cast<T*>(VirtualAlloc(nullptr, sizeof(T) * Len,
- MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE));
+ mPtr = reinterpret_cast<T*>(VirtualAlloc(
+ nullptr, sizeof(T) * Len, MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE));
if (mPtr == nullptr) {
die("VirtualAlloc error");
}
#else
- mPtr = reinterpret_cast<T*>(mmap(nullptr, sizeof(T) * Len,
- PROT_READ | PROT_WRITE, MAP_ANON | MAP_PRIVATE, -1, 0));
+ mPtr = reinterpret_cast<T*>(mmap(nullptr,
+ sizeof(T) * Len,
+ PROT_READ | PROT_WRITE,
+ MAP_ANON | MAP_PRIVATE,
+ -1,
+ 0));
if (mPtr == MAP_FAILED) {
die("Mmap error");
}
#endif
return mPtr[aIndex];
}
private:
@@ -95,41 +102,49 @@ class MemSlotList
{
static const size_t kGroups = 1024 - 1;
static const size_t kGroupSize = (1024 * 1024) / sizeof(MemSlot);
MappedArray<MemSlot, kGroupSize> mSlots[kGroups];
MappedArray<MemSlotList, 1> mNext;
public:
- MemSlot& operator[] (size_t aIndex) const
+ MemSlot& operator[](size_t aIndex) const
{
if (aIndex < kGroupSize * kGroups) {
return mSlots[aIndex / kGroupSize][aIndex % kGroupSize];
}
aIndex -= kGroupSize * kGroups;
return mNext[0][aIndex];
}
};
/* Helper class for memory buffers */
class Buffer
{
public:
- Buffer() : mBuf(nullptr), mLength(0) {}
+ Buffer()
+ : mBuf(nullptr)
+ , mLength(0)
+ {
+ }
Buffer(const void* aBuf, size_t aLength)
- : mBuf(reinterpret_cast<const char*>(aBuf)), mLength(aLength)
- {}
+ : mBuf(reinterpret_cast<const char*>(aBuf))
+ , mLength(aLength)
+ {
+ }
/* Constructor for string literals. */
- template <size_t Size>
+ template<size_t Size>
explicit Buffer(const char (&aStr)[Size])
- : mBuf(aStr), mLength(Size - 1)
- {}
+ : mBuf(aStr)
+ , mLength(Size - 1)
+ {
+ }
/* Returns a sub-buffer up-to but not including the given aNeedle character.
* The "parent" buffer itself is altered to begin after the aNeedle
* character.
* If the aNeedle character is not found, return the entire buffer, and empty
* the "parent" buffer. */
Buffer SplitChar(char aNeedle)
{
@@ -160,20 +175,20 @@ public:
* buffer. */
void Slide(Buffer aOther)
{
memmove(const_cast<char*>(aOther.mBuf), mBuf, mLength);
mBuf = aOther.mBuf;
}
/* Returns whether the two involved buffers have the same content. */
- bool operator ==(Buffer aOther)
+ bool operator==(Buffer aOther)
{
- return mLength == aOther.mLength && (mBuf == aOther.mBuf ||
- !strncmp(mBuf, aOther.mBuf, mLength));
+ return mLength == aOther.mLength &&
+ (mBuf == aOther.mBuf || !strncmp(mBuf, aOther.mBuf, mLength));
}
/* Returns whether the buffer is empty. */
explicit operator bool() { return mLength; }
/* Returns the memory location of the buffer. */
const char* get() { return mBuf; }
@@ -190,23 +205,25 @@ public:
}
private:
const char* mBuf;
size_t mLength;
};
/* Helper class to read from a file descriptor line by line. */
-class FdReader {
+class FdReader
+{
public:
explicit FdReader(int aFd)
: mFd(aFd)
, mData(&mRawBuf, 0)
, mBuf(&mRawBuf, sizeof(mRawBuf))
- {}
+ {
+ }
/* Read a line from the file descriptor and returns it as a Buffer instance */
Buffer ReadLine()
{
while (true) {
Buffer result = mData.SplitChar('\n');
/* There are essentially three different cases here:
@@ -268,79 +285,81 @@ private:
/* read() buffer */
char mRawBuf[4096];
};
MOZ_BEGIN_EXTERN_C
/* Function declarations for all the replace_malloc _impl functions.
* See memory/build/replace_malloc.c */
-#define MALLOC_DECL(name, return_type, ...) \
- return_type name ## _impl(__VA_ARGS__);
+#define MALLOC_DECL(name, return_type, ...) \
+ return_type name##_impl(__VA_ARGS__);
#define MALLOC_FUNCS MALLOC_FUNCS_MALLOC
#include "malloc_decls.h"
-#define MALLOC_DECL(name, return_type, ...) \
- return_type name(__VA_ARGS__);
+#define MALLOC_DECL(name, return_type, ...) return_type name(__VA_ARGS__);
#define MALLOC_FUNCS MALLOC_FUNCS_JEMALLOC
#include "malloc_decls.h"
#ifdef ANDROID
/* mozjemalloc uses MozTagAnonymousMemory, which doesn't have an inline
* implementation on Android */
void
-MozTagAnonymousMemory(const void* aPtr, size_t aLength, const char* aTag) {}
+MozTagAnonymousMemory(const void* aPtr, size_t aLength, const char* aTag)
+{
+}
/* mozjemalloc and jemalloc use pthread_atfork, which Android doesn't have.
* While gecko has one in libmozglue, the replay program can't use that.
* Since we're not going to fork anyways, make it a dummy function. */
int
-pthread_atfork(void (*aPrepare)(void), void (*aParent)(void),
+pthread_atfork(void (*aPrepare)(void),
+ void (*aParent)(void),
void (*aChild)(void))
{
return 0;
}
#endif
MOZ_END_EXTERN_C
-size_t parseNumber(Buffer aBuf)
+size_t
+parseNumber(Buffer aBuf)
{
if (!aBuf) {
die("Malformed input");
}
size_t result = 0;
- for (const char* c = aBuf.get(), *end = aBuf.GetEnd(); c < end; c++) {
+ for (const char *c = aBuf.get(), *end = aBuf.GetEnd(); c < end; c++) {
if (*c < '0' || *c > '9') {
die("Malformed input");
}
result *= 10;
result += *c - '0';
}
return result;
}
/* Class to handle dispatching the replay function calls to replace-malloc. */
class Replay
{
public:
- Replay(): mOps(0) {
+ Replay()
+ : mOps(0)
+ {
#ifdef _WIN32
// See comment in FdPrintf.h as to why native win32 handles are used.
mStdErr = reinterpret_cast<intptr_t>(GetStdHandle(STD_ERROR_HANDLE));
#else
mStdErr = fileno(stderr);
#endif
}
- MemSlot& operator[] (size_t index) const
- {
- return mSlots[index];
- }
+ MemSlot& operator[](size_t index) const { return mSlots[index]; }
void malloc(Buffer& aArgs, Buffer& aResult)
{
MemSlot& aSlot = SlotForResult(aResult);
mOps++;
size_t size = parseNumber(aArgs);
aSlot.mPtr = ::malloc_impl(size);
}
@@ -431,19 +450,24 @@ public:
if (aArgs || aResult) {
die("Malformed input");
}
mOps++;
jemalloc_stats_t stats;
::jemalloc_stats(&stats);
FdPrintf(mStdErr,
"#%zu mapped: %zu; allocated: %zu; waste: %zu; dirty: %zu; "
- "bookkeep: %zu; binunused: %zu\n", mOps, stats.mapped,
- stats.allocated, stats.waste, stats.page_cache,
- stats.bookkeeping, stats.bin_unused);
+ "bookkeep: %zu; binunused: %zu\n",
+ mOps,
+ stats.mapped,
+ stats.allocated,
+ stats.waste,
+ stats.page_cache,
+ stats.bookkeeping,
+ stats.bin_unused);
/* TODO: Add more data, like actual RSS as measured by OS, but compensated
* for the replay internal data. */
}
private:
MemSlot& SlotForResult(Buffer& aResult)
{
/* Parse result value and get the corresponding slot. */
@@ -457,17 +481,16 @@ private:
return mSlots[slot_id];
}
intptr_t mStdErr;
size_t mOps;
MemSlotList mSlots;
};
-
int
main()
{
size_t first_pid = 0;
FdReader reader(0);
Replay replay;
/* Read log from stdin and dispatch function calls to the Replay instance.