Bug 921224 (part 2) - Use a smaller mark stack when incremental GC is disabled. r=wmccloskey.

--HG--
extra : rebase_source : 86fdb1f981db31751f07a1e2c367caa31637cc5a
This commit is contained in:
Nicholas Nethercote 2013-11-14 18:43:13 -08:00
parent 7e277cbf48
commit dcebcaee1d
10 changed files with 57 additions and 23 deletions

View File

@ -363,8 +363,8 @@ InternalConst(JSContext *cx, unsigned argc, jsval *vp)
if (!flat)
return false;
if (JS_FlatStringEqualsAscii(flat, "MARK_STACK_LENGTH")) {
vp[0] = UINT_TO_JSVAL(js::MARK_STACK_LENGTH);
if (JS_FlatStringEqualsAscii(flat, "INCREMENTAL_MARK_STACK_BASE_CAPACITY")) {
vp[0] = UINT_TO_JSVAL(js::INCREMENTAL_MARK_STACK_BASE_CAPACITY);
} else {
JS_ReportError(cx, "unknown const name");
return false;

View File

@ -1474,7 +1474,7 @@ GCMarker::processMarkStackTop(SliceBudget &budget)
/* Call the trace hook if necessary. */
const Class *clasp = type->clasp;
if (clasp->trace) {
JS_ASSERT_IF(runtime->gcMode == JSGC_MODE_INCREMENTAL &&
JS_ASSERT_IF(runtime->gcMode() == JSGC_MODE_INCREMENTAL &&
runtime->gcIncrementalEnabled,
clasp->flags & JSCLASS_IMPLEMENTS_BARRIERS);
clasp->trace(this, obj);

View File

@ -5,7 +5,7 @@ function build_getter(i) {
function test()
{
var N = internalConst("MARK_STACK_LENGTH") + 2;
var N = internalConst("INCREMENTAL_MARK_STACK_BASE_CAPACITY") + 2;
var o = {};
var descriptor = { enumerable: true};
for (var i = 0; i != N; ++i) {

View File

@ -2067,10 +2067,10 @@ JS_SetGCParameter(JSRuntime *rt, JSGCParamKey key, uint32_t value)
break;
default:
JS_ASSERT(key == JSGC_MODE);
rt->gcMode = JSGCMode(value);
JS_ASSERT(rt->gcMode == JSGC_MODE_GLOBAL ||
rt->gcMode == JSGC_MODE_COMPARTMENT ||
rt->gcMode == JSGC_MODE_INCREMENTAL);
rt->setGCMode(JSGCMode(value));
JS_ASSERT(rt->gcMode() == JSGC_MODE_GLOBAL ||
rt->gcMode() == JSGC_MODE_COMPARTMENT ||
rt->gcMode() == JSGC_MODE_INCREMENTAL);
return;
}
}
@ -2086,7 +2086,7 @@ JS_GetGCParameter(JSRuntime *rt, JSGCParamKey key)
case JSGC_BYTES:
return uint32_t(rt->gcBytes);
case JSGC_MODE:
return uint32_t(rt->gcMode);
return uint32_t(rt->gcMode());
case JSGC_UNUSED_CHUNKS:
return uint32_t(rt->gcChunkPool.getEmptyCount());
case JSGC_TOTAL_CHUNKS:

View File

@ -901,7 +901,7 @@ JS::NotifyDidPaint(JSRuntime *rt)
JS_FRIEND_API(bool)
JS::IsIncrementalGCEnabled(JSRuntime *rt)
{
return rt->gcIncrementalEnabled && rt->gcMode == JSGC_MODE_INCREMENTAL;
return rt->gcIncrementalEnabled && rt->gcMode() == JSGC_MODE_INCREMENTAL;
}
JS_FRIEND_API(bool)

View File

@ -1676,9 +1676,9 @@ GCMarker::GCMarker(JSRuntime *rt)
}
bool
GCMarker::init()
GCMarker::init(JSGCMode gcMode)
{
return stack.init(MARK_STACK_LENGTH);
return stack.init(gcMode);
}
void
@ -4550,7 +4550,7 @@ BudgetIncrementalGC(JSRuntime *rt, int64_t *budget)
return;
}
if (rt->gcMode != JSGC_MODE_INCREMENTAL) {
if (rt->gcMode() != JSGC_MODE_INCREMENTAL) {
ResetIncrementalGC(rt, "GC mode change");
*budget = SliceBudget::Unlimited;
rt->gcStats.nonincremental("GC mode");
@ -4741,7 +4741,7 @@ Collect(JSRuntime *rt, bool incremental, int64_t budget,
int compartmentCount = 0;
int collectedCount = 0;
for (ZonesIter zone(rt, WithAtoms); !zone.done(); zone.next()) {
if (rt->gcMode == JSGC_MODE_GLOBAL)
if (rt->gcMode() == JSGC_MODE_GLOBAL)
zone->scheduleGC();
/* This is a heuristic to avoid resets. */

View File

@ -908,6 +908,9 @@ struct GCChunkHasher {
typedef HashSet<js::gc::Chunk *, GCChunkHasher, SystemAllocPolicy> GCChunkSet;
static const size_t NON_INCREMENTAL_MARK_STACK_BASE_CAPACITY = 4096;
static const size_t INCREMENTAL_MARK_STACK_BASE_CAPACITY = 32768;
template<class T>
struct MarkStack {
T *stack_;
@ -940,10 +943,25 @@ struct MarkStack {
end_ = stack + capacity;
}
bool init(size_t baseCapacity) {
baseCapacity_ = baseCapacity;
void setBaseCapacity(JSGCMode mode) {
switch (mode) {
case JSGC_MODE_GLOBAL:
case JSGC_MODE_COMPARTMENT:
baseCapacity_ = NON_INCREMENTAL_MARK_STACK_BASE_CAPACITY;
break;
case JSGC_MODE_INCREMENTAL:
baseCapacity_ = INCREMENTAL_MARK_STACK_BASE_CAPACITY;
break;
default:
MOZ_ASSUME_UNREACHABLE("bad gc mode");
}
if (baseCapacity_ > maxCapacity_)
baseCapacity_ = maxCapacity_;
}
bool init(JSGCMode gcMode) {
setBaseCapacity(gcMode);
JS_ASSERT(!stack_);
T *newStack = js_pod_malloc<T>(baseCapacity_);
@ -1032,6 +1050,12 @@ struct MarkStack {
return true;
}
void setGCMode(JSGCMode gcMode) {
// The mark stack won't be resized until the next call to reset(), but
// that will happen at the end of the next GC.
setBaseCapacity(gcMode);
}
size_t sizeOfExcludingThis(mozilla::MallocSizeOf mallocSizeOf) const {
return mallocSizeOf(stack_);
}
@ -1077,8 +1101,6 @@ struct SliceBudget {
}
};
static const size_t MARK_STACK_LENGTH = 32768;
struct GrayRoot {
void *thing;
JSGCTraceKind kind;
@ -1119,7 +1141,7 @@ struct GCMarker : public JSTracer {
public:
explicit GCMarker(JSRuntime *rt);
bool init();
bool init(JSGCMode gcMode);
void setMaxCapacity(size_t maxCap) { stack.setMaxCapacity(maxCap); }
size_t maxCapacity() const { return stack.maxCapacity_; }
@ -1198,6 +1220,8 @@ struct GCMarker : public JSTracer {
static void GrayCallback(JSTracer *trc, void **thing, JSGCTraceKind kind);
void setGCMode(JSGCMode mode) { stack.setGCMode(mode); }
size_t sizeOfExcludingThis(mozilla::MallocSizeOf mallocSizeOf) const;
MarkStack<uintptr_t> stack;

View File

@ -1301,7 +1301,7 @@ NewObject(ExclusiveContext *cx, const Class *clasp, types::TypeObject *type_, JS
rt->gcIncrementalEnabled = false;
#ifdef DEBUG
if (rt->gcMode == JSGC_MODE_INCREMENTAL) {
if (rt->gcMode() == JSGC_MODE_INCREMENTAL) {
fprintf(stderr,
"The class %s has a trace hook but does not declare the\n"
"JSCLASS_IMPLEMENTS_BARRIERS flag. Please ensure that it correctly\n"

View File

@ -168,7 +168,6 @@ JSRuntime::JSRuntime(JSUseHelperThreads useHelperThreads)
gcNextFullGCTime(0),
gcLastGCTime(0),
gcJitReleaseTime(0),
gcMode(JSGC_MODE_GLOBAL),
gcAllocationThreshold(30 * 1024 * 1024),
gcHighFrequencyGC(false),
gcHighFrequencyTimeThreshold(1000),
@ -294,6 +293,8 @@ JSRuntime::JSRuntime(JSUseHelperThreads useHelperThreads)
{
liveRuntimesCount++;
setGCMode(JSGC_MODE_GLOBAL);
/* Initialize infallibly first, so we can goto bad and JS_DestroyRuntime. */
JS_INIT_CLIST(&onNewGlobalObjectWatchers);
@ -355,7 +356,7 @@ JSRuntime::init(uint32_t maxbytes)
if (!js_InitGC(this, maxbytes))
return false;
if (!gcMarker.init())
if (!gcMarker.init(gcMode()))
return false;
const char *size = getenv("JSGC_MARK_STACK_LIMIT");

View File

@ -1015,7 +1015,16 @@ struct JSRuntime : public JS::shadow::Runtime,
int64_t gcNextFullGCTime;
int64_t gcLastGCTime;
int64_t gcJitReleaseTime;
JSGCMode gcMode;
private:
JSGCMode gcMode_;
public:
JSGCMode gcMode() const { return gcMode_; }
void setGCMode(JSGCMode mode) {
gcMode_ = mode;
gcMarker.setGCMode(mode);
}
size_t gcAllocationThreshold;
bool gcHighFrequencyGC;
uint64_t gcHighFrequencyTimeThreshold;