diff --git a/js/src/jsapi-tests/Makefile.in b/js/src/jsapi-tests/Makefile.in index 8d4d9496957..22f317ebbf0 100644 --- a/js/src/jsapi-tests/Makefile.in +++ b/js/src/jsapi-tests/Makefile.in @@ -48,7 +48,6 @@ PROGRAM = jsapi-tests$(BIN_SUFFIX) CPPSRCS = \ tests.cpp \ selfTest.cpp \ - testConservativeGC.cpp \ testContexts.cpp \ testDebugger.cpp \ testDefineGetterSetterNonEnumerable.cpp \ diff --git a/js/src/jsapi-tests/testConservativeGC.cpp b/js/src/jsapi-tests/testConservativeGC.cpp deleted file mode 100644 index 6c3d0913b71..00000000000 --- a/js/src/jsapi-tests/testConservativeGC.cpp +++ /dev/null @@ -1,59 +0,0 @@ -#include "tests.h" -#include "jsobj.h" -#include "jsstr.h" - -BEGIN_TEST(testConservativeGC) -{ - jsval v1; - EVAL("Math.sqrt(42);", &v1); - CHECK(JSVAL_IS_DOUBLE(v1)); - double numCopy = *JSVAL_TO_DOUBLE(v1); - - jsval v2; - EVAL("({foo: 'bar'});", &v2); - CHECK(JSVAL_IS_OBJECT(v2)); - JSObject objCopy = *JSVAL_TO_OBJECT(v2); - - jsval v3; - EVAL("String(Math.PI);", &v3); - CHECK(JSVAL_IS_STRING(v3)); - JSString strCopy = *JSVAL_TO_STRING(v3); - - jsval tmp; - EVAL("Math.sqrt(41);", &tmp); - CHECK(JSVAL_IS_DOUBLE(tmp)); - jsdouble *num2 = JSVAL_TO_DOUBLE(tmp); - jsdouble num2Copy = *num2; - - EVAL("({foo2: 'bar2'});", &tmp); - CHECK(JSVAL_IS_OBJECT(tmp)); - JSObject *obj2 = JSVAL_TO_OBJECT(tmp); - JSObject obj2Copy = *obj2; - - EVAL("String(Math.sqrt(3));", &tmp); - CHECK(JSVAL_IS_STRING(tmp)); - JSString *str2 = JSVAL_TO_STRING(tmp); - JSString str2Copy = *str2; - - tmp = JSVAL_NULL; - - JS_GC(cx); - - EVAL("var a = [];\n" - "for (var i = 0; i != 10000; ++i) {\n" - "a.push(i + 0.1, [1, 2], String(Math.sqrt(i)));\n" - "}", &tmp); - - JS_GC(cx); - - CHECK(numCopy == *JSVAL_TO_DOUBLE(v1)); - CHECK(!memcmp(&objCopy, JSVAL_TO_OBJECT(v2), sizeof(objCopy))); - CHECK(!memcmp(&strCopy, JSVAL_TO_STRING(v3), sizeof(strCopy))); - - CHECK(num2Copy == *num2); - CHECK(!memcmp(&obj2Copy, obj2, sizeof(obj2Copy))); - CHECK(!memcmp(&str2Copy, str2, sizeof(str2Copy))); - - return true; -} -END_TEST(testConservativeGC) diff --git a/js/src/jsapi-tests/testIsAboutToBeFinalized.cpp b/js/src/jsapi-tests/testIsAboutToBeFinalized.cpp index c6f1c27a2a7..6d0c31200e0 100644 --- a/js/src/jsapi-tests/testIsAboutToBeFinalized.cpp +++ b/js/src/jsapi-tests/testIsAboutToBeFinalized.cpp @@ -5,7 +5,6 @@ static JSGCCallback oldGCCallback; static void **checkPointers; static jsuint checkPointersLength; -static size_t checkPointersStaticStrings; static JSBool TestAboutToBeFinalizedCallback(JSContext *cx, JSGCStatus status) @@ -22,54 +21,7 @@ TestAboutToBeFinalizedCallback(JSContext *cx, JSGCStatus status) return !oldGCCallback || oldGCCallback(cx, status); } -static JS_NEVER_INLINE size_t -NativeFrameCleaner() -{ - char buffer[1 << 16]; - memset(buffer, 0, sizeof buffer); - size_t count = 0; - for (size_t i = 0; i != sizeof buffer; ++i) { - if (buffer[i]) - count++; - } - return count; -} - BEGIN_TEST(testIsAboutToBeFinalized_bug528645) -{ - /* - * Due to the conservative GC we use separated never-inline function to - * test rooted elements. - */ - createAndTestRooted(); - NativeFrameCleaner(); - - JS_GC(cx); - - /* Everything is unrooted except unit strings. */ - for (jsuint i = 0; i != checkPointersLength; ++i) { - void *p = checkPointers[i]; - if (p) { - CHECK(JSString::isStatic(p)); - CHECK(checkPointersStaticStrings != 0); - --checkPointersStaticStrings; - } - } - CHECK(checkPointersStaticStrings == 0); - - free(checkPointers); - checkPointers = NULL; - JS_SetGCCallback(cx, oldGCCallback); - - return true; -} - -JS_NEVER_INLINE bool createAndTestRooted(); - -END_TEST(testIsAboutToBeFinalized_bug528645) - -JS_NEVER_INLINE bool -cls_testIsAboutToBeFinalized_bug528645::createAndTestRooted() { jsvalRoot root(cx); @@ -88,22 +40,23 @@ cls_testIsAboutToBeFinalized_bug528645::createAndTestRooted() JSBool ok = JS_GetArrayLength(cx, array, &checkPointersLength); CHECK(ok); - checkPointers = (void **) malloc(sizeof(void *) * checkPointersLength); - CHECK(checkPointers); + void **elems = (void **) malloc(sizeof(void *) * checkPointersLength); + CHECK(elems); - checkPointersStaticStrings = 0; + size_t staticStrings = 0; for (jsuint i = 0; i != checkPointersLength; ++i) { jsval v; ok = JS_GetElement(cx, array, i, &v); CHECK(ok); JS_ASSERT(JSVAL_IS_GCTHING(v)); JS_ASSERT(!JSVAL_IS_NULL(v)); - checkPointers[i] = JSVAL_TO_GCTHING(v); - if (JSString::isStatic(checkPointers[i])) - ++checkPointersStaticStrings; + elems[i] = JSVAL_TO_GCTHING(v); + if (JSString::isStatic(elems[i])) + ++staticStrings; } oldGCCallback = JS_SetGCCallback(cx, TestAboutToBeFinalizedCallback); + checkPointers = elems; JS_GC(cx); /* @@ -112,5 +65,25 @@ cls_testIsAboutToBeFinalized_bug528645::createAndTestRooted() */ for (jsuint i = 0; i != checkPointersLength; ++i) CHECK(checkPointers[i]); -} + root = JSVAL_NULL; + JS_GC(cx); + + /* Everything is unrooted except unit strings. */ + for (jsuint i = 0; i != checkPointersLength; ++i) { + void *p = checkPointers[i]; + if (p) { + CHECK(JSString::isStatic(p)); + CHECK(staticStrings != 0); + --staticStrings; + } + } + CHECK(staticStrings == 0); + + checkPointers = NULL; + JS_SetGCCallback(cx, oldGCCallback); + free(elems); + + return true; +} +END_TEST(testIsAboutToBeFinalized_bug528645) diff --git a/js/src/jsapi.cpp b/js/src/jsapi.cpp index 073bfdfbdc5..dd1f50fb46e 100644 --- a/js/src/jsapi.cpp +++ b/js/src/jsapi.cpp @@ -842,16 +842,11 @@ JS_SuspendRequest(JSContext *cx) { #ifdef JS_THREADSAFE jsrefcount saveDepth = cx->requestDepth; - if (saveDepth == 0) - return 0; - do { + while (cx->requestDepth) { cx->outstandingRequests++; /* compensate for JS_EndRequest */ JS_EndRequest(cx); - } while (cx->requestDepth); - - JS_THREAD_DATA(cx)->conservativeGC.enable(); - + } return saveDepth; #else return 0; @@ -862,16 +857,11 @@ JS_PUBLIC_API(void) JS_ResumeRequest(JSContext *cx, jsrefcount saveDepth) { #ifdef JS_THREADSAFE - if (saveDepth == 0) - return; - - JS_THREAD_DATA(cx)->conservativeGC.disable(); - - JS_ASSERT(cx->outstandingRequests != 0); - do { + JS_ASSERT(!cx->requestDepth); + while (--saveDepth >= 0) { JS_BeginRequest(cx); cx->outstandingRequests--; /* compensate for JS_BeginRequest */ - } while (--saveDepth != 0); + } #endif } diff --git a/js/src/jscntxt.cpp b/js/src/jscntxt.cpp index 88234b3a039..d905d040e67 100644 --- a/js/src/jscntxt.cpp +++ b/js/src/jscntxt.cpp @@ -61,7 +61,6 @@ #include "jsiter.h" #include "jslock.h" #include "jsmath.h" -#include "jsnativestack.h" #include "jsnum.h" #include "jsobj.h" #include "jsopcode.h" @@ -72,6 +71,7 @@ #include "jsstaticcheck.h" #include "jsstr.h" #include "jstracer.h" +#include "jsnativestack.h" #include "jscntxtinlines.h" @@ -524,7 +524,6 @@ JSThreadData::finish() for (size_t i = 0; i != JS_ARRAY_LENGTH(scriptsToGC); ++i) JS_ASSERT(!scriptsToGC[i]); JS_ASSERT(!localRootStack); - JS_ASSERT(conservativeGC.enableCount == 0); #endif if (dtoaState) diff --git a/js/src/jscntxt.h b/js/src/jscntxt.h index 5bfc7d799f0..504e400a93c 100644 --- a/js/src/jscntxt.h +++ b/js/src/jscntxt.h @@ -1033,8 +1033,6 @@ struct JSThreadData { /* Base address of the native stack for the current thread. */ jsuword *nativeStackBase; - js::ConservativeGCThreadData conservativeGC; - bool init(); void finish(); void mark(JSTracer *trc); diff --git a/js/src/jsgc.cpp b/js/src/jsgc.cpp index 9d7245c06b5..23d75fca14b 100644 --- a/js/src/jsgc.cpp +++ b/js/src/jsgc.cpp @@ -809,14 +809,6 @@ GetFinalizableArenaTraceKind(JSGCArenaInfo *ainfo) return GetFinalizableTraceKind(ainfo->list->thingKind); } -static inline size_t -GetArenaTraceKind(JSGCArenaInfo *ainfo) -{ - if (!ainfo->list) - return JSTRACE_DOUBLE; - return GetFinalizableArenaTraceKind(ainfo); -} - static inline size_t GetFinalizableThingTraceKind(void *thing) { @@ -874,7 +866,9 @@ js_GetGCThingTraceKind(void *thing) return JSTRACE_STRING; JSGCArenaInfo *ainfo = JSGCArenaInfo::fromGCThing(thing); - return GetArenaTraceKind(ainfo); + if (!ainfo->list) + return JSTRACE_DOUBLE; + return GetFinalizableArenaTraceKind(ainfo); } JSRuntime * @@ -934,405 +928,6 @@ js_InitGC(JSRuntime *rt, uint32 maxbytes) return true; } -namespace js { - -struct GCChunkHasher -{ - typedef jsuword Lookup; - static HashNumber hash(jsuword chunk) { - /* - * Strip zeros for better distribution after multiplying by the golden - * ratio. - */ - JS_ASSERT(!(chunk & GC_CHUNK_MASK)); - return HashNumber(chunk >> GC_CHUNK_SHIFT); - } - static bool match(jsuword k, jsuword l) { - JS_ASSERT(!(k & GC_CHUNK_MASK)); - JS_ASSERT(!(l & GC_CHUNK_MASK)); - return k == l; - } -}; - -class ConservativeGCStackMarker { - public: - ConservativeGCStackMarker(JSTracer *trc); - - ~ConservativeGCStackMarker() { -#ifdef JS_DUMP_CONSERVATIVE_GC_ROOTS - dumpConservativeRoots(); -#endif -#ifdef JS_GCMETER - JSConservativeGCStats *total = &trc->context->runtime->gcStats.conservative; - total->words += stats.words; - total->unique += stats.unique; - total->oddaddress += stats.oddaddress; - total->outside += stats.outside; - total->notchunk += stats.notchunk; - total->notarena += stats.notarena; - total->wrongtag += stats.wrongtag; - total->notlive += stats.notlive; - total->gcthings += stats.gcthings; - total->raw += stats.raw; - total->unmarked += stats.unmarked; -#endif - } - - void markRoots(); - - private: - void markRange(jsuword *begin, jsuword *end); - void markWord(jsuword w); - - JSTracer *trc; - jsuword gcthingAddressStart; - jsuword gcthingAddressSpan; - HashSet chunkSet; - HashSet, SystemAllocPolicy> history; - -#if defined(JS_DUMP_CONSERVATIVE_GC_ROOTS) || defined(JS_GCMETER) - JSConservativeGCStats stats; - - public: - static void dumpStats(FILE *fp, JSConservativeGCStats *stats); - -# define CONSERVATIVE_METER(x) ((void) (x)) -# define CONSERVATIVE_METER_IF(condition, x) ((void) ((condition) && (x))) - -#else - -# define CONSERVATIVE_METER(x) ((void) 0) -# define CONSERVATIVE_METER_IF(condition, x) ((void) 0) - -#endif - -#ifdef JS_DUMP_CONSERVATIVE_GC_ROOTS - private: - struct ConservativeRoot { void *thing; uint32 traceKind; }; - Vector conservativeRoots; - const char *dumpFileName; - - void dumpConservativeRoots(); -#endif -}; - -ConservativeGCStackMarker::ConservativeGCStackMarker(JSTracer *trc) - : trc(trc) -{ - /* - * If initializing fails because we are out of memory, stack scanning - * slows down but is otherwise unaffected. - */ - history.init(); - - JSRuntime *rt = trc->context->runtime; - jsuword minchunk = 0, maxchunk = 0; - bool chunkSetOk = chunkSet.init(rt->gcChunks.length()); - for (JSGCChunkInfo **i = rt->gcChunks.begin(); i != rt->gcChunks.end(); ++i) { - jsuword chunk =(*i)->getChunk(); - if (chunkSetOk) { - JS_ASSERT(!chunkSet.has(chunk)); - JS_ALWAYS_TRUE(chunkSet.put(chunk)); - } - - if (minchunk == 0) - minchunk = maxchunk = chunk; - else if (chunk < minchunk) - minchunk = chunk; - else if (chunk > maxchunk) - maxchunk = chunk; - } - - gcthingAddressStart = minchunk; - gcthingAddressSpan = (minchunk != 0) - ? maxchunk + GC_MARK_BITMAP_ARRAY_OFFSET - : 0; - -#ifdef JS_DUMP_CONSERVATIVE_GC_ROOTS - dumpFileName = getenv("JS_DUMP_CONSERVATIVE_GC_ROOTS"); - memset(&stats, 0, sizeof(stats)); -#endif -} - -#if defined(JS_DUMP_CONSERVATIVE_GC_ROOTS) || defined(JS_GCMETER) -/* static */ -void -ConservativeGCStackMarker::dumpStats(FILE *fp, JSConservativeGCStats *stats) -{ -#define ULSTAT(x) ((unsigned long)(stats->x)) - fprintf(fp, "CONSERVATIVE STACK SCANNING:\n"); - fprintf(fp, " number of stack words: %lu\n", ULSTAT(words)); - fprintf(fp, " number of unique words: %lu\n", ULSTAT(unique)); - fprintf(fp, " excluded, low bit set: %lu\n", ULSTAT(oddaddress)); - fprintf(fp, " not withing chunk range: %lu\n", ULSTAT(outside)); - fprintf(fp, " not withing a chunk: %lu\n", ULSTAT(notchunk)); - fprintf(fp, " not withing an arena: %lu\n", ULSTAT(notarena)); - fprintf(fp, " excluded, wrong tag: %lu\n", ULSTAT(wrongtag)); - fprintf(fp, " excluded, not live: %lu\n", ULSTAT(notlive)); - fprintf(fp, " things marked: %lu\n", ULSTAT(gcthings)); - fprintf(fp, " raw pointers marked: %lu\n", ULSTAT(raw)); - fprintf(fp, " conservative roots: %lu\n", ULSTAT(unmarked)); -#undef ULSTAT -} -#endif - -#ifdef JS_DUMP_CONSERVATIVE_GC_ROOTS -void -ConservativeGCStackMarker::dumpConservativeRoots() -{ - if (!dumpFileName) - return; - - JS_ASSERT(stats.unmarked == conservativeRoots.length()); - - FILE *fp = !strcmp(dumpFileName, "stdout") ? stdout - : !strcmp(dumpFileName, "stderr") ? stderr - : fopen(dumpFileName, "aw"); - if (!fp) { - fprintf(stderr, - "Warning: cannot open %s to dump the conservative roots\n", - dumpFileName); - return; - } - - dumpStats(fp, &stats); - for (ConservativeRoot *i = conservativeRoots.begin(); - i != conservativeRoots.end(); - ++i) { - fprintf(fp, " %p: ", i->thing); - switch (i->traceKind) { - default: - JS_NOT_REACHED("Unknown trace kind"); - - case JSTRACE_OBJECT: { - JSObject *obj = (JSObject *) i->thing; - fprintf(fp, "object %s", obj->getClass()->name); - break; - } - case JSTRACE_STRING: { - JSString *str = (JSString *) i->thing; - char buf[50]; - js_PutEscapedString(buf, sizeof buf, str, '"'); - fprintf(fp, "string %s", buf); - break; - } - case JSTRACE_DOUBLE: { - jsdouble *dp = (jsdouble *) i->thing; - fprintf(fp, "double %e", *dp); - break; - } -# if JS_HAS_XML_SUPPORT - case JSTRACE_XML: { - JSXML *xml = (JSXML *) i->thing; - fprintf(fp, "xml %u", xml->xml_class); - break; - } -# endif - } - fputc('\n', fp); - } - fputc('\n', fp); - - if (fp != stdout && fp != stderr) - fclose(fp); -} -#endif /* JS_DUMP_CONSERVATIVE_GC_ROOTS */ - -void -ConservativeGCStackMarker::markWord(jsuword w) -{ -#define RETURN(x) do { CONSERVATIVE_METER(stats.x++); return; } while (0) - - JSRuntime *rt = trc->context->runtime; - - CONSERVATIVE_METER(stats.unique++); - - /* If this is an odd addresses or a tagged integer, skip it. */ - if (w & 1) - RETURN(oddaddress); - - /* Strip off the tag bits. */ - jsuword tag = w & JSVAL_TAGMASK; - jsuword p = w & ~(JSVAL_TAGMASK); - - /* Also ignore tagged special values (they never contain pointers). */ - if (tag == JSVAL_SPECIAL) - RETURN(wrongtag); - - /* The remaining pointer must be within the heap boundaries. */ - if ((p - gcthingAddressStart) >= gcthingAddressSpan) - RETURN(outside); - - if ((p & GC_CHUNK_MASK) >= GC_MARK_BITMAP_ARRAY_OFFSET) - RETURN(outside); - - jsuword chunk = p & ~GC_CHUNK_MASK; - JSGCChunkInfo *ci; - if (JS_LIKELY(chunkSet.initialized())) { - if (!chunkSet.has(chunk)) - RETURN(notchunk); - ci = JSGCChunkInfo::fromChunk(chunk); - } else { - ci = JSGCChunkInfo::fromChunk(chunk); - for (JSGCChunkInfo **i = rt->gcChunks.begin(); ; ++i) { - if (i == rt->gcChunks.end()) - RETURN(notchunk); - if (*i == ci) - break; - } - } - - size_t arenaIndex = (p & GC_CHUNK_MASK) >> GC_ARENA_SHIFT; - if (JS_TEST_BIT(ci->getFreeArenaBitmap(), arenaIndex)) - RETURN(notarena); - - JSGCArena *a = JSGCArena::fromChunkAndIndex(chunk, arenaIndex); - JSGCArenaInfo *ainfo = a->getInfo(); - - JSGCThing *thing; - if (!ainfo->list) { /* doubles */ - if (tag && tag != JSVAL_DOUBLE) - RETURN(wrongtag); - JS_STATIC_ASSERT(JSVAL_TAGMASK == 7 && (sizeof(double) - 1) == 7); - thing = (JSGCThing *) p; - } else { - if (tag == JSVAL_DOUBLE) - RETURN(wrongtag); - jsuword start = a->toPageStart(); - jsuword offset = p - start; - size_t thingSize = ainfo->list->thingSize; - p = (start + offset - (offset % thingSize)); - thing = (JSGCThing *) p; - - /* Make sure the thing is not on the freelist of the arena. */ - JSGCThing *cursor = ainfo->freeList; - while (cursor) { - /* If the cursor moves past the thing, its not in the freelist. */ - if (thing < cursor) - break; - /* If we find it on the freelist, its dead. */ - if (thing == cursor) - RETURN(notlive); - cursor = cursor->link; - } - } - - CONSERVATIVE_METER(stats.gcthings++); - CONSERVATIVE_METER_IF(!tag, stats.raw++); - - /* - * We have now a valid pointer, that is either raw or tagged properly. - * Since we do not rely on the conservative scanning yet and assume that - * all the roots are precisely reported, any unmarked GC things here mean - * a leak. - */ - if (IS_GC_MARKING_TRACER(trc)) { - if (!js_IsAboutToBeFinalized(thing)) - return; - CONSERVATIVE_METER(stats.unmarked++); - } - - uint32 traceKind = GetArenaTraceKind(ainfo); -#ifdef JS_DUMP_CONSERVATIVE_GC_ROOTS - if (IS_GC_MARKING_TRACER(trc) && dumpFileName) { - ConservativeRoot root = {thing, traceKind}; - conservativeRoots.append(root); - } -#endif - JS_SET_TRACING_NAME(trc, "machine stack"); - js_CallGCMarker(trc, thing, traceKind); - -#undef RETURN -} - -void -ConservativeGCStackMarker::markRange(jsuword *begin, jsuword *end) -{ - JS_ASSERT(begin <= end); - if (history.initialized()) { - for (jsuword *i = begin; i != end; ++i) { - CONSERVATIVE_METER(stats.words++); - jsuword p = *i; - if (history.has(p)) - continue; - markWord(p); - - /* - * If adding the address to the hash table fails because we are - * out of memory, stack scanning slows down but is otherwise - * unaffected. - */ - history.put(p); - } - } else { - for (jsuword *i = begin; i != end; ++i) - markWord(*i); - } -} - -void -ConservativeGCStackMarker::markRoots() -{ - /* Do conservative scanning of the stack. */ - for (ThreadDataIter i(trc->context->runtime); !i.empty(); i.popFront()) { - JSThreadData *td = i.threadData(); - ConservativeGCThreadData *ctd = &td->conservativeGC; - if (ctd->enableCount) { -#if JS_STACK_GROWTH_DIRECTION > 0 - JS_ASSERT(td->nativeStackBase <= ctd->nativeStackTop); - markRange(td->nativeStackBase, ctd->nativeStackTop); -#else - JS_ASSERT(td->nativeStackBase >= ctd->nativeStackTop + 1); - markRange(ctd->nativeStackTop + 1, td->nativeStackBase); -#endif - markRange(ctd->registerSnapshot.words, - JS_ARRAY_END(ctd->registerSnapshot.words)); - } - } -} - -/* static */ -JS_NEVER_INLINE void -ConservativeGCThreadData::enable(bool knownStackBoundary) -{ - /* Update the native stack pointer if it points to a bigger stack. */ -#if JS_STACK_GROWTH_DIRECTION > 0 -# define CMP > -#else -# define CMP < -#endif - jsuword dummy; - if (knownStackBoundary || enableCount == 0 || &dummy CMP nativeStackTop) - nativeStackTop = &dummy; -#undef CMP - - /* Update the register snapshot with the latest values. */ -#if defined(_MSC_VER) -# pragma warning(push) -# pragma warning(disable: 4611) -#endif - setjmp(registerSnapshot.jmpbuf); -#if defined(_MSC_VER) -# pragma warning(pop) -#endif - - ++enableCount; -} - -JS_NEVER_INLINE void -ConservativeGCThreadData::disable() -{ - JS_ASSERT(enableCount != 0); - --enableCount; -#ifdef DEBUG - if (enableCount == 0) - nativeStackTop = NULL; -#endif -} - -} /* namespace js */ - - #ifdef JS_GCMETER static void @@ -1498,8 +1093,6 @@ js_DumpGCStats(JSRuntime *rt, FILE *fp) fprintf(fp, " scheduled close hooks: %lu\n", ULSTAT(closelater)); fprintf(fp, " max scheduled close hooks: %lu\n", ULSTAT(maxcloselater)); - ConservativeGCStackMarker::dumpStats(fp, &rt->gcStats.conservative); - #undef UL #undef ULSTAT #undef PERCENT @@ -2619,6 +2212,7 @@ JS_REQUIRES_STACK void js_TraceRuntime(JSTracer *trc) { JSRuntime *rt = trc->context->runtime; + JSContext *iter, *acx; for (GCRoots::Range r = rt->gcRootsHash.all(); !r.empty(); r.popFront()) gc_root_traversal(r.front(), trc); @@ -2630,8 +2224,8 @@ js_TraceRuntime(JSTracer *trc) js_TraceRuntimeNumberState(trc); js_MarkTraps(trc); - JSContext *iter = NULL; - while (JSContext *acx = js_ContextIterator(rt, JS_TRUE, &iter)) + iter = NULL; + while ((acx = js_ContextIterator(rt, JS_TRUE, &iter)) != NULL) js_TraceContext(trc, acx); for (ThreadDataIter i(rt); !i.empty(); i.popFront()) @@ -2639,14 +2233,6 @@ js_TraceRuntime(JSTracer *trc) if (rt->gcExtraRootsTraceOp) rt->gcExtraRootsTraceOp(trc, rt->gcExtraRootsData); - - /* - * For now we use the conservative stack scanner only in the check mode - * and mark conservatively after marking all other roots to detect - * conservative leaks. - */ - if (rt->state != JSRTS_LANDING) - ConservativeGCStackMarker(trc).markRoots(); } void @@ -3418,7 +3004,6 @@ LetOtherGCFinish(JSContext *cx) * finish before we wait. */ JS_ASSERT(rt->gcThread); - JS_THREAD_DATA(cx)->conservativeGC.enable(true); /* * Wait for GC to finish on the other thread, even if requestDebit is 0 @@ -3430,7 +3015,6 @@ LetOtherGCFinish(JSContext *cx) JS_AWAIT_GC_DONE(rt); } while (rt->gcThread); - JS_THREAD_DATA(cx)->conservativeGC.disable(); cx->thread->gcWaiting = false; rt->requestCount += requestDebit; } @@ -3557,17 +3141,6 @@ GCUntilDone(JSContext *cx, JSGCInvocationKind gckind GCTIMER_PARAM) METER(rt->gcStats.poke++); - /* - * Do not scan the current thread when on the shutdown or when the - * GC is called outside a request. - */ - bool scanGCThreadStack = (rt->state != JSRTS_LANDING) -#ifndef JS_THREADSAFE - && (rt->gcThread->contextsInRequests != 0) -#endif - ; - if (scanGCThreadStack) - JS_THREAD_DATA(cx)->conservativeGC.enable(true); bool firstRun = true; do { rt->gcPoke = false; @@ -3586,9 +3159,6 @@ GCUntilDone(JSContext *cx, JSGCInvocationKind gckind GCTIMER_PARAM) // - a finalizer called js_RemoveRoot or js_UnlockGCThingRT. } while (rt->gcPoke); - if (rt->state != JSRTS_LANDING) - JS_THREAD_DATA(cx)->conservativeGC.disable(); - rt->gcRegenShapes = false; rt->setGCLastBytes(rt->gcBytes); diff --git a/js/src/jsgc.h b/js/src/jsgc.h index 5b2b4414900..29319d8e611 100644 --- a/js/src/jsgc.h +++ b/js/src/jsgc.h @@ -42,9 +42,6 @@ /* * JS Garbage Collector. */ -#include - -#include "jstypes.h" #include "jsprvtd.h" #include "jspubtd.h" #include "jsdhash.h" @@ -377,10 +374,10 @@ struct JSWeakRoots { #define JS_CLEAR_WEAK_ROOTS(wr) (memset((wr), 0, sizeof(JSWeakRoots))) -namespace js { - #ifdef JS_THREADSAFE +namespace js { + /* * During the finalization we do not free immediately. Rather we add the * corresponding pointers to a buffer which we later release on the @@ -423,30 +420,8 @@ class BackgroundSweepTask : public JSBackgroundTask { virtual void run(); }; -#endif /* JS_THREADSAFE */ - -struct ConservativeGCThreadData { - - /* - * The GC scans conservatively between JSThreadData::nativeStackBase and - * nativeStackTop unless the latter is NULL. - */ - jsuword *nativeStackTop; - - union { - jmp_buf jmpbuf; - jsuword words[JS_HOWMANY(sizeof(jmp_buf), sizeof(jsuword))]; - } registerSnapshot; - - size_t enableCount; - - JS_NEVER_INLINE void enable(bool knownStackBoundary = false); - void disable(); -}; - -} /* namespace js */ - -#define JS_DUMP_CONSERVATIVE_GC_ROOTS 1 +} +#endif extern void js_FinalizeStringRT(JSRuntime *rt, JSString *str); @@ -458,25 +433,6 @@ const bool JS_WANT_GC_METER_PRINT = true; const bool JS_WANT_GC_METER_PRINT = false; #endif -#if defined JS_GCMETER || defined JS_DUMP_CONSERVATIVE_GC_ROOTS - -struct JSConservativeGCStats { - uint32 words; /* number of words on native stacks */ - uint32 unique; /* number of unique words */ - uint32 oddaddress; /* excluded because low bit was set */ - uint32 outside; /* not within chunk min/max address range */ - uint32 notchunk; /* not within a valid chunk */ - uint32 notarena; /* not within non-free arena */ - uint32 wrongtag; /* tagged pointer but wrong type */ - uint32 notlive; /* gcthing is not allocated */ - uint32 gcthings; /* number of live gcthings */ - uint32 raw; /* number of raw pointers marked */ - uint32 unmarked; /* number of unmarked gc things discovered on the - stack */ -}; - -#endif - #ifdef JS_GCMETER struct JSGCArenaStats { @@ -525,8 +481,6 @@ struct JSGCStats { JSGCArenaStats arenaStats[FINALIZE_LIMIT]; JSGCArenaStats doubleArenaStats; - - JSConservativeGCStats conservative; }; extern JS_FRIEND_API(void) diff --git a/js/src/jsstr.cpp b/js/src/jsstr.cpp index 08d7bdae73c..ba55886ef27 100644 --- a/js/src/jsstr.cpp +++ b/js/src/jsstr.cpp @@ -5531,7 +5531,7 @@ Utf8ToOneUcs4Char(const uint8 *utf8Buffer, int utf8Length) return ucs4Char; } -#if defined DEBUG || defined JS_DUMP_CONSERVATIVE_GC_ROOTS +#ifdef DEBUG JS_FRIEND_API(size_t) js_PutEscapedStringImpl(char *buffer, size_t bufferSize, FILE *fp, diff --git a/js/src/jstypes.h b/js/src/jstypes.h index 11a7a627409..f664ac8fac5 100644 --- a/js/src/jstypes.h +++ b/js/src/jstypes.h @@ -204,16 +204,6 @@ # endif #endif -#ifndef JS_NEVER_INLINE -# if defined _MSC_VER -# define JS_NEVER_INLINE __declspec(noinline) -# elif defined __GNUC__ -# define JS_NEVER_INLINE __attribute__((noinline)) -# else -# define JS_NEVER_INLINE -# endif -#endif - #ifdef NS_STATIC_CHECKING /* * Attributes for static analysis. Functions declared with JS_REQUIRES_STACK diff --git a/js/src/tests/jstests.py b/js/src/tests/jstests.py index 3c36ffe9944..df0800cc525 100644 --- a/js/src/tests/jstests.py +++ b/js/src/tests/jstests.py @@ -149,13 +149,6 @@ class ResultsSink: for path in paths: print ' %s'%path - if OPTIONS.failure_file: - failure_file = open(OPTIONS.failure_file, 'w') - if not self.all_passed(): - for path in self.groups['REGRESSIONS']: - print >> failure_file, path - failure_file.close() - suffix = '' if self.finished else ' (partial run -- interrupted by user)' if self.all_passed(): print 'PASS' + suffix @@ -225,8 +218,6 @@ if __name__ == '__main__': help='extra args to pass to valgrind') op.add_option('-c', '--check-manifest', dest='check_manifest', action='store_true', help='check for test files not listed in the manifest') - op.add_option('--failure-file', dest='failure_file', - help='write tests that have not passed to the given file') (OPTIONS, args) = op.parse_args() if len(args) < 1: if not OPTIONS.check_manifest: