void Statistics::endSlice() { slices.back().end = PRMJ_Now(); if (JSAccumulateTelemetryDataCallback cb = runtime->telemetryCallback) { (*cb)(JS_TELEMETRY_GC_SLICE_MS, t(slices.back().end - slices.back().start)); (*cb)(JS_TELEMETRY_GC_RESET, !!slices.back().resetReason); } bool last = runtime->gcIncrementalState == gc::NO_INCREMENTAL; if (last) endGC(); if (GCSliceCallback cb = runtime->gcSliceCallback) { if (last) (*cb)(runtime, GC_CYCLE_END, GCDescription(!!compartment)); else (*cb)(runtime, GC_SLICE_END, GCDescription(!!compartment)); } /* Do this after the slice callback since it uses these values. */ if (last) PodArrayZero(counts); }
static void random_init(JSRuntime *rt) { int64 tmp, tmp2; /* Do at most once. */ if (rt->rngInitialized) return; rt->rngInitialized = JS_TRUE; /* rt->rngMultiplier = 0x5DEECE66DL */ JSLL_ISHL(tmp, 0x5, 32); JSLL_UI2L(tmp2, 0xDEECE66DL); JSLL_OR(rt->rngMultiplier, tmp, tmp2); /* rt->rngAddend = 0xBL */ JSLL_I2L(rt->rngAddend, 0xBL); /* rt->rngMask = (1L << 48) - 1 */ JSLL_I2L(tmp, 1); JSLL_SHL(tmp2, tmp, 48); JSLL_SUB(rt->rngMask, tmp2, tmp); /* rt->rngDscale = (jsdouble)(1L << 53) */ JSLL_SHL(tmp2, tmp, 53); JSLL_L2D(rt->rngDscale, tmp2); /* Finally, set the seed from current time. */ random_setSeed(rt, PRMJ_Now()); }
Statistics::Statistics(JSRuntime *rt) : runtime(rt), startupTime(PRMJ_Now()), fp(NULL), fullFormat(false), gcDepth(0), collectedCount(0), compartmentCount(0), nonincrementalReason(NULL) { PodArrayZero(phaseTotals); PodArrayZero(counts); char *env = getenv("MOZ_GCTIMER"); if (!env || strcmp(env, "none") == 0) { fp = NULL; return; } if (strcmp(env, "stdout") == 0) { fullFormat = false; fp = stdout; } else if (strcmp(env, "stderr") == 0) { fullFormat = false; fp = stderr; } else { fullFormat = true; fp = fopen(env, "a"); JS_ASSERT(fp); } }
void Statistics::endSlice() { slices.back().end = PRMJ_Now(); slices.back().endFaults = gc::GetPageFaultCount(); if (JSAccumulateTelemetryDataCallback cb = runtime->telemetryCallback) { (*cb)(JS_TELEMETRY_GC_SLICE_MS, t(slices.back().end - slices.back().start)); (*cb)(JS_TELEMETRY_GC_RESET, !!slices.back().resetReason); } bool last = runtime->gcIncrementalState == gc::NO_INCREMENTAL; if (last) endGC(); // Slice callbacks should only fire for the outermost level if (--gcDepth == 0) { bool wasFullGC = collectedCount == compartmentCount; if (GCSliceCallback cb = runtime->gcSliceCallback) (*cb)(runtime, last ? GC_CYCLE_END : GC_SLICE_END, GCDescription(!wasFullGC)); } /* Do this after the slice callback since it uses these values. */ if (last) PodArrayZero(counts); }
void Statistics::endSCC(unsigned scc, int64_t start) { if (scc >= sccTimes.length() && !sccTimes.resize(scc + 1)) return; sccTimes[scc] += PRMJ_Now() - start; }
PRMJ_NowS(void) { PRInt64 us, us2s; us = PRMJ_Now(); LL_UI2L(us2s, PRMJ_USEC_PER_SEC); LL_DIV(us, us, us2s); return us; }
void Statistics::beginPhase(Phase phase) { phaseStarts[phase] = PRMJ_Now(); if (phase == gcstats::PHASE_MARK) Probes::GCStartMarkPhase(); else if (phase == gcstats::PHASE_SWEEP) Probes::GCStartSweepPhase(); }
PRMJ_NowMS(void) { PRInt64 us, us2ms; us = PRMJ_Now(); LL_UI2L(us2ms, PRMJ_USEC_PER_MSEC); LL_DIV(us, us, us2ms); return us; }
void Statistics::beginPhase(Phase phase) { phaseStartTimes[phase] = PRMJ_Now(); phaseStartFaults[phase] = gc::GetPageFaultCount(); if (phase == gcstats::PHASE_MARK) Probes::GCStartMarkPhase(); else if (phase == gcstats::PHASE_SWEEP) Probes::GCStartSweepPhase(); }
void Statistics::endPhase(Phase phase) { int64_t t = PRMJ_Now() - phaseStartTimes[phase]; slices.back().phaseTimes[phase] += t; phaseTimes[phase] += t; phaseStartTimes[phase] = 0; if (phase == gcstats::PHASE_MARK) Probes::GCEndMarkPhase(); else if (phase == gcstats::PHASE_SWEEP) Probes::GCEndSweepPhase(); }
void Statistics::beginPhase(Phase phase) { /* Guard against re-entry */ JS_ASSERT(!phaseStartTimes[phase]); phaseStartTimes[phase] = PRMJ_Now(); if (phase == gcstats::PHASE_MARK) Probes::GCStartMarkPhase(); else if (phase == gcstats::PHASE_SWEEP) Probes::GCStartSweepPhase(); }
void js_InitRandom(JSContext *cx) { /* * Set the seed from current time. Since we have a RNG per context and we often bring * up several contexts at the same time, we xor in some additional values, namely * the context and its successor. We don't just use the context because it might be * possible to reverse engineer the context pointer if one guesses the time right. */ random_setSeed(cx, (PRMJ_Now() / 1000) ^ int64(cx) ^ int64(cx->link.next)); }
void Statistics::endPhase(Phase phase) { int64_t t = PRMJ_Now() - phaseStartTimes[phase]; slices.back().phaseTimes[phase] += t; phaseTimes[phase] += t; size_t faults = gc::GetPageFaultCount() - phaseStartFaults[phase]; slices.back().phaseFaults[phase] += faults; phaseFaults[phase] += faults; if (phase == gcstats::PHASE_MARK) Probes::GCEndMarkPhase(); else if (phase == gcstats::PHASE_SWEEP) Probes::GCEndSweepPhase(); }
bool SavedStacksMetadataCallback(JSContext *cx, JSObject **pmetadata) { SavedStacks &stacks = cx->compartment()->savedStacks(); if (stacks.allocationSkipCount > 0) { stacks.allocationSkipCount--; return true; } stacks.chooseSamplingProbability(cx); if (stacks.allocationSamplingProbability == 0.0) return true; // If the sampling probability is set to 1.0, we are always taking a sample // and can therefore leave allocationSkipCount at 0. if (stacks.allocationSamplingProbability != 1.0) { // Rather than generating a random number on every allocation to decide // if we want to sample that particular allocation (which would be // expensive), we calculate the number of allocations to skip before // taking the next sample. // // P = the probability we sample any given event. // // ~P = 1-P, the probability we don't sample a given event. // // (~P)^n = the probability that we skip at least the next n events. // // let X = random between 0 and 1. // // floor(log base ~P of X) = n, aka the number of events we should skip // until we take the next sample. Any value for X less than (~P)^n // yields a skip count greater than n, so the likelihood of a skip count // greater than n is (~P)^n, as required. double notSamplingProb = 1.0 - stacks.allocationSamplingProbability; stacks.allocationSkipCount = std::floor(std::log(random_nextDouble(&stacks.rngState)) / std::log(notSamplingProb)); } RootedSavedFrame frame(cx); if (!stacks.saveCurrentStack(cx, &frame)) return false; *pmetadata = frame; return Debugger::onLogAllocationSite(cx, frame, PRMJ_Now()); }
void Statistics::beginSlice(JSCompartment *comp, gcreason::Reason reason) { compartment = comp; bool first = runtime->gcIncrementalState == gc::NO_INCREMENTAL; if (first) beginGC(); SliceData data(reason, PRMJ_Now()); (void) slices.append(data); /* Ignore any OOMs here. */ if (JSAccumulateTelemetryDataCallback cb = runtime->telemetryCallback) (*cb)(JS_TELEMETRY_GC_REASON, reason); if (GCSliceCallback cb = runtime->gcSliceCallback) (*cb)(runtime, first ? GC_CYCLE_BEGIN : GC_SLICE_BEGIN, GCDescription(!!compartment)); }
void GCTimer::finish(bool lastGC) { end = PRMJ_Now(); if (startMark > 0) { if (JS_WANT_GC_SUITE_PRINT) { fprintf(stderr, "%f %f %f\n", TIMEDIFF(enter, end), TIMEDIFF(startMark, startSweep), TIMEDIFF(startSweep, sweepDestroyEnd)); } else { static FILE *gcFile; if (!gcFile) { gcFile = fopen("gcTimer.dat", "a"); fprintf(gcFile, " AppTime, Total, Wait, Mark, Sweep, FinObj,"); fprintf(gcFile, " FinStr, SwShapes, Destroy, End, +Chu, -Chu\n"); } JS_ASSERT(gcFile); /* App , Tot , Wai , Mar , Swe , FiO , FiS , SwS , Des , End */ fprintf(gcFile, "%12.0f, %6.1f, %6.1f, %6.1f, %6.1f, %6.1f, %6.1f, %8.1f, %6.1f, %6.1f, ", TIMEDIFF(getFirstEnter(), enter), TIMEDIFF(enter, end), TIMEDIFF(enter, startMark), TIMEDIFF(startMark, startSweep), TIMEDIFF(startSweep, sweepDestroyEnd), TIMEDIFF(startSweep, sweepObjectEnd), TIMEDIFF(sweepObjectEnd, sweepStringEnd), TIMEDIFF(sweepStringEnd, sweepShapeEnd), TIMEDIFF(sweepShapeEnd, sweepDestroyEnd), TIMEDIFF(sweepDestroyEnd, end)); fprintf(gcFile, "%4d, %4d\n", newChunkCount, destroyChunkCount); fflush(gcFile); if (lastGC) { fclose(gcFile); gcFile = NULL; } } } newChunkCount = 0; destroyChunkCount = 0; }
void Statistics::endSlice() { slices.back().end = PRMJ_Now(); if (JSAccumulateTelemetryDataCallback cb = runtime->telemetryCallback) (*cb)(JS_TELEMETRY_GC_SLICE_MS, t(slices.back().end - slices.back().start)); bool last = runtime->gcIncrementalState == gc::NO_INCREMENTAL; if (last) endGC(); if (GCSliceCallback cb = runtime->gcSliceCallback) { if (last) (*cb)(runtime, GC_CYCLE_END, GCDescription(formatData(), !!compartment)); else (*cb)(runtime, GC_SLICE_END, GCDescription(NULL, !!compartment)); } }
bool LCovRuntime::fillWithFilename(char *name, size_t length) { const char* outDir = getenv("JS_CODE_COVERAGE_OUTPUT_DIR"); if (!outDir || *outDir == 0) return false; int64_t timestamp = static_cast<double>(PRMJ_Now()) / PRMJ_USEC_PER_SEC; static mozilla::Atomic<size_t> globalRuntimeId(0); size_t rid = globalRuntimeId++; size_t len = JS_snprintf(name, length, "%s/%" PRId64 "-%" PRIuSIZE "-%" PRIuSIZE ".info", outDir, timestamp, pid_, rid); if (length <= len) { fprintf(stderr, "Warning: LCovRuntime::init: Cannot serialize file name."); return false; } return true; }
void Statistics::beginSlice(int collectedCount, int compartmentCount, gcreason::Reason reason) { this->collectedCount = collectedCount; this->compartmentCount = compartmentCount; bool first = runtime->gcIncrementalState == gc::NO_INCREMENTAL; if (first) beginGC(); SliceData data(reason, PRMJ_Now(), gc::GetPageFaultCount()); (void) slices.append(data); /* Ignore any OOMs here. */ if (JSAccumulateTelemetryDataCallback cb = runtime->telemetryCallback) (*cb)(JS_TELEMETRY_GC_REASON, reason); // Slice callbacks should only fire for the outermost level if (++gcDepth == 1) { bool wasFullGC = collectedCount == compartmentCount; if (GCSliceCallback cb = runtime->gcSliceCallback) (*cb)(runtime, first ? GC_CYCLE_BEGIN : GC_SLICE_BEGIN, GCDescription(!wasFullGC)); } }
void js_InitRandom(JSThreadData *data) { /* Finally, set the seed from current time. */ random_setSeed(data, PRMJ_Now() / 1000); }
GCTimer::GCTimer() { getFirstEnter(); memset(this, 0, sizeof(GCTimer)); enter = PRMJ_Now(); }
int64_t Statistics::beginSCC() { return PRMJ_Now(); }
void ExecutableAllocator::initSeed() { random_setSeed(&rngSeed, (PRMJ_Now() / 1000) ^ int64_t(this)); }
uint64 GCTimer::getFirstEnter() { static uint64 firstEnter = PRMJ_Now(); return firstEnter; }