mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
Bug 708382 - GC marking - merging string and object stacks. r=wmccloskey
--HG-- extra : rebase_source : ca47672218af276ed0bbdfd53add6207c524179b
This commit is contained in:
parent
a83337c3b7
commit
f902c0a6df
@ -439,7 +439,6 @@ struct JSRuntime
|
||||
|
||||
/* Pre-allocated space for the GC mark stacks. Pointer type ensures alignment. */
|
||||
void *gcMarkStackObjs[js::OBJECT_MARK_STACK_SIZE / sizeof(void *)];
|
||||
void *gcMarkStackRopes[js::ROPES_MARK_STACK_SIZE / sizeof(void *)];
|
||||
void *gcMarkStackTypes[js::TYPE_MARK_STACK_SIZE / sizeof(void *)];
|
||||
void *gcMarkStackXMLs[js::XML_MARK_STACK_SIZE / sizeof(void *)];
|
||||
void *gcMarkStackLarges[js::LARGE_MARK_STACK_SIZE / sizeof(void *)];
|
||||
|
@ -1736,7 +1736,6 @@ GCMarker::GCMarker(JSContext *cx)
|
||||
: color(BLACK),
|
||||
unmarkedArenaStackTop(NULL),
|
||||
objStack(cx->runtime->gcMarkStackObjs, sizeof(cx->runtime->gcMarkStackObjs)),
|
||||
ropeStack(cx->runtime->gcMarkStackRopes, sizeof(cx->runtime->gcMarkStackRopes)),
|
||||
typeStack(cx->runtime->gcMarkStackTypes, sizeof(cx->runtime->gcMarkStackTypes)),
|
||||
xmlStack(cx->runtime->gcMarkStackXMLs, sizeof(cx->runtime->gcMarkStackXMLs)),
|
||||
largeStack(cx->runtime->gcMarkStackLarges, sizeof(cx->runtime->gcMarkStackLarges))
|
||||
|
@ -1631,7 +1631,6 @@ struct LargeMarkItem
|
||||
};
|
||||
|
||||
static const size_t OBJECT_MARK_STACK_SIZE = 32768 * sizeof(JSObject *);
|
||||
static const size_t ROPES_MARK_STACK_SIZE = 1024 * sizeof(JSString *);
|
||||
static const size_t XML_MARK_STACK_SIZE = 1024 * sizeof(JSXML *);
|
||||
static const size_t TYPE_MARK_STACK_SIZE = 1024 * sizeof(types::TypeObject *);
|
||||
static const size_t LARGE_MARK_STACK_SIZE = 64 * sizeof(LargeMarkItem);
|
||||
@ -1654,8 +1653,7 @@ struct GCMarker : public JSTracer {
|
||||
void dumpConservativeRoots();
|
||||
#endif
|
||||
|
||||
MarkStack<JSObject *> objStack;
|
||||
MarkStack<JSRope *> ropeStack;
|
||||
MarkStack<void *> objStack;
|
||||
MarkStack<types::TypeObject *> typeStack;
|
||||
MarkStack<JSXML *> xmlStack;
|
||||
MarkStack<LargeMarkItem> largeStack;
|
||||
@ -1687,7 +1685,6 @@ struct GCMarker : public JSTracer {
|
||||
|
||||
bool isMarkStackEmpty() {
|
||||
return objStack.isEmpty() &&
|
||||
ropeStack.isEmpty() &&
|
||||
typeStack.isEmpty() &&
|
||||
xmlStack.isEmpty() &&
|
||||
largeStack.isEmpty();
|
||||
@ -1700,11 +1697,6 @@ struct GCMarker : public JSTracer {
|
||||
delayMarkingChildren(obj);
|
||||
}
|
||||
|
||||
void pushRope(JSRope *rope) {
|
||||
if (!ropeStack.push(rope))
|
||||
delayMarkingChildren(rope);
|
||||
}
|
||||
|
||||
void pushType(types::TypeObject *type) {
|
||||
if (!typeStack.push(type))
|
||||
delayMarkingChildren(type);
|
||||
|
@ -732,11 +732,22 @@ ScanLinearString(GCMarker *gcmarker, JSLinearString *str)
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* The function tries to scan the whole rope tree using the marking stack as
|
||||
* temporary storage. If that becomes full, the unscanned ropes are added to
|
||||
* the delayed marking list. When the function returns, the marking stack is
|
||||
* at the same depth as it was on entry.
|
||||
*
|
||||
* The function relies on the fact that a rope can only point to other ropes or
|
||||
* linear strings, it cannot refer to other GC things of other types.
|
||||
*/
|
||||
static void
|
||||
ScanRope(GCMarker *gcmarker, JSRope *rope)
|
||||
{
|
||||
JS_ASSERT(rope->JSString::isRope());
|
||||
do {
|
||||
unsigned savedTos = gcmarker->objStack.tos;
|
||||
for (;;) {
|
||||
JS_ASSERT(GetGCThingTraceKind(rope) == JSTRACE_STRING);
|
||||
JS_ASSERT(rope->JSString::isRope());
|
||||
JS_COMPARTMENT_ASSERT_STR(gcmarker->runtime, rope);
|
||||
JS_ASSERT(rope->isMarked());
|
||||
JSRope *next = NULL;
|
||||
@ -755,16 +766,33 @@ ScanRope(GCMarker *gcmarker, JSRope *rope)
|
||||
ScanLinearString(gcmarker, &left->asLinear());
|
||||
} else {
|
||||
/*
|
||||
* Both children are ropes, set aside the right one to scan
|
||||
* it later.
|
||||
* When both children are ropes, set aside the right one to
|
||||
* scan it later.
|
||||
*/
|
||||
if (next)
|
||||
gcmarker->pushRope(next);
|
||||
if (next && !gcmarker->objStack.push(next))
|
||||
gcmarker->delayMarkingChildren(next);
|
||||
next = &left->asRope();
|
||||
}
|
||||
}
|
||||
rope = next;
|
||||
} while (rope);
|
||||
if (next) {
|
||||
rope = next;
|
||||
} else if (savedTos != gcmarker->objStack.tos) {
|
||||
JS_ASSERT(savedTos < gcmarker->objStack.tos);
|
||||
rope = static_cast<JSRope *>(gcmarker->objStack.pop());
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
JS_ASSERT(savedTos == gcmarker->objStack.tos);
|
||||
}
|
||||
|
||||
static inline void
|
||||
ScanString(GCMarker *gcmarker, JSString *str)
|
||||
{
|
||||
if (str->isLinear())
|
||||
ScanLinearString(gcmarker, &str->asLinear());
|
||||
else
|
||||
ScanRope(gcmarker, &str->asRope());
|
||||
}
|
||||
|
||||
static inline void
|
||||
@ -773,15 +801,12 @@ PushMarkStack(GCMarker *gcmarker, JSString *str)
|
||||
JS_COMPARTMENT_ASSERT_STR(gcmarker->runtime, str);
|
||||
|
||||
/*
|
||||
* We scan the string directly rather than pushing on the stack except
|
||||
* when we have a rope and both its children are also ropes.
|
||||
* As string can only refer to other strings we fully scan its GC graph
|
||||
* using the explicit stack when navigating the rope tree to avoid
|
||||
* dealing with strings on the stack in drainMarkStack.
|
||||
*/
|
||||
if (str->markIfUnmarked()) {
|
||||
if (str->isLinear())
|
||||
ScanLinearString(gcmarker, &str->asLinear());
|
||||
else
|
||||
ScanRope(gcmarker, &str->asRope());
|
||||
}
|
||||
if (str->markIfUnmarked())
|
||||
ScanString(gcmarker, str);
|
||||
}
|
||||
|
||||
static const uintN LARGE_OBJECT_CHUNK_SIZE = 2048;
|
||||
@ -1053,11 +1078,8 @@ GCMarker::drainMarkStack()
|
||||
rt->gcCheckCompartment = rt->gcCurrentCompartment;
|
||||
|
||||
while (!isMarkStackEmpty()) {
|
||||
while (!ropeStack.isEmpty())
|
||||
ScanRope(this, ropeStack.pop());
|
||||
|
||||
while (!objStack.isEmpty())
|
||||
ScanObject(this, objStack.pop());
|
||||
ScanObject(this, static_cast<JSObject *>(objStack.pop()));
|
||||
|
||||
while (!typeStack.isEmpty())
|
||||
ScanTypeObject(this, typeStack.pop());
|
||||
|
Loading…
Reference in New Issue
Block a user