mirror of
https://github.com/mozilla/gecko-dev.git
synced 2025-03-02 22:37:50 +00:00
Bug 1420975 - Add a environment variable to record JS stack for leaks. r=froydnj,mrbkap
This patch adds a new environment variable XPCOM_MEM_LOG_JS_STACK that changes XPCOM leakchecking to record a JS stack for all objects, in addition to a C++ stack. This is useful when a C++ object is being leaked due to JS. The JS stack will be printed if the object leaks, if it is used in combination with XPCOM_MEM_BLOAT_LOG=1 and XPCOM_MEM_LOG_CLASSES=nsFoo, if nsFoo is the class of interest. This patch moves a few XPConnect functions for recording the stack into xpcpublic.h so they can be called from nsTraceRefcnt.cpp. MozReview-Commit-ID: FX2QVCSXz4f --HG-- extra : rebase_source : 5bd4e341072f4cf7d3be774b63d2107479fe9985
This commit is contained in:
parent
f6ce1f10e0
commit
9d063bfac8
@ -2353,18 +2353,6 @@ xpc_JSObjectToID(JSContext* cx, JSObject* obj);
|
||||
extern bool
|
||||
xpc_JSObjectIsID(JSContext* cx, JSObject* obj);
|
||||
|
||||
/***************************************************************************/
|
||||
// in XPCDebug.cpp
|
||||
|
||||
extern bool
|
||||
xpc_DumpJSStack(bool showArgs, bool showLocals, bool showThisProps);
|
||||
|
||||
// Return a newly-allocated string containing a representation of the
|
||||
// current JS stack.
|
||||
extern JS::UniqueChars
|
||||
xpc_PrintJSStack(JSContext* cx, bool showArgs, bool showLocals,
|
||||
bool showThisProps);
|
||||
|
||||
/******************************************************************************
|
||||
* Handles pre/post script processing.
|
||||
*/
|
||||
|
@ -254,6 +254,17 @@ xpc_TryUnmarkWrappedGrayObject(nsISupports* aWrappedJS);
|
||||
extern void
|
||||
xpc_UnmarkSkippableJSHolders();
|
||||
|
||||
// Defined in XPCDebug.cpp.
|
||||
extern bool
|
||||
xpc_DumpJSStack(bool showArgs, bool showLocals, bool showThisProps);
|
||||
|
||||
// Return a newly-allocated string containing a representation of the
|
||||
// current JS stack. Defined in XPCDebug.cpp.
|
||||
extern JS::UniqueChars
|
||||
xpc_PrintJSStack(JSContext* cx, bool showArgs, bool showLocals,
|
||||
bool showThisProps);
|
||||
|
||||
|
||||
// readable string conversions, static methods and members only
|
||||
class XPCStringConvert
|
||||
{
|
||||
|
@ -34,6 +34,7 @@
|
||||
#include "mozilla/AutoRestore.h"
|
||||
#include "mozilla/BlockingResourceBase.h"
|
||||
#include "mozilla/PoisonIOInterposer.h"
|
||||
#include "mozilla/UniquePtr.h"
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
@ -83,6 +84,7 @@ static PLHashTable* gObjectsToLog;
|
||||
static PLHashTable* gSerialNumbers;
|
||||
static intptr_t gNextSerialNumber;
|
||||
static bool gDumpedStatistics = false;
|
||||
static bool gLogJSStacks = false;
|
||||
|
||||
// By default, debug builds only do bloat logging. Bloat logging
|
||||
// only tries to record when an object is created or destroyed, so we
|
||||
@ -133,6 +135,27 @@ struct SerialNumberRecord
|
||||
// XPCOM equivalents do leak-checking, and if you try to leak-check while
|
||||
// leak-checking, you're gonna have a bad time.
|
||||
std::vector<void*> allocationStack;
|
||||
mozilla::UniquePtr<char[]> jsStack;
|
||||
|
||||
void SaveJSStack() {
|
||||
// If this thread isn't running JS, there's nothing to do.
|
||||
if (!CycleCollectedJSContext::Get()) {
|
||||
return;
|
||||
}
|
||||
|
||||
JSContext* cx = nsContentUtils::GetCurrentJSContextForThread();
|
||||
if (!cx) {
|
||||
return;
|
||||
}
|
||||
|
||||
JS::UniqueChars chars = xpc_PrintJSStack(cx,
|
||||
/*showArgs=*/ false,
|
||||
/*showLocals=*/ false,
|
||||
/*showThisProps=*/ false);
|
||||
size_t len = strlen(chars.get());
|
||||
jsStack = MakeUnique<char[]>(len + 1);
|
||||
memcpy(jsStack.get(), chars.get(), len + 1);
|
||||
}
|
||||
};
|
||||
|
||||
struct nsTraceRefcntStats
|
||||
@ -472,6 +495,15 @@ DumpSerialNumbers(PLHashEntry* aHashEntry, int aIndex, void* aClosure)
|
||||
fprintf(outputFile, "%s\n", buf);
|
||||
}
|
||||
}
|
||||
|
||||
if (gLogJSStacks) {
|
||||
if (record->jsStack) {
|
||||
fprintf(outputFile, "JS allocation stack:\n%s\n", record->jsStack.get());
|
||||
} else {
|
||||
fprintf(outputFile, "There is no JS context on the stack.\n");
|
||||
}
|
||||
}
|
||||
|
||||
return HT_ENUMERATE_NEXT;
|
||||
}
|
||||
|
||||
@ -587,6 +619,9 @@ GetSerialNumber(void* aPtr, bool aCreate)
|
||||
WalkTheStackSavingLocations(record->allocationStack);
|
||||
PL_HashTableRawAdd(gSerialNumbers, hep, HashNumber(aPtr),
|
||||
aPtr, static_cast<void*>(record));
|
||||
if (gLogJSStacks) {
|
||||
record->SaveJSStack();
|
||||
}
|
||||
return gNextSerialNumber;
|
||||
}
|
||||
|
||||
@ -829,6 +864,10 @@ InitTraceLog()
|
||||
}
|
||||
}
|
||||
|
||||
if (getenv("XPCOM_MEM_LOG_JS_STACK")) {
|
||||
fprintf(stdout, "### XPCOM_MEM_LOG_JS_STACK defined\n");
|
||||
gLogJSStacks = true;
|
||||
}
|
||||
|
||||
if (gBloatLog) {
|
||||
gLogging = OnlyBloatLogging;
|
||||
|
Loading…
x
Reference in New Issue
Block a user