mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
Bug 706227 - Add way for JS_GC API users to give detailed reason for invocation (r=mccr8)
This commit is contained in:
parent
7b71a67efd
commit
502e67c72c
@ -816,7 +816,7 @@ nsDOMWindowUtils::GarbageCollect(nsICycleCollectorListener *aListener)
|
||||
}
|
||||
#endif
|
||||
|
||||
nsJSContext::GarbageCollectNow();
|
||||
nsJSContext::GarbageCollectNow(js::gcreason::DOM_UTILS);
|
||||
nsJSContext::CycleCollectNow(aListener);
|
||||
|
||||
return NS_OK;
|
||||
|
@ -2272,7 +2272,7 @@ nsGlobalWindow::SetNewDocument(nsIDocument* aDocument,
|
||||
newInnerWindow->mChromeEventHandler = mChromeEventHandler;
|
||||
}
|
||||
|
||||
mContext->GC();
|
||||
mContext->GC(js::gcreason::SET_NEW_DOCUMENT);
|
||||
mContext->DidInitializeContext();
|
||||
|
||||
if (newInnerWindow && !newInnerWindow->mHasNotifiedGlobalCreated && mDoc) {
|
||||
@ -2429,7 +2429,7 @@ nsGlobalWindow::SetDocShell(nsIDocShell* aDocShell)
|
||||
}
|
||||
|
||||
if (mContext) {
|
||||
mContext->GC();
|
||||
mContext->GC(js::gcreason::SET_DOC_SHELL);
|
||||
mContext->FinalizeContext();
|
||||
mContext = nsnull;
|
||||
}
|
||||
|
@ -43,6 +43,7 @@
|
||||
#include "nsISupports.h"
|
||||
#include "nsCOMPtr.h"
|
||||
#include "nsIProgrammingLanguage.h"
|
||||
#include "jsfriendapi.h"
|
||||
#include "jspubtd.h"
|
||||
|
||||
class nsIScriptGlobalObject;
|
||||
@ -354,7 +355,7 @@ public:
|
||||
*
|
||||
* @return NS_OK if the method is successful
|
||||
*/
|
||||
virtual void GC() = 0;
|
||||
virtual void GC(js::gcreason::Reason aReason) = 0;
|
||||
|
||||
/**
|
||||
* Inform the context that a script was evaluated.
|
||||
|
@ -203,7 +203,7 @@ nsMemoryPressureObserver::Observe(nsISupports* aSubject, const char* aTopic,
|
||||
const PRUnichar* aData)
|
||||
{
|
||||
if (sGCOnMemoryPressure) {
|
||||
nsJSContext::GarbageCollectNow(true);
|
||||
nsJSContext::GarbageCollectNow(js::gcreason::MEM_PRESSURE, nsGCShrinking);
|
||||
nsJSContext::CycleCollectNow();
|
||||
}
|
||||
return NS_OK;
|
||||
@ -1111,7 +1111,7 @@ nsJSContext::DestroyJSContext()
|
||||
js_options_dot_str, this);
|
||||
|
||||
if (mGCOnDestruction) {
|
||||
PokeGC();
|
||||
PokeGC(js::gcreason::NSJSCONTEXT_DESTROY);
|
||||
}
|
||||
|
||||
// Let xpconnect destroy the JSContext when it thinks the time is right.
|
||||
@ -3220,7 +3220,7 @@ nsJSContext::ScriptExecuted()
|
||||
|
||||
//static
|
||||
void
|
||||
nsJSContext::GarbageCollectNow(bool shrinkingGC)
|
||||
nsJSContext::GarbageCollectNow(js::gcreason::Reason reason, PRUint32 gckind)
|
||||
{
|
||||
NS_TIME_FUNCTION_MIN(1.0);
|
||||
SAMPLE_LABEL("GC", "GarbageCollectNow");
|
||||
@ -3238,7 +3238,7 @@ nsJSContext::GarbageCollectNow(bool shrinkingGC)
|
||||
sLoadingInProgress = false;
|
||||
|
||||
if (nsContentUtils::XPConnect()) {
|
||||
nsContentUtils::XPConnect()->GarbageCollect(shrinkingGC);
|
||||
nsContentUtils::XPConnect()->GarbageCollect(reason, gckind);
|
||||
}
|
||||
}
|
||||
|
||||
@ -3276,7 +3276,7 @@ nsJSContext::CycleCollectNow(nsICycleCollectorListener *aListener)
|
||||
// If we collected a substantial amount of cycles, poke the GC since more objects
|
||||
// might be unreachable now.
|
||||
if (sCCollectedWaitingForGC > 250) {
|
||||
PokeGC();
|
||||
PokeGC(js::gcreason::CC_WAITING);
|
||||
}
|
||||
|
||||
PRTime now = PR_Now();
|
||||
@ -3315,7 +3315,8 @@ GCTimerFired(nsITimer *aTimer, void *aClosure)
|
||||
{
|
||||
NS_RELEASE(sGCTimer);
|
||||
|
||||
nsJSContext::GarbageCollectNow();
|
||||
uintptr_t reason = reinterpret_cast<uintptr_t>(aClosure);
|
||||
nsJSContext::GarbageCollectNow(static_cast<js::gcreason::Reason>(reason), nsGCNormal);
|
||||
}
|
||||
|
||||
void
|
||||
@ -3359,12 +3360,12 @@ nsJSContext::LoadEnd()
|
||||
|
||||
// Its probably a good idea to GC soon since we have finished loading.
|
||||
sLoadingInProgress = false;
|
||||
PokeGC();
|
||||
PokeGC(js::gcreason::LOAD_END);
|
||||
}
|
||||
|
||||
// static
|
||||
void
|
||||
nsJSContext::PokeGC()
|
||||
nsJSContext::PokeGC(js::gcreason::Reason aReason)
|
||||
{
|
||||
if (sGCTimer) {
|
||||
// There's already a timer for GC'ing, just return
|
||||
@ -3380,7 +3381,7 @@ nsJSContext::PokeGC()
|
||||
|
||||
static bool first = true;
|
||||
|
||||
sGCTimer->InitWithFuncCallback(GCTimerFired, nsnull,
|
||||
sGCTimer->InitWithFuncCallback(GCTimerFired, reinterpret_cast<void *>(aReason),
|
||||
first
|
||||
? NS_FIRST_GC_DELAY
|
||||
: NS_GC_DELAY,
|
||||
@ -3473,9 +3474,9 @@ nsJSContext::KillCCTimer()
|
||||
}
|
||||
|
||||
void
|
||||
nsJSContext::GC()
|
||||
nsJSContext::GC(js::gcreason::Reason aReason)
|
||||
{
|
||||
PokeGC();
|
||||
PokeGC(aReason);
|
||||
}
|
||||
|
||||
static void
|
||||
@ -3513,7 +3514,7 @@ DOMGCFinishedCallback(JSRuntime *rt, JSCompartment *comp, const char *status)
|
||||
// probably a time of heavy activity and we want to delay
|
||||
// the full GC, but we do want it to happen eventually.
|
||||
if (comp) {
|
||||
nsJSContext::PokeGC();
|
||||
nsJSContext::PokeGC(js::gcreason::POST_COMPARTMENT);
|
||||
|
||||
// We poked the GC, so we can kill any pending CC here.
|
||||
nsJSContext::KillCCTimer();
|
||||
|
@ -41,10 +41,12 @@
|
||||
#include "nsIScriptRuntime.h"
|
||||
#include "nsCOMPtr.h"
|
||||
#include "jsapi.h"
|
||||
#include "jsfriendapi.h"
|
||||
#include "nsIObserver.h"
|
||||
#include "nsIXPCScriptNotify.h"
|
||||
#include "prtime.h"
|
||||
#include "nsCycleCollectionParticipant.h"
|
||||
#include "nsIXPConnect.h"
|
||||
|
||||
class nsIXPConnectJSObjectHolder;
|
||||
class nsRootedJSValueArray;
|
||||
@ -179,11 +181,11 @@ public:
|
||||
static void LoadStart();
|
||||
static void LoadEnd();
|
||||
|
||||
static void GarbageCollectNow(bool shrinkingGC = false);
|
||||
static void GarbageCollectNow(js::gcreason::Reason reason, PRUint32 gckind = nsGCNormal);
|
||||
static void ShrinkGCBuffersNow();
|
||||
static void CycleCollectNow(nsICycleCollectorListener *aListener = nsnull);
|
||||
|
||||
static void PokeGC();
|
||||
static void PokeGC(js::gcreason::Reason aReason);
|
||||
static void KillGCTimer();
|
||||
|
||||
static void PokeShrinkGCBuffers();
|
||||
@ -193,7 +195,7 @@ public:
|
||||
static void MaybePokeCC();
|
||||
static void KillCCTimer();
|
||||
|
||||
virtual void GC();
|
||||
virtual void GC(js::gcreason::Reason aReason);
|
||||
|
||||
protected:
|
||||
nsresult InitializeExternalClasses();
|
||||
|
@ -800,14 +800,14 @@ ContentChild::GetIndexedDBPath()
|
||||
bool
|
||||
ContentChild::RecvGarbageCollect()
|
||||
{
|
||||
nsJSContext::GarbageCollectNow();
|
||||
nsJSContext::GarbageCollectNow(js::gcreason::DOM_IPC);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
ContentChild::RecvCycleCollect()
|
||||
{
|
||||
nsJSContext::GarbageCollectNow();
|
||||
nsJSContext::GarbageCollectNow(js::gcreason::DOM_IPC);
|
||||
nsJSContext::CycleCollectNow();
|
||||
return true;
|
||||
}
|
||||
|
@ -3794,10 +3794,10 @@ WorkerPrivate::GarbageCollectInternal(JSContext* aCx, bool aShrinking,
|
||||
AssertIsOnWorkerThread();
|
||||
|
||||
if (aShrinking) {
|
||||
JS_ShrinkingGC(aCx);
|
||||
js::ShrinkingGC(aCx, js::gcreason::DOM_WORKER);
|
||||
}
|
||||
else {
|
||||
JS_GC(aCx);
|
||||
js::GCForReason(aCx, js::gcreason::DOM_WORKER);
|
||||
}
|
||||
|
||||
if (aCollectChildren) {
|
||||
|
@ -38,6 +38,7 @@
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
#include <stdio.h>
|
||||
#include <ctype.h>
|
||||
|
||||
#include "jscntxt.h"
|
||||
#include "jscrashformat.h"
|
||||
@ -52,6 +53,22 @@
|
||||
namespace js {
|
||||
namespace gcstats {
|
||||
|
||||
static const char *
|
||||
ExplainReason(gcreason::Reason reason)
|
||||
{
|
||||
switch (reason) {
|
||||
#define SWITCH_REASON(name) \
|
||||
case gcreason::name: \
|
||||
return #name;
|
||||
GCREASONS(SWITCH_REASON)
|
||||
|
||||
default:
|
||||
JS_NOT_REACHED("bad GC reason");
|
||||
return "?";
|
||||
#undef SWITCH_REASON
|
||||
}
|
||||
}
|
||||
|
||||
Statistics::ColumnInfo::ColumnInfo(const char *title, double t, double total)
|
||||
: title(title)
|
||||
{
|
||||
@ -117,8 +134,8 @@ Statistics::makeTable(ColumnInfo *cols)
|
||||
}
|
||||
|
||||
Statistics::Statistics(JSRuntime *rt)
|
||||
: runtime(rt)
|
||||
, triggerReason(PUBLIC_API) //dummy reason to satisfy makeTable
|
||||
: runtime(rt),
|
||||
triggerReason(gcreason::NO_REASON)
|
||||
{
|
||||
PodArrayZero(counts);
|
||||
PodArrayZero(totals);
|
||||
@ -178,7 +195,7 @@ struct GCCrashData
|
||||
};
|
||||
|
||||
void
|
||||
Statistics::beginGC(JSCompartment *comp, Reason reason)
|
||||
Statistics::beginGC(JSCompartment *comp, gcreason::Reason reason)
|
||||
{
|
||||
compartment = comp;
|
||||
|
||||
@ -276,7 +293,6 @@ Statistics::endGC()
|
||||
if (JSAccumulateTelemetryDataCallback cb = runtime->telemetryCallback) {
|
||||
(*cb)(JS_TELEMETRY_GC_REASON, triggerReason);
|
||||
(*cb)(JS_TELEMETRY_GC_IS_COMPARTMENTAL, compartment ? 1 : 0);
|
||||
(*cb)(JS_TELEMETRY_GC_IS_SHAPE_REGEN, 0);
|
||||
(*cb)(JS_TELEMETRY_GC_MS, t(PHASE_GC));
|
||||
(*cb)(JS_TELEMETRY_GC_MARK_MS, t(PHASE_MARK));
|
||||
(*cb)(JS_TELEMETRY_GC_SWEEP_MS, t(PHASE_SWEEP));
|
||||
|
@ -42,6 +42,7 @@
|
||||
|
||||
#include <string.h>
|
||||
|
||||
#include "jsfriendapi.h"
|
||||
#include "jspubtd.h"
|
||||
#include "jsutil.h"
|
||||
|
||||
@ -50,32 +51,6 @@ struct JSCompartment;
|
||||
namespace js {
|
||||
namespace gcstats {
|
||||
|
||||
enum Reason {
|
||||
PUBLIC_API,
|
||||
MAYBEGC,
|
||||
LASTCONTEXT,
|
||||
DESTROYCONTEXT,
|
||||
LASTDITCH,
|
||||
TOOMUCHMALLOC,
|
||||
ALLOCTRIGGER,
|
||||
CHUNK,
|
||||
SHAPE,
|
||||
REFILL
|
||||
};
|
||||
static const int NUM_REASONS = REFILL + 1;
|
||||
|
||||
static inline const char *
|
||||
ExplainReason(Reason r)
|
||||
{
|
||||
static const char *strs[] = {" API", "Maybe", "LastC", "DestC", "LastD",
|
||||
"Mallc", "Alloc", "Chunk", "Shape", "Refil"};
|
||||
|
||||
JS_ASSERT(strcmp(strs[SHAPE], "Shape") == 0 &&
|
||||
sizeof(strs) / sizeof(strs[0]) == NUM_REASONS);
|
||||
|
||||
return strs[r];
|
||||
}
|
||||
|
||||
enum Phase {
|
||||
PHASE_GC,
|
||||
PHASE_MARK,
|
||||
@ -103,7 +78,7 @@ struct Statistics {
|
||||
Statistics(JSRuntime *rt);
|
||||
~Statistics();
|
||||
|
||||
void beginGC(JSCompartment *comp, Reason reason);
|
||||
void beginGC(JSCompartment *comp, gcreason::Reason reason);
|
||||
void endGC();
|
||||
|
||||
void beginPhase(Phase phase);
|
||||
@ -122,7 +97,7 @@ struct Statistics {
|
||||
FILE *fp;
|
||||
bool fullFormat;
|
||||
|
||||
Reason triggerReason;
|
||||
gcreason::Reason triggerReason;
|
||||
JSCompartment *compartment;
|
||||
|
||||
uint64_t phaseStarts[PHASE_LIMIT];
|
||||
@ -140,8 +115,8 @@ struct Statistics {
|
||||
|
||||
struct ColumnInfo {
|
||||
const char *title;
|
||||
char str[12];
|
||||
char totalStr[12];
|
||||
char str[32];
|
||||
char totalStr[32];
|
||||
int width;
|
||||
|
||||
ColumnInfo() {}
|
||||
@ -155,7 +130,8 @@ struct Statistics {
|
||||
};
|
||||
|
||||
struct AutoGC {
|
||||
AutoGC(Statistics &stats, JSCompartment *comp, Reason reason JS_GUARD_OBJECT_NOTIFIER_PARAM)
|
||||
AutoGC(Statistics &stats, JSCompartment *comp, gcreason::Reason reason
|
||||
JS_GUARD_OBJECT_NOTIFIER_PARAM)
|
||||
: stats(stats) { JS_GUARD_OBJECT_NOTIFIER_INIT; stats.beginGC(comp, reason); }
|
||||
~AutoGC() { stats.endGC(); }
|
||||
|
||||
|
@ -735,6 +735,7 @@ JSRuntime::JSRuntime()
|
||||
gcIsNeeded(0),
|
||||
gcWeakMapList(NULL),
|
||||
gcStats(thisFromCtor()),
|
||||
gcTriggerReason(gcreason::NO_REASON),
|
||||
gcTriggerCompartment(NULL),
|
||||
gcCurrentCompartment(NULL),
|
||||
gcCheckCompartment(NULL),
|
||||
@ -2857,7 +2858,7 @@ JS_CompartmentGC(JSContext *cx, JSCompartment *comp)
|
||||
JS_ASSERT(comp != cx->runtime->atomsCompartment);
|
||||
|
||||
js::gc::VerifyBarriers(cx, true);
|
||||
js_GC(cx, comp, GC_NORMAL, gcstats::PUBLIC_API);
|
||||
js_GC(cx, comp, GC_NORMAL, gcreason::API);
|
||||
}
|
||||
|
||||
JS_PUBLIC_API(void)
|
||||
|
@ -323,13 +323,13 @@ js_DestroyContext(JSContext *cx, JSDestroyContextMode mode)
|
||||
#endif
|
||||
|
||||
if (last) {
|
||||
js_GC(cx, NULL, GC_NORMAL, gcstats::LASTCONTEXT);
|
||||
js_GC(cx, NULL, GC_NORMAL, gcreason::LAST_CONTEXT);
|
||||
|
||||
/* Take the runtime down, now that it has no contexts or atoms. */
|
||||
JS_LOCK_GC(rt);
|
||||
} else {
|
||||
if (mode == JSDCM_FORCE_GC)
|
||||
js_GC(cx, NULL, GC_NORMAL, gcstats::DESTROYCONTEXT);
|
||||
js_GC(cx, NULL, GC_NORMAL, gcreason::DESTROY_CONTEXT);
|
||||
else if (mode == JSDCM_MAYBE_GC)
|
||||
JS_MaybeGC(cx);
|
||||
|
||||
@ -1179,7 +1179,7 @@ JSContext::runningWithTrustedPrincipals() const
|
||||
JS_FRIEND_API(void)
|
||||
JSRuntime::onTooMuchMalloc()
|
||||
{
|
||||
TriggerGC(this, gcstats::TOOMUCHMALLOC);
|
||||
TriggerGC(this, gcreason::TOO_MUCH_MALLOC);
|
||||
}
|
||||
|
||||
JS_FRIEND_API(void *)
|
||||
|
@ -318,7 +318,7 @@ struct JSRuntime
|
||||
js::gcstats::Statistics gcStats;
|
||||
|
||||
/* The reason that an interrupt-triggered GC should be called. */
|
||||
js::gcstats::Reason gcTriggerReason;
|
||||
js::gcreason::Reason gcTriggerReason;
|
||||
|
||||
/* Pre-allocated space for the GC mark stack. */
|
||||
uintptr_t gcMarkStackArray[js::MARK_STACK_LENGTH];
|
||||
|
@ -128,9 +128,15 @@ JS_NewObjectWithUniqueType(JSContext *cx, JSClass *clasp, JSObject *proto, JSObj
|
||||
}
|
||||
|
||||
JS_FRIEND_API(void)
|
||||
JS_ShrinkingGC(JSContext *cx)
|
||||
js::GCForReason(JSContext *cx, gcreason::Reason reason)
|
||||
{
|
||||
js_GC(cx, NULL, GC_SHRINK, gcstats::PUBLIC_API);
|
||||
js_GC(cx, NULL, GC_NORMAL, reason);
|
||||
}
|
||||
|
||||
JS_FRIEND_API(void)
|
||||
js::ShrinkingGC(JSContext *cx, gcreason::Reason reason)
|
||||
{
|
||||
js_GC(cx, NULL, GC_SHRINK, reason);
|
||||
}
|
||||
|
||||
JS_FRIEND_API(void)
|
||||
|
@ -72,9 +72,6 @@ JS_NewObjectWithUniqueType(JSContext *cx, JSClass *clasp, JSObject *proto, JSObj
|
||||
extern JS_FRIEND_API(uint32_t)
|
||||
JS_ObjectCountDynamicSlots(JSObject *obj);
|
||||
|
||||
extern JS_FRIEND_API(void)
|
||||
JS_ShrinkingGC(JSContext *cx);
|
||||
|
||||
extern JS_FRIEND_API(void)
|
||||
JS_ShrinkGCBuffers(JSRuntime *rt);
|
||||
|
||||
@ -101,7 +98,6 @@ JS_TraceShapeCycleCollectorChildren(JSTracer *trc, void *shape);
|
||||
enum {
|
||||
JS_TELEMETRY_GC_REASON,
|
||||
JS_TELEMETRY_GC_IS_COMPARTMENTAL,
|
||||
JS_TELEMETRY_GC_IS_SHAPE_REGEN,
|
||||
JS_TELEMETRY_GC_MS,
|
||||
JS_TELEMETRY_GC_MARK_MS,
|
||||
JS_TELEMETRY_GC_SWEEP_MS
|
||||
@ -572,6 +568,56 @@ GetRuntimeCompartments(JSRuntime *rt);
|
||||
extern JS_FRIEND_API(size_t)
|
||||
SizeOfJSContext();
|
||||
|
||||
#define GCREASONS(D) \
|
||||
/* Reasons internal to the JS engine */ \
|
||||
D(API) \
|
||||
D(MAYBEGC) \
|
||||
D(LAST_CONTEXT) \
|
||||
D(DESTROY_CONTEXT) \
|
||||
D(LAST_DITCH) \
|
||||
D(TOO_MUCH_MALLOC) \
|
||||
D(ALLOC_TRIGGER) \
|
||||
D(UNUSED1) /* was CHUNK */ \
|
||||
D(UNUSED2) /* was SHAPE */ \
|
||||
D(UNUSED3) /* was REFILL */ \
|
||||
\
|
||||
/* Reasons from Firefox */ \
|
||||
D(DOM_WINDOW_UTILS) \
|
||||
D(COMPONENT_UTILS) \
|
||||
D(MEM_PRESSURE) \
|
||||
D(CC_WAITING) \
|
||||
D(CC_FORCED) \
|
||||
D(LOAD_END) \
|
||||
D(POST_COMPARTMENT) \
|
||||
D(PAGE_HIDE) \
|
||||
D(NSJSCONTEXT_DESTROY) \
|
||||
D(SET_NEW_DOCUMENT) \
|
||||
D(SET_DOC_SHELL) \
|
||||
D(DOM_UTILS) \
|
||||
D(DOM_IPC) \
|
||||
D(DOM_WORKER) \
|
||||
D(INTER_SLICE_GC) \
|
||||
D(REFRESH_FRAME)
|
||||
|
||||
namespace gcreason {
|
||||
|
||||
/* GCReasons will end up looking like JSGC_MAYBEGC */
|
||||
enum Reason {
|
||||
#define MAKE_REASON(name) name,
|
||||
GCREASONS(MAKE_REASON)
|
||||
#undef MAKE_REASON
|
||||
NO_REASON,
|
||||
NUM_REASONS
|
||||
};
|
||||
|
||||
} /* namespace gcreason */
|
||||
|
||||
extern JS_FRIEND_API(void)
|
||||
GCForReason(JSContext *cx, gcreason::Reason reason);
|
||||
|
||||
extern JS_FRIEND_API(void)
|
||||
ShrinkingGC(JSContext *cx, gcreason::Reason reason);
|
||||
|
||||
extern JS_FRIEND_API(bool)
|
||||
IsIncrementalBarrierNeeded(JSRuntime *rt);
|
||||
|
||||
|
@ -742,7 +742,7 @@ Chunk::allocateArena(JSCompartment *comp, AllocKind thingKind)
|
||||
rt->gcBytes += ArenaSize;
|
||||
comp->gcBytes += ArenaSize;
|
||||
if (comp->gcBytes >= comp->gcTriggerBytes)
|
||||
TriggerCompartmentGC(comp, gcstats::ALLOCTRIGGER);
|
||||
TriggerCompartmentGC(comp, gcreason::ALLOC_TRIGGER);
|
||||
|
||||
return aheader;
|
||||
}
|
||||
@ -1647,7 +1647,7 @@ RunLastDitchGC(JSContext *cx)
|
||||
|
||||
/* The last ditch GC preserves all atoms. */
|
||||
AutoKeepAtoms keep(rt);
|
||||
js_GC(cx, rt->gcTriggerCompartment, GC_NORMAL, gcstats::LASTDITCH);
|
||||
js_GC(cx, rt->gcTriggerCompartment, GC_NORMAL, gcreason::LAST_DITCH);
|
||||
}
|
||||
|
||||
/* static */ void *
|
||||
@ -2137,7 +2137,7 @@ MarkRuntime(JSTracer *trc)
|
||||
}
|
||||
|
||||
void
|
||||
TriggerGC(JSRuntime *rt, gcstats::Reason reason)
|
||||
TriggerGC(JSRuntime *rt, gcreason::Reason reason)
|
||||
{
|
||||
JS_ASSERT(rt->onOwnerThread());
|
||||
|
||||
@ -2152,7 +2152,7 @@ TriggerGC(JSRuntime *rt, gcstats::Reason reason)
|
||||
}
|
||||
|
||||
void
|
||||
TriggerCompartmentGC(JSCompartment *comp, gcstats::Reason reason)
|
||||
TriggerCompartmentGC(JSCompartment *comp, gcreason::Reason reason)
|
||||
{
|
||||
JSRuntime *rt = comp->rt;
|
||||
JS_ASSERT(!rt->gcRunning);
|
||||
@ -2198,18 +2198,18 @@ MaybeGC(JSContext *cx)
|
||||
JS_ASSERT(rt->onOwnerThread());
|
||||
|
||||
if (rt->gcZeal()) {
|
||||
js_GC(cx, NULL, GC_NORMAL, gcstats::MAYBEGC);
|
||||
js_GC(cx, NULL, GC_NORMAL, gcreason::MAYBEGC);
|
||||
return;
|
||||
}
|
||||
|
||||
JSCompartment *comp = cx->compartment;
|
||||
if (rt->gcIsNeeded) {
|
||||
js_GC(cx, (comp == rt->gcTriggerCompartment) ? comp : NULL, GC_NORMAL, gcstats::MAYBEGC);
|
||||
js_GC(cx, (comp == rt->gcTriggerCompartment) ? comp : NULL, GC_NORMAL, gcreason::MAYBEGC);
|
||||
return;
|
||||
}
|
||||
|
||||
if (comp->gcBytes > 8192 && comp->gcBytes >= 3 * (comp->gcTriggerBytes / 4)) {
|
||||
js_GC(cx, (rt->gcMode == JSGC_MODE_COMPARTMENT) ? comp : NULL, GC_NORMAL, gcstats::MAYBEGC);
|
||||
js_GC(cx, (rt->gcMode == JSGC_MODE_COMPARTMENT) ? comp : NULL, GC_NORMAL, gcreason::MAYBEGC);
|
||||
return;
|
||||
}
|
||||
|
||||
@ -2223,7 +2223,7 @@ MaybeGC(JSContext *cx)
|
||||
if (rt->gcChunkAllocationSinceLastGC ||
|
||||
rt->gcNumArenasFreeCommitted > FreeCommittedArenasThreshold)
|
||||
{
|
||||
js_GC(cx, NULL, GC_SHRINK, gcstats::MAYBEGC);
|
||||
js_GC(cx, NULL, GC_SHRINK, gcreason::MAYBEGC);
|
||||
} else {
|
||||
rt->gcNextFullGCTime = now + GC_IDLE_FULL_SPAN;
|
||||
}
|
||||
@ -2966,7 +2966,7 @@ GCCycle(JSContext *cx, JSCompartment *comp, JSGCInvocationKind gckind)
|
||||
}
|
||||
|
||||
void
|
||||
js_GC(JSContext *cx, JSCompartment *comp, JSGCInvocationKind gckind, gcstats::Reason reason)
|
||||
js_GC(JSContext *cx, JSCompartment *comp, JSGCInvocationKind gckind, gcreason::Reason reason)
|
||||
{
|
||||
JSRuntime *rt = cx->runtime;
|
||||
JS_AbortIfWrongThread(rt);
|
||||
|
@ -1382,11 +1382,11 @@ MarkContext(JSTracer *trc, JSContext *acx);
|
||||
|
||||
/* Must be called with GC lock taken. */
|
||||
extern void
|
||||
TriggerGC(JSRuntime *rt, js::gcstats::Reason reason);
|
||||
TriggerGC(JSRuntime *rt, js::gcreason::Reason reason);
|
||||
|
||||
/* Must be called with GC lock taken. */
|
||||
extern void
|
||||
TriggerCompartmentGC(JSCompartment *comp, js::gcstats::Reason reason);
|
||||
TriggerCompartmentGC(JSCompartment *comp, js::gcreason::Reason reason);
|
||||
|
||||
extern void
|
||||
MaybeGC(JSContext *cx);
|
||||
@ -1409,7 +1409,7 @@ typedef enum JSGCInvocationKind {
|
||||
|
||||
/* Pass NULL for |comp| to get a full GC. */
|
||||
extern void
|
||||
js_GC(JSContext *cx, JSCompartment *comp, JSGCInvocationKind gckind, js::gcstats::Reason r);
|
||||
js_GC(JSContext *cx, JSCompartment *comp, JSGCInvocationKind gckind, js::gcreason::Reason r);
|
||||
|
||||
namespace js {
|
||||
|
||||
|
@ -390,9 +390,15 @@ interface nsIXPCFunctionThisTranslator : nsISupports
|
||||
#define NS_XPCONNECT_CID \
|
||||
{ 0xcb6593e0, 0xf9b2, 0x11d2, \
|
||||
{ 0xbd, 0xd6, 0x0, 0x0, 0x64, 0x65, 0x73, 0x74 } }
|
||||
|
||||
enum nsGCType {
|
||||
nsGCNormal,
|
||||
nsGCShrinking,
|
||||
nsGCIncremental
|
||||
};
|
||||
%}
|
||||
|
||||
[uuid(241e6db3-e018-4d99-b976-c782a05f9c77)]
|
||||
[uuid(686bb1d0-4711-11e1-b86c-0800200c9a66)]
|
||||
interface nsIXPConnect : nsISupports
|
||||
{
|
||||
%{ C++
|
||||
@ -723,8 +729,10 @@ interface nsIXPConnect : nsISupports
|
||||
|
||||
/**
|
||||
* Trigger a JS garbage collection.
|
||||
* Use a js::gcreason::Reason from jsfriendapi.h for the kind.
|
||||
* Use the nsGCType enum for the kind.
|
||||
*/
|
||||
void GarbageCollect(in boolean shrinkingGC);
|
||||
void GarbageCollect(in PRUint32 reason, in PRUint32 kind);
|
||||
|
||||
/**
|
||||
* Define quick stubs on the given object, @a proto.
|
||||
|
@ -3600,7 +3600,7 @@ nsXPCComponents_Utils::GetWeakReference(const JS::Value &object, JSContext *cx,
|
||||
NS_IMETHODIMP
|
||||
nsXPCComponents_Utils::ForceGC(JSContext *cx)
|
||||
{
|
||||
JS_GC(cx);
|
||||
js::GCForReason(cx, js::gcreason::COMPONENT_UTILS);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
@ -3608,7 +3608,7 @@ nsXPCComponents_Utils::ForceGC(JSContext *cx)
|
||||
NS_IMETHODIMP
|
||||
nsXPCComponents_Utils::ForceShrinkingGC(JSContext *cx)
|
||||
{
|
||||
JS_ShrinkingGC(cx);
|
||||
js::ShrinkingGC(cx, js::gcreason::COMPONENT_UTILS);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
@ -3636,9 +3636,9 @@ class PreciseGCRunnable : public nsRunnable
|
||||
}
|
||||
|
||||
if (mShrinking)
|
||||
JS_ShrinkingGC(mCx);
|
||||
js::ShrinkingGC(mCx, js::gcreason::COMPONENT_UTILS);
|
||||
else
|
||||
JS_GC(mCx);
|
||||
js::GCForReason(mCx, js::gcreason::COMPONENT_UTILS);
|
||||
|
||||
mCallback->Callback();
|
||||
return NS_OK;
|
||||
|
@ -1870,9 +1870,6 @@ AccumulateTelemetryCallback(int id, uint32_t sample)
|
||||
case JS_TELEMETRY_GC_IS_COMPARTMENTAL:
|
||||
Telemetry::Accumulate(Telemetry::GC_IS_COMPARTMENTAL, sample);
|
||||
break;
|
||||
case JS_TELEMETRY_GC_IS_SHAPE_REGEN:
|
||||
Telemetry::Accumulate(Telemetry::GC_IS_SHAPE_REGEN, sample);
|
||||
break;
|
||||
case JS_TELEMETRY_GC_MS:
|
||||
Telemetry::Accumulate(Telemetry::GC_MS, sample);
|
||||
break;
|
||||
|
@ -365,7 +365,7 @@ nsXPConnect::NeedCollect()
|
||||
}
|
||||
|
||||
void
|
||||
nsXPConnect::Collect(bool shrinkingGC)
|
||||
nsXPConnect::Collect(PRUint32 reason, PRUint32 kind)
|
||||
{
|
||||
// We're dividing JS objects into 2 categories:
|
||||
//
|
||||
@ -424,16 +424,20 @@ nsXPConnect::Collect(bool shrinkingGC)
|
||||
// XPCCallContext::Init we disable the conservative scanner if that call
|
||||
// has started the request on this thread.
|
||||
js::AutoSkipConservativeScan ascs(cx);
|
||||
if (shrinkingGC)
|
||||
JS_ShrinkingGC(cx);
|
||||
else
|
||||
JS_GC(cx);
|
||||
MOZ_ASSERT(reason < js::gcreason::NUM_REASONS);
|
||||
js::gcreason::Reason gcreason = (js::gcreason::Reason)reason;
|
||||
if (kind == nsGCShrinking) {
|
||||
js::ShrinkingGC(cx, gcreason);
|
||||
} else {
|
||||
MOZ_ASSERT(kind == nsGCNormal);
|
||||
js::GCForReason(cx, gcreason);
|
||||
}
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsXPConnect::GarbageCollect(bool shrinkingGC)
|
||||
nsXPConnect::GarbageCollect(PRUint32 reason, PRUint32 kind)
|
||||
{
|
||||
Collect(shrinkingGC);
|
||||
Collect(reason, kind);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
@ -549,7 +549,7 @@ public:
|
||||
virtual nsresult FinishCycleCollection();
|
||||
virtual nsCycleCollectionParticipant *ToParticipant(void *p);
|
||||
virtual bool NeedCollect();
|
||||
virtual void Collect(bool shrinkingGC=false);
|
||||
virtual void Collect(PRUint32 reason, PRUint32 kind);
|
||||
#ifdef DEBUG_CC
|
||||
virtual void PrintAllReferencesTo(void *p);
|
||||
#endif
|
||||
|
@ -198,6 +198,8 @@ static const char sPrintOptionsContractID[] = "@mozilla.org/gfx/printset
|
||||
|
||||
#include "mozilla/dom/Element.h"
|
||||
|
||||
#include "jsfriendapi.h"
|
||||
|
||||
using namespace mozilla;
|
||||
|
||||
#ifdef NS_DEBUG
|
||||
@ -1287,7 +1289,7 @@ DocumentViewerImpl::PageHide(bool aIsUnload)
|
||||
|
||||
if (aIsUnload) {
|
||||
// Poke the GC. The window might be collectable garbage now.
|
||||
nsJSContext::PokeGC();
|
||||
nsJSContext::PokeGC(js::gcreason::PAGE_HIDE);
|
||||
|
||||
// if Destroy() was called during OnPageHide(), mDocument is nsnull.
|
||||
NS_ENSURE_STATE(mDocument);
|
||||
|
@ -75,7 +75,6 @@ HISTOGRAM(CYCLE_COLLECTOR_TIME_BETWEEN, 1, 120, 50, EXPONENTIAL, "Time spent in
|
||||
*/
|
||||
HISTOGRAM(GC_REASON, 1, 20, 20, LINEAR, "Reason (enum value) for initiating a GC")
|
||||
HISTOGRAM_BOOLEAN(GC_IS_COMPARTMENTAL, "Is it a compartmental GC?")
|
||||
HISTOGRAM_BOOLEAN(GC_IS_SHAPE_REGEN, "Is it a shape regenerating GC?")
|
||||
HISTOGRAM(GC_MS, 1, 10000, 50, EXPONENTIAL, "Time spent running JS GC (ms)")
|
||||
HISTOGRAM(GC_MARK_MS, 1, 10000, 50, EXPONENTIAL, "Time spent running JS GC mark phase (ms)")
|
||||
HISTOGRAM(GC_SWEEP_MS, 1, 10000, 50, EXPONENTIAL, "Time spent running JS GC sweep phase (ms)")
|
||||
|
@ -2823,7 +2823,7 @@ nsCycleCollector::GCIfNeeded(bool aForceGC)
|
||||
// rt->Collect() must be called from the main thread,
|
||||
// because it invokes XPCJSRuntime::GCCallback(cx, JSGC_BEGIN)
|
||||
// which returns false if not in the main thread.
|
||||
rt->Collect();
|
||||
rt->Collect(js::gcreason::CC_FORCED, nsGCNormal);
|
||||
#ifdef COLLECT_TIME_DEBUG
|
||||
printf("cc: GC() took %lldms\n", (PR_Now() - start) / PR_USEC_PER_MSEC);
|
||||
#endif
|
||||
|
@ -106,9 +106,10 @@ struct nsCycleCollectionJSRuntime : public nsCycleCollectionLanguageRuntime
|
||||
virtual bool NeedCollect() = 0;
|
||||
|
||||
/**
|
||||
* Runs the JavaScript GC.
|
||||
* Runs the JavaScript GC. |reason| is a gcreason::Reason from jsfriendapi.h.
|
||||
* |kind| is a nsGCType from nsIXPConnect.idl.
|
||||
*/
|
||||
virtual void Collect(bool shrinkingGC = false) = 0;
|
||||
virtual void Collect(PRUint32 reason, PRUint32 kind) = 0;
|
||||
};
|
||||
|
||||
#ifdef DEBUG
|
||||
|
Loading…
Reference in New Issue
Block a user