mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-11-27 23:02:20 +00:00
Backed out changesets 06c511b6093e, dbec0bed9bf5, bfedb105396e (bug 1088831) for causing various assertions on a CLOSED TREE.
This commit is contained in:
parent
12472a6fb2
commit
e4e3786f32
@ -27,7 +27,6 @@ using namespace js::gc;
|
||||
using namespace js::gcstats;
|
||||
|
||||
using mozilla::PodArrayZero;
|
||||
using mozilla::PodZero;
|
||||
|
||||
/* Except for the first and last, slices of less than 10ms are not reported. */
|
||||
static const int64_t SLICE_MIN_REPORT_TIME = 10 * PRMJ_USEC_PER_MSEC;
|
||||
@ -284,7 +283,6 @@ struct PhaseInfo
|
||||
static const Phase PHASE_NO_PARENT = PHASE_LIMIT;
|
||||
|
||||
static const PhaseInfo phases[] = {
|
||||
{ PHASE_MUTATOR, "Mutator Running", PHASE_NO_PARENT },
|
||||
{ PHASE_GC_BEGIN, "Begin Callback", PHASE_NO_PARENT },
|
||||
{ PHASE_WAIT_BACKGROUND_THREAD, "Wait Background Thread", PHASE_NO_PARENT },
|
||||
{ PHASE_MARK_DISCARD_CODE, "Mark Discard Code", PHASE_NO_PARENT },
|
||||
@ -328,9 +326,6 @@ static const PhaseInfo phases[] = {
|
||||
{ PHASE_COMPACT_UPDATE, "Compact Update", PHASE_COMPACT, },
|
||||
{ PHASE_COMPACT_UPDATE_GRAY, "Compact Update Gray", PHASE_COMPACT_UPDATE, },
|
||||
{ PHASE_GC_END, "End Callback", PHASE_NO_PARENT },
|
||||
{ PHASE_MINOR_GC, "Minor GC", PHASE_NO_PARENT },
|
||||
{ PHASE_COMPACT_STOREBUFFER_IN_MINOR_GC, "Compact Store Buffers", PHASE_MINOR_GC },
|
||||
{ PHASE_COMPACT_STOREBUFFER_NO_PARENT, "Compact Store Buffers (toplevel)", PHASE_NO_PARENT },
|
||||
{ PHASE_LIMIT, nullptr, PHASE_NO_PARENT }
|
||||
};
|
||||
|
||||
@ -390,8 +385,6 @@ Statistics::formatData(StatisticsSerializer &ss, uint64_t timestamp)
|
||||
ss.appendNumber("Total Zones", "%d", "", zoneStats.zoneCount);
|
||||
ss.appendNumber("Total Compartments", "%d", "", zoneStats.compartmentCount);
|
||||
ss.appendNumber("Minor GCs", "%d", "", counts[STAT_MINOR_GC]);
|
||||
ss.appendNumber("Store Buffer Compactions", "%d", "", counts[STAT_COMPACT_STOREBUFFER]);
|
||||
ss.appendNumber("Store Buffer Overflows", "%d", "", counts[STAT_STOREBUFFER_OVERFLOW]);
|
||||
ss.appendNumber("MMU (20ms)", "%d", "%", int(mmu20 * 100));
|
||||
ss.appendNumber("MMU (50ms)", "%d", "%", int(mmu50 * 100));
|
||||
ss.appendDecimal("SCC Sweep Total", "ms", t(sccTotal));
|
||||
@ -483,8 +476,6 @@ Statistics::formatDescription()
|
||||
Zones Collected: %d of %d\n\
|
||||
Compartments Collected: %d of %d\n\
|
||||
MinorGCs since last GC: %d\n\
|
||||
Store Buffer Compactions: %d\n\
|
||||
Store Buffer Overflows: %d\n\
|
||||
MMU 20ms:%.1f%%; 50ms:%.1f%%\n\
|
||||
SCC Sweep Total (MaxPause): %.3fms (%.3fms)\n\
|
||||
HeapSize: %.3f MiB\n\
|
||||
@ -500,8 +491,6 @@ Statistics::formatDescription()
|
||||
zoneStats.collectedZoneCount, zoneStats.zoneCount,
|
||||
zoneStats.collectedCompartmentCount, zoneStats.compartmentCount,
|
||||
counts[STAT_MINOR_GC],
|
||||
counts[STAT_COMPACT_STOREBUFFER],
|
||||
counts[STAT_STOREBUFFER_OVERFLOW],
|
||||
mmu20 * 100., mmu50 * 100.,
|
||||
t(sccTotal), t(sccLongest),
|
||||
double(preBytes) / 1024. / 1024.,
|
||||
@ -644,8 +633,6 @@ Statistics::Statistics(JSRuntime *rt)
|
||||
fullFormat(false),
|
||||
gcDepth(0),
|
||||
nonincrementalReason(nullptr),
|
||||
timingMutator(false),
|
||||
timedGCStart(0),
|
||||
preBytes(0),
|
||||
maxPauseInInterval(0),
|
||||
phaseNestingDepth(0),
|
||||
@ -653,8 +640,6 @@ Statistics::Statistics(JSRuntime *rt)
|
||||
{
|
||||
PodArrayZero(phaseTotals);
|
||||
PodArrayZero(counts);
|
||||
PodArrayZero(phaseStartTimes);
|
||||
PodArrayZero(phaseTimes);
|
||||
|
||||
char *env = getenv("MOZ_GCTIMER");
|
||||
if (!env || strcmp(env, "none") == 0) {
|
||||
@ -738,6 +723,9 @@ Statistics::printStats()
|
||||
void
|
||||
Statistics::beginGC(JSGCInvocationKind kind)
|
||||
{
|
||||
PodArrayZero(phaseStartTimes);
|
||||
PodArrayZero(phaseTimes);
|
||||
|
||||
slices.clearAndFree();
|
||||
sccTimes.clearAndFree();
|
||||
gckind = kind;
|
||||
@ -779,11 +767,6 @@ Statistics::endGC()
|
||||
|
||||
if (fp)
|
||||
printStats();
|
||||
|
||||
// Clear the timers at the end of a GC because we accumulate time for some
|
||||
// phases (eg storebuffer compaction) during the mutator's run.
|
||||
PodZero(&phaseStartTimes[PHASE_GC_BEGIN], PHASE_LIMIT - PHASE_GC_BEGIN);
|
||||
PodZero(&phaseTimes[PHASE_GC_BEGIN], PHASE_LIMIT - PHASE_GC_BEGIN);
|
||||
}
|
||||
|
||||
void
|
||||
@ -840,58 +823,17 @@ Statistics::endSlice()
|
||||
PodArrayZero(counts);
|
||||
}
|
||||
|
||||
void
|
||||
Statistics::startTimingMutator()
|
||||
{
|
||||
MOZ_ASSERT(!timingMutator);
|
||||
|
||||
// Should only be called from outside of GC
|
||||
MOZ_ASSERT(phaseNestingDepth == 0);
|
||||
|
||||
timingMutator = true;
|
||||
timedGCTime = 0;
|
||||
phaseStartTimes[PHASE_MUTATOR] = 0;
|
||||
phaseTimes[PHASE_MUTATOR] = 0;
|
||||
timedGCStart = 0;
|
||||
|
||||
beginPhase(PHASE_MUTATOR);
|
||||
}
|
||||
|
||||
void
|
||||
Statistics::stopTimingMutator(double &mutator_ms, double &gc_ms)
|
||||
{
|
||||
MOZ_ASSERT(timingMutator);
|
||||
|
||||
// Should only be called from outside of GC
|
||||
MOZ_ASSERT(phaseNestingDepth == 1 && phaseNesting[0] == PHASE_MUTATOR);
|
||||
|
||||
endPhase(PHASE_MUTATOR);
|
||||
mutator_ms = t(phaseTimes[PHASE_MUTATOR]);
|
||||
gc_ms = t(timedGCTime);
|
||||
timingMutator = false;
|
||||
}
|
||||
|
||||
void
|
||||
Statistics::beginPhase(Phase phase)
|
||||
{
|
||||
/* Guard against re-entry */
|
||||
MOZ_ASSERT(!phaseStartTimes[phase]);
|
||||
|
||||
if (timingMutator) {
|
||||
if (phaseNestingDepth == 1 && phaseNesting[0] == PHASE_MUTATOR) {
|
||||
endPhase(PHASE_MUTATOR);
|
||||
timedGCStart = PRMJ_Now();
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef DEBUG
|
||||
MOZ_ASSERT(phases[phase].index == phase);
|
||||
Phase parent = phaseNestingDepth ? phaseNesting[phaseNestingDepth - 1] : PHASE_NO_PARENT;
|
||||
MOZ_ASSERT(phaseNestingDepth < MAX_NESTING);
|
||||
MOZ_ASSERT_IF(gcDepth == 1, phases[phase].parent == parent);
|
||||
MOZ_ASSERT_IF(phase == PHASE_COMPACT_STOREBUFFER_IN_MINOR_GC, parent == PHASE_MINOR_GC);
|
||||
MOZ_ASSERT_IF(phase == PHASE_COMPACT_STOREBUFFER_NO_PARENT, parent == PHASE_NO_PARENT);
|
||||
|
||||
phaseNesting[phaseNestingDepth] = phase;
|
||||
phaseNestingDepth++;
|
||||
#endif
|
||||
@ -904,19 +846,10 @@ Statistics::endPhase(Phase phase)
|
||||
{
|
||||
phaseNestingDepth--;
|
||||
|
||||
int64_t now = PRMJ_Now();
|
||||
int64_t t = now - phaseStartTimes[phase];
|
||||
if (!slices.empty())
|
||||
slices.back().phaseTimes[phase] += t;
|
||||
int64_t t = PRMJ_Now() - phaseStartTimes[phase];
|
||||
slices.back().phaseTimes[phase] += t;
|
||||
phaseTimes[phase] += t;
|
||||
phaseStartTimes[phase] = 0;
|
||||
|
||||
if (timingMutator) {
|
||||
if (phaseNestingDepth == 0 && phase != PHASE_MUTATOR) {
|
||||
timedGCTime += now - timedGCStart;
|
||||
beginPhase(PHASE_MUTATOR);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -27,7 +27,6 @@ class GCParallelTask;
|
||||
namespace gcstats {
|
||||
|
||||
enum Phase {
|
||||
PHASE_MUTATOR,
|
||||
PHASE_GC_BEGIN,
|
||||
PHASE_WAIT_BACKGROUND_THREAD,
|
||||
PHASE_MARK_DISCARD_CODE,
|
||||
@ -71,9 +70,6 @@ enum Phase {
|
||||
PHASE_COMPACT_UPDATE,
|
||||
PHASE_COMPACT_UPDATE_GRAY,
|
||||
PHASE_GC_END,
|
||||
PHASE_MINOR_GC,
|
||||
PHASE_COMPACT_STOREBUFFER_IN_MINOR_GC,
|
||||
PHASE_COMPACT_STOREBUFFER_NO_PARENT,
|
||||
|
||||
PHASE_LIMIT
|
||||
};
|
||||
@ -83,13 +79,6 @@ enum Stat {
|
||||
STAT_DESTROY_CHUNK,
|
||||
STAT_MINOR_GC,
|
||||
|
||||
// Number of times the storebuffers were compacted
|
||||
STAT_COMPACT_STOREBUFFER,
|
||||
|
||||
// Number of times a 'put' into a storebuffer overflowed, triggering a
|
||||
// compaction
|
||||
STAT_STOREBUFFER_OVERFLOW,
|
||||
|
||||
STAT_LIMIT
|
||||
};
|
||||
|
||||
@ -129,9 +118,6 @@ struct Statistics
|
||||
JS::gcreason::Reason reason);
|
||||
void endSlice();
|
||||
|
||||
void startTimingMutator();
|
||||
void stopTimingMutator(double &mutator_ms, double &gc_ms);
|
||||
|
||||
void reset(const char *reason) { slices.back().resetReason = reason; }
|
||||
void nonincremental(const char *reason) { nonincrementalReason = reason; }
|
||||
|
||||
@ -193,13 +179,6 @@ struct Statistics
|
||||
/* Most recent time when the given phase started. */
|
||||
int64_t phaseStartTimes[PHASE_LIMIT];
|
||||
|
||||
/* Are we currently timing mutator vs GC time? */
|
||||
bool timingMutator;
|
||||
|
||||
/* Bookkeeping for GC timings when timingMutator is true */
|
||||
int64_t timedGCStart;
|
||||
int64_t timedGCTime;
|
||||
|
||||
/* Total time in a given phase for this GC. */
|
||||
int64_t phaseTimes[PHASE_LIMIT];
|
||||
|
||||
@ -215,10 +194,12 @@ struct Statistics
|
||||
/* Records the maximum GC pause in an API-controlled interval (in us). */
|
||||
int64_t maxPauseInInterval;
|
||||
|
||||
#ifdef DEBUG
|
||||
/* Phases that are currently on stack. */
|
||||
static const size_t MAX_NESTING = 8;
|
||||
Phase phaseNesting[MAX_NESTING];
|
||||
size_t phaseNestingDepth;
|
||||
#endif
|
||||
mozilla::DebugOnly<size_t> phaseNestingDepth;
|
||||
|
||||
/* Sweep times for SCCs of compartments. */
|
||||
Vector<int64_t, 0, SystemAllocPolicy> sccTimes;
|
||||
|
@ -10,7 +10,6 @@
|
||||
|
||||
#include "mozilla/Assertions.h"
|
||||
|
||||
#include "gc/Statistics.h"
|
||||
#include "vm/ArgumentsObject.h"
|
||||
#include "vm/ForkJoin.h"
|
||||
|
||||
@ -20,12 +19,6 @@ using namespace js;
|
||||
using namespace js::gc;
|
||||
using mozilla::ReentrancyGuard;
|
||||
|
||||
gcstats::Statistics&
|
||||
StoreBuffer::stats()
|
||||
{
|
||||
return runtime_->gc.stats;
|
||||
}
|
||||
|
||||
/*** Edges ***/
|
||||
|
||||
void
|
||||
@ -100,8 +93,6 @@ StoreBuffer::MonoTypeBuffer<T>::handleOverflow(StoreBuffer *owner)
|
||||
* Compact the buffer now, and if that fails to free enough space then
|
||||
* trigger a minor collection.
|
||||
*/
|
||||
gcstats::AutoPhase ap(owner->stats(), gcstats::PHASE_COMPACT_STOREBUFFER_NO_PARENT);
|
||||
owner->stats().count(gcstats::STAT_STOREBUFFER_OVERFLOW);
|
||||
compact(owner);
|
||||
if (isLowOnSpace())
|
||||
owner->setAboutToOverflow();
|
||||
@ -110,10 +101,8 @@ StoreBuffer::MonoTypeBuffer<T>::handleOverflow(StoreBuffer *owner)
|
||||
* A minor GC has already been triggered, so there's no point
|
||||
* compacting unless the buffer is totally full.
|
||||
*/
|
||||
if (storage_->availableInCurrentChunk() < sizeof(T)) {
|
||||
owner->stats().count(gcstats::STAT_STOREBUFFER_OVERFLOW);
|
||||
maybeCompact(owner, gcstats::PHASE_COMPACT_STOREBUFFER_NO_PARENT);
|
||||
}
|
||||
if (storage_->availableInCurrentChunk() < sizeof(T))
|
||||
maybeCompact(owner);
|
||||
}
|
||||
}
|
||||
|
||||
@ -141,7 +130,6 @@ StoreBuffer::MonoTypeBuffer<T>::compactRemoveDuplicates(StoreBuffer *owner)
|
||||
storage_->release(insert.mark());
|
||||
|
||||
duplicates.clear();
|
||||
owner->stats().count(gcstats::STAT_COMPACT_STOREBUFFER);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
@ -155,13 +143,11 @@ StoreBuffer::MonoTypeBuffer<T>::compact(StoreBuffer *owner)
|
||||
|
||||
template <typename T>
|
||||
void
|
||||
StoreBuffer::MonoTypeBuffer<T>::maybeCompact(StoreBuffer *owner, int phase)
|
||||
StoreBuffer::MonoTypeBuffer<T>::maybeCompact(StoreBuffer *owner)
|
||||
{
|
||||
MOZ_ASSERT(storage_);
|
||||
if (storage_->used() != usedAtLastCompact_) {
|
||||
gcstats::AutoPhase ap(owner->stats(), static_cast<gcstats::Phase>(phase));
|
||||
if (storage_->used() != usedAtLastCompact_)
|
||||
compact(owner);
|
||||
}
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
@ -173,8 +159,7 @@ StoreBuffer::MonoTypeBuffer<T>::mark(StoreBuffer *owner, JSTracer *trc)
|
||||
if (!storage_)
|
||||
return;
|
||||
|
||||
maybeCompact(owner, gcstats::PHASE_COMPACT_STOREBUFFER_IN_MINOR_GC);
|
||||
|
||||
maybeCompact(owner);
|
||||
for (LifoAlloc::Enum e(*storage_); !e.empty(); e.popFront<T>()) {
|
||||
T *edge = e.get<T>();
|
||||
edge->mark(trc);
|
||||
|
@ -22,10 +22,6 @@
|
||||
|
||||
namespace js {
|
||||
|
||||
namespace gcstats {
|
||||
struct Statistics;
|
||||
}
|
||||
|
||||
MOZ_NORETURN void
|
||||
CrashAtUnhandlableOOM(const char *reason);
|
||||
|
||||
@ -144,7 +140,7 @@ class StoreBuffer
|
||||
virtual void compact(StoreBuffer *owner);
|
||||
|
||||
/* Compacts if any entries have been added since the last compaction. */
|
||||
void maybeCompact(StoreBuffer *owner, int phase);
|
||||
void maybeCompact(StoreBuffer *owner);
|
||||
|
||||
/* Add one item to the buffer. */
|
||||
void put(StoreBuffer *owner, const T &t) {
|
||||
@ -493,8 +489,6 @@ class StoreBuffer
|
||||
putFromAnyThread(bufferGeneric, CallbackRef<Key>(callback, key, data));
|
||||
}
|
||||
|
||||
gcstats::Statistics& stats();
|
||||
|
||||
/* Methods to mark the source of all edges in the store buffer. */
|
||||
void markAll(JSTracer *trc);
|
||||
void markValues(JSTracer *trc) { bufferVal.mark(this, trc); }
|
||||
|
@ -503,10 +503,7 @@ js::gc::GCRuntime::endVerifyPostBarriers()
|
||||
if (!edges.init())
|
||||
goto oom;
|
||||
trc->edges = &edges;
|
||||
{
|
||||
gcstats::AutoPhase ap(stats, gcstats::PHASE_MINOR_GC);
|
||||
storeBuffer.markAll(trc);
|
||||
}
|
||||
storeBuffer.markAll(trc);
|
||||
|
||||
/* Walk the heap to find any edges not the the |edges| set. */
|
||||
trc->setTraceCallback(PostVerifierVisitEdge);
|
||||
|
@ -6282,7 +6282,6 @@ void
|
||||
GCRuntime::minorGC(JS::gcreason::Reason reason)
|
||||
{
|
||||
#ifdef JSGC_GENERATIONAL
|
||||
gcstats::AutoPhase ap(stats, gcstats::PHASE_MINOR_GC);
|
||||
minorGCRequested = false;
|
||||
TraceLogger *logger = TraceLoggerForMainThread(rt);
|
||||
AutoTraceLog logMinorGC(logger, TraceLogger::MinorGC);
|
||||
@ -6297,7 +6296,6 @@ GCRuntime::minorGC(JSContext *cx, JS::gcreason::Reason reason)
|
||||
// Alternate to the runtime-taking form above which allows marking type
|
||||
// objects as needing pretenuring.
|
||||
#ifdef JSGC_GENERATIONAL
|
||||
gcstats::AutoPhase ap(stats, gcstats::PHASE_MINOR_GC);
|
||||
minorGCRequested = false;
|
||||
TraceLogger *logger = TraceLoggerForMainThread(rt);
|
||||
AutoTraceLog logMinorGC(logger, TraceLogger::MinorGC);
|
||||
|
@ -1669,43 +1669,6 @@ Quit(JSContext *cx, unsigned argc, jsval *vp)
|
||||
return false;
|
||||
}
|
||||
|
||||
static bool
|
||||
StartTimingMutator(JSContext *cx, unsigned argc, jsval *vp)
|
||||
{
|
||||
CallArgs args = CallArgsFromVp(argc, vp);
|
||||
if (args.length() > 0) {
|
||||
JS_ReportErrorNumber(cx, my_GetErrorMessage, nullptr,
|
||||
JSSMSG_TOO_MANY_ARGS, "startTimingMutator");
|
||||
return false;
|
||||
}
|
||||
|
||||
cx->runtime()->gc.stats.startTimingMutator();
|
||||
args.rval().setUndefined();
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool
|
||||
StopTimingMutator(JSContext *cx, unsigned argc, jsval *vp)
|
||||
{
|
||||
CallArgs args = CallArgsFromVp(argc, vp);
|
||||
if (args.length() > 0) {
|
||||
JS_ReportErrorNumber(cx, my_GetErrorMessage, nullptr,
|
||||
JSSMSG_TOO_MANY_ARGS, "stopTimingMutator");
|
||||
return false;
|
||||
}
|
||||
|
||||
double mutator_ms, gc_ms;
|
||||
cx->runtime()->gc.stats.stopTimingMutator(mutator_ms, gc_ms);
|
||||
double total_ms = mutator_ms + gc_ms;
|
||||
if (total_ms > 0) {
|
||||
fprintf(gOutFile, "Mutator: %.3fms (%.1f%%), GC: %.3fms (%.1f%%)\n",
|
||||
mutator_ms, mutator_ms / total_ms * 100.0, gc_ms, gc_ms / total_ms * 100.0);
|
||||
}
|
||||
|
||||
args.rval().setUndefined();
|
||||
return true;
|
||||
}
|
||||
|
||||
static const char *
|
||||
ToSource(JSContext *cx, MutableHandleValue vp, JSAutoByteString *bytes)
|
||||
{
|
||||
@ -4310,14 +4273,6 @@ static const JSFunctionSpecWithHelp shell_functions[] = {
|
||||
" Throw if the first two arguments are not the same (both +0 or both -0,\n"
|
||||
" both NaN, or non-zero and ===)."),
|
||||
|
||||
JS_FN_HELP("startTimingMutator", StartTimingMutator, 0, 0,
|
||||
"startTimingMutator()",
|
||||
" Start accounting time to mutator vs GC."),
|
||||
|
||||
JS_FN_HELP("stopTimingMutator", StopTimingMutator, 0, 0,
|
||||
"stopTimingMutator()",
|
||||
" Stop accounting time to mutator vs GC and dump the results."),
|
||||
|
||||
JS_FN_HELP("throwError", ThrowError, 0, 0,
|
||||
"throwError()",
|
||||
" Throw an error from JS_ReportError."),
|
||||
|
Loading…
Reference in New Issue
Block a user