mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-11-26 14:22:01 +00:00
bug 723286 - remove JSContext * parameter from heap-traversal and related API. r=:billm
This commit is contained in:
parent
72f481f48f
commit
2d371cbf51
@ -220,8 +220,8 @@ static JSClass sNPObjectMemberClass =
|
||||
static void
|
||||
OnWrapperDestroyed();
|
||||
|
||||
static JSBool
|
||||
DelayedReleaseGCCallback(JSContext* cx, JSGCStatus status)
|
||||
static void
|
||||
DelayedReleaseGCCallback(JSRuntime* rt, JSGCStatus status)
|
||||
{
|
||||
if (JSGC_END == status) {
|
||||
// Take ownership of sDelayedReleases and null it out now. The
|
||||
@ -238,7 +238,6 @@ DelayedReleaseGCCallback(JSContext* cx, JSGCStatus status)
|
||||
}
|
||||
}
|
||||
}
|
||||
return JS_TRUE;
|
||||
}
|
||||
|
||||
static void
|
||||
|
@ -507,10 +507,12 @@ DumpHeap(JSContext *cx,
|
||||
}
|
||||
}
|
||||
|
||||
ok = JS_DumpHeap(cx, dumpFile, startThing, startTraceKind, thingToFind,
|
||||
ok = JS_DumpHeap(JS_GetRuntime(cx), dumpFile, startThing, startTraceKind, thingToFind,
|
||||
maxDepth, thingToIgnore);
|
||||
if (dumpFile != stdout)
|
||||
fclose(dumpFile);
|
||||
if (!ok)
|
||||
JS_ReportOutOfMemory(cx);
|
||||
return ok;
|
||||
|
||||
not_traceable_arg:
|
||||
|
@ -2835,7 +2835,7 @@ jsdService::DumpHeap(const nsACString &fileName)
|
||||
rv = NS_ERROR_FAILURE;
|
||||
} else {
|
||||
JSContext *cx = JSD_GetDefaultJSContext (mCx);
|
||||
if (!JS_DumpHeap(cx, file, NULL, JSTRACE_OBJECT, NULL, (size_t)-1, NULL))
|
||||
if (!JS_DumpHeap(JS_GetRuntime(cx), file, NULL, JSTRACE_OBJECT, NULL, (size_t)-1, NULL))
|
||||
rv = NS_ERROR_FAILURE;
|
||||
if (file != stdout)
|
||||
fclose(file);
|
||||
|
@ -23,12 +23,11 @@ struct StringWrapper
|
||||
bool strOk;
|
||||
} sw;
|
||||
|
||||
JSBool
|
||||
GCCallback(JSContext *cx, JSGCStatus status)
|
||||
void
|
||||
FinalizeCallback(JSContext *cx, JSFinalizeStatus status)
|
||||
{
|
||||
if (status == JSGC_MARK_END)
|
||||
if (status == JSFINALIZE_START)
|
||||
sw.strOk = !JS_IsAboutToBeFinalized(sw.str);
|
||||
return true;
|
||||
}
|
||||
|
||||
BEGIN_TEST(testInternAcrossGC)
|
||||
@ -36,7 +35,7 @@ BEGIN_TEST(testInternAcrossGC)
|
||||
sw.str = JS_InternString(cx, "wrapped chars that another test shouldn't be using");
|
||||
sw.strOk = false;
|
||||
CHECK(sw.str);
|
||||
JS_SetGCCallback(cx, GCCallback);
|
||||
JS_SetFinalizeCallback(rt, FinalizeCallback);
|
||||
JS_GC(cx);
|
||||
CHECK(sw.strOk);
|
||||
return true;
|
||||
|
@ -755,6 +755,7 @@ JSRuntime::JSRuntime()
|
||||
#endif
|
||||
gcCallback(NULL),
|
||||
gcSliceCallback(NULL),
|
||||
gcFinalizeCallback(NULL),
|
||||
gcMallocBytes(0),
|
||||
gcBlackRootsTraceOp(NULL),
|
||||
gcBlackRootsData(NULL),
|
||||
@ -2428,9 +2429,9 @@ JS_SetExtraGCRootsTracer(JSRuntime *rt, JSTraceDataOp traceOp, void *data)
|
||||
}
|
||||
|
||||
JS_PUBLIC_API(void)
|
||||
JS_TracerInit(JSTracer *trc, JSContext *cx, JSTraceCallback callback)
|
||||
JS_TracerInit(JSTracer *trc, JSRuntime *rt, JSTraceCallback callback)
|
||||
{
|
||||
InitTracer(trc, cx->runtime, cx, callback);
|
||||
InitTracer(trc, rt, callback);
|
||||
}
|
||||
|
||||
JS_PUBLIC_API(void)
|
||||
@ -2605,7 +2606,7 @@ struct JSHeapDumpNode {
|
||||
typedef struct JSDumpingTracer {
|
||||
JSTracer base;
|
||||
JSDHashTable visited;
|
||||
JSBool ok;
|
||||
bool ok;
|
||||
void *startThing;
|
||||
void *thingToFind;
|
||||
void *thingToIgnore;
|
||||
@ -2619,7 +2620,6 @@ DumpNotify(JSTracer *trc, void **thingp, JSGCTraceKind kind)
|
||||
{
|
||||
void *thing = *thingp;
|
||||
JSDumpingTracer *dtrc;
|
||||
JSContext *cx;
|
||||
JSDHashEntryStub *entry;
|
||||
|
||||
JS_ASSERT(trc->callback == DumpNotify);
|
||||
@ -2628,8 +2628,6 @@ DumpNotify(JSTracer *trc, void **thingp, JSGCTraceKind kind)
|
||||
if (!dtrc->ok || thing == dtrc->thingToIgnore)
|
||||
return;
|
||||
|
||||
cx = trc->context;
|
||||
|
||||
/*
|
||||
* Check if we have already seen thing unless it is thingToFind to include
|
||||
* it to the graph each time we reach it and print all live things that
|
||||
@ -2650,8 +2648,7 @@ DumpNotify(JSTracer *trc, void **thingp, JSGCTraceKind kind)
|
||||
entry = (JSDHashEntryStub *)
|
||||
JS_DHashTableOperate(&dtrc->visited, thing, JS_DHASH_ADD);
|
||||
if (!entry) {
|
||||
JS_ReportOutOfMemory(cx);
|
||||
dtrc->ok = JS_FALSE;
|
||||
dtrc->ok = false;
|
||||
return;
|
||||
}
|
||||
if (entry->key)
|
||||
@ -2664,7 +2661,7 @@ DumpNotify(JSTracer *trc, void **thingp, JSGCTraceKind kind)
|
||||
size_t bytes = offsetof(JSHeapDumpNode, edgeName) + edgeNameSize;
|
||||
JSHeapDumpNode *node = (JSHeapDumpNode *) OffTheBooks::malloc_(bytes);
|
||||
if (!node) {
|
||||
dtrc->ok = JS_FALSE;
|
||||
dtrc->ok = false;
|
||||
return;
|
||||
}
|
||||
|
||||
@ -2685,7 +2682,6 @@ DumpNode(JSDumpingTracer *dtrc, FILE* fp, JSHeapDumpNode *node)
|
||||
{
|
||||
JSHeapDumpNode *prev, *following;
|
||||
size_t chainLimit;
|
||||
JSBool ok;
|
||||
enum { MAX_PARENTS_TO_PRINT = 10 };
|
||||
|
||||
JS_PrintTraceThingInfo(dtrc->buffer, sizeof dtrc->buffer,
|
||||
@ -2718,21 +2714,21 @@ DumpNode(JSDumpingTracer *dtrc, FILE* fp, JSHeapDumpNode *node)
|
||||
|
||||
node = prev;
|
||||
prev = following;
|
||||
ok = JS_TRUE;
|
||||
bool ok = true;
|
||||
do {
|
||||
/* Loop must continue even when !ok to restore the parent chain. */
|
||||
if (ok) {
|
||||
if (!prev) {
|
||||
/* Print edge from some runtime root or startThing. */
|
||||
if (fputs(node->edgeName, fp) < 0)
|
||||
ok = JS_FALSE;
|
||||
ok = false;
|
||||
} else {
|
||||
JS_PrintTraceThingInfo(dtrc->buffer, sizeof dtrc->buffer,
|
||||
&dtrc->base, prev->thing, prev->kind,
|
||||
JS_FALSE);
|
||||
if (fprintf(fp, "(%p %s).%s",
|
||||
prev->thing, dtrc->buffer, node->edgeName) < 0) {
|
||||
ok = JS_FALSE;
|
||||
ok = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -2746,7 +2742,7 @@ DumpNode(JSDumpingTracer *dtrc, FILE* fp, JSHeapDumpNode *node)
|
||||
}
|
||||
|
||||
JS_PUBLIC_API(JSBool)
|
||||
JS_DumpHeap(JSContext *cx, FILE *fp, void* startThing, JSGCTraceKind startKind,
|
||||
JS_DumpHeap(JSRuntime *rt, FILE *fp, void* startThing, JSGCTraceKind startKind,
|
||||
void *thingToFind, size_t maxDepth, void *thingToIgnore)
|
||||
{
|
||||
JSDumpingTracer dtrc;
|
||||
@ -2757,12 +2753,11 @@ JS_DumpHeap(JSContext *cx, FILE *fp, void* startThing, JSGCTraceKind startKind,
|
||||
if (maxDepth == 0)
|
||||
return JS_TRUE;
|
||||
|
||||
JS_TracerInit(&dtrc.base, cx, DumpNotify);
|
||||
JS_TracerInit(&dtrc.base, rt, DumpNotify);
|
||||
if (!JS_DHashTableInit(&dtrc.visited, JS_DHashGetStubOps(),
|
||||
NULL, sizeof(JSDHashEntryStub),
|
||||
JS_DHASH_DEFAULT_CAPACITY(100))) {
|
||||
JS_ReportOutOfMemory(cx);
|
||||
return JS_FALSE;
|
||||
return false;
|
||||
}
|
||||
dtrc.ok = JS_TRUE;
|
||||
dtrc.startThing = startThing;
|
||||
@ -2863,23 +2858,18 @@ JS_MaybeGC(JSContext *cx)
|
||||
MaybeGC(cx);
|
||||
}
|
||||
|
||||
JS_PUBLIC_API(JSGCCallback)
|
||||
JS_SetGCCallback(JSContext *cx, JSGCCallback cb)
|
||||
JS_PUBLIC_API(void)
|
||||
JS_SetGCCallback(JSRuntime *rt, JSGCCallback cb)
|
||||
{
|
||||
AssertNoGC(cx);
|
||||
CHECK_REQUEST(cx);
|
||||
return JS_SetGCCallbackRT(cx->runtime, cb);
|
||||
AssertNoGC(rt);
|
||||
rt->gcCallback = cb;
|
||||
}
|
||||
|
||||
JS_PUBLIC_API(JSGCCallback)
|
||||
JS_SetGCCallbackRT(JSRuntime *rt, JSGCCallback cb)
|
||||
JS_PUBLIC_API(void)
|
||||
JS_SetFinalizeCallback(JSRuntime *rt, JSFinalizeCallback cb)
|
||||
{
|
||||
JSGCCallback oldcb;
|
||||
|
||||
AssertNoGC(rt);
|
||||
oldcb = rt->gcCallback;
|
||||
rt->gcCallback = cb;
|
||||
return oldcb;
|
||||
rt->gcFinalizeCallback = cb;
|
||||
}
|
||||
|
||||
JS_PUBLIC_API(JSBool)
|
||||
@ -3352,6 +3342,12 @@ JS_IsNative(JSObject *obj)
|
||||
return obj->isNative();
|
||||
}
|
||||
|
||||
JS_PUBLIC_API(JSRuntime *)
|
||||
JS_GetObjectRuntime(JSObject *obj)
|
||||
{
|
||||
return obj->compartment()->rt;
|
||||
}
|
||||
|
||||
JS_PUBLIC_API(JSBool)
|
||||
JS_FreezeObject(JSContext *cx, JSObject *obj)
|
||||
{
|
||||
|
@ -1426,17 +1426,20 @@ typedef JSBool
|
||||
(* JSContextCallback)(JSContext *cx, unsigned contextOp);
|
||||
|
||||
typedef enum JSGCStatus {
|
||||
/* These callbacks happen outside the GC lock. */
|
||||
JSGC_BEGIN,
|
||||
JSGC_END,
|
||||
|
||||
/* These callbacks happen within the GC lock. */
|
||||
JSGC_MARK_END,
|
||||
JSGC_FINALIZE_END
|
||||
JSGC_END
|
||||
} JSGCStatus;
|
||||
|
||||
typedef JSBool
|
||||
(* JSGCCallback)(JSContext *cx, JSGCStatus status);
|
||||
typedef void
|
||||
(* JSGCCallback)(JSRuntime *rt, JSGCStatus status);
|
||||
|
||||
typedef enum JSFinalizeStatus {
|
||||
JSFINALIZE_START,
|
||||
JSFINALIZE_END
|
||||
} JSFinalizeStatus;
|
||||
|
||||
typedef void
|
||||
(* JSFinalizeCallback)(JSContext *cx, JSFinalizeStatus status);
|
||||
|
||||
/*
|
||||
* Generic trace operation that calls JS_CallTracer on each traceable thing
|
||||
@ -3119,7 +3122,6 @@ typedef void
|
||||
|
||||
struct JSTracer {
|
||||
JSRuntime *runtime;
|
||||
JSContext *context;
|
||||
JSTraceCallback callback;
|
||||
JSTraceNamePrinter debugPrinter;
|
||||
const void *debugPrintArg;
|
||||
@ -3218,7 +3220,7 @@ JS_CallTracer(JSTracer *trc, void *thing, JSGCTraceKind kind);
|
||||
* API for JSTraceCallback implementations.
|
||||
*/
|
||||
extern JS_PUBLIC_API(void)
|
||||
JS_TracerInit(JSTracer *trc, JSContext *cx, JSTraceCallback callback);
|
||||
JS_TracerInit(JSTracer *trc, JSRuntime *rt, JSTraceCallback callback);
|
||||
|
||||
extern JS_PUBLIC_API(void)
|
||||
JS_TraceChildren(JSTracer *trc, void *thing, JSGCTraceKind kind);
|
||||
@ -3251,7 +3253,7 @@ JS_GetTraceEdgeName(JSTracer *trc, char *buffer, int bufferSize);
|
||||
* thingToIgnore: thing to ignore during the graph traversal when non-null.
|
||||
*/
|
||||
extern JS_PUBLIC_API(JSBool)
|
||||
JS_DumpHeap(JSContext *cx, FILE *fp, void* startThing, JSGCTraceKind kind,
|
||||
JS_DumpHeap(JSRuntime *rt, FILE *fp, void* startThing, JSGCTraceKind kind,
|
||||
void *thingToFind, size_t maxDepth, void *thingToIgnore);
|
||||
|
||||
#endif
|
||||
@ -3268,11 +3270,11 @@ JS_CompartmentGC(JSContext *cx, JSCompartment *comp);
|
||||
extern JS_PUBLIC_API(void)
|
||||
JS_MaybeGC(JSContext *cx);
|
||||
|
||||
extern JS_PUBLIC_API(JSGCCallback)
|
||||
JS_SetGCCallback(JSContext *cx, JSGCCallback cb);
|
||||
extern JS_PUBLIC_API(void)
|
||||
JS_SetGCCallback(JSRuntime *rt, JSGCCallback cb);
|
||||
|
||||
extern JS_PUBLIC_API(JSGCCallback)
|
||||
JS_SetGCCallbackRT(JSRuntime *rt, JSGCCallback cb);
|
||||
extern JS_PUBLIC_API(void)
|
||||
JS_SetFinalizeCallback(JSRuntime *rt, JSFinalizeCallback cb);
|
||||
|
||||
extern JS_PUBLIC_API(JSBool)
|
||||
JS_IsGCMarkingTracer(JSTracer *trc);
|
||||
@ -3708,6 +3710,9 @@ JS_IsExtensible(JSObject *obj);
|
||||
extern JS_PUBLIC_API(JSBool)
|
||||
JS_IsNative(JSObject *obj);
|
||||
|
||||
extern JS_PUBLIC_API(JSRuntime *)
|
||||
JS_GetObjectRuntime(JSObject *obj);
|
||||
|
||||
/*
|
||||
* Unlike JS_NewObject, JS_NewObjectWithGivenProto does not compute a default
|
||||
* proto if proto's actual parameter value is null.
|
||||
|
@ -437,6 +437,7 @@ struct JSRuntime : js::RuntimeFriendFields
|
||||
|
||||
JSGCCallback gcCallback;
|
||||
js::GCSliceCallback gcSliceCallback;
|
||||
JSFinalizeCallback gcFinalizeCallback;
|
||||
|
||||
private:
|
||||
/*
|
||||
|
@ -468,17 +468,17 @@ struct DumpingChildInfo {
|
||||
{}
|
||||
};
|
||||
|
||||
typedef HashSet<void *, DefaultHasher<void *>, ContextAllocPolicy> PtrSet;
|
||||
typedef HashSet<void *, DefaultHasher<void *>, SystemAllocPolicy> PtrSet;
|
||||
|
||||
struct JSDumpHeapTracer : public JSTracer {
|
||||
PtrSet visited;
|
||||
FILE *output;
|
||||
Vector<DumpingChildInfo, 0, ContextAllocPolicy> nodes;
|
||||
Vector<DumpingChildInfo, 0, SystemAllocPolicy> nodes;
|
||||
char buffer[200];
|
||||
bool rootTracing;
|
||||
|
||||
JSDumpHeapTracer(JSContext *cx, FILE *fp)
|
||||
: visited(cx), output(fp), nodes(cx)
|
||||
JSDumpHeapTracer(FILE *fp)
|
||||
: output(fp)
|
||||
{}
|
||||
};
|
||||
|
||||
@ -530,10 +530,10 @@ DumpHeapVisitChild(JSTracer *trc, void **thingp, JSGCTraceKind kind)
|
||||
}
|
||||
|
||||
void
|
||||
js::DumpHeapComplete(JSContext *cx, FILE *fp)
|
||||
js::DumpHeapComplete(JSRuntime *rt, FILE *fp)
|
||||
{
|
||||
JSDumpHeapTracer dtrc(cx, fp);
|
||||
JS_TracerInit(&dtrc, cx, DumpHeapPushIfNew);
|
||||
JSDumpHeapTracer dtrc(fp);
|
||||
JS_TracerInit(&dtrc, rt, DumpHeapPushIfNew);
|
||||
if (!dtrc.visited.init(10000))
|
||||
return;
|
||||
|
||||
|
@ -221,7 +221,7 @@ typedef bool
|
||||
* fp is the file for the dump output.
|
||||
*/
|
||||
extern JS_FRIEND_API(void)
|
||||
DumpHeapComplete(JSContext *cx, FILE *fp);
|
||||
DumpHeapComplete(JSRuntime *rt, FILE *fp);
|
||||
|
||||
#endif
|
||||
|
||||
@ -519,15 +519,15 @@ IsObjectInContextCompartment(const JSObject *obj, const JSContext *cx);
|
||||
#define JSITER_FOR_OF 0x20 /* harmony for-of loop */
|
||||
|
||||
inline uintptr_t
|
||||
GetContextStackLimit(const JSContext *cx)
|
||||
GetNativeStackLimit(const JSRuntime *rt)
|
||||
{
|
||||
return RuntimeFriendFields::get(GetRuntime(cx))->nativeStackLimit;
|
||||
return RuntimeFriendFields::get(rt)->nativeStackLimit;
|
||||
}
|
||||
|
||||
#define JS_CHECK_RECURSION(cx, onerror) \
|
||||
JS_BEGIN_MACRO \
|
||||
int stackDummy_; \
|
||||
if (!JS_CHECK_STACK_SIZE(js::GetContextStackLimit(cx), &stackDummy_)) { \
|
||||
if (!JS_CHECK_STACK_SIZE(js::GetNativeStackLimit(js::GetRuntime(cx)), &stackDummy_)) { \
|
||||
js_ReportOverRecursed(cx); \
|
||||
onerror; \
|
||||
} \
|
||||
|
@ -1823,10 +1823,9 @@ js_UnlockGCThingRT(JSRuntime *rt, void *thing)
|
||||
namespace js {
|
||||
|
||||
void
|
||||
InitTracer(JSTracer *trc, JSRuntime *rt, JSContext *cx, JSTraceCallback callback)
|
||||
InitTracer(JSTracer *trc, JSRuntime *rt, JSTraceCallback callback)
|
||||
{
|
||||
trc->runtime = rt;
|
||||
trc->context = cx;
|
||||
trc->callback = callback;
|
||||
trc->debugPrinter = NULL;
|
||||
trc->debugPrintArg = NULL;
|
||||
@ -1894,9 +1893,9 @@ GCMarker::init(bool lazy)
|
||||
}
|
||||
|
||||
void
|
||||
GCMarker::start(JSRuntime *rt, JSContext *cx)
|
||||
GCMarker::start(JSRuntime *rt)
|
||||
{
|
||||
InitTracer(this, rt, cx, NULL);
|
||||
InitTracer(this, rt, NULL);
|
||||
JS_ASSERT(!started);
|
||||
started = true;
|
||||
color = BLACK;
|
||||
@ -2162,8 +2161,7 @@ gc_root_traversal(JSTracer *trc, const RootEntry &entry)
|
||||
* that mark callbacks are not in place during compartment GCs.
|
||||
*/
|
||||
JSTracer checker;
|
||||
JS_ASSERT(trc->runtime == trc->context->runtime);
|
||||
JS_TracerInit(&checker, trc->context, EmptyMarkCallback);
|
||||
JS_TracerInit(&checker, trc->runtime, EmptyMarkCallback);
|
||||
ConservativeGCTest test = MarkIfGCThingWord(&checker, reinterpret_cast<uintptr_t>(ptr));
|
||||
if (test != CGCT_VALID && entry.value.name) {
|
||||
fprintf(stderr,
|
||||
@ -3055,9 +3053,6 @@ EndMarkPhase(JSContext *cx)
|
||||
ValidateIncrementalMarking(cx);
|
||||
#endif
|
||||
|
||||
if (rt->gcCallback)
|
||||
(void) rt->gcCallback(cx, JSGC_MARK_END);
|
||||
|
||||
#ifdef DEBUG
|
||||
/* Make sure that we didn't mark an object in another compartment */
|
||||
if (rt->gcCurrentCompartment) {
|
||||
@ -3146,7 +3141,7 @@ ValidateIncrementalMarking(JSContext *cx)
|
||||
while (thing < end) {
|
||||
Cell *cell = (Cell *)thing;
|
||||
if (bitmap->isMarked(cell, BLACK) && !incBitmap.isMarked(cell, BLACK)) {
|
||||
JS_DumpHeap(cx, stdout, NULL, JSGCTraceKind(0), NULL, 100000, NULL);
|
||||
JS_DumpHeap(rt, stdout, NULL, JSGCTraceKind(0), NULL, 100000, NULL);
|
||||
printf("Assertion cell: %p (%d)\n", (void *)cell, cell->getAllocKind());
|
||||
}
|
||||
JS_ASSERT_IF(bitmap->isMarked(cell, BLACK), incBitmap.isMarked(cell, BLACK));
|
||||
@ -3179,6 +3174,9 @@ SweepPhase(JSContext *cx, JSGCInvocationKind gckind)
|
||||
for (GCCompartmentsIter c(rt); !c.done(); c.next())
|
||||
c->arenas.purge();
|
||||
|
||||
if (rt->gcFinalizeCallback)
|
||||
rt->gcFinalizeCallback(cx, JSFINALIZE_START);
|
||||
|
||||
/*
|
||||
* Sweep phase.
|
||||
*
|
||||
@ -3274,8 +3272,8 @@ SweepPhase(JSContext *cx, JSGCInvocationKind gckind)
|
||||
|
||||
{
|
||||
gcstats::AutoPhase ap(rt->gcStats, gcstats::PHASE_XPCONNECT);
|
||||
if (rt->gcCallback)
|
||||
(void) rt->gcCallback(cx, JSGC_FINALIZE_END);
|
||||
if (rt->gcFinalizeCallback)
|
||||
rt->gcFinalizeCallback(cx, JSFINALIZE_END);
|
||||
}
|
||||
|
||||
for (CompartmentsIter c(rt); !c.done(); c.next())
|
||||
@ -3290,7 +3288,7 @@ MarkAndSweep(JSContext *cx, JSGCInvocationKind gckind)
|
||||
|
||||
AutoUnlockGC unlock(rt);
|
||||
|
||||
rt->gcMarker.start(rt, cx);
|
||||
rt->gcMarker.start(rt);
|
||||
JS_ASSERT(!rt->gcMarker.callback);
|
||||
|
||||
BeginMarkPhase(rt);
|
||||
@ -3325,15 +3323,8 @@ class AutoHeapSession {
|
||||
/* ...while this class is to be used only for garbage collection. */
|
||||
class AutoGCSession : AutoHeapSession {
|
||||
public:
|
||||
explicit AutoGCSession(JSContext *cx, JSCompartment *comp);
|
||||
explicit AutoGCSession(JSRuntime *rt, JSCompartment *comp);
|
||||
~AutoGCSession();
|
||||
|
||||
private:
|
||||
/*
|
||||
* We should not be depending on cx->compartment in the GC, so set it to
|
||||
* NULL to look for violations.
|
||||
*/
|
||||
SwitchToCompartment switcher;
|
||||
};
|
||||
|
||||
/* Start a new heap session. */
|
||||
@ -3351,9 +3342,8 @@ AutoHeapSession::~AutoHeapSession()
|
||||
runtime->gcRunning = false;
|
||||
}
|
||||
|
||||
AutoGCSession::AutoGCSession(JSContext *cx, JSCompartment *comp)
|
||||
: AutoHeapSession(cx->runtime),
|
||||
switcher(cx, (JSCompartment *)NULL)
|
||||
AutoGCSession::AutoGCSession(JSRuntime *rt, JSCompartment *comp)
|
||||
: AutoHeapSession(rt)
|
||||
{
|
||||
JS_ASSERT(!runtime->gcCurrentCompartment);
|
||||
runtime->gcCurrentCompartment = comp;
|
||||
@ -3482,12 +3472,12 @@ IncrementalGCSlice(JSContext *cx, int64_t budget, JSGCInvocationKind gckind)
|
||||
}
|
||||
|
||||
if (rt->gcIncrementalState == MARK_ROOTS) {
|
||||
rt->gcMarker.start(rt, cx);
|
||||
rt->gcMarker.start(rt);
|
||||
JS_ASSERT(IS_GC_MARKING_TRACER(&rt->gcMarker));
|
||||
|
||||
for (GCCompartmentsIter c(rt); !c.done(); c.next()) {
|
||||
c->discardJitCode(cx);
|
||||
c->barrierMarker_.start(rt, NULL);
|
||||
c->barrierMarker_.start(rt);
|
||||
}
|
||||
|
||||
BeginMarkPhase(rt);
|
||||
@ -3503,14 +3493,10 @@ IncrementalGCSlice(JSContext *cx, int64_t budget, JSGCInvocationKind gckind)
|
||||
if (!rt->gcMarker.hasBufferedGrayRoots())
|
||||
sliceBudget.reset();
|
||||
|
||||
rt->gcMarker.context = cx;
|
||||
bool finished = rt->gcMarker.drainMarkStack(sliceBudget);
|
||||
|
||||
for (GCCompartmentsIter c(rt); !c.done(); c.next()) {
|
||||
c->barrierMarker_.context = cx;
|
||||
for (GCCompartmentsIter c(rt); !c.done(); c.next())
|
||||
finished &= c->barrierMarker_.drainMarkStack(sliceBudget);
|
||||
c->barrierMarker_.context = NULL;
|
||||
}
|
||||
|
||||
if (finished) {
|
||||
JS_ASSERT(rt->gcMarker.isDrained());
|
||||
@ -3645,7 +3631,7 @@ GCCycle(JSContext *cx, JSCompartment *comp, int64_t budget, JSGCInvocationKind g
|
||||
if (rt->gcRunning)
|
||||
return;
|
||||
|
||||
AutoGCSession gcsession(cx, comp);
|
||||
AutoGCSession gcsession(rt, comp);
|
||||
|
||||
/* Don't GC if we are reporting an OOM. */
|
||||
if (rt->inOOMReport)
|
||||
@ -3728,10 +3714,8 @@ Collect(JSContext *cx, JSCompartment *comp, int64_t budget,
|
||||
* is the last context). Invoke the callback regardless.
|
||||
*/
|
||||
if (rt->gcIncrementalState == NO_INCREMENTAL) {
|
||||
if (JSGCCallback callback = rt->gcCallback) {
|
||||
if (!callback(cx, JSGC_BEGIN) && rt->hasContexts())
|
||||
return;
|
||||
}
|
||||
if (JSGCCallback callback = rt->gcCallback)
|
||||
callback(rt, JSGC_BEGIN);
|
||||
}
|
||||
|
||||
{
|
||||
@ -3743,7 +3727,7 @@ Collect(JSContext *cx, JSCompartment *comp, int64_t budget,
|
||||
|
||||
if (rt->gcIncrementalState == NO_INCREMENTAL) {
|
||||
if (JSGCCallback callback = rt->gcCallback)
|
||||
(void) callback(cx, JSGC_END);
|
||||
callback(rt, JSGC_END);
|
||||
}
|
||||
|
||||
/*
|
||||
@ -3962,7 +3946,7 @@ NewCompartment(JSContext *cx, JSPrincipals *principals)
|
||||
* resetting the GC.
|
||||
*/
|
||||
if (!rt->gcIncrementalCompartment)
|
||||
compartment->barrierMarker_.start(rt, NULL);
|
||||
compartment->barrierMarker_.start(rt);
|
||||
}
|
||||
|
||||
if (rt->compartments.append(compartment))
|
||||
@ -4110,7 +4094,7 @@ struct VerifyNode
|
||||
EdgeValue edges[1];
|
||||
};
|
||||
|
||||
typedef HashMap<void *, VerifyNode *> NodeMap;
|
||||
typedef HashMap<void *, VerifyNode *, DefaultHasher<void *>, SystemAllocPolicy> NodeMap;
|
||||
|
||||
/*
|
||||
* The verifier data structures are simple. The entire graph is stored in a
|
||||
@ -4139,7 +4123,7 @@ struct VerifyTracer : JSTracer {
|
||||
char *term;
|
||||
NodeMap nodemap;
|
||||
|
||||
VerifyTracer(JSContext *cx) : root(NULL), nodemap(cx) {}
|
||||
VerifyTracer() : root(NULL) {}
|
||||
~VerifyTracer() { js_free(root); }
|
||||
};
|
||||
|
||||
@ -4230,13 +4214,13 @@ StartVerifyBarriers(JSContext *cx)
|
||||
|
||||
PurgeRuntime(rt);
|
||||
|
||||
VerifyTracer *trc = new (js_malloc(sizeof(VerifyTracer))) VerifyTracer(cx);
|
||||
VerifyTracer *trc = new (js_malloc(sizeof(VerifyTracer))) VerifyTracer;
|
||||
|
||||
rt->gcNumber++;
|
||||
trc->number = rt->gcNumber;
|
||||
trc->count = 0;
|
||||
|
||||
JS_TracerInit(trc, cx, AccumulateEdge);
|
||||
JS_TracerInit(trc, rt, AccumulateEdge);
|
||||
|
||||
const size_t size = 64 * 1024 * 1024;
|
||||
trc->root = (VerifyNode *)js_malloc(size);
|
||||
@ -4279,7 +4263,7 @@ StartVerifyBarriers(JSContext *cx)
|
||||
rt->gcIncrementalState = MARK;
|
||||
for (CompartmentsIter c(rt); !c.done(); c.next()) {
|
||||
c->needsBarrier_ = true;
|
||||
c->barrierMarker_.start(rt, NULL);
|
||||
c->barrierMarker_.start(rt);
|
||||
c->arenas.prepareForIncrementalGC(c);
|
||||
}
|
||||
|
||||
@ -4385,7 +4369,7 @@ EndVerifyBarriers(JSContext *cx)
|
||||
rt->gcVerifyData = NULL;
|
||||
rt->gcIncrementalState = NO_INCREMENTAL;
|
||||
|
||||
JS_TracerInit(trc, cx, MarkFromAutorooter);
|
||||
JS_TracerInit(trc, rt, MarkFromAutorooter);
|
||||
|
||||
AutoGCRooter::traceAll(trc);
|
||||
|
||||
@ -4394,10 +4378,10 @@ EndVerifyBarriers(JSContext *cx)
|
||||
* Verify that all the current roots were reachable previously, or else
|
||||
* are marked.
|
||||
*/
|
||||
JS_TracerInit(trc, cx, CheckReachable);
|
||||
JS_TracerInit(trc, rt, CheckReachable);
|
||||
MarkRuntime(trc, true);
|
||||
|
||||
JS_TracerInit(trc, cx, CheckEdge);
|
||||
JS_TracerInit(trc, rt, CheckEdge);
|
||||
|
||||
/* Start after the roots. */
|
||||
VerifyNode *node = NextNode(trc->root);
|
||||
|
@ -1410,7 +1410,7 @@ GCDebugSlice(JSContext *cx, int64_t objCount);
|
||||
namespace js {
|
||||
|
||||
void
|
||||
InitTracer(JSTracer *trc, JSRuntime *rt, JSContext *cx, JSTraceCallback callback);
|
||||
InitTracer(JSTracer *trc, JSRuntime *rt, JSTraceCallback callback);
|
||||
|
||||
#ifdef JS_THREADSAFE
|
||||
|
||||
@ -1772,7 +1772,7 @@ struct GCMarker : public JSTracer {
|
||||
void setSizeLimit(size_t size) { stack.setSizeLimit(size); }
|
||||
size_t sizeLimit() const { return stack.sizeLimit; }
|
||||
|
||||
void start(JSRuntime *rt, JSContext *cx);
|
||||
void start(JSRuntime *rt);
|
||||
void stop();
|
||||
void reset();
|
||||
|
||||
|
@ -1474,7 +1474,7 @@ struct JSCountHeapNode {
|
||||
typedef struct JSCountHeapTracer {
|
||||
JSTracer base;
|
||||
JSDHashTable visited;
|
||||
JSBool ok;
|
||||
bool ok;
|
||||
JSCountHeapNode *traceList;
|
||||
JSCountHeapNode *recycleList;
|
||||
} JSCountHeapTracer;
|
||||
@ -1495,8 +1495,7 @@ CountHeapNotify(JSTracer *trc, void **thingp, JSGCTraceKind kind)
|
||||
entry = (JSDHashEntryStub *)
|
||||
JS_DHashTableOperate(&countTracer->visited, thing, JS_DHASH_ADD);
|
||||
if (!entry) {
|
||||
JS_ReportOutOfMemory(trc->context);
|
||||
countTracer->ok = JS_FALSE;
|
||||
countTracer->ok = false;
|
||||
return;
|
||||
}
|
||||
if (entry->key)
|
||||
@ -1509,7 +1508,7 @@ CountHeapNotify(JSTracer *trc, void **thingp, JSGCTraceKind kind)
|
||||
} else {
|
||||
node = (JSCountHeapNode *) js_malloc(sizeof *node);
|
||||
if (!node) {
|
||||
countTracer->ok = JS_FALSE;
|
||||
countTracer->ok = false;
|
||||
return;
|
||||
}
|
||||
}
|
||||
@ -1580,14 +1579,14 @@ CountHeap(JSContext *cx, unsigned argc, jsval *vp)
|
||||
}
|
||||
}
|
||||
|
||||
JS_TracerInit(&countTracer.base, cx, CountHeapNotify);
|
||||
JS_TracerInit(&countTracer.base, JS_GetRuntime(cx), CountHeapNotify);
|
||||
if (!JS_DHashTableInit(&countTracer.visited, JS_DHashGetStubOps(),
|
||||
NULL, sizeof(JSDHashEntryStub),
|
||||
JS_DHASH_DEFAULT_CAPACITY(100))) {
|
||||
JS_ReportOutOfMemory(cx);
|
||||
return JS_FALSE;
|
||||
}
|
||||
countTracer.ok = JS_TRUE;
|
||||
countTracer.ok = true;
|
||||
countTracer.traceList = NULL;
|
||||
countTracer.recycleList = NULL;
|
||||
|
||||
@ -1612,8 +1611,12 @@ CountHeap(JSContext *cx, unsigned argc, jsval *vp)
|
||||
js_free(node);
|
||||
}
|
||||
JS_DHashTableFinish(&countTracer.visited);
|
||||
if (!countTracer.ok) {
|
||||
JS_ReportOutOfMemory(cx);
|
||||
return false;
|
||||
}
|
||||
|
||||
return countTracer.ok && JS_NewNumberValue(cx, (double) counter, vp);
|
||||
return JS_NewNumberValue(cx, (double) counter, vp);
|
||||
}
|
||||
|
||||
static jsrefcount finalizeCount = 0;
|
||||
@ -2533,12 +2536,16 @@ DumpHeap(JSContext *cx, unsigned argc, jsval *vp)
|
||||
}
|
||||
}
|
||||
|
||||
ok = JS_DumpHeap(cx, dumpFile, startThing, startTraceKind, thingToFind,
|
||||
ok = JS_DumpHeap(JS_GetRuntime(cx), dumpFile, startThing, startTraceKind, thingToFind,
|
||||
maxDepth, thingToIgnore);
|
||||
if (dumpFile != stdout)
|
||||
fclose(dumpFile);
|
||||
if (!ok) {
|
||||
JS_ReportOutOfMemory(cx);
|
||||
return false;
|
||||
}
|
||||
JS_SET_RVAL(cx, vp, JSVAL_VOID);
|
||||
return ok;
|
||||
return true;
|
||||
|
||||
not_traceable_arg:
|
||||
JS_ReportError(cx, "argument '%s' is not null or a heap-allocated thing",
|
||||
|
@ -133,7 +133,7 @@ class HeapReverser : public JSTracer {
|
||||
struct Edge {
|
||||
public:
|
||||
Edge(char *name, void *origin) : name(name), origin(origin) { }
|
||||
~Edge() { free(name); }
|
||||
~Edge() { js_free(name); }
|
||||
|
||||
/*
|
||||
* Move constructor and move assignment. These allow us to live in
|
||||
@ -166,12 +166,12 @@ class HeapReverser : public JSTracer {
|
||||
* The result of a reversal is a map from Cells' addresses to Node
|
||||
* structures describing their incoming edges.
|
||||
*/
|
||||
typedef HashMap<void *, Node> Map;
|
||||
typedef HashMap<void *, Node, DefaultHasher<void *>, SystemAllocPolicy> Map;
|
||||
Map map;
|
||||
|
||||
/* Construct a HeapReverser for |context|'s heap. */
|
||||
HeapReverser(JSContext *cx) : map(cx), roots(cx), rooter(cx, 0, NULL), work(cx), parent(NULL) {
|
||||
JS_TracerInit(this, cx, traverseEdgeWithThis);
|
||||
HeapReverser(JSContext *cx) : rooter(cx, 0, NULL), parent(NULL) {
|
||||
JS_TracerInit(this, JS_GetRuntime(cx), traverseEdgeWithThis);
|
||||
}
|
||||
|
||||
bool init() { return map.init(); }
|
||||
@ -193,7 +193,7 @@ class HeapReverser : public JSTracer {
|
||||
* rule. This is kind of dumb, but JSAPI doesn't provide any less restricted
|
||||
* way to register arrays of roots.
|
||||
*/
|
||||
Vector<jsval> roots;
|
||||
Vector<jsval, 0, SystemAllocPolicy> roots;
|
||||
AutoArrayRooter rooter;
|
||||
|
||||
/*
|
||||
@ -232,7 +232,7 @@ class HeapReverser : public JSTracer {
|
||||
* A stack of work items. We represent the stack explicitly to avoid
|
||||
* overflowing the C++ stack when traversing long chains of objects.
|
||||
*/
|
||||
Vector<Child> work;
|
||||
Vector<Child, 0, SystemAllocPolicy> work;
|
||||
|
||||
/* When traverseEdge is called, the Cell and kind at which the edge originated. */
|
||||
void *parent;
|
||||
@ -323,7 +323,7 @@ HeapReverser::getEdgeDescription()
|
||||
{
|
||||
if (!debugPrinter && debugPrintIndex == (size_t) -1) {
|
||||
const char *arg = static_cast<const char *>(debugPrintArg);
|
||||
char *name = static_cast<char *>(context->malloc_(strlen(arg) + 1));
|
||||
char *name = static_cast<char *>(js_malloc(strlen(arg) + 1));
|
||||
if (!name)
|
||||
return NULL;
|
||||
strcpy(name, arg);
|
||||
@ -332,7 +332,7 @@ HeapReverser::getEdgeDescription()
|
||||
|
||||
/* Lovely; but a fixed size is required by JSTraceNamePrinter. */
|
||||
static const int nameSize = 200;
|
||||
char *name = static_cast<char *>(context->malloc_(nameSize));
|
||||
char *name = static_cast<char *>(js_malloc(nameSize));
|
||||
if (!name)
|
||||
return NULL;
|
||||
if (debugPrinter)
|
||||
@ -342,7 +342,7 @@ HeapReverser::getEdgeDescription()
|
||||
static_cast<const char *>(debugPrintArg), debugPrintIndex);
|
||||
|
||||
/* Shrink storage to fit. */
|
||||
return static_cast<char *>(context->realloc_(name, strlen(name) + 1));
|
||||
return static_cast<char *>(js_realloc(name, strlen(name) + 1));
|
||||
}
|
||||
|
||||
|
||||
|
@ -644,10 +644,12 @@ DumpHeap(JSContext *cx, unsigned argc, jsval *vp)
|
||||
}
|
||||
}
|
||||
|
||||
ok = JS_DumpHeap(cx, dumpFile, startThing, startTraceKind, thingToFind,
|
||||
ok = JS_DumpHeap(JS_GetRuntime(cx), dumpFile, startThing, startTraceKind, thingToFind,
|
||||
maxDepth, thingToIgnore);
|
||||
if (dumpFile != gOutFile)
|
||||
fclose(dumpFile);
|
||||
if (!ok)
|
||||
JS_ReportOutOfMemory(cx);
|
||||
return ok;
|
||||
|
||||
not_traceable_arg:
|
||||
|
@ -654,30 +654,56 @@ SweepCompartment(nsCStringHashKey& aKey, JSCompartment *compartment, void *aClos
|
||||
return PL_DHASH_NEXT;
|
||||
}
|
||||
|
||||
// static
|
||||
JSBool XPCJSRuntime::GCCallback(JSContext *cx, JSGCStatus status)
|
||||
/* static */ void
|
||||
XPCJSRuntime::GCCallback(JSRuntime *rt, JSGCStatus status)
|
||||
{
|
||||
XPCJSRuntime* self = nsXPConnect::GetRuntimeInstance();
|
||||
if (!self)
|
||||
return true;
|
||||
return;
|
||||
|
||||
switch (status) {
|
||||
case JSGC_BEGIN:
|
||||
{
|
||||
if (!NS_IsMainThread()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// We seem to sometime lose the unrooted global flag. Restore it
|
||||
// here. FIXME: bug 584495.
|
||||
JSContext *iter = nsnull;
|
||||
while (JSContext *acx = JS_ContextIterator(JS_GetRuntime(cx), &iter)) {
|
||||
while (JSContext *acx = JS_ContextIterator(rt, &iter)) {
|
||||
if (!js::HasUnrootedGlobal(acx))
|
||||
JS_ToggleOptions(acx, JSOPTION_UNROOTED_GLOBAL);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case JSGC_MARK_END:
|
||||
case JSGC_END:
|
||||
{
|
||||
// Do any deferred releases of native objects.
|
||||
#ifdef XPC_TRACK_DEFERRED_RELEASES
|
||||
printf("XPC - Begin deferred Release of %d nsISupports pointers\n",
|
||||
self->mNativesToReleaseArray.Length());
|
||||
#endif
|
||||
DoDeferredRelease(self->mNativesToReleaseArray);
|
||||
#ifdef XPC_TRACK_DEFERRED_RELEASES
|
||||
printf("XPC - End deferred Releases\n");
|
||||
#endif
|
||||
|
||||
self->GetXPConnect()->ClearGCBeforeCC();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
nsTArray<JSGCCallback> callbacks(self->extraGCCallbacks);
|
||||
for (PRUint32 i = 0; i < callbacks.Length(); ++i)
|
||||
callbacks[i](rt, status);
|
||||
}
|
||||
|
||||
/* static */ void
|
||||
XPCJSRuntime::FinalizeCallback(JSContext *cx, JSFinalizeStatus status)
|
||||
{
|
||||
XPCJSRuntime* self = nsXPConnect::GetRuntimeInstance();
|
||||
if (!self)
|
||||
return;
|
||||
|
||||
switch (status) {
|
||||
case JSFINALIZE_START:
|
||||
{
|
||||
NS_ASSERTION(!self->mDoingFinalization, "bad state");
|
||||
|
||||
@ -710,7 +736,7 @@ JSBool XPCJSRuntime::GCCallback(JSContext *cx, JSGCStatus status)
|
||||
self->mDoingFinalization = true;
|
||||
break;
|
||||
}
|
||||
case JSGC_FINALIZE_END:
|
||||
case JSFINALIZE_END:
|
||||
{
|
||||
NS_ASSERTION(self->mDoingFinalization, "bad state");
|
||||
self->mDoingFinalization = false;
|
||||
@ -897,36 +923,7 @@ JSBool XPCJSRuntime::GCCallback(JSContext *cx, JSGCStatus status)
|
||||
|
||||
break;
|
||||
}
|
||||
case JSGC_END:
|
||||
{
|
||||
// NOTE that this event happens outside of the gc lock in
|
||||
// the js engine. So this could be simultaneous with the
|
||||
// events above.
|
||||
|
||||
// Do any deferred releases of native objects.
|
||||
#ifdef XPC_TRACK_DEFERRED_RELEASES
|
||||
printf("XPC - Begin deferred Release of %d nsISupports pointers\n",
|
||||
self->mNativesToReleaseArray.Length());
|
||||
#endif
|
||||
DoDeferredRelease(self->mNativesToReleaseArray);
|
||||
#ifdef XPC_TRACK_DEFERRED_RELEASES
|
||||
printf("XPC - End deferred Releases\n");
|
||||
#endif
|
||||
|
||||
self->GetXPConnect()->ClearGCBeforeCC();
|
||||
break;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
nsTArray<JSGCCallback> callbacks(self->extraGCCallbacks);
|
||||
for (PRUint32 i = 0; i < callbacks.Length(); ++i) {
|
||||
if (!callbacks[i](cx, status))
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
//static
|
||||
@ -2067,7 +2064,8 @@ XPCJSRuntime::XPCJSRuntime(nsXPConnect* aXPConnect)
|
||||
JS_SetNativeStackQuota(mJSRuntime, 128 * sizeof(size_t) * 1024);
|
||||
JS_SetContextCallback(mJSRuntime, ContextCallback);
|
||||
JS_SetCompartmentCallback(mJSRuntime, CompartmentCallback);
|
||||
JS_SetGCCallbackRT(mJSRuntime, GCCallback);
|
||||
JS_SetGCCallback(mJSRuntime, GCCallback);
|
||||
JS_SetFinalizeCallback(mJSRuntime, FinalizeCallback);
|
||||
JS_SetExtraGCRootsTracer(mJSRuntime, TraceBlackJS, this);
|
||||
JS_SetGrayGCRootsTracer(mJSRuntime, TraceGrayJS, this);
|
||||
JS_SetWrapObjectCallbacks(mJSRuntime,
|
||||
|
@ -228,21 +228,17 @@ nsXPConnect::ReleaseXPConnectSingleton()
|
||||
// force a dump of the JavaScript gc heap if JS is still alive
|
||||
// if requested through XPC_SHUTDOWN_HEAP_DUMP environment variable
|
||||
{
|
||||
// autoscope
|
||||
XPCCallContext ccx(NATIVE_CALLER);
|
||||
if (ccx.IsValid()) {
|
||||
const char* dumpName = getenv("XPC_SHUTDOWN_HEAP_DUMP");
|
||||
if (dumpName) {
|
||||
FILE* dumpFile = (*dumpName == '\0' ||
|
||||
strcmp(dumpName, "stdout") == 0)
|
||||
? stdout
|
||||
: fopen(dumpName, "w");
|
||||
if (dumpFile) {
|
||||
JS_DumpHeap(ccx, dumpFile, nsnull, JSTRACE_OBJECT, nsnull,
|
||||
static_cast<size_t>(-1), nsnull);
|
||||
if (dumpFile != stdout)
|
||||
fclose(dumpFile);
|
||||
}
|
||||
const char* dumpName = getenv("XPC_SHUTDOWN_HEAP_DUMP");
|
||||
if (dumpName) {
|
||||
FILE* dumpFile = (*dumpName == '\0' ||
|
||||
strcmp(dumpName, "stdout") == 0)
|
||||
? stdout
|
||||
: fopen(dumpName, "w");
|
||||
if (dumpFile) {
|
||||
JS_DumpHeap(xpc->GetRuntime()->GetJSRuntime(), dumpFile, nsnull,
|
||||
JSTRACE_OBJECT, nsnull, static_cast<size_t>(-1), nsnull);
|
||||
if (dumpFile != stdout)
|
||||
fclose(dumpFile);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -499,11 +495,11 @@ TraceWeakMappingChild(JSTracer *trc, void **thingp, JSGCTraceKind kind)
|
||||
|
||||
struct NoteWeakMapsTracer : public js::WeakMapTracer
|
||||
{
|
||||
NoteWeakMapsTracer(JSContext *cx, js::WeakMapTraceCallback cb,
|
||||
NoteWeakMapsTracer(JSRuntime *rt, js::WeakMapTraceCallback cb,
|
||||
nsCycleCollectionTraversalCallback &cccb)
|
||||
: js::WeakMapTracer(js::GetRuntime(cx), cb), mCb(cccb), mChildTracer(cccb)
|
||||
: js::WeakMapTracer(rt, cb), mCb(cccb), mChildTracer(cccb)
|
||||
{
|
||||
JS_TracerInit(&mChildTracer, cx, TraceWeakMappingChild);
|
||||
JS_TracerInit(&mChildTracer, rt, TraceWeakMappingChild);
|
||||
}
|
||||
nsCycleCollectionTraversalCallback &mCb;
|
||||
NoteWeakMapChildrenTracer mChildTracer;
|
||||
@ -598,8 +594,7 @@ nsXPConnect::BeginCycleCollection(nsCycleCollectionTraversalCallback &cb,
|
||||
|
||||
GetRuntime()->AddXPConnectRoots(cb);
|
||||
|
||||
NoteWeakMapsTracer trc(mCycleCollectionContext->GetJSContext(),
|
||||
TraceWeakMapping, cb);
|
||||
NoteWeakMapsTracer trc(GetRuntime()->GetJSRuntime(), TraceWeakMapping, cb);
|
||||
js::TraceWeakMaps(&trc);
|
||||
|
||||
return NS_OK;
|
||||
@ -724,7 +719,7 @@ UnmarkGrayChildren(JSTracer *trc, void **thingp, JSGCTraceKind kind)
|
||||
{
|
||||
void *thing = *thingp;
|
||||
int stackDummy;
|
||||
if (!JS_CHECK_STACK_SIZE(js::GetContextStackLimit(trc->context), &stackDummy)) {
|
||||
if (!JS_CHECK_STACK_SIZE(js::GetNativeStackLimit(trc->runtime), &stackDummy)) {
|
||||
/*
|
||||
* If we run out of stack, we take a more drastic measure: require that
|
||||
* we GC again before the next CC.
|
||||
@ -753,17 +748,9 @@ xpc_UnmarkGrayObjectRecursive(JSObject *obj)
|
||||
// Unmark.
|
||||
js::gc::AsCell(obj)->unmark(js::gc::GRAY);
|
||||
|
||||
// Tracing requires a JSContext...
|
||||
JSContext *cx;
|
||||
nsXPConnect* xpc = nsXPConnect::GetXPConnect();
|
||||
if (!xpc || NS_FAILED(xpc->GetSafeJSContext(&cx)) || !cx) {
|
||||
NS_ERROR("Failed to get safe JSContext!");
|
||||
return;
|
||||
}
|
||||
|
||||
// Trace children.
|
||||
JSTracer trc;
|
||||
JS_TracerInit(&trc, cx, UnmarkGrayChildren);
|
||||
JS_TracerInit(&trc, JS_GetObjectRuntime(obj), UnmarkGrayChildren);
|
||||
JS_TraceChildren(&trc, obj, JSTRACE_OBJECT);
|
||||
}
|
||||
|
||||
@ -861,8 +848,6 @@ WrapperIsNotMainThreadOnly(XPCWrappedNative *wrapper)
|
||||
NS_IMETHODIMP
|
||||
nsXPConnect::Traverse(void *p, nsCycleCollectionTraversalCallback &cb)
|
||||
{
|
||||
JSContext *cx = mCycleCollectionContext->GetJSContext();
|
||||
|
||||
JSGCTraceKind traceKind = js_GetGCThingTraceKind(p);
|
||||
JSObject *obj = nsnull;
|
||||
js::Class *clazz = nsnull;
|
||||
@ -970,7 +955,7 @@ nsXPConnect::Traverse(void *p, nsCycleCollectionTraversalCallback &cb)
|
||||
|
||||
TraversalTracer trc(cb);
|
||||
|
||||
JS_TracerInit(&trc, cx, NoteJSChild);
|
||||
JS_TracerInit(&trc, GetRuntime()->GetJSRuntime(), NoteJSChild);
|
||||
trc.eagerlyTraceWeakMaps = false;
|
||||
JS_TraceChildren(&trc, p, traceKind);
|
||||
|
||||
@ -1222,7 +1207,7 @@ xpc_CreateGlobalObject(JSContext *cx, JSClass *clasp,
|
||||
#ifdef DEBUG
|
||||
if (clasp->flags & JSCLASS_XPCONNECT_GLOBAL) {
|
||||
VerifyTraceXPCGlobalCalledTracer trc;
|
||||
JS_TracerInit(&trc.base, cx, VerifyTraceXPCGlobalCalled);
|
||||
JS_TracerInit(&trc.base, JS_GetRuntime(cx), VerifyTraceXPCGlobalCalled);
|
||||
trc.ok = false;
|
||||
JS_TraceChildren(&trc.base, *global, JSTRACE_OBJECT);
|
||||
NS_ABORT_IF_FALSE(trc.ok, "Trace hook needs to call TraceXPCGlobal if JSCLASS_XPCONNECT_GLOBAL is set.");
|
||||
@ -2779,13 +2764,12 @@ void
|
||||
DumpJSHeap(FILE* file)
|
||||
{
|
||||
NS_ABORT_IF_FALSE(NS_IsMainThread(), "Must dump GC heap on main thread.");
|
||||
JSContext *cx;
|
||||
nsXPConnect* xpc = nsXPConnect::GetXPConnect();
|
||||
if (!xpc || NS_FAILED(xpc->GetSafeJSContext(&cx)) || !cx) {
|
||||
NS_ERROR("Failed to get safe JSContext!");
|
||||
if (!xpc) {
|
||||
NS_ERROR("Failed to get nsXPConnect instance!");
|
||||
return;
|
||||
}
|
||||
js::DumpHeapComplete(cx, file);
|
||||
js::DumpHeapComplete(xpc->GetRuntime()->GetJSRuntime(), file);
|
||||
}
|
||||
#endif
|
||||
|
||||
|
@ -751,7 +751,8 @@ public:
|
||||
void AddXPConnectRoots(nsCycleCollectionTraversalCallback& cb);
|
||||
void UnmarkSkippableJSHolders();
|
||||
|
||||
static JSBool GCCallback(JSContext *cx, JSGCStatus status);
|
||||
static void GCCallback(JSRuntime *rt, JSGCStatus status);
|
||||
static void FinalizeCallback(JSContext *cx, JSFinalizeStatus status);
|
||||
|
||||
inline void AddVariantRoot(XPCTraceableVariant* variant);
|
||||
inline void AddWrappedJSRoot(nsXPCWrappedJS* wrappedJS);
|
||||
|
Loading…
Reference in New Issue
Block a user