Bug 1465505: Replace PRMJ_Now() by mozilla::TimeStamp r=jonco

Notice as TimeStamp is not an integral type, it can't be wrapped by
mozilla::Atomic. However, we wrap it in MainThreadData to assure it only
is accessed from the main thread.

Another issue is that TimeStamp class does allow some operations on a
Null value, with assertions on debug builds.

MozReview-Commit-ID: 9GPNDUooQmI

--HG--
extra : rebase_source : e2b5fe81a4c5c696425583a04395f2ae79aeaccc
This commit is contained in:
Wander Lairson Costa 2018-07-04 16:55:11 -03:00
parent a892a1e9b1
commit 4c52aa4d3f
9 changed files with 49 additions and 32 deletions

View File

@ -141,7 +141,7 @@ typedef enum JSGCParamKey {
* See setGCLastBytes in jsgc.cpp.
*
* Pref: javascript.options.mem.gc_high_frequency_time_limit_ms
* Default: HighFrequencyThresholdUsec
* Default: HighFrequencyThreshold
*/
JSGC_HIGH_FREQUENCY_TIME_LIMIT = 11,

View File

@ -7,6 +7,8 @@
#ifndef js_SliceBudget_h
#define js_SliceBudget_h
#include "mozilla/TimeStamp.h"
#include <stdint.h>
#include "jstypes.h"
@ -35,7 +37,7 @@ struct JS_PUBLIC_API(WorkBudget)
*/
class JS_PUBLIC_API(SliceBudget)
{
static const int64_t unlimitedDeadline = INT64_MAX;
static const mozilla::TimeStamp unlimitedDeadline;
static const intptr_t unlimitedStartCounter = INTPTR_MAX;
bool checkOverBudget();
@ -49,7 +51,7 @@ class JS_PUBLIC_API(SliceBudget)
TimeBudget timeBudget;
WorkBudget workBudget;
int64_t deadline; /* in microseconds */
mozilla::TimeStamp deadline;
intptr_t counter;
static const intptr_t CounterReset = 1000;
@ -81,8 +83,8 @@ class JS_PUBLIC_API(SliceBudget)
return checkOverBudget();
}
bool isWorkBudget() const { return deadline == 0; }
bool isTimeBudget() const { return deadline > 0 && !isUnlimited(); }
bool isWorkBudget() const { return deadline.IsNull(); }
bool isTimeBudget() const { return !deadline.IsNull() && !isUnlimited(); }
bool isUnlimited() const { return deadline == unlimitedDeadline; }
int describe(char* buffer, size_t maxlen) const;

View File

@ -305,7 +305,7 @@ namespace TuningDefaults {
static const bool DynamicHeapGrowthEnabled = false;
/* JSGC_HIGH_FREQUENCY_TIME_LIMIT */
static const uint64_t HighFrequencyThresholdUsec = 1000000;
static const auto HighFrequencyThreshold = mozilla::TimeDuration::FromSeconds(1);
/* JSGC_HIGH_FREQUENCY_LOW_LIMIT */
static const uint64_t HighFrequencyLowLimitBytes = 100 * 1024 * 1024;
@ -346,6 +346,8 @@ namespace TuningDefaults {
}}} // namespace js::gc::TuningDefaults
static const auto ONE_SECOND = mozilla::TimeDuration::FromSeconds(1);
/*
* We start to incremental collection for a zone when a proportion of its
* threshold is reached. This is configured by the
@ -953,7 +955,7 @@ GCRuntime::GCRuntime(JSRuntime* rt) :
numArenasFreeCommitted(0),
verifyPreData(nullptr),
chunkAllocationSinceLastGC(false),
lastGCTime(PRMJ_Now()),
lastGCTime(mozilla::TimeStamp::Now()),
mode(TuningDefaults::Mode),
numActiveZoneIters(0),
cleanUpEverything(false),
@ -1414,7 +1416,7 @@ GCSchedulingTunables::setParameter(JSGCParamKey key, uint32_t value, const AutoL
gcMaxNurseryBytes_ = value;
break;
case JSGC_HIGH_FREQUENCY_TIME_LIMIT:
highFrequencyThresholdUsec_ = value * PRMJ_USEC_PER_MSEC;
highFrequencyThreshold_ = mozilla::TimeDuration::FromMilliseconds(value);
break;
case JSGC_HIGH_FREQUENCY_LOW_LIMIT: {
uint64_t newLimit = (uint64_t)value * 1024 * 1024;
@ -1570,7 +1572,7 @@ GCSchedulingTunables::GCSchedulingTunables()
allocThresholdFactorAvoidInterrupt_(TuningDefaults::AllocThresholdFactorAvoidInterrupt),
zoneAllocDelayBytes_(TuningDefaults::ZoneAllocDelayBytes),
dynamicHeapGrowthEnabled_(TuningDefaults::DynamicHeapGrowthEnabled),
highFrequencyThresholdUsec_(TuningDefaults::HighFrequencyThresholdUsec),
highFrequencyThreshold_(TuningDefaults::HighFrequencyThreshold),
highFrequencyLowLimitBytes_(TuningDefaults::HighFrequencyLowLimitBytes),
highFrequencyHighLimitBytes_(TuningDefaults::HighFrequencyHighLimitBytes),
highFrequencyHeapGrowthMax_(TuningDefaults::HighFrequencyHeapGrowthMax),
@ -1621,8 +1623,8 @@ GCSchedulingTunables::resetParameter(JSGCParamKey key, const AutoLockGC& lock)
gcMaxNurseryBytes_ = JS::DefaultNurseryBytes;
break;
case JSGC_HIGH_FREQUENCY_TIME_LIMIT:
highFrequencyThresholdUsec_ =
TuningDefaults::HighFrequencyThresholdUsec;
highFrequencyThreshold_ =
TuningDefaults::HighFrequencyThreshold;
break;
case JSGC_HIGH_FREQUENCY_LOW_LIMIT:
setHighFrequencyLowLimit(TuningDefaults::HighFrequencyLowLimitBytes);
@ -1698,7 +1700,7 @@ GCRuntime::getParameter(JSGCParamKey key, const AutoLockGC& lock)
case JSGC_MARK_STACK_LIMIT:
return marker.maxCapacity();
case JSGC_HIGH_FREQUENCY_TIME_LIMIT:
return tunables.highFrequencyThresholdUsec() / PRMJ_USEC_PER_MSEC;
return tunables.highFrequencyThreshold().ToMilliseconds();
case JSGC_HIGH_FREQUENCY_LOW_LIMIT:
return tunables.highFrequencyLowLimitBytes() / 1024 / 1024;
case JSGC_HIGH_FREQUENCY_HIGH_LIMIT:
@ -2142,7 +2144,8 @@ GCRuntime::shouldCompact()
return true;
}
return !isIncremental || rt->lastAnimationTime + PRMJ_USEC_PER_SEC < PRMJ_Now();
const auto &lastAnimationTime = rt->lastAnimationTime.ref();
return !isIncremental || lastAnimationTime.IsNull() || lastAnimationTime + ONE_SECOND < mozilla::TimeStamp::Now();
}
bool
@ -3248,6 +3251,8 @@ ArenaLists::queueForegroundThingsForSweep()
gcScriptArenasToUpdate = arenaListsToSweep(AllocKind::SCRIPT);
}
const mozilla::TimeStamp SliceBudget::unlimitedDeadline = mozilla::TimeStamp::Now() + mozilla::TimeDuration::Forever();
SliceBudget::SliceBudget()
: timeBudget(UnlimitedTimeBudget), workBudget(UnlimitedWorkBudget)
{
@ -3261,7 +3266,7 @@ SliceBudget::SliceBudget(TimeBudget time)
makeUnlimited();
} else {
// Note: TimeBudget(0) is equivalent to WorkBudget(CounterReset).
deadline = PRMJ_Now() + time.budget * PRMJ_USEC_PER_MSEC;
deadline = mozilla::TimeStamp::Now() + mozilla::TimeDuration::FromMilliseconds(time.budget);
counter = CounterReset;
}
}
@ -3272,7 +3277,7 @@ SliceBudget::SliceBudget(WorkBudget work)
if (work.budget < 0) {
makeUnlimited();
} else {
deadline = 0;
deadline = mozilla::TimeStamp();
counter = work.budget;
}
}
@ -3291,7 +3296,10 @@ SliceBudget::describe(char* buffer, size_t maxlen) const
bool
SliceBudget::checkOverBudget()
{
bool over = PRMJ_Now() >= deadline;
if (deadline.IsNull())
return true;
bool over = mozilla::TimeStamp::Now() >= deadline;
if (!over)
counter = CounterReset;
return over;
@ -4053,9 +4061,10 @@ GCRuntime::purgeRuntime()
}
bool
GCRuntime::shouldPreserveJITCode(Realm* realm, int64_t currentTime,
GCRuntime::shouldPreserveJITCode(Realm* realm, const mozilla::TimeStamp &currentTime,
JS::gcreason::Reason reason, bool canAllocateMoreCode)
{
if (cleanUpEverything)
return false;
if (!canAllocateMoreCode)
@ -4065,8 +4074,11 @@ GCRuntime::shouldPreserveJITCode(Realm* realm, int64_t currentTime,
return true;
if (realm->preserveJitCode())
return true;
if (realm->lastAnimationTime + PRMJ_USEC_PER_SEC >= currentTime)
const auto &lastAnimationTime = realm->lastAnimationTime.ref();
if (!lastAnimationTime.IsNull() && lastAnimationTime + ONE_SECOND >= currentTime)
return true;
if (reason == JS::gcreason::DEBUG_GC)
return true;
@ -4240,7 +4252,7 @@ GCRuntime::prepareZonesForCollection(JS::gcreason::Reason reason, bool* isFullOu
*isFullOut = true;
bool any = false;
int64_t currentTime = PRMJ_Now();
auto currentTime = mozilla::TimeStamp::Now();
for (ZonesIter zone(rt, WithAtoms); !zone.done(); zone.next()) {
/* Set up which zones will be collected. */
@ -6784,7 +6796,7 @@ GCRuntime::finishCollection()
marker.stop();
clearBufferedGrayRoots();
uint64_t currentTime = PRMJ_Now();
auto currentTime = mozilla::TimeStamp::Now();
schedulingState.updateHighFrequencyMode(lastGCTime, currentTime, tunables);
for (ZonesIter zone(rt, WithAtoms); !zone.done(); zone.next()) {

View File

@ -10,6 +10,7 @@
#include "mozilla/Atomics.h"
#include "mozilla/EnumSet.h"
#include "mozilla/Maybe.h"
#include "mozilla/TimeStamp.h"
#include "gc/ArenaList.h"
#include "gc/AtomMarking.h"
@ -600,7 +601,7 @@ class GCRuntime
void purgeRuntime();
MOZ_MUST_USE bool beginMarkPhase(JS::gcreason::Reason reason, AutoGCSession& session);
bool prepareZonesForCollection(JS::gcreason::Reason reason, bool* isFullOut);
bool shouldPreserveJITCode(JS::Realm* realm, int64_t currentTime,
bool shouldPreserveJITCode(JS::Realm* realm, const mozilla::TimeStamp &currentTime,
JS::gcreason::Reason reason, bool canAllocateMoreCode);
void traceRuntimeForMajorGC(JSTracer* trc, AutoGCSession& session);
void traceRuntimeAtoms(JSTracer* trc, const AutoAccessAtomsZone& atomsAccess);
@ -748,7 +749,7 @@ class GCRuntime
private:
UnprotectedData<bool> chunkAllocationSinceLastGC;
MainThreadData<int64_t> lastGCTime;
MainThreadData<mozilla::TimeStamp> lastGCTime;
/*
* JSGC_MODE

View File

@ -389,9 +389,9 @@ class GCSchedulingTunables
* JSGC_HIGH_FREQUENCY_TIME_LIMIT
*
* We enter high-frequency mode if we GC a twice within this many
* microseconds. This value is stored directly in microseconds.
* microseconds.
*/
MainThreadData<uint64_t> highFrequencyThresholdUsec_;
MainThreadData<mozilla::TimeDuration> highFrequencyThreshold_;
/*
* JSGC_HIGH_FREQUENCY_LOW_LIMIT
@ -450,7 +450,7 @@ class GCSchedulingTunables
double allocThresholdFactorAvoidInterrupt() const { return allocThresholdFactorAvoidInterrupt_; }
size_t zoneAllocDelayBytes() const { return zoneAllocDelayBytes_; }
bool isDynamicHeapGrowthEnabled() const { return dynamicHeapGrowthEnabled_; }
uint64_t highFrequencyThresholdUsec() const { return highFrequencyThresholdUsec_; }
const mozilla::TimeDuration &highFrequencyThreshold() const { return highFrequencyThreshold_; }
uint64_t highFrequencyLowLimitBytes() const { return highFrequencyLowLimitBytes_; }
uint64_t highFrequencyHighLimitBytes() const { return highFrequencyHighLimitBytes_; }
double highFrequencyHeapGrowthMax() const { return highFrequencyHeapGrowthMax_; }
@ -495,11 +495,11 @@ class GCSchedulingState
bool inHighFrequencyGCMode() const { return inHighFrequencyGCMode_; }
void updateHighFrequencyMode(uint64_t lastGCTime, uint64_t currentTime,
void updateHighFrequencyMode(const mozilla::TimeStamp &lastGCTime, const mozilla::TimeStamp &currentTime,
const GCSchedulingTunables& tunables) {
inHighFrequencyGCMode_ =
tunables.isDynamicHeapGrowthEnabled() && lastGCTime &&
lastGCTime + tunables.highFrequencyThresholdUsec() > currentTime;
tunables.isDynamicHeapGrowthEnabled() && !lastGCTime.IsNull() &&
lastGCTime + tunables.highFrequencyThreshold() > currentTime;
}
};

View File

@ -8,6 +8,7 @@
#include "mozilla/Atomics.h"
#include "mozilla/PodOperations.h"
#include "mozilla/TimeStamp.h"
#include <stdint.h>
@ -420,7 +421,7 @@ js::NotifyAnimationActivity(JSObject* obj)
{
MOZ_ASSERT(obj->is<GlobalObject>());
int64_t timeNow = PRMJ_Now();
auto timeNow = mozilla::TimeStamp::Now();
obj->as<GlobalObject>().realm()->lastAnimationTime = timeNow;
obj->runtimeFromMainThread()->lastAnimationTime = timeNow;
}

View File

@ -10,6 +10,7 @@
#include "mozilla/LinkedList.h"
#include "mozilla/Maybe.h"
#include "mozilla/MemoryReporting.h"
#include "mozilla/TimeStamp.h"
#include "mozilla/Tuple.h"
#include "mozilla/Variant.h"
#include "mozilla/XorShift128PlusRNG.h"
@ -422,7 +423,7 @@ class JS::Realm : public JS::shadow::Realm
js::ReadBarrieredScriptSourceObject selfHostingScriptSource { nullptr };
// Last time at which an animation was played for this realm.
int64_t lastAnimationTime = 0;
js::MainThreadData<mozilla::TimeStamp> lastAnimationTime;
/*
* For generational GC, record whether a write barrier has added this

View File

@ -173,7 +173,6 @@ JSRuntime::JSRuntime(JSRuntime* parentRuntime)
autoWritableJitCodeActive_(false),
oomCallback(nullptr),
debuggerMallocSizeOf(ReturnZeroSize),
lastAnimationTime(0),
performanceMonitoring_(),
stackFormat_(parentRuntime ? js::StackFormat::Default
: js::StackFormat::SpiderMonkey),

View File

@ -16,6 +16,7 @@
#include "mozilla/MemoryReporting.h"
#include "mozilla/Scoped.h"
#include "mozilla/ThreadLocal.h"
#include "mozilla/TimeStamp.h"
#include "mozilla/Vector.h"
#include <algorithm>
@ -934,7 +935,7 @@ struct JSRuntime : public js::MallocProvider<JSRuntime>
js::MainThreadData<mozilla::MallocSizeOf> debuggerMallocSizeOf;
/* Last time at which an animation was played for this runtime. */
mozilla::Atomic<int64_t> lastAnimationTime;
js::MainThreadData<mozilla::TimeStamp> lastAnimationTime;
private:
js::MainThreadData<js::PerformanceMonitoring> performanceMonitoring_;