diff --git a/js/src/Makefile.in b/js/src/Makefile.in index b0e6e7efd5461caf6790b0b2875228d58b205777..e9c10d1e4598b7b33e9511ce89afd8ae2c9fb594 100644 --- a/js/src/Makefile.in +++ b/js/src/Makefile.in @@ -148,7 +148,6 @@ CPPSRCS = \ Memory.cpp \ Statistics.cpp \ StoreBuffer.cpp \ - FindSCCs.cpp \ Iteration.cpp \ Verifier.cpp \ StringBuffer.cpp \ diff --git a/js/src/gc/FindSCCs.cpp b/js/src/gc/FindSCCs-inl.h similarity index 55% rename from js/src/gc/FindSCCs.cpp rename to js/src/gc/FindSCCs-inl.h index 505279fe2edfec3274267456279f0bd897b4fa5f..403ed2c1f58c59eee882e2e618ddf999a24a5898 100644 --- a/js/src/gc/FindSCCs.cpp +++ b/js/src/gc/FindSCCs-inl.h @@ -4,14 +4,15 @@ * 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 "FindSCCs.h" - #include "jsfriendapi.h" +#include "gc/FindSCCs.h" + namespace js { namespace gc { -ComponentFinder::ComponentFinder(uintptr_t sl) +template<class Node> +ComponentFinder<Node>::ComponentFinder(uintptr_t sl) : clock(1), stack(NULL), firstComponent(NULL), @@ -21,78 +22,50 @@ ComponentFinder::ComponentFinder(uintptr_t sl) { } -ComponentFinder::~ComponentFinder() +template<class Node> +ComponentFinder<Node>::~ComponentFinder() { JS_ASSERT(!stack); JS_ASSERT(!firstComponent); } +template<class Node> void -ComponentFinder::addNode(GraphNodeBase *v) +ComponentFinder<Node>::addNode(Node *v) { if (v->gcDiscoveryTime == Undefined) { JS_ASSERT(v->gcLowLink == Undefined); - JS_ASSERT(!v->gcNextGraphNode); processNode(v); } } +template<class Node> void -ComponentFinder::checkStackFull() -{ - /* - * Check for exceeding the size of the C stack. - * - * If this happens we give up and return all vertices in one group, by - * pushing them onto the output list with lowLink set to 1. - */ - - if (!stackFull) { - int stackDummy; - if (!JS_CHECK_STACK_SIZE(stackLimit, &stackDummy)) - stackFull = true; - } - - if (stackFull) { - GraphNodeBase *w; - while (stack) { - w = stack; - stack = w->gcNextGraphNode; - - w->gcLowLink = 1; - w->gcNextGraphNode = firstComponent; - firstComponent = w; - } - } -} - -void -ComponentFinder::processNode(GraphNodeBase *v) +ComponentFinder<Node>::processNode(Node *v) { v->gcDiscoveryTime = clock; v->gcLowLink = clock; ++clock; - JS_ASSERT(!v->gcNextGraphNode); v->gcNextGraphNode = stack; stack = v; - checkStackFull(); - if (stackFull) + int stackDummy; + if (stackFull || !JS_CHECK_STACK_SIZE(stackLimit, &stackDummy)) { + stackFull = true; return; + } - GraphNodeBase *old = cur; + Node *old = cur; cur = v; cur->findOutgoingEdges(*this); cur = old; - if (stackFull) { - JS_ASSERT(!stack); + if (stackFull) return; - } if (v->gcLowLink == v->gcDiscoveryTime) { - GraphNodeBase *w; + Node *w; do { JS_ASSERT(stack); w = stack; @@ -110,6 +83,12 @@ ComponentFinder::processNode(GraphNodeBase *v) */ w->gcDiscoveryTime = Finished; + /* Figure out which group we're in. */ + if (firstComponent && firstComponent->gcLowLink == w->gcLowLink) + w->gcNextGraphComponent = firstComponent->gcNextGraphComponent; + else + w->gcNextGraphComponent = firstComponent; + /* * Prepend the component to the beginning of the output list to * reverse the list and achieve the desired order. @@ -120,8 +99,9 @@ ComponentFinder::processNode(GraphNodeBase *v) } } +template<class Node> void -ComponentFinder::addEdgeTo(GraphNodeBase *w) +ComponentFinder<Node>::addEdgeTo(Node *w) { if (w->gcDiscoveryTime == Undefined) { processNode(w); @@ -131,45 +111,44 @@ ComponentFinder::addEdgeTo(GraphNodeBase *w) } } -GraphNodeBase * -ComponentFinder::getResultsList() -{ - JS_ASSERT(!stack); - GraphNodeBase *result = firstComponent; - firstComponent = NULL; - return result; -} - -GraphNodeBase * -ComponentFinder::removeFirstGroup(GraphNodeBase *resultsList) +template<class Node> +Node * +ComponentFinder<Node>::getResultsList() { - /* Remove the first group from resultsList and return the new list head. */ + if (stackFull) { + /* + * All nodes after the stack overflow are in |stack|. Put them all in + * one big component of their own. + */ + Node *firstGoodComponent = firstComponent; + for (Node *v = stack; v; v = stack) { + stack = v->gcNextGraphNode; + v->gcNextGraphComponent = firstGoodComponent; + v->gcNextGraphNode = firstComponent; + firstComponent = v; + } + stackFull = false; + } - JS_ASSERT(resultsList); + JS_ASSERT(!stack); - GraphNodeBase *v = resultsList; - unsigned lowLink = v->gcLowLink; + Node *result = firstComponent; + firstComponent = NULL; - GraphNodeBase *last; - do { + for (Node *v = result; v; v = v->gcNextGraphNode) { v->gcDiscoveryTime = Undefined; v->gcLowLink = Undefined; - last = v; - v = v->gcNextGraphNode; } - while (v && v->gcLowLink == lowLink); - last->gcNextGraphNode = NULL; - return v; + return result; } -void -ComponentFinder::removeAllRemaining(GraphNodeBase *resultsList) +template<class Node> +/* static */ void +ComponentFinder<Node>::mergeCompartmentGroups(Node *first) { - for (GraphNodeBase *v = resultsList; v; v = v->gcNextGraphNode) { - v->gcDiscoveryTime = Undefined; - v->gcLowLink = Undefined; - } + for (Node *v = first; v; v = v->gcNextGraphNode) + v->gcNextGraphComponent = NULL; } } /* namespace gc */ diff --git a/js/src/gc/FindSCCs.h b/js/src/gc/FindSCCs.h index 571f77b737d6585df14fa843b7796e76a422936a..73fb6cbda340f6c4846ff4ff1a6428e2025a6ae9 100644 --- a/js/src/gc/FindSCCs.h +++ b/js/src/gc/FindSCCs.h @@ -12,50 +12,32 @@ namespace js { namespace gc { -class ComponentFinder; - -struct GraphNodeBase { - GraphNodeBase *gcNextGraphNode; +template<class Node> +struct GraphNodeBase +{ + Node *gcNextGraphNode; + Node *gcNextGraphComponent; unsigned gcDiscoveryTime; unsigned gcLowLink; GraphNodeBase() : gcNextGraphNode(NULL), + gcNextGraphComponent(NULL), gcDiscoveryTime(0), gcLowLink(0) {} - virtual ~GraphNodeBase() {} - virtual void findOutgoingEdges(ComponentFinder& finder) = 0; -}; - -template <class T> static T * -NextGraphNode(const T *current) -{ - const GraphNodeBase *node = current; - return static_cast<T *>(node->gcNextGraphNode); -} + ~GraphNodeBase() {} -template <class T> void -AddGraphNode(T *&listHead, T *newFirstNode) -{ - GraphNodeBase *node = newFirstNode; - JS_ASSERT(!node->gcNextGraphNode); - node->gcNextGraphNode = listHead; - listHead = newFirstNode; -} - -template <class T> static T * -RemoveGraphNode(T *&listHead) -{ - GraphNodeBase *node = listHead; - if (!node) + Node *nextNodeInGroup() const { + if (gcNextGraphNode && gcNextGraphNode->gcNextGraphComponent == gcNextGraphComponent) + return gcNextGraphNode; return NULL; + } - T *result = listHead; - listHead = static_cast<T *>(node->gcNextGraphNode); - node->gcNextGraphNode = NULL; - return result; -} + Node *nextGroup() const { + return gcNextGraphComponent; + } +}; /* * Find the strongly connected components of a graph using Tarjan's algorithm, @@ -66,45 +48,35 @@ RemoveGraphNode(T *&listHead) * * struct MyGraphNode : public GraphNodeBase * { - * void findOutgoingEdges(ComponentFinder& finder) + * void findOutgoingEdges(ComponentFinder<MyGraphNode> &finder) * { * for edge in my_outgoing_edges: * if is_relevant(edge): * finder.addEdgeTo(edge.destination) * } * } + * + * ComponentFinder<MyGraphNode> finder; + * finder.addNode(v); */ +template<class Node> class ComponentFinder { public: ComponentFinder(uintptr_t stackLimit); ~ComponentFinder(); - void addNode(GraphNodeBase *v); - GraphNodeBase *getResultsList(); - - template <class T> static T * - getNextGroup(T *&resultsList) { - T *group = resultsList; - if (resultsList) - resultsList = static_cast<T *>(removeFirstGroup(resultsList)); - return group; - } - template <class T> static T * - getAllRemaining(T *&resultsList) { - T *all = resultsList; - removeAllRemaining(resultsList); - resultsList = NULL; - return all; - } + /* Forces all nodes to be added to a single component. */ + void useOneComponent() { stackFull = true; } - private: - static GraphNodeBase *removeFirstGroup(GraphNodeBase *resultsList); - static void removeAllRemaining(GraphNodeBase *resultsList); + void addNode(Node *v); + Node *getResultsList(); + + static void mergeCompartmentGroups(Node *first); public: /* Call from implementation of GraphNodeBase::findOutgoingEdges(). */ - void addEdgeTo(GraphNodeBase *w); + void addEdgeTo(Node *w); private: /* Constant used to indicate an unprocessed vertex. */ @@ -113,14 +85,13 @@ class ComponentFinder /* Constant used to indicate an processed vertex that is no longer on the stack. */ static const unsigned Finished = (unsigned)-1; - void processNode(GraphNodeBase *v); - void checkStackFull(); + void processNode(Node *v); private: unsigned clock; - GraphNodeBase *stack; - GraphNodeBase *firstComponent; - GraphNodeBase *cur; + Node *stack; + Node *firstComponent; + Node *cur; uintptr_t stackLimit; bool stackFull; }; diff --git a/js/src/jsapi-tests/testFindSCCs.cpp b/js/src/jsapi-tests/testFindSCCs.cpp index 8028eac3b26c9388a261fd714108837c89a93079..29188e716400561aa6c20bec7ab693d364340745 100644 --- a/js/src/jsapi-tests/testFindSCCs.cpp +++ b/js/src/jsapi-tests/testFindSCCs.cpp @@ -11,27 +11,30 @@ #include <string.h> #include <stdarg.h> -#include "../gc/FindSCCs.h" #include "jscntxt.h" #include "jsgc.h" +#include "gc/FindSCCs.h" + +#include "gc/FindSCCs-inl.h" + static const unsigned MaxVertices = 10; using js::gc::GraphNodeBase; using js::gc::ComponentFinder; -struct TestNode : public GraphNodeBase +struct TestNode : public GraphNodeBase<TestNode> { unsigned index; bool hasEdge[MaxVertices]; - void findOutgoingEdges(ComponentFinder& finder); + void findOutgoingEdges(ComponentFinder<TestNode> &finder); }; static TestNode Vertex[MaxVertices]; void -TestNode::findOutgoingEdges(ComponentFinder& finder) +TestNode::findOutgoingEdges(ComponentFinder<TestNode> &finder) { for (unsigned i = 0; i < MaxVertices; ++i) { if (hasEdge[i]) @@ -131,8 +134,8 @@ BEGIN_TEST(testFindSCCs) } unsigned vertex_count; -ComponentFinder *finder; -GraphNodeBase *resultsList; +ComponentFinder<TestNode> *finder; +TestNode *resultsList; void setup(unsigned count) { @@ -152,7 +155,7 @@ void edge(unsigned src_index, unsigned dest_index) void run() { - finder = new ComponentFinder(rt->nativeStackLimit); + finder = new ComponentFinder<TestNode>(rt->nativeStackLimit); for (unsigned i = 0; i < vertex_count; ++i) finder->addNode(&Vertex[i]); resultsList = finder->getResultsList(); @@ -160,25 +163,26 @@ void run() bool group(int vertex, ...) { - TestNode *v = (TestNode *)ComponentFinder::getNextGroup(resultsList); + TestNode *v = resultsList; va_list ap; va_start(ap, vertex); while (vertex != -1) { CHECK(v != NULL); CHECK(v->index == unsigned(vertex)); - v = (TestNode *)v->gcNextGraphNode; + v = v->nextNodeInGroup(); vertex = va_arg(ap, int); } va_end(ap); CHECK(v == NULL); + resultsList = resultsList->nextGroup(); return true; } bool remaining(int vertex, ...) { - TestNode *v = (TestNode *)ComponentFinder::getAllRemaining(resultsList); + TestNode *v = resultsList; va_list ap; va_start(ap, vertex); @@ -191,6 +195,7 @@ bool remaining(int vertex, ...) va_end(ap); CHECK(v == NULL); + resultsList = NULL; return true; } @@ -204,7 +209,7 @@ bool end() } END_TEST(testFindSCCs) -struct TestNode2 : public GraphNodeBase +struct TestNode2 : public GraphNodeBase<TestNode2> { TestNode2 *edge; @@ -214,8 +219,7 @@ struct TestNode2 : public GraphNodeBase } void - findOutgoingEdges(ComponentFinder& finder) - { + findOutgoingEdges(ComponentFinder<TestNode2> &finder) { if (edge) finder.addEdgeTo(edge); } @@ -236,27 +240,34 @@ BEGIN_TEST(testFindSCCsStackLimit) * is returned containing all the vertices. */ const unsigned max = 1000000; + const unsigned initial = 10; TestNode2 *vertices = new TestNode2[max](); - for (unsigned i = 0; i < (max - 10); ++i) + for (unsigned i = initial; i < (max - 10); ++i) vertices[i].edge = &vertices[i + 1]; - ComponentFinder finder(rt->nativeStackLimit); + ComponentFinder<TestNode2> finder(rt->nativeStackLimit); for (unsigned i = 0; i < max; ++i) finder.addNode(&vertices[i]); - GraphNodeBase *r = finder.getResultsList(); + TestNode2 *r = finder.getResultsList(); CHECK(r); - GraphNodeBase *v = finder.getNextGroup(r); - CHECK(v); + TestNode2 *v = r; unsigned count = 0; while (v) { ++count; - v = v->gcNextGraphNode; + v = v->nextNodeInGroup(); + } + CHECK(count == max - initial); + + count = 0; + v = r->nextGroup(); + while (v) { + ++count; + CHECK(!v->nextNodeInGroup()); + v = v->nextGroup(); } - CHECK(count == max); - CHECK(finder.getNextGroup(r) == NULL); delete [] vertices; return true; diff --git a/js/src/jsapi.cpp b/js/src/jsapi.cpp index b89096587269a948173cb844cdf7562712167331..e019463e28d625ec81afd1686647a2f4388f6ffe 100644 --- a/js/src/jsapi.cpp +++ b/js/src/jsapi.cpp @@ -801,8 +801,8 @@ JSRuntime::JSRuntime(JSUseHelperThreads useHelperThreads) gcFoundBlackGrayEdges(false), gcSweepingCompartments(NULL), gcCompartmentGroupIndex(0), - gcRemainingCompartmentGroups(NULL), - gcCompartmentGroup(NULL), + gcCompartmentGroups(NULL), + gcCurrentCompartmentGroup(NULL), gcSweepPhase(0), gcSweepCompartment(NULL), gcSweepKindIndex(0), diff --git a/js/src/jscntxt.h b/js/src/jscntxt.h index 462a254c683cfa14d39a74bc030907161373b312..1bea1d1c47974cf3f9ca180cb72bdd7911205de0 100644 --- a/js/src/jscntxt.h +++ b/js/src/jscntxt.h @@ -718,8 +718,8 @@ struct JSRuntime : js::RuntimeFriendFields /* * Incremental sweep state. */ - JSCompartment *gcRemainingCompartmentGroups; - JSCompartment *gcCompartmentGroup; + JSCompartment *gcCompartmentGroups; + JSCompartment *gcCurrentCompartmentGroup; int gcSweepPhase; JSCompartment *gcSweepCompartment; int gcSweepKindIndex; diff --git a/js/src/jscompartment.h b/js/src/jscompartment.h index 8f1460bf053e5abe51340a55a79e101fe8e25389..caa6182040363f6880201cbf81e0c6ed6bcbd33d 100644 --- a/js/src/jscompartment.h +++ b/js/src/jscompartment.h @@ -118,7 +118,7 @@ class AutoDebugModeGC; class DebugScopes; } -struct JSCompartment : public js::gc::GraphNodeBase +struct JSCompartment : public js::gc::GraphNodeBase<JSCompartment> { JSRuntime *rt; JSPrincipals *principals; @@ -425,7 +425,7 @@ struct JSCompartment : public js::gc::GraphNodeBase void sweepCrossCompartmentWrappers(); void purge(); - virtual void findOutgoingEdges(js::gc::ComponentFinder& finder); + void findOutgoingEdges(js::gc::ComponentFinder<JSCompartment> &finder); void setGCLastBytes(size_t lastBytes, size_t lastMallocBytes, js::JSGCInvocationKind gckind); void reduceGCTriggerBytes(size_t amount); diff --git a/js/src/jsgc.cpp b/js/src/jsgc.cpp index ae82b64c98382cbefb594447fdee249a910202ce..6d639ba3d0cfb42c34d8a9bb809597c3777e960e 100644 --- a/js/src/jsgc.cpp +++ b/js/src/jsgc.cpp @@ -74,6 +74,7 @@ #include "builtin/MapObject.h" #include "frontend/Parser.h" +#include "gc/FindSCCs.h" #include "gc/GCInternals.h" #include "gc/Marking.h" #include "gc/Memory.h" @@ -90,11 +91,10 @@ #include "jsinterpinlines.h" #include "jsobjinlines.h" +#include "gc/FindSCCs-inl.h" #include "vm/ScopeObject-inl.h" #include "vm/String-inl.h" -#include "gc/FindSCCs.h" - #ifdef MOZ_VALGRIND # define JS_VALGRIND #endif @@ -2069,29 +2069,26 @@ SweepBackgroundThings(JSRuntime* rt, bool onBackgroundThread) */ FreeOp fop(rt, false); for (int phase = 0 ; phase < BackgroundPhaseCount ; ++phase) { - for (JSCompartment *c = rt->gcSweepingCompartments; c; c = NextGraphNode(c)) { + for (JSCompartment *comp = rt->gcSweepingCompartments; comp; comp = comp->gcNextGraphNode) { for (int index = 0 ; index < BackgroundPhaseLength[phase] ; ++index) { AllocKind kind = BackgroundPhases[phase][index]; - ArenaHeader *arenas = c->arenas.arenaListsToSweep[kind]; - if (arenas) { + ArenaHeader *arenas = comp->arenas.arenaListsToSweep[kind]; + if (arenas) ArenaLists::backgroundFinalize(&fop, arenas, onBackgroundThread); - } } } } - while (rt->gcSweepingCompartments) - RemoveGraphNode(rt->gcSweepingCompartments); + rt->gcSweepingCompartments = NULL; } #ifdef JS_THREADSAFE static void AssertBackgroundSweepingFinished(JSRuntime *rt) { + JS_ASSERT(!rt->gcSweepingCompartments); for (CompartmentsIter c(rt); !c.done(); c.next()) { - JS_ASSERT(!c->gcNextGraphNode); for (unsigned i = 0 ; i < FINALIZE_LIMIT ; ++i) { - JS_ASSERT(!c->gcNextGraphNode); JS_ASSERT(!c->arenas.arenaListsToSweep[i]); JS_ASSERT(c->arenas.doneBackgroundFinalize(AllocKind(i))); } @@ -2760,11 +2757,7 @@ MarkGrayReferences(JSRuntime *rt) gcmarker->setMarkColorBlack(); } -#ifdef DEBUG -static void -ValidateIncrementalMarking(JSRuntime *rt); -#endif - +#if 0 #ifdef DEBUG static void ValidateIncrementalMarking(JSRuntime *rt) @@ -2874,7 +2867,7 @@ ValidateIncrementalMarking(JSRuntime *rt) rt->gcIncrementalState = state; } - +#endif #endif static void @@ -2909,7 +2902,7 @@ DropStringWrappers(JSRuntime *rt) */ void -JSCompartment::findOutgoingEdges(ComponentFinder& finder) +JSCompartment::findOutgoingEdges(ComponentFinder<JSCompartment> &finder) { /* * Any compartment may have a pointer to an atom in the atoms @@ -2959,32 +2952,27 @@ JSCompartment::findOutgoingEdges(ComponentFinder& finder) static void FindCompartmentGroups(JSRuntime *rt) { - JS_ASSERT(!rt->gcRemainingCompartmentGroups); - if (rt->gcIsIncremental) { - ComponentFinder finder(rt->nativeStackLimit); - for (GCCompartmentsIter c(rt); !c.done(); c.next()) { - JS_ASSERT(c->isGCMarking()); - finder.addNode(c); - } - rt->gcRemainingCompartmentGroups = static_cast<JSCompartment *>(finder.getResultsList()); - } else { - for (GCCompartmentsIter c(rt); !c.done(); c.next()) - AddGraphNode(rt->gcRemainingCompartmentGroups, c.get()); + ComponentFinder<JSCompartment> finder(rt->nativeStackLimit); + if (!rt->gcIsIncremental) + finder.useOneComponent(); + + for (GCCompartmentsIter c(rt); !c.done(); c.next()) { + JS_ASSERT(c->isGCMarking()); + finder.addNode(c); } + rt->gcCompartmentGroups = finder.getResultsList(); + rt->gcCurrentCompartmentGroup = rt->gcCompartmentGroups; rt->gcCompartmentGroupIndex = 0; } static void GetNextCompartmentGroup(JSRuntime *rt) { - JS_ASSERT(!rt->gcCompartmentGroup); - if (rt->gcIsIncremental) - rt->gcCompartmentGroup = - ComponentFinder::getNextGroup(rt->gcRemainingCompartmentGroups); - else - rt->gcCompartmentGroup = - ComponentFinder::getAllRemaining(rt->gcRemainingCompartmentGroups); + rt->gcCurrentCompartmentGroup = rt->gcCurrentCompartmentGroup->nextGroup(); ++rt->gcCompartmentGroupIndex; + + if (!rt->gcIsIncremental) + ComponentFinder<JSCompartment>::mergeCompartmentGroups(rt->gcCurrentCompartmentGroup); } /* @@ -3252,11 +3240,6 @@ EndMarkingCompartmentGroup(JSRuntime *rt) c->setGCState(JSCompartment::Mark); } -#ifdef DEBUG - if (rt->gcIsIncremental && rt->gcValidate && rt->gcCompartmentGroupIndex == 0) - ValidateIncrementalMarking(rt); -#endif - JS_ASSERT(rt->gcMarker.isDrained()); } @@ -3264,7 +3247,7 @@ static void BeginSweepingCompartmentGroup(JSRuntime *rt) { /* - * Begin sweeping the group of compartments in gcCompartmentGroup, + * Begin sweeping the group of compartments in gcCurrentCompartmentGroup, * performing actions that must be done before yielding to caller. */ @@ -3346,7 +3329,7 @@ BeginSweepingCompartmentGroup(JSRuntime *rt) #endif rt->gcSweepPhase = 0; - rt->gcSweepCompartment = rt->gcCompartmentGroup; + rt->gcSweepCompartment = rt->gcCurrentCompartmentGroup; rt->gcSweepKindIndex = 0; { @@ -3360,7 +3343,7 @@ static void EndSweepingCompartmentGroup(JSRuntime *rt) { /* Update the GC state for compartments we have swept and unlink the list. */ - while (JSCompartment *c = RemoveGraphNode(rt->gcCompartmentGroup)) { + for (GCCompartmentGroupIter c(rt); !c.done(); c.next()) { JS_ASSERT(c->isGCSweeping()); c->setGCState(JSCompartment::Finished); } @@ -3389,7 +3372,6 @@ BeginSweepPhase(JSRuntime *rt) #endif #ifdef DEBUG - JS_ASSERT(!rt->gcCompartmentGroup); for (CompartmentsIter c(rt); !c.done(); c.next()) { JS_ASSERT(!c->gcIncomingGrayPointers); for (JSCompartment::WrapperEnum e(c); !e.empty(); e.popFront()) { @@ -3401,7 +3383,6 @@ BeginSweepPhase(JSRuntime *rt) DropStringWrappers(rt); FindCompartmentGroups(rt); - GetNextCompartmentGroup(rt); EndMarkingCompartmentGroup(rt); BeginSweepingCompartmentGroup(rt); } @@ -3439,26 +3420,26 @@ SweepPhase(JSRuntime *rt, SliceBudget &sliceBudget) gcstats::AutoPhase ap(rt->gcStats, FinalizePhaseStatsPhase[rt->gcSweepPhase]); for (; rt->gcSweepCompartment; - rt->gcSweepCompartment = NextGraphNode(rt->gcSweepCompartment)) - { - JSCompartment *c = rt->gcSweepCompartment; + rt->gcSweepCompartment = rt->gcSweepCompartment->nextNodeInGroup()) + { + JSCompartment *c = rt->gcSweepCompartment; - while (rt->gcSweepKindIndex < FinalizePhaseLength[rt->gcSweepPhase]) { - AllocKind kind = FinalizePhases[rt->gcSweepPhase][rt->gcSweepKindIndex]; + while (rt->gcSweepKindIndex < FinalizePhaseLength[rt->gcSweepPhase]) { + AllocKind kind = FinalizePhases[rt->gcSweepPhase][rt->gcSweepKindIndex]; - if (!c->arenas.foregroundFinalize(&fop, kind, sliceBudget)) - return false; /* Yield to the mutator. */ + if (!c->arenas.foregroundFinalize(&fop, kind, sliceBudget)) + return false; /* Yield to the mutator. */ - ++rt->gcSweepKindIndex; - } - rt->gcSweepKindIndex = 0; + ++rt->gcSweepKindIndex; } - rt->gcSweepCompartment = rt->gcCompartmentGroup; + rt->gcSweepKindIndex = 0; + } + rt->gcSweepCompartment = rt->gcCurrentCompartmentGroup; } EndSweepingCompartmentGroup(rt); GetNextCompartmentGroup(rt); - if (!rt->gcCompartmentGroup) + if (!rt->gcCurrentCompartmentGroup) return true; /* We're finished. */ EndMarkingCompartmentGroup(rt); BeginSweepingCompartmentGroup(rt); @@ -3548,8 +3529,10 @@ EndSweepPhase(JSRuntime *rt, JSGCInvocationKind gckind, bool lastGC) /* Set up list of compartments for sweeping of background things. */ JS_ASSERT(!rt->gcSweepingCompartments); - for (GCCompartmentsIter c(rt); !c.done(); c.next()) - AddGraphNode(rt->gcSweepingCompartments, c.get()); + for (GCCompartmentsIter c(rt); !c.done(); c.next()) { + c->gcNextGraphNode = rt->gcSweepingCompartments; + rt->gcSweepingCompartments = c; + } /* If not sweeping on background thread then we must do it here. */ if (!rt->gcSweepOnBackgroundThread) { @@ -3719,7 +3702,6 @@ ResetIncrementalGC(JSRuntime *rt, const char *reason) for (GCCompartmentsIter c(rt); !c.done(); c.next()) { JS_ASSERT(c->isCollecting()); JS_ASSERT(!c->needsBarrier()); - JS_ASSERT(!NextGraphNode(c.get())); JS_ASSERT(!c->gcLiveArrayBuffers); for (unsigned i = 0 ; i < FINALIZE_LIMIT ; ++i) JS_ASSERT(!c->arenas.arenaListsToSweep[i]); diff --git a/js/src/jsgcinlines.h b/js/src/jsgcinlines.h index 7aea3e58c68e8be18a6a5c034f122417ed912fad..71303f28db603a383c2f2a47129f10c96200cd2f 100644 --- a/js/src/jsgcinlines.h +++ b/js/src/jsgcinlines.h @@ -451,6 +451,7 @@ class GCCompartmentsIter { JSCompartment *operator->() const { return get(); } }; +/* Iterates over all compartments in the current compartment group. */ class GCCompartmentGroupIter { private: JSCompartment *current; @@ -458,14 +459,14 @@ class GCCompartmentGroupIter { public: GCCompartmentGroupIter(JSRuntime *rt) { JS_ASSERT(rt->isHeapBusy()); - current = rt->gcCompartmentGroup; + current = rt->gcCurrentCompartmentGroup; } - bool done() const { return current == NULL; } + bool done() const { return !current; } void next() { JS_ASSERT(!done()); - current = NextGraphNode(current); + current = current->nextNodeInGroup(); } JSCompartment *get() const { diff --git a/js/src/vm/Debugger.cpp b/js/src/vm/Debugger.cpp index 17af3b65f53bbd4368fa7691d615c2a2de8b9545..363aca9af5c1213f3836764a813ab23ddbb62865 100644 --- a/js/src/vm/Debugger.cpp +++ b/js/src/vm/Debugger.cpp @@ -24,6 +24,7 @@ #include "methodjit/Retcon.h" #include "js/Vector.h" +#include "gc/FindSCCs-inl.h" #include "vm/Stack-inl.h" using namespace js; @@ -1560,7 +1561,7 @@ Debugger::detachAllDebuggersFromGlobal(FreeOp *fop, GlobalObject *global, } /* static */ void -Debugger::findCompartmentEdges(JSCompartment *comp, js::gc::ComponentFinder &finder) +Debugger::findCompartmentEdges(JSCompartment *comp, js::gc::ComponentFinder<JSCompartment> &finder) { /* * For debugger cross compartment wrappers, add edges in the opposite @@ -1574,7 +1575,8 @@ Debugger::findCompartmentEdges(JSCompartment *comp, js::gc::ComponentFinder &fin continue; if (dbg->scripts.hasKeyInCompartment(comp) || dbg->objects.hasKeyInCompartment(comp) || - dbg->environments.hasKeyInCompartment(comp)) { + dbg->environments.hasKeyInCompartment(comp)) + { finder.addEdgeTo(w); } } diff --git a/js/src/vm/Debugger.h b/js/src/vm/Debugger.h index 9450159b5b13d5b791721c09ee6fff492690ecc4..e07bb5df0d0d96f58f0841a2884c3509e3ed2f2a 100644 --- a/js/src/vm/Debugger.h +++ b/js/src/vm/Debugger.h @@ -378,7 +378,7 @@ class Debugger : private mozilla::LinkedListElement<Debugger> GlobalObjectSet::Enum *compartmentEnum); static unsigned gcGrayLinkSlot(); static bool isDebugWrapper(RawObject o); - static void findCompartmentEdges(JSCompartment *v, js::gc::ComponentFinder &finder); + static void findCompartmentEdges(JSCompartment *v, gc::ComponentFinder<JSCompartment> &finder); static inline JSTrapStatus onEnterFrame(JSContext *cx, Value *vp); static inline bool onLeaveFrame(JSContext *cx, bool ok);