Merge inbound to mozilla-central r=merge a=merge

This commit is contained in:
Csoregi Natalia 2017-11-06 12:45:47 +02:00
commit a731ff981c
13 changed files with 247 additions and 164 deletions

View File

@ -929,7 +929,7 @@ D3D11DXVA2Manager::CopyToImage(IMFSample* aVideoSample,
NS_ENSURE_TRUE(client, E_FAIL);
RefPtr<IDXGIKeyedMutex> mutex;
HRESULT hr;
HRESULT hr = S_OK;
RefPtr<ID3D11Texture2D> texture = image->GetTexture();
texture->QueryInterface((IDXGIKeyedMutex**)getter_AddRefs(mutex));
@ -987,7 +987,9 @@ D3D11DXVA2Manager::CopyToImage(IMFSample* aVideoSample,
// It appears some race-condition may allow us to arrive here even when mSyncObject
// is null. It's better to avoid that crash.
client->SyncWithObject(mSyncObject);
mSyncObject->Synchronize();
if (!mSyncObject->Synchronize(true)) {
return DXGI_ERROR_DEVICE_RESET;
}
}
image.forget(aOutImage);

View File

@ -115,6 +115,10 @@ WMFMediaDataDecoder::ProcessError(HRESULT aError, const char* aReason)
SendTelemetry(aError);
mRecordedError = true;
}
//TODO: For the error DXGI_ERROR_DEVICE_RESET, we could return
// NS_ERROR_DOM_MEDIA_NEED_NEW_DECODER to get the latest device. Maybe retry
// up to 3 times.
return DecodePromise::CreateAndReject(
MediaResult(NS_ERROR_DOM_MEDIA_DECODE_ERR,
RESULT_DETAIL("%s:%x", aReason, aError)),
@ -127,7 +131,10 @@ WMFMediaDataDecoder::ProcessDecode(MediaRawData* aSample)
DecodedData results;
HRESULT hr = mMFTManager->Input(aSample);
if (hr == MF_E_NOTACCEPTING) {
ProcessOutput(results);
hr = ProcessOutput(results);
if (FAILED(hr)) {
return ProcessError(hr, "MFTManager::Output(1)");
}
hr = mMFTManager->Input(aSample);
}
@ -143,7 +150,7 @@ WMFMediaDataDecoder::ProcessDecode(MediaRawData* aSample)
if (SUCCEEDED(hr) || hr == MF_E_TRANSFORM_NEED_MORE_INPUT) {
return DecodePromise::CreateAndResolve(Move(results), __func__);
}
return ProcessError(hr, "MFTManager::Output");
return ProcessError(hr, "MFTManager::Output(2)");
}
HRESULT

View File

@ -108,6 +108,6 @@ load oscillator-ended-1.html
load oscillator-ended-2.html
skip-if(Android&&AndroidVersion=='22') load video-replay-after-audio-end.html # bug 1315125, bug 1358876
# This needs to run at the end to avoid leaking busted state into other tests.
load 691096-1.html
skip-if(Android) load 691096-1.html # Bug 1365451
load 1236639.html
test-pref(media.navigator.permission.disabled,true) load 1388372.html

View File

@ -843,6 +843,7 @@ tags=msg
skip-if = android_version == '17' # android(bug 1232305)
tags=msg
[test_mediarecorder_record_addtracked_stream.html]
skip-if = toolkit == 'android' # Bug 1408241
tags=msg capturestream
[test_mediarecorder_record_audiocontext.html]
skip-if = android_version == '17' # android(bug 1232305)

View File

@ -28,14 +28,15 @@ public:
static already_AddRefed<SyncObjectHost> CreateSyncObjectHost(
#ifdef XP_WIN
ID3D11Device* aDevice = nullptr
ID3D11Device* aDevice = nullptr
#endif
);
);
virtual bool Init() = 0;
virtual SyncHandle GetSyncHandle() = 0;
// Return false for failed synchronization.
virtual bool Synchronize() = 0;
protected:
@ -50,9 +51,9 @@ public:
static already_AddRefed<SyncObjectClient> CreateSyncObjectClient(SyncHandle aHandle
#ifdef XP_WIN
, ID3D11Device* aDevice = nullptr
, ID3D11Device* aDevice = nullptr
#endif
);
);
enum class SyncType {
D3D11,
@ -60,7 +61,8 @@ public:
virtual SyncType GetSyncType() = 0;
virtual void Synchronize() = 0;
// Return false for failed synchronization.
virtual bool Synchronize(bool aFallible = false) = 0;
virtual bool IsSyncObjectValid() = 0;

View File

@ -1697,7 +1697,7 @@ SyncObjectD3D11Client::SyncObjectD3D11Client(SyncHandle aSyncHandle, ID3D11Devic
}
bool
SyncObjectD3D11Client::Init()
SyncObjectD3D11Client::Init(bool aFallible)
{
if (mKeyedMutex) {
return true;
@ -1709,7 +1709,7 @@ SyncObjectD3D11Client::Init()
(void**)(ID3D11Texture2D**)getter_AddRefs(mSyncTexture));
if (FAILED(hr) || !mSyncTexture) {
gfxCriticalNote << "Failed to OpenSharedResource for SyncObjectD3D11: " << hexa(hr);
if (ShouldDevCrashOnSyncInitFailure()) {
if (!aFallible && ShouldDevCrashOnSyncInitFailure()) {
gfxDevCrash(LogReason::D3D11FinalizeFrame) << "Without device reset: " << hexa(hr);
}
return false;
@ -1719,8 +1719,13 @@ SyncObjectD3D11Client::Init()
if (FAILED(hr) || !mKeyedMutex) {
// Leave both the critical error and MOZ_CRASH for now; the critical error lets
// us "save" the hr value. We will probably eventually replace this with gfxDevCrash.
gfxCriticalError() << "Failed to get KeyedMutex (2): " << hexa(hr);
MOZ_CRASH("GFX: Cannot get D3D11 KeyedMutex");
if (!aFallible) {
gfxCriticalError() << "Failed to get KeyedMutex (2): " << hexa(hr);
MOZ_CRASH("GFX: Cannot get D3D11 KeyedMutex");
} else {
gfxCriticalNote << "Failed to get KeyedMutex (3): " << hexa(hr);
}
return false;
}
return true;
@ -1747,8 +1752,8 @@ SyncObjectD3D11Client::IsSyncObjectValid()
// into our sync object and only use a lock for this sync object.
// This way, we don't have to sync every texture we send to the compositor.
// We only have to do this once per transaction.
void
SyncObjectD3D11Client::Synchronize()
bool
SyncObjectD3D11Client::Synchronize(bool aFallible)
{
// Since this can be called from either the Paint or Main thread.
// We don't want this to race since we initialize the sync texture here
@ -1756,10 +1761,10 @@ SyncObjectD3D11Client::Synchronize()
MutexAutoLock syncLock(mSyncLock);
if (!mSyncedTextures.size()) {
return;
return true;
}
if (!Init()) {
return;
if (!Init(aFallible)) {
return false;
}
HRESULT hr;
@ -1768,9 +1773,14 @@ SyncObjectD3D11Client::Synchronize()
if (hr == WAIT_TIMEOUT) {
if (DeviceManagerDx::Get()->HasDeviceReset()) {
gfxWarning() << "AcquireSync timed out because of device reset.";
return;
return false;
}
gfxDevCrash(LogReason::D3D11SyncLock) << "Timeout on the D3D11 sync lock";
if (aFallible) {
gfxWarning() << "Timeout on the D3D11 sync lock.";
} else {
gfxDevCrash(LogReason::D3D11SyncLock) << "Timeout on the D3D11 sync lock.";
}
return false;
}
D3D11_BOX box;
@ -1782,13 +1792,13 @@ SyncObjectD3D11Client::Synchronize()
if (dev == DeviceManagerDx::Get()->GetContentDevice()) {
if (DeviceManagerDx::Get()->HasDeviceReset()) {
return;
return false;
}
}
if (dev != mDevice) {
gfxWarning() << "Attempt to sync texture from invalid device.";
return;
return false;
}
RefPtr<ID3D11DeviceContext> ctx;
@ -1799,6 +1809,8 @@ SyncObjectD3D11Client::Synchronize()
}
mSyncedTextures.clear();
return true;
}
uint32_t

View File

@ -478,7 +478,7 @@ class SyncObjectD3D11Client : public SyncObjectClient
public:
explicit SyncObjectD3D11Client(SyncHandle aSyncHandle, ID3D11Device* aDevice);
virtual void Synchronize() override;
virtual bool Synchronize(bool aFallible) override;
virtual bool IsSyncObjectValid() override;
@ -487,7 +487,7 @@ public:
void RegisterTexture(ID3D11Texture2D* aTexture);
private:
bool Init();
bool Init(bool aFallible);
SyncHandle mSyncHandle;
RefPtr<ID3D11Device> mDevice;

View File

@ -1210,10 +1210,11 @@ class GCRuntime
AtomMarkingRuntime atomMarking;
private:
// When empty, chunks reside in the emptyChunks pool and are re-used as
// needed or eventually expired if not re-used. The emptyChunks pool gets
// refilled from the background allocation task heuristically so that empty
// chunks should always available for immediate allocation without syscalls.
// When chunks are empty, they reside in the emptyChunks pool and are
// re-used as needed or eventually expired if not re-used. The emptyChunks
// pool gets refilled from the background allocation task heuristically so
// that empty chunks should always be available for immediate allocation
// without syscalls.
GCLockData<ChunkPool> emptyChunks_;
// Chunks which have had some, but not all, of their arenas allocated live

View File

@ -116,7 +116,8 @@ js::Nursery::Nursery(JSRuntime* rt)
, currentStartPosition_(0)
, currentEnd_(0)
, currentChunk_(0)
, maxNurseryChunks_(0)
, maxChunkCount_(0)
, chunkCountLimit_(0)
, previousPromotionRate_(0)
, profileThreshold_(0)
, enableProfiling_(false)
@ -140,15 +141,18 @@ js::Nursery::init(uint32_t maxNurseryBytes, AutoLockGCBgAlloc& lock)
return false;
/* maxNurseryBytes parameter is rounded down to a multiple of chunk size. */
maxNurseryChunks_ = maxNurseryBytes >> ChunkShift;
chunkCountLimit_ = maxNurseryBytes >> ChunkShift;
/* If no chunks are specified then the nursery is permanently disabled. */
if (maxNurseryChunks_ == 0)
if (chunkCountLimit_ == 0)
return true;
updateNumChunksLocked(1, lock);
if (numChunks() == 0)
maxChunkCount_ = 1;
if (!allocateNextChunk(0, lock)) {
maxChunkCount_ = 0;
return false;
}
/* After this point the Nursery has been enabled */
setCurrentChunk(0);
setStartPosition();
@ -192,12 +196,17 @@ js::Nursery::enable()
{
MOZ_ASSERT(isEmpty());
MOZ_ASSERT(!runtime()->gc.isVerifyPreBarriersEnabled());
if (isEnabled() || !maxChunks())
if (isEnabled() || !chunkCountLimit())
return;
updateNumChunks(1);
if (numChunks() == 0)
return;
{
AutoLockGCBgAlloc lock(runtime());
maxChunkCount_ = 1;
if (!allocateNextChunk(0, lock)) {
maxChunkCount_ = 0;
return;
}
}
setCurrentChunk(0);
setStartPosition();
@ -215,8 +224,12 @@ js::Nursery::disable()
MOZ_ASSERT(isEmpty());
if (!isEnabled())
return;
updateNumChunks(0);
freeChunksFrom(0);
maxChunkCount_ = 0;
currentEnd_ = 0;
runtime()->gc.storeBuffer().disable();
}
@ -237,7 +250,7 @@ js::Nursery::isEmpty() const
void
js::Nursery::enterZealMode() {
if (isEnabled())
updateNumChunks(maxNurseryChunks_);
maxChunkCount_ = chunkCountLimit();
}
void
@ -303,9 +316,19 @@ js::Nursery::allocate(size_t size)
#endif
if (currentEnd() < position() + size) {
if (currentChunk_ + 1 == numChunks())
unsigned chunkno = currentChunk_ + 1;
MOZ_ASSERT(chunkno <= chunkCountLimit());
MOZ_ASSERT(chunkno <= maxChunkCount());
MOZ_ASSERT(chunkno <= allocatedChunkCount());
if (chunkno == maxChunkCount())
return nullptr;
setCurrentChunk(currentChunk_ + 1);
if (MOZ_UNLIKELY(chunkno == allocatedChunkCount())) {
AutoLockGCBgAlloc lock(runtime());
if (!allocateNextChunk(chunkno, lock))
return nullptr;
MOZ_ASSERT(chunkno < allocatedChunkCount());
}
setCurrentChunk(chunkno);
}
void* thing = (void*)position();
@ -524,6 +547,7 @@ js::Nursery::renderProfileJSON(JSONPrinter& json) const
json.property("bytes_used", previousGC.nurseryUsedBytes);
json.property("cur_capacity", previousGC.nurseryCapacity);
json.property("new_capacity", spaceToEnd());
json.property("lazy_capacity", allocatedChunkCount() * ChunkSize);
json.beginObjectProperty("phase_times");
@ -686,7 +710,7 @@ js::Nursery::collect(JS::gcreason::Reason reason)
// Disable the nursery if the user changed the configuration setting. The
// nursery can only be re-enabled by resetting the configurationa and
// restarting firefox.
if (maxNurseryChunks_ == 0)
if (chunkCountLimit_ == 0)
disable();
endProfile(ProfileKey::Total);
@ -709,7 +733,7 @@ js::Nursery::collect(JS::gcreason::Reason reason)
fprintf(stderr, "MinorGC: %20s %5.1f%% %4u ",
JS::gcreason::ExplainReason(reason),
promotionRate * 100,
numChunks());
maxChunkCount());
printProfileDurations(profileDurations_);
if (reportTenurings_) {
@ -914,18 +938,18 @@ js::Nursery::clear()
{
#ifdef JS_GC_ZEAL
/* Poison the nursery contents so touching a freed object will crash. */
for (unsigned i = 0; i < numChunks(); i++)
for (unsigned i = 0; i < allocatedChunkCount(); i++)
chunk(i).poisonAndInit(runtime(), JS_SWEPT_NURSERY_PATTERN);
if (runtime()->hasZealMode(ZealMode::GenerationalGC)) {
/* Only reset the alloc point when we are close to the end. */
if (currentChunk_ + 1 == numChunks())
if (currentChunk_ + 1 == maxChunkCount())
setCurrentChunk(0);
} else
#endif
{
#ifdef JS_CRASH_DIAGNOSTICS
for (unsigned i = 0; i < numChunks(); ++i)
for (unsigned i = 0; i < allocatedChunkCount(); ++i)
chunk(i).poisonAndInit(runtime(), JS_SWEPT_NURSERY_PATTERN);
#endif
setCurrentChunk(0);
@ -938,7 +962,7 @@ js::Nursery::clear()
size_t
js::Nursery::spaceToEnd() const
{
unsigned lastChunk = numChunks() - 1;
unsigned lastChunk = maxChunkCount() - 1;
MOZ_ASSERT(lastChunk >= currentStartChunk_);
MOZ_ASSERT(currentStartPosition_ - chunk(currentStartChunk_).start() <= NurseryChunkUsableSize);
@ -946,7 +970,7 @@ js::Nursery::spaceToEnd() const
size_t bytes = (chunk(currentStartChunk_).end() - currentStartPosition_) +
((lastChunk - currentStartChunk_) * NurseryChunkUsableSize);
MOZ_ASSERT(bytes <= numChunks() * NurseryChunkUsableSize);
MOZ_ASSERT(bytes <= maxChunkCount() * NurseryChunkUsableSize);
return bytes;
}
@ -954,14 +978,40 @@ js::Nursery::spaceToEnd() const
MOZ_ALWAYS_INLINE void
js::Nursery::setCurrentChunk(unsigned chunkno)
{
MOZ_ASSERT(chunkno < maxChunks());
MOZ_ASSERT(chunkno < numChunks());
MOZ_ASSERT(chunkno < chunkCountLimit());
MOZ_ASSERT(chunkno < allocatedChunkCount());
currentChunk_ = chunkno;
position_ = chunk(chunkno).start();
currentEnd_ = chunk(chunkno).end();
chunk(chunkno).poisonAndInit(runtime(), JS_FRESH_NURSERY_PATTERN);
}
bool
js::Nursery::allocateNextChunk(const unsigned chunkno,
AutoLockGCBgAlloc& lock)
{
const unsigned priorCount = allocatedChunkCount();
const unsigned newCount = priorCount + 1;
MOZ_ASSERT((chunkno == currentChunk_ + 1) || (chunkno == 0 && allocatedChunkCount() == 0));
MOZ_ASSERT(chunkno == allocatedChunkCount());
MOZ_ASSERT(chunkno < chunkCountLimit());
MOZ_ASSERT(chunkno < maxChunkCount());
if (!chunks_.resize(newCount))
return false;
Chunk* newChunk;
newChunk = runtime()->gc.getOrAllocChunk(lock);
if (!newChunk) {
chunks_.shrinkTo(priorCount);
return false;
}
chunks_[chunkno] = NurseryChunk::fromChunk(newChunk);
return true;
}
MOZ_ALWAYS_INLINE void
js::Nursery::setStartPosition()
{
@ -998,23 +1048,25 @@ js::Nursery::maybeResizeNursery(JS::gcreason::Reason reason)
float(previousGC.tenuredBytes) / float(previousGC.nurseryCapacity);
newMaxNurseryChunks = runtime()->gc.tunables.gcMaxNurseryBytes() >> ChunkShift;
if (newMaxNurseryChunks != maxNurseryChunks_) {
maxNurseryChunks_ = newMaxNurseryChunks;
if (newMaxNurseryChunks != chunkCountLimit_) {
chunkCountLimit_ = newMaxNurseryChunks;
/* The configured maximum nursery size is changing */
const int extraChunks = numChunks() - newMaxNurseryChunks;
if (extraChunks > 0) {
if (maxChunkCount() > newMaxNurseryChunks) {
/* We need to shrink the nursery */
shrinkAllocableSpace(extraChunks);
shrinkAllocableSpace(newMaxNurseryChunks);
previousPromotionRate_ = promotionRate;
return;
}
}
if (promotionRate > GrowThreshold)
if (promotionRate > GrowThreshold) {
// The GC nursery is an optimization and so if we fail to allocate
// nursery chunks we do not report an error.
growAllocableSpace();
else if (promotionRate < ShrinkThreshold && previousPromotionRate_ < ShrinkThreshold)
shrinkAllocableSpace(1);
} else if (promotionRate < ShrinkThreshold && previousPromotionRate_ < ShrinkThreshold) {
shrinkAllocableSpace(maxChunkCount() - 1);
}
previousPromotionRate_ = promotionRate;
}
@ -1022,72 +1074,46 @@ js::Nursery::maybeResizeNursery(JS::gcreason::Reason reason)
void
js::Nursery::growAllocableSpace()
{
updateNumChunks(Min(numChunks() * 2, maxNurseryChunks_));
maxChunkCount_ = Min(maxChunkCount() * 2, chunkCountLimit());
}
void
js::Nursery::shrinkAllocableSpace(unsigned removeNumChunks)
js::Nursery::freeChunksFrom(unsigned firstFreeChunk)
{
MOZ_ASSERT(firstFreeChunk < chunks_.length());
{
AutoLockGC lock(runtime());
for (unsigned i = firstFreeChunk; i < chunks_.length(); i++)
runtime()->gc.recycleChunk(chunk(i).toChunk(runtime()), lock);
}
chunks_.shrinkTo(firstFreeChunk);
}
void
js::Nursery::shrinkAllocableSpace(unsigned newCount)
{
#ifdef JS_GC_ZEAL
if (runtime()->hasZealMode(ZealMode::GenerationalGC))
return;
#endif
updateNumChunks(Max(numChunks() - removeNumChunks, 1u));
// Don't shrink the nursery to zero (use Nursery::disable() instead) and
// don't attempt to shrink it to the same size.
if ((newCount == 0) || (newCount == maxChunkCount()))
return;
MOZ_ASSERT(newCount < maxChunkCount());
if (newCount < allocatedChunkCount())
freeChunksFrom(newCount);
maxChunkCount_ = newCount;
}
void
js::Nursery::minimizeAllocableSpace()
{
#ifdef JS_GC_ZEAL
if (runtime()->hasZealMode(ZealMode::GenerationalGC))
return;
#endif
updateNumChunks(1);
}
void
js::Nursery::updateNumChunks(unsigned newCount)
{
if (numChunks() != newCount) {
AutoLockGCBgAlloc lock(runtime());
updateNumChunksLocked(newCount, lock);
}
}
void
js::Nursery::updateNumChunksLocked(unsigned newCount,
AutoLockGCBgAlloc& lock)
{
// The GC nursery is an optimization and so if we fail to allocate nursery
// chunks we do not report an error.
MOZ_ASSERT(newCount <= maxChunks());
unsigned priorCount = numChunks();
MOZ_ASSERT(priorCount != newCount);
if (newCount < priorCount) {
// Shrink the nursery and free unused chunks.
for (unsigned i = newCount; i < priorCount; i++)
runtime()->gc.recycleChunk(chunk(i).toChunk(runtime()), lock);
chunks_.shrinkTo(newCount);
return;
}
// Grow the nursery and allocate new chunks.
if (!chunks_.resize(newCount))
return;
for (unsigned i = priorCount; i < newCount; i++) {
auto newChunk = runtime()->gc.getOrAllocChunk(lock);
if (!newChunk) {
chunks_.shrinkTo(i);
return;
}
chunks_[i] = NurseryChunk::fromChunk(newChunk);
chunk(i).poisonAndInit(runtime(), JS_FRESH_NURSERY_PATTERN);
}
shrinkAllocableSpace(1);
}
bool

View File

@ -141,15 +141,22 @@ class Nursery
MOZ_MUST_USE bool init(uint32_t maxNurseryBytes, AutoLockGCBgAlloc& lock);
unsigned maxChunks() const { return maxNurseryChunks_; }
unsigned numChunks() const { return chunks_.length(); }
unsigned chunkCountLimit() const { return chunkCountLimit_; }
bool exists() const { return maxChunks() != 0; }
size_t nurserySize() const { return maxChunks() << ChunkShift; }
// Number of allocated (ready to use) chunks.
unsigned allocatedChunkCount() const { return chunks_.length(); }
// Total number of chunks and the capacity of the nursery. Chunks will be
// lazilly allocated and added to the chunks array up to this limit, after
// that the nursery must be collected, this limit may be raised during
// collection.
unsigned maxChunkCount() const { return maxChunkCount_; }
bool exists() const { return chunkCountLimit() != 0; }
void enable();
void disable();
bool isEnabled() const { return numChunks() != 0; }
bool isEnabled() const { return maxChunkCount() != 0; }
/* Return true if no allocations have been made since the last collection. */
bool isEmpty() const;
@ -234,7 +241,7 @@ class Nursery
MOZ_MUST_USE bool queueDictionaryModeObjectToSweep(NativeObject* obj);
size_t sizeOfHeapCommitted() const {
return numChunks() * gc::ChunkSize;
return allocatedChunkCount() * gc::ChunkSize;
}
size_t sizeOfMallocedBuffers(mozilla::MallocSizeOf mallocSizeOf) const {
if (!mallocedBuffers.initialized())
@ -253,7 +260,7 @@ class Nursery
MOZ_ALWAYS_INLINE size_t freeSpace() const {
MOZ_ASSERT(currentEnd_ - position_ <= NurseryChunkUsableSize);
return (currentEnd_ - position_) +
(numChunks() - currentChunk_ - 1) * NurseryChunkUsableSize;
(maxChunkCount() - currentChunk_ - 1) * NurseryChunkUsableSize;
}
#ifdef JS_GC_ZEAL
@ -311,8 +318,18 @@ class Nursery
/* The index of the chunk that is currently being allocated from. */
unsigned currentChunk_;
/* Maximum number of chunks to allocate for the nursery. */
unsigned maxNurseryChunks_;
/*
* The nursery may grow the chunks_ vector up to this size without a
* collection. This allows the nursery to grow lazilly. This limit may
* change during maybeResizeNursery() each collection.
*/
unsigned maxChunkCount_;
/*
* This limit is fixed by configuration. It represents the maximum size
* the nursery is permitted to tune itself to in maybeResizeNursery();
*/
unsigned chunkCountLimit_;
/* Promotion rate for the previous minor collection. */
float previousPromotionRate_;
@ -419,8 +436,6 @@ class Nursery
Canary* lastCanary_;
#endif
NurseryChunk* allocChunk();
NurseryChunk& chunk(unsigned index) const {
return *chunks_[index];
}
@ -428,9 +443,12 @@ class Nursery
void setCurrentChunk(unsigned chunkno);
void setStartPosition();
void updateNumChunks(unsigned newCount);
void updateNumChunksLocked(unsigned newCount,
AutoLockGCBgAlloc& lock);
/*
* Allocate the next chunk, or the first chunk for initialization.
* Callers will probably want to call setCurrentChunk(0) next.
*/
MOZ_MUST_USE bool allocateNextChunk(unsigned chunkno,
AutoLockGCBgAlloc& lock);
MOZ_ALWAYS_INLINE uintptr_t currentEnd() const;
@ -483,9 +501,13 @@ class Nursery
/* Change the allocable space provided by the nursery. */
void maybeResizeNursery(JS::gcreason::Reason reason);
void growAllocableSpace();
void shrinkAllocableSpace(unsigned removeNumChunks);
void shrinkAllocableSpace(unsigned newCount);
void minimizeAllocableSpace();
// Free the chunks starting at firstFreeChunk until the end of the chunks
// vector. Shrinks the vector but does not update maxChunkCount().
void freeChunksFrom(unsigned firstFreeChunk);
/* Profile recording and printing. */
void maybeClearProfileDurations();
void startProfile(ProfileKey key);

View File

@ -3263,7 +3263,7 @@ class ValueObserver final
: public nsIObserver
, public ValueObserverHashKey
{
~ValueObserver() { Preferences::RemoveObserver(this, mPrefName.get()); }
~ValueObserver() = default;
public:
NS_DECL_ISUPPORTS
@ -4681,8 +4681,7 @@ pref_InitInitialObjects()
if (!strcmp(NS_STRINGIFY(MOZ_UPDATE_CHANNEL), "nightly") ||
!strcmp(NS_STRINGIFY(MOZ_UPDATE_CHANNEL), "aurora") ||
!strcmp(NS_STRINGIFY(MOZ_UPDATE_CHANNEL), "beta") ||
developerBuild) {
!strcmp(NS_STRINGIFY(MOZ_UPDATE_CHANNEL), "beta") || developerBuild) {
PREF_SetBoolPref(kTelemetryPref, true, true);
} else {
PREF_SetBoolPref(kTelemetryPref, false, true);
@ -4951,13 +4950,13 @@ NotifyObserver(const char* aPref, void* aClosure)
}
static void
RegisterPriorityCallback(PrefChangedFunc aCallback,
const char* aPref,
void* aClosure)
RegisterCallbackHelper(PrefChangedFunc aCallback,
const char* aPref,
void* aClosure,
Preferences::MatchKind aMatchKind,
bool aIsPriority)
{
MOZ_ASSERT(Preferences::IsServiceAvailable());
ValueObserverHashKey hashKey(aPref, aCallback, Preferences::ExactMatch);
ValueObserverHashKey hashKey(aPref, aCallback, aMatchKind);
RefPtr<ValueObserver> observer;
gObserverTable->Get(&hashKey, getter_AddRefs(observer));
if (observer) {
@ -4965,15 +4964,27 @@ RegisterPriorityCallback(PrefChangedFunc aCallback,
return;
}
observer = new ValueObserver(aPref, aCallback, Preferences::ExactMatch);
observer = new ValueObserver(aPref, aCallback, aMatchKind);
observer->AppendClosure(aClosure);
PREF_RegisterCallback(aPref,
NotifyObserver,
static_cast<nsIObserver*>(observer),
/* isPriority */ true);
PREF_RegisterCallback(
aPref, NotifyObserver, static_cast<nsIObserver*>(observer), aIsPriority);
gObserverTable->Put(observer, observer);
}
// RegisterVarCacheCallback uses high priority callbacks to ensure that cache
// observers are called prior to ordinary pref observers. Doing this ensures
// that ordinary observers will never get stale values from cache variables.
static void
RegisterVarCacheCallback(PrefChangedFunc aCallback,
const char* aPref,
void* aClosure)
{
MOZ_ASSERT(Preferences::IsServiceAvailable());
RegisterCallbackHelper(
aCallback, aPref, aClosure, Preferences::ExactMatch, /* isPriority */ true);
}
/* static */ nsresult
Preferences::RegisterCallback(PrefChangedFunc aCallback,
const char* aPref,
@ -4983,20 +4994,8 @@ Preferences::RegisterCallback(PrefChangedFunc aCallback,
MOZ_ASSERT(aCallback);
NS_ENSURE_TRUE(InitStaticMembers(), NS_ERROR_NOT_AVAILABLE);
ValueObserverHashKey hashKey(aPref, aCallback, aMatchKind);
RefPtr<ValueObserver> observer;
gObserverTable->Get(&hashKey, getter_AddRefs(observer));
if (observer) {
observer->AppendClosure(aClosure);
return NS_OK;
}
observer = new ValueObserver(aPref, aCallback, aMatchKind);
observer->AppendClosure(aClosure);
nsresult rv = AddStrongObserver(observer, aPref);
NS_ENSURE_SUCCESS(rv, rv);
gObserverTable->Put(observer, observer);
RegisterCallbackHelper(
aCallback, aPref, aClosure, aMatchKind, /* isPriority */ false);
return NS_OK;
}
@ -5037,15 +5036,14 @@ Preferences::UnregisterCallback(PrefChangedFunc aCallback,
observer->RemoveClosure(aClosure);
if (observer->HasNoClosures()) {
// Delete the callback since its list of closures is empty.
MOZ_ALWAYS_SUCCEEDS(
PREF_UnregisterCallback(aPref, NotifyObserver, observer));
gObserverTable->Remove(observer);
}
return NS_OK;
}
// We insert cache observers using RegisterPriorityCallback to ensure they are
// called prior to ordinary pref observers. Doing this ensures that ordinary
// observers will never get stale values from cache variables.
static void
BoolVarChanged(const char* aPref, void* aClosure)
{
@ -5076,7 +5074,7 @@ Preferences::AddBoolVarCache(bool* aCache, const char* aPref, bool aDefault)
data->mCacheLocation = aCache;
data->mDefaultValueBool = aDefault;
CacheDataAppendElement(data);
RegisterPriorityCallback(BoolVarChanged, aPref, data);
RegisterVarCacheCallback(BoolVarChanged, aPref, data);
return NS_OK;
}
@ -5103,7 +5101,7 @@ Preferences::AddIntVarCache(int32_t* aCache,
data->mCacheLocation = aCache;
data->mDefaultValueInt = aDefault;
CacheDataAppendElement(data);
RegisterPriorityCallback(IntVarChanged, aPref, data);
RegisterVarCacheCallback(IntVarChanged, aPref, data);
return NS_OK;
}
@ -5130,7 +5128,7 @@ Preferences::AddUintVarCache(uint32_t* aCache,
data->mCacheLocation = aCache;
data->mDefaultValueUint = aDefault;
CacheDataAppendElement(data);
RegisterPriorityCallback(UintVarChanged, aPref, data);
RegisterVarCacheCallback(UintVarChanged, aPref, data);
return NS_OK;
}
@ -5159,7 +5157,7 @@ Preferences::AddAtomicUintVarCache(Atomic<uint32_t, Order>* aCache,
data->mCacheLocation = aCache;
data->mDefaultValueUint = aDefault;
CacheDataAppendElement(data);
RegisterPriorityCallback(AtomicUintVarChanged<Order>, aPref, data);
RegisterVarCacheCallback(AtomicUintVarChanged<Order>, aPref, data);
return NS_OK;
}
@ -5192,7 +5190,7 @@ Preferences::AddFloatVarCache(float* aCache, const char* aPref, float aDefault)
data->mCacheLocation = aCache;
data->mDefaultValueFloat = aDefault;
CacheDataAppendElement(data);
RegisterPriorityCallback(FloatVarChanged, aPref, data);
RegisterVarCacheCallback(FloatVarChanged, aPref, data);
return NS_OK;
}

View File

@ -1338,6 +1338,8 @@ nsCookieService::TryInitDB(bool aRecreateDB)
// No more upgrades. Update the schema version.
rv = mDefaultDBState->syncConn->SetSchemaVersion(COOKIES_SCHEMA_VERSION);
NS_ENSURE_SUCCESS(rv, RESULT_RETRY);
Telemetry::Accumulate(Telemetry::MOZ_SQLITE_COOKIES_OLD_SCHEMA, dbSchemaVersion);
MOZ_FALLTHROUGH;
case COOKIES_SCHEMA_VERSION:
@ -1429,6 +1431,7 @@ nsCookieService::TryInitDB(bool aRecreateDB)
gCookieService->ImportCookies(oldCookieFile);
oldCookieFile->Remove(false);
gCookieService->mDBState = initialState;
Telemetry::Accumulate(Telemetry::MOZ_SQLITE_COOKIES_OLD_SCHEMA, 0);
});
NS_DispatchToMainThread(runnable);

View File

@ -4426,6 +4426,15 @@
"n_buckets": 10,
"description": "Time spent on SQLite read() (ms) *** No longer needed (bug 1156565). Delete histogram and accumulation code! ***"
},
"MOZ_SQLITE_COOKIES_OLD_SCHEMA": {
"record_in_processes": ["main"],
"expires_in_version": "62",
"kind": "enumerated",
"n_values": 10,
"bug_numbers": [1412218],
"alert_emails": ["necko@mozilla.com", "junior@mozilla.com"],
"description": "Old schema version of the cookie database. 0 for having legacy cookies.txt."
},
"MOZ_SQLITE_COOKIES_BLOCK_MAIN_THREAD_MS": {
"record_in_processes": ["main"],
"expires_in_version": "never",