From 10e5d880fae1c4293c3578dce6cc1e197f98980e Mon Sep 17 00:00:00 2001 From: Seth Fowler Date: Wed, 26 Nov 2014 13:22:10 -0800 Subject: [PATCH 01/64] Bug 1057904 (Part 1) - Use RawAccessRef in FrameBlender and related classes and clean up. r=tn --- image/src/FrameBlender.cpp | 203 ++++++++++++++++------------------- image/src/FrameBlender.h | 36 ++++--- image/src/FrameSequence.cpp | 103 ------------------ image/src/FrameSequence.h | 206 ------------------------------------ image/src/RasterImage.cpp | 53 ++-------- image/src/imgFrame.cpp | 35 ++++++ image/src/imgFrame.h | 1 + image/src/moz.build | 1 - 8 files changed, 158 insertions(+), 480 deletions(-) delete mode 100644 image/src/FrameSequence.cpp delete mode 100644 image/src/FrameSequence.h diff --git a/image/src/FrameBlender.cpp b/image/src/FrameBlender.cpp index 06e406671c13..9f47601816e8 100644 --- a/image/src/FrameBlender.cpp +++ b/image/src/FrameBlender.cpp @@ -6,6 +6,7 @@ #include "FrameBlender.h" #include "mozilla/MemoryReporting.h" +#include "mozilla/Move.h" #include "MainThreadUtils.h" #include "pixman.h" @@ -16,14 +17,10 @@ using namespace gfx; namespace image { -FrameBlender::FrameBlender(FrameSequence* aSequenceToUse /* = nullptr */) - : mFrames(aSequenceToUse) - , mAnim(nullptr) +FrameBlender::FrameBlender() + : mAnim(nullptr) , mLoopCount(-1) { - if (!mFrames) { - mFrames = new FrameSequence(); - } } FrameBlender::~FrameBlender() @@ -31,47 +28,57 @@ FrameBlender::~FrameBlender() delete mAnim; } -already_AddRefed -FrameBlender::GetFrameSequence() +already_AddRefed +FrameBlender::GetFrame(uint32_t aFrameNum) { - nsRefPtr seq(mFrames); - return seq.forget(); + if (mAnim && mAnim->lastCompositedFrameIndex == int32_t(aFrameNum)) { + nsRefPtr frame = mAnim->compositingFrame.get(); + return frame.forget(); + } + return RawGetFrame(aFrameNum); } already_AddRefed -FrameBlender::GetFrame(uint32_t framenum) const +FrameBlender::RawGetFrame(uint32_t aFrameNum) { if (!mAnim) { - NS_ASSERTION(framenum == 0, "Don't ask for a frame > 0 if we're not animated!"); - return mFrames->GetFrame(0).GetFrame(); + NS_ASSERTION(aFrameNum == 0, + "Don't ask for a frame > 0 if we're not animated!"); + aFrameNum = 0; } - if (mAnim->lastCompositedFrameIndex == int32_t(framenum)) { - return mAnim->compositingFrame.GetFrame(); + if (aFrameNum >= mFrames.Length()) { + return nullptr; } - return mFrames->GetFrame(framenum).GetFrame(); + nsRefPtr frame = mFrames[aFrameNum].get(); + return frame.forget(); } -already_AddRefed -FrameBlender::RawGetFrame(uint32_t framenum) const +int32_t +FrameBlender::GetFrameDisposalMethod(uint32_t aFrameNum) const { if (!mAnim) { - NS_ASSERTION(framenum == 0, "Don't ask for a frame > 0 if we're not animated!"); - return mFrames->GetFrame(0).GetFrame(); + NS_ASSERTION(aFrameNum == 0, + "Don't ask for a frame > 0 if we're not animated!"); + aFrameNum = 0; } - return mFrames->GetFrame(framenum).GetFrame(); + if (aFrameNum >= mFrames.Length()) { + return FrameBlender::kDisposeNotSpecified; + } + return mFrames[aFrameNum]->GetFrameDisposalMethod(); } uint32_t FrameBlender::GetNumFrames() const { - return mFrames->GetNumFrames(); + return mFrames.Length(); } int32_t -FrameBlender::GetTimeoutForFrame(uint32_t framenum) const +FrameBlender::GetTimeoutForFrame(uint32_t aFrameNum) { - nsRefPtr frame = RawGetFrame(framenum); + nsRefPtr frame = RawGetFrame(aFrameNum); const int32_t timeout = frame->GetRawTimeout(); + // Ensure a minimal time between updates so we don't throttle the UI thread. // consider 0 == unspecified and make it fast but not too fast. Unless we have // a single loop GIF. See bug 890743, bug 125137, bug 139677, and bug 207059. @@ -85,8 +92,10 @@ FrameBlender::GetTimeoutForFrame(uint32_t framenum) const // It seems that there are broken tools out there that set a 0ms or 10ms // timeout when they really want a "default" one. So munge values in that // range. - if (timeout >= 0 && timeout <= 10 && mLoopCount != 0) + if (timeout >= 0 && timeout <= 10 && mLoopCount != 0) { return 100; + } + return timeout; } @@ -103,60 +112,33 @@ FrameBlender::GetLoopCount() const } void -FrameBlender::RemoveFrame(uint32_t framenum) +FrameBlender::RemoveFrame(uint32_t aFrameNum) { - NS_ABORT_IF_FALSE(framenum < GetNumFrames(), "Deleting invalid frame!"); - - mFrames->RemoveFrame(framenum); + MOZ_ASSERT(aFrameNum < GetNumFrames(), "Deleting invalid frame!"); + mFrames.RemoveElementAt(aFrameNum); } void FrameBlender::ClearFrames() { - // Forget our old frame sequence, letting whoever else has it deal with it. - mFrames = new FrameSequence(); + mFrames.Clear(); + mFrames.Compact(); } void -FrameBlender::InsertFrame(uint32_t framenum, imgFrame* aFrame) +FrameBlender::InsertFrame(uint32_t aFrameNum, RawAccessFrameRef&& aRef) { - NS_ABORT_IF_FALSE(framenum <= GetNumFrames(), "Inserting invalid frame!"); - mFrames->InsertFrame(framenum, aFrame); - if (GetNumFrames() > 1) { - EnsureAnimExists(); - } -} + MOZ_ASSERT(aRef, "Need a reference to a frame"); + MOZ_ASSERT(aFrameNum <= GetNumFrames(), "Inserting invalid frame"); -already_AddRefed -FrameBlender::SwapFrame(uint32_t framenum, imgFrame* aFrame) -{ - NS_ABORT_IF_FALSE(framenum < GetNumFrames(), "Swapping invalid frame!"); - - nsRefPtr ret; - - // Steal the imgFrame from wherever it's currently stored - if (mAnim && mAnim->lastCompositedFrameIndex == int32_t(framenum)) { - ret = mAnim->compositingFrame.Forget(); - mAnim->lastCompositedFrameIndex = -1; - nsRefPtr toDelete(mFrames->SwapFrame(framenum, aFrame)); - } else { - ret = mFrames->SwapFrame(framenum, aFrame); - } - - return ret.forget(); -} - -void -FrameBlender::EnsureAnimExists() -{ - if (!mAnim) { - // Create the animation context + mFrames.InsertElementAt(aFrameNum, Move(aRef)); + if (GetNumFrames() == 2) { + MOZ_ASSERT(!mAnim, "Shouldn't have an animation context yet"); mAnim = new Anim(); - - // We should only get into this code path directly after we've created our - // second frame (hence we know we're animated). - MOZ_ASSERT(GetNumFrames() == 2); } + + MOZ_ASSERT(GetNumFrames() < 2 || mAnim, + "If we're animated we should have an animation context now"); } //****************************************************************************** @@ -167,20 +149,16 @@ FrameBlender::DoBlend(nsIntRect* aDirtyRect, uint32_t aPrevFrameIndex, uint32_t aNextFrameIndex) { - if (!aDirtyRect) { - return false; - } + nsRefPtr prevFrame = GetFrame(aPrevFrameIndex); + nsRefPtr nextFrame = GetFrame(aNextFrameIndex); - const FrameDataPair& prevFrame = mFrames->GetFrame(aPrevFrameIndex); - const FrameDataPair& nextFrame = mFrames->GetFrame(aNextFrameIndex); - if (!prevFrame.HasFrameData() || !nextFrame.HasFrameData()) { - return false; - } + MOZ_ASSERT(prevFrame && nextFrame, "Should have frames here"); - int32_t prevFrameDisposalMethod = prevFrame->GetFrameDisposalMethod(); + int32_t prevFrameDisposalMethod = GetFrameDisposalMethod(aPrevFrameIndex); if (prevFrameDisposalMethod == FrameBlender::kDisposeRestorePrevious && - !mAnim->compositingPrevFrame) + !mAnim->compositingPrevFrame) { prevFrameDisposalMethod = FrameBlender::kDisposeClear; + } nsIntRect prevFrameRect = prevFrame->GetRect(); bool isFullPrevFrame = (prevFrameRect.x == 0 && prevFrameRect.y == 0 && @@ -190,10 +168,11 @@ FrameBlender::DoBlend(nsIntRect* aDirtyRect, // Optimization: DisposeClearAll if the previous frame is the same size as // container and it's clearing itself if (isFullPrevFrame && - (prevFrameDisposalMethod == FrameBlender::kDisposeClear)) + (prevFrameDisposalMethod == FrameBlender::kDisposeClear)) { prevFrameDisposalMethod = FrameBlender::kDisposeClearAll; + } - int32_t nextFrameDisposalMethod = nextFrame->GetFrameDisposalMethod(); + int32_t nextFrameDisposalMethod = GetFrameDisposalMethod(aNextFrameIndex); nsIntRect nextFrameRect = nextFrame->GetRect(); bool isFullNextFrame = (nextFrameRect.x == 0 && nextFrameRect.y == 0 && nextFrameRect.width == mSize.width && @@ -260,14 +239,13 @@ FrameBlender::DoBlend(nsIntRect* aDirtyRect, // Create the Compositing Frame if (!mAnim->compositingFrame) { - mAnim->compositingFrame.SetFrame(new imgFrame()); - nsresult rv = - mAnim->compositingFrame->InitForDecoder(mSize, SurfaceFormat::B8G8R8A8); + nsRefPtr newFrame = new imgFrame; + nsresult rv = newFrame->InitForDecoder(mSize, SurfaceFormat::B8G8R8A8); if (NS_FAILED(rv)) { - mAnim->compositingFrame.SetFrame(nullptr); + mAnim->compositingFrame.reset(); return false; } - mAnim->compositingFrame.LockAndGetData(); + mAnim->compositingFrame = newFrame->RawAccessRef(); needToBlankComposite = true; } else if (int32_t(aNextFrameIndex) != mAnim->lastCompositedFrameIndex+1) { @@ -310,18 +288,18 @@ FrameBlender::DoBlend(nsIntRect* aDirtyRect, if (needToBlankComposite) { // If we just created the composite, it could have anything in its // buffer. Clear whole frame - ClearFrame(mAnim->compositingFrame.GetFrameData(), + ClearFrame(mAnim->compositingFrame->GetRawData(), mAnim->compositingFrame->GetRect()); } else { // Only blank out previous frame area (both color & Mask/Alpha) - ClearFrame(mAnim->compositingFrame.GetFrameData(), + ClearFrame(mAnim->compositingFrame->GetRawData(), mAnim->compositingFrame->GetRect(), prevFrameRect); } break; case FrameBlender::kDisposeClearAll: - ClearFrame(mAnim->compositingFrame.GetFrameData(), + ClearFrame(mAnim->compositingFrame->GetRawData(), mAnim->compositingFrame->GetRect()); break; @@ -329,16 +307,16 @@ FrameBlender::DoBlend(nsIntRect* aDirtyRect, // It would be better to copy only the area changed back to // compositingFrame. if (mAnim->compositingPrevFrame) { - CopyFrameImage(mAnim->compositingPrevFrame.GetFrameData(), + CopyFrameImage(mAnim->compositingPrevFrame->GetRawData(), mAnim->compositingPrevFrame->GetRect(), - mAnim->compositingFrame.GetFrameData(), + mAnim->compositingFrame->GetRawData(), mAnim->compositingFrame->GetRect()); // destroy only if we don't need it for this frame's disposal if (nextFrameDisposalMethod != FrameBlender::kDisposeRestorePrevious) - mAnim->compositingPrevFrame.SetFrame(nullptr); + mAnim->compositingPrevFrame.reset(); } else { - ClearFrame(mAnim->compositingFrame.GetFrameData(), + ClearFrame(mAnim->compositingFrame->GetRawData(), mAnim->compositingFrame->GetRect()); } break; @@ -353,22 +331,22 @@ FrameBlender::DoBlend(nsIntRect* aDirtyRect, if (mAnim->lastCompositedFrameIndex != int32_t(aNextFrameIndex - 1)) { if (isFullPrevFrame && !prevFrame->GetIsPaletted()) { // Just copy the bits - CopyFrameImage(prevFrame.GetFrameData(), + CopyFrameImage(prevFrame->GetRawData(), prevFrame->GetRect(), - mAnim->compositingFrame.GetFrameData(), + mAnim->compositingFrame->GetRawData(), mAnim->compositingFrame->GetRect()); } else { if (needToBlankComposite) { // Only blank composite when prev is transparent or not full. if (prevFrame->GetHasAlpha() || !isFullPrevFrame) { - ClearFrame(mAnim->compositingFrame.GetFrameData(), + ClearFrame(mAnim->compositingFrame->GetRawData(), mAnim->compositingFrame->GetRect()); } } - DrawFrameTo(prevFrame.GetFrameData(), prevFrameRect, + DrawFrameTo(prevFrame->GetRawData(), prevFrameRect, prevFrame->PaletteDataLength(), prevFrame->GetHasAlpha(), - mAnim->compositingFrame.GetFrameData(), + mAnim->compositingFrame->GetRawData(), mAnim->compositingFrame->GetRect(), FrameBlendMethod(prevFrame->GetBlendMethod())); } @@ -377,7 +355,7 @@ FrameBlender::DoBlend(nsIntRect* aDirtyRect, } else if (needToBlankComposite) { // If we just created the composite, it could have anything in it's // buffers. Clear them - ClearFrame(mAnim->compositingFrame.GetFrameData(), + ClearFrame(mAnim->compositingFrame->GetRawData(), mAnim->compositingFrame->GetRect()); } @@ -390,29 +368,27 @@ FrameBlender::DoBlend(nsIntRect* aDirtyRect, // It would be better if we just stored the area that nextFrame is going to // overwrite. if (!mAnim->compositingPrevFrame) { - mAnim->compositingPrevFrame.SetFrame(new imgFrame()); - nsresult rv = - mAnim->compositingPrevFrame->InitForDecoder(mSize, - SurfaceFormat::B8G8R8A8); + nsRefPtr newFrame = new imgFrame; + nsresult rv = newFrame->InitForDecoder(mSize, SurfaceFormat::B8G8R8A8); if (NS_FAILED(rv)) { - mAnim->compositingPrevFrame.SetFrame(nullptr); + mAnim->compositingPrevFrame.reset(); return false; } - mAnim->compositingPrevFrame.LockAndGetData(); + mAnim->compositingPrevFrame = newFrame->RawAccessRef(); } - CopyFrameImage(mAnim->compositingFrame.GetFrameData(), + CopyFrameImage(mAnim->compositingFrame->GetRawData(), mAnim->compositingFrame->GetRect(), - mAnim->compositingPrevFrame.GetFrameData(), + mAnim->compositingPrevFrame->GetRawData(), mAnim->compositingPrevFrame->GetRect()); } // blit next frame into it's correct spot - DrawFrameTo(nextFrame.GetFrameData(), nextFrameRect, + DrawFrameTo(nextFrame->GetRawData(), nextFrameRect, nextFrame->PaletteDataLength(), nextFrame->GetHasAlpha(), - mAnim->compositingFrame.GetFrameData(), + mAnim->compositingFrame->GetRawData(), mAnim->compositingFrame->GetRect(), FrameBlendMethod(nextFrame->GetBlendMethod())); @@ -590,14 +566,23 @@ size_t FrameBlender::SizeOfDecodedWithComputedFallbackIfHeap(gfxMemoryLocation aLocation, MallocSizeOf aMallocSizeOf) const { - size_t n = mFrames->SizeOfDecodedWithComputedFallbackIfHeap(aLocation, aMallocSizeOf); + size_t n = 0; + + for (uint32_t i = 0; i < mFrames.Length(); ++i) { + n += mFrames[i]->SizeOfExcludingThisWithComputedFallbackIfHeap(aLocation, + aMallocSizeOf); + } if (mAnim) { if (mAnim->compositingFrame) { - n += mAnim->compositingFrame->SizeOfExcludingThisWithComputedFallbackIfHeap(aLocation, aMallocSizeOf); + n += mAnim->compositingFrame + ->SizeOfExcludingThisWithComputedFallbackIfHeap(aLocation, + aMallocSizeOf); } if (mAnim->compositingPrevFrame) { - n += mAnim->compositingPrevFrame->SizeOfExcludingThisWithComputedFallbackIfHeap(aLocation, aMallocSizeOf); + n += mAnim->compositingPrevFrame + ->SizeOfExcludingThisWithComputedFallbackIfHeap(aLocation, + aMallocSizeOf); } } diff --git a/image/src/FrameBlender.h b/image/src/FrameBlender.h index a7fc62f84691..f70774420c16 100644 --- a/image/src/FrameBlender.h +++ b/image/src/FrameBlender.h @@ -9,14 +9,12 @@ #include "mozilla/MemoryReporting.h" #include "gfxTypes.h" -#include "FrameSequence.h" +#include "imgFrame.h" #include "nsCOMPtr.h" namespace mozilla { namespace image { -class imgFrame; - /** * FrameBlender stores and gives access to imgFrames. It also knows how to * blend frames from previous to next, looping if necessary. @@ -32,28 +30,25 @@ public: * * If aSequenceToUse is not specified, it will be allocated automatically. */ - explicit FrameBlender(FrameSequence* aSequenceToUse = nullptr); + FrameBlender(); ~FrameBlender(); bool DoBlend(nsIntRect* aDirtyRect, uint32_t aPrevFrameIndex, uint32_t aNextFrameIndex); - already_AddRefed GetFrameSequence(); - /** * Get the @aIndex-th frame, including (if applicable) any results of * blending. */ - already_AddRefed GetFrame(uint32_t aIndex) const; + already_AddRefed GetFrame(uint32_t aIndex); /** * Get the @aIndex-th frame in the frame index, ignoring results of blending. */ - already_AddRefed RawGetFrame(uint32_t aIndex) const; + already_AddRefed RawGetFrame(uint32_t aIndex); - void InsertFrame(uint32_t framenum, imgFrame* aFrame); - void RemoveFrame(uint32_t framenum); - already_AddRefed SwapFrame(uint32_t framenum, imgFrame* aFrame); + void InsertFrame(uint32_t aFrameNum, RawAccessFrameRef&& aRef); + void RemoveFrame(uint32_t aFrameNum); void ClearFrames(); /* The total number of frames in this image. */ @@ -64,7 +59,7 @@ public: * falls in between a certain range then the timeout is adjusted so that * it's never 0. If the animation does not loop then no adjustments are made. */ - int32_t GetTimeoutForFrame(uint32_t framenum) const; + int32_t GetTimeoutForFrame(uint32_t aFrameNum); /* * Set number of times to loop the image. @@ -112,6 +107,15 @@ public: private: + /** + * Get the disposal method of the @aIndex-th frame. + * + * Note that it's not safe to use GetFrame(aIndex)->GetFrameDisposalMethod() + * instead, because the frame GetFrame() returns may be a blended frame which + * does not have the correct disposal method set. + */ + int32_t GetFrameDisposalMethod(uint32_t aIndex) const; + struct Anim { //! Track the last composited frame for Optimizations (See DoComposite code) @@ -125,7 +129,7 @@ private: * lastCompositedFrameIndex to -1. Code assume that if * lastCompositedFrameIndex >= 0 then compositingFrame exists. */ - FrameDataPair compositingFrame; + RawAccessFrameRef compositingFrame; /** the previous composited frame, for DISPOSE_RESTORE_PREVIOUS * @@ -133,15 +137,13 @@ private: * stored in cases where the image specifies it wants the last frame back * when it's done with the current frame. */ - FrameDataPair compositingPrevFrame; + RawAccessFrameRef compositingPrevFrame; Anim() : lastCompositedFrameIndex(-1) {} }; - void EnsureAnimExists(); - /** Clears an area of with transparent black. * * @param aFrameData Target Frame data @@ -180,7 +182,7 @@ private: private: // data //! All the frames of the image - nsRefPtr mFrames; + nsTArray mFrames; nsIntSize mSize; Anim* mAnim; int32_t mLoopCount; diff --git a/image/src/FrameSequence.cpp b/image/src/FrameSequence.cpp deleted file mode 100644 index 5131f164a1c6..000000000000 --- a/image/src/FrameSequence.cpp +++ /dev/null @@ -1,103 +0,0 @@ -/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- - * This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ - -#include "FrameSequence.h" - -namespace mozilla { -namespace image { - -FrameSequence::~FrameSequence() -{ - ClearFrames(); -} - -const FrameDataPair& -FrameSequence::GetFrame(uint32_t framenum) const -{ - if (framenum >= mFrames.Length()) { - static FrameDataPair empty; - return empty; - } - - return mFrames[framenum]; -} - -uint32_t -FrameSequence::GetNumFrames() const -{ - return mFrames.Length(); -} - -void -FrameSequence::RemoveFrame(uint32_t framenum) -{ - NS_ABORT_IF_FALSE(framenum < mFrames.Length(), "Deleting invalid frame!"); - - mFrames.RemoveElementAt(framenum); -} - -void -FrameSequence::ClearFrames() -{ - // Since FrameDataPair holds an nsAutoPtr to its frame, clearing the mFrames - // array also deletes all the frames. - mFrames.Clear(); -} - -void -FrameSequence::InsertFrame(uint32_t framenum, imgFrame* aFrame) -{ - NS_ABORT_IF_FALSE(framenum <= mFrames.Length(), "Inserting invalid frame!"); - mFrames.InsertElementAt(framenum, aFrame); - if (GetNumFrames() > 1) { - // If we're creating our second element, we now know we're animated. - // Therefore, we need to lock the first frame too. - if (GetNumFrames() == 2) { - mFrames[0].LockAndGetData(); - } - - // Whenever we have more than one frame, we always lock *all* our frames - // so we have all the image data pointers. - mFrames[framenum].LockAndGetData(); - } -} - -already_AddRefed -FrameSequence::SwapFrame(uint32_t framenum, imgFrame* aFrame) -{ - NS_ABORT_IF_FALSE(framenum < mFrames.Length(), "Swapping invalid frame!"); - - FrameDataPair ret; - - // Steal the imgFrame. - if (framenum < mFrames.Length()) { - ret = mFrames[framenum]; - } - - if (aFrame) { - mFrames.ReplaceElementAt(framenum, aFrame); - } else { - mFrames.RemoveElementAt(framenum); - } - - return ret.GetFrame(); -} - -size_t -FrameSequence::SizeOfDecodedWithComputedFallbackIfHeap(gfxMemoryLocation aLocation, - MallocSizeOf aMallocSizeOf) const -{ - size_t n = 0; - for (uint32_t i = 0; i < mFrames.Length(); ++i) { - FrameDataPair fdp = mFrames.SafeElementAt(i, FrameDataPair()); - NS_ABORT_IF_FALSE(fdp, "Null frame in frame array!"); - n += fdp->SizeOfExcludingThisWithComputedFallbackIfHeap(aLocation, aMallocSizeOf); - } - - return n; -} - -} // namespace image -} // namespace mozilla diff --git a/image/src/FrameSequence.h b/image/src/FrameSequence.h deleted file mode 100644 index f011243c7ca5..000000000000 --- a/image/src/FrameSequence.h +++ /dev/null @@ -1,206 +0,0 @@ -/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- - * - * This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ - -#ifndef mozilla_imagelib_FrameSequence_h_ -#define mozilla_imagelib_FrameSequence_h_ - -#include "nsTArray.h" -#include "mozilla/MemoryReporting.h" -#include "mozilla/Move.h" -#include "gfxTypes.h" -#include "imgFrame.h" - -namespace mozilla { -namespace image { - -/** - * FrameDataPair is a slightly-smart tuple of (frame, raw frame data) where the - * raw frame data is allowed to be (and is, initially) null. - * - * If you call LockAndGetData, you will be able to call GetFrameData() on that - * instance, and when the FrameDataPair is destructed, the imgFrame lock will - * be unlocked. - */ -class FrameDataPair -{ -public: - explicit FrameDataPair(imgFrame* frame) - : mFrame(frame) - , mFrameData(nullptr) - {} - - FrameDataPair() - : mFrameData(nullptr) - {} - - FrameDataPair(const FrameDataPair& aOther) - : mFrame(aOther.mFrame) - , mFrameData(nullptr) - {} - - FrameDataPair(FrameDataPair&& aOther) - : mFrame(Move(aOther.mFrame)) - , mFrameData(aOther.mFrameData) - { - aOther.mFrameData = nullptr; - } - - ~FrameDataPair() - { - if (mFrameData) { - mFrame->UnlockImageData(); - } - } - - FrameDataPair& operator=(const FrameDataPair& aOther) - { - if (&aOther != this) { - mFrame = aOther.mFrame; - mFrameData = nullptr; - } - return *this; - } - - FrameDataPair& operator=(FrameDataPair&& aOther) - { - MOZ_ASSERT(&aOther != this, "Moving to self"); - mFrame = Move(aOther.mFrame); - mFrameData = aOther.mFrameData; - aOther.mFrameData = nullptr; - return *this; - } - - // Lock the frame and store its mFrameData. The frame will be unlocked (and - // deleted) when this FrameDataPair is deleted. - void LockAndGetData() - { - if (mFrame) { - if (NS_SUCCEEDED(mFrame->LockImageData())) { - if (mFrame->GetIsPaletted()) { - mFrameData = reinterpret_cast(mFrame->GetPaletteData()); - } else { - mFrameData = mFrame->GetImageData(); - } - } - } - } - - // Null out this FrameDataPair and return its frame. You must ensure the - // frame will be deleted separately. - already_AddRefed Forget() - { - if (mFrameData) { - mFrame->UnlockImageData(); - } - - mFrameData = nullptr; - return mFrame.forget(); - } - - bool HasFrameData() const - { - if (mFrameData) { - MOZ_ASSERT(!!mFrame); - } - return !!mFrameData; - } - - uint8_t* GetFrameData() const - { - return mFrameData; - } - - already_AddRefed GetFrame() const - { - nsRefPtr frame = mFrame; - return frame.forget(); - } - - // Resets this FrameDataPair to work with a different frame. Takes ownership - // of the frame, deleting the old frame (if any). - void SetFrame(imgFrame* frame) - { - if (mFrameData) { - mFrame->UnlockImageData(); - } - - mFrame = frame; - mFrameData = nullptr; - } - - imgFrame* operator->() const - { - return mFrame.get(); - } - - bool operator==(imgFrame* other) const - { - return mFrame == other; - } - - operator bool() const - { - return mFrame != nullptr; - } - -private: - nsRefPtr mFrame; - uint8_t* mFrameData; -}; - -/** - * FrameSequence stores image frames (and their associated raw data pointers). - * It is little more than a smart array. - */ -class FrameSequence -{ - ~FrameSequence(); - -public: - - NS_INLINE_DECL_THREADSAFE_REFCOUNTING(FrameSequence) - - /** - * Get the read-only (frame, data) pair at index aIndex. - */ - const FrameDataPair& GetFrame(uint32_t aIndex) const; - - /** - * Insert a frame into the array. FrameSequence takes ownership of the frame. - */ - void InsertFrame(uint32_t framenum, imgFrame* aFrame); - - /** - * Remove (and delete) the frame at index framenum. - */ - void RemoveFrame(uint32_t framenum); - - /** - * Swap aFrame with the frame at sequence framenum, and return that frame. - * You take ownership over the frame returned. - */ - already_AddRefed SwapFrame(uint32_t framenum, imgFrame* aFrame); - - /** - * Remove (and delete) all frames. - */ - void ClearFrames(); - - /* The total number of frames in this image. */ - uint32_t GetNumFrames() const; - - size_t SizeOfDecodedWithComputedFallbackIfHeap(gfxMemoryLocation aLocation, - MallocSizeOf aMallocSizeOf) const; - -private: // data - //! All the frames of the image - nsTArray mFrames; -}; - -} // namespace image -} // namespace mozilla - -#endif /* mozilla_imagelib_FrameSequence_h_ */ diff --git a/image/src/RasterImage.cpp b/image/src/RasterImage.cpp index 72f894c0d95e..8c331c3866d6 100644 --- a/image/src/RasterImage.cpp +++ b/image/src/RasterImage.cpp @@ -361,15 +361,6 @@ RasterImage::~RasterImage() ReentrantMonitorAutoEnter lock(mDecodingMonitor); DecodePool::StopDecoding(this); mDecoder = nullptr; - - // Unlock the last frame (if we have any). Our invariant is that, while we - // have a decoder open, the last frame is always locked. - // This would be done in ShutdownDecoder, but since mDecoder is non-null, - // we didn't call ShutdownDecoder and we need to do it manually. - if (GetNumFrames() > 0) { - nsRefPtr curframe = mFrameBlender.RawGetFrame(GetNumFrames() - 1); - curframe->UnlockImageData(); - } } // Release any HQ scaled frames from the surface cache. @@ -1023,18 +1014,20 @@ RasterImage::InternalAddFrameHelper(uint32_t framenum, imgFrame *aFrame, if (framenum > GetNumFrames()) return NS_ERROR_INVALID_ARG; - nsRefPtr frame(aFrame); - - // We are in the middle of decoding. This will be unlocked when we finish - // decoding or switch to another frame. - frame->LockImageData(); + nsRefPtr frame = aFrame; + RawAccessFrameRef ref = frame->RawAccessRef(); + if (!ref) { + // Probably the OS discarded the frame. Exceedingly unlikely since we just + // created it, but it could happen. + return NS_ERROR_FAILURE; + } if (paletteData && paletteLength) frame->GetPaletteData(paletteData, paletteLength); frame->GetImageData(imageData, imageLength); - mFrameBlender.InsertFrame(framenum, frame); + mFrameBlender.InsertFrame(framenum, Move(ref)); frame.forget(aRetFrame); return NS_OK; @@ -1071,13 +1064,6 @@ RasterImage::InternalAddFrame(uint32_t framenum, NS_WARNING("imgFrame::Init should succeed"); NS_ENSURE_SUCCESS(rv, rv); - // We know we are in a decoder. Therefore, we must unlock the previous frame - // when we move on to decoding into the next frame. - if (GetNumFrames() > 0) { - nsRefPtr prevframe = mFrameBlender.RawGetFrame(GetNumFrames() - 1); - prevframe->UnlockImageData(); - } - if (GetNumFrames() == 0) { return InternalAddFrameHelper(framenum, frame, imageData, imageLength, paletteData, paletteLength, aRetFrame); @@ -1241,11 +1227,6 @@ RasterImage::EnsureFrame(uint32_t aFrameNum, int32_t aX, int32_t aY, } // Not reusable, so replace the frame directly. - - // We know this frame is already locked, because it's the one we're currently - // writing to. - frame->UnlockImageData(); - mFrameBlender.RemoveFrame(aFrameNum); nsRefPtr newFrame(new imgFrame()); nsIntRect frameRect(aX, aY, aWidth, aHeight); @@ -1329,8 +1310,7 @@ RasterImage::DecodingComplete() // into the first frame again immediately and this produces severe tearing. if (mMultipart) { if (GetNumFrames() == 1) { - mMultipartDecodedFrame = mFrameBlender.SwapFrame(GetCurrentFrameIndex(), - mMultipartDecodedFrame); + mMultipartDecodedFrame = mFrameBlender.GetFrame(GetCurrentFrameIndex()); } else { // Don't double buffer for animated multipart images. It entails more // complexity and it's not really needed since we already are smart about @@ -1931,14 +1911,6 @@ RasterImage::InitDecoder(bool aDoSizeDecode) NS_ABORT_IF_FALSE(0, "Shouldn't get here!"); } - // If we already have frames, we're probably in the multipart/x-mixed-replace - // case. Regardless, we need to lock the last frame. Our invariant is that, - // while we have a decoder open, the last frame is always locked. - if (GetNumFrames() > 0) { - nsRefPtr curframe = mFrameBlender.RawGetFrame(GetNumFrames() - 1); - curframe->LockImageData(); - } - // Initialize the decoder mDecoder->SetSizeDecode(aDoSizeDecode); mDecoder->SetDecodeFlags(mFrameDecodeFlags); @@ -2001,13 +1973,6 @@ RasterImage::ShutdownDecoder(ShutdownReason aReason) decoder->Finish(aReason); - // Unlock the last frame (if we have any). Our invariant is that, while we - // have a decoder open, the last frame is always locked. - if (GetNumFrames() > 0) { - nsRefPtr curframe = mFrameBlender.RawGetFrame(GetNumFrames() - 1); - curframe->UnlockImageData(); - } - // Kill off our decode request, if it's pending. (If not, this call is // harmless.) DecodePool::StopDecoding(this); diff --git a/image/src/imgFrame.cpp b/image/src/imgFrame.cpp index dd9d461fe323..fcc0015b8050 100644 --- a/image/src/imgFrame.cpp +++ b/image/src/imgFrame.cpp @@ -579,9 +579,34 @@ imgFrame::GetStride() const return VolatileSurfaceStride(mSize, mFormat); } +<<<<<<< found SurfaceFormat imgFrame::GetFormat() const { +||||||| expected +bool imgFrame::GetNeedsBackground() const +{ + // We need a background painted if we have alpha or we're incomplete. +======= +bool imgFrame::GetNeedsBackground() const +{ + // We need a background painted if we're incomplete. + if (!ImageComplete()) { + return true; + } + + // We need a background painted if we might not be opaque. +>>>>>>> replacement +<<<<<<< found return mFormat; +||||||| expected + return (mFormat == SurfaceFormat::B8G8R8A8 || !ImageComplete()); +======= + if (mFormat == SurfaceFormat::B8G8R8A8 && !mHasNoAlpha) { + return true; + } + + return false; +>>>>>>> replacement } uint32_t imgFrame::GetImageBytesPerRow() const @@ -653,6 +678,16 @@ uint32_t* imgFrame::GetPaletteData() const return data; } +uint8_t* +imgFrame::GetRawData() const +{ + MOZ_ASSERT(mLockCount, "Should be locked to call GetRawData()"); + if (mPalettedImageData) { + return mPalettedImageData; + } + return GetImageData(); +} + nsresult imgFrame::LockImageData() { MOZ_ASSERT(NS_IsMainThread()); diff --git a/image/src/imgFrame.h b/image/src/imgFrame.h index 55052e880973..ca9fd0a940c9 100644 --- a/image/src/imgFrame.h +++ b/image/src/imgFrame.h @@ -96,6 +96,7 @@ public: uint8_t* GetImageData() const; void GetPaletteData(uint32_t **aPalette, uint32_t *length) const; uint32_t* GetPaletteData() const; + uint8_t* GetRawData() const; int32_t GetRawTimeout() const; void SetRawTimeout(int32_t aTimeout); diff --git a/image/src/moz.build b/image/src/moz.build index c4ebae1ba685..1d022ea87cb3 100644 --- a/image/src/moz.build +++ b/image/src/moz.build @@ -22,7 +22,6 @@ UNIFIED_SOURCES += [ 'DynamicImage.cpp', 'FrameAnimator.cpp', 'FrameBlender.cpp', - 'FrameSequence.cpp', 'FrozenImage.cpp', 'Image.cpp', 'ImageFactory.cpp', From dbd2810ea1c7cfdddbeaefafac9fdea409fe023b Mon Sep 17 00:00:00 2001 From: Seth Fowler Date: Wed, 26 Nov 2014 13:22:10 -0800 Subject: [PATCH 02/64] Bug 1057904 (Part 2) - Make imgFrame::LockImageData and UnlockImageData private. r=tn --- image/src/imgFrame.h | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/image/src/imgFrame.h b/image/src/imgFrame.h index ca9fd0a940c9..1014071b4dec 100644 --- a/image/src/imgFrame.h +++ b/image/src/imgFrame.h @@ -64,9 +64,8 @@ public: * This is appropriate to use when drawing content into an imgFrame, as it * uses the same graphics backend as normal content drawing. The downside is * that the underlying surface may not be stored in a volatile buffer on all - * platforms, and raw access to the surface (using RawAccessRef() or - * LockImageData()) may be much more expensive than in the InitForDecoder() - * case. + * platforms, and raw access to the surface (using RawAccessRef()) may be much + * more expensive than in the InitForDecoder() case. */ nsresult InitWithDrawable(gfxDrawable* aDrawable, const nsIntSize& aSize, @@ -113,9 +112,6 @@ public: bool GetCompositingFailed() const; void SetCompositingFailed(bool val); - nsresult LockImageData(); - nsresult UnlockImageData(); - void SetDiscardable(); void SetOptimizable(); @@ -151,6 +147,8 @@ private: // methods ~imgFrame(); + nsresult LockImageData(); + nsresult UnlockImageData(); nsresult Optimize(); struct SurfaceWithFormat { From 8689c4e4294dfa365ac633add8071b6ef70e1225 Mon Sep 17 00:00:00 2001 From: Seth Fowler Date: Wed, 26 Nov 2014 13:22:10 -0800 Subject: [PATCH 03/64] Bug 1060869 (Part 1) - Add lifetime control to SurfaceCache. r=dholbert --- image/src/RasterImage.cpp | 11 +- image/src/SurfaceCache.cpp | 300 +++++++++++++++++++++++++++++-------- image/src/SurfaceCache.h | 131 +++++++++++++--- image/src/VectorImage.cpp | 9 +- 4 files changed, 358 insertions(+), 93 deletions(-) diff --git a/image/src/RasterImage.cpp b/image/src/RasterImage.cpp index 8c331c3866d6..1e80e667db26 100644 --- a/image/src/RasterImage.cpp +++ b/image/src/RasterImage.cpp @@ -205,7 +205,8 @@ public: // Insert the new surface into the cache immediately. We need to do this so // that we won't start multiple scaling jobs for the same size. SurfaceCache::Insert(mDstRef.get(), ImageKey(mImage.get()), - RasterSurfaceKey(mDstSize.ToIntSize(), mImageFlags)); + RasterSurfaceKey(mDstSize.ToIntSize(), mImageFlags), + Lifetime::Transient); return true; } @@ -259,9 +260,9 @@ public: NS_WARNING("HQ scaling failed"); // Remove the frame from the cache since we know we don't need it. - SurfaceCache::RemoveIfPresent(ImageKey(mImage.get()), - RasterSurfaceKey(mDstSize.ToIntSize(), - mImageFlags)); + SurfaceCache::RemoveSurface(ImageKey(mImage.get()), + RasterSurfaceKey(mDstSize.ToIntSize(), + mImageFlags)); // Release everything we're holding, too. mSrcRef.reset(); @@ -364,7 +365,7 @@ RasterImage::~RasterImage() } // Release any HQ scaled frames from the surface cache. - SurfaceCache::Discard(this); + SurfaceCache::RemoveImage(ImageKey(this)); mAnim = nullptr; diff --git a/image/src/SurfaceCache.cpp b/image/src/SurfaceCache.cpp index 565fc2a99afb..f6e4914fdade 100644 --- a/image/src/SurfaceCache.cpp +++ b/image/src/SurfaceCache.cpp @@ -118,18 +118,18 @@ class CachedSurface public: NS_INLINE_DECL_REFCOUNTING(CachedSurface) - CachedSurface(imgFrame* aSurface, - const IntSize aTargetSize, - const Cost aCost, - const ImageKey aImageKey, - const SurfaceKey& aSurfaceKey) + CachedSurface(imgFrame* aSurface, + const Cost aCost, + const ImageKey aImageKey, + const SurfaceKey& aSurfaceKey, + const Lifetime aLifetime) : mSurface(aSurface) - , mTargetSize(aTargetSize) , mCost(aCost) , mImageKey(aImageKey) , mSurfaceKey(aSurfaceKey) + , mLifetime(aLifetime) { - MOZ_ASSERT(mSurface, "Must have a valid SourceSurface"); + MOZ_ASSERT(mSurface, "Must have a valid surface"); MOZ_ASSERT(mImageKey, "Must have a valid image key"); } @@ -138,18 +138,34 @@ public: return mSurface->DrawableRef(); } + void SetLocked(bool aLocked) + { + if (aLocked && mLifetime == Lifetime::Persistent) { + // This may fail, and that's OK. We make no guarantees about whether + // locking is successful if you call SurfaceCache::LockImage() after + // SurfaceCache::Insert(). + mDrawableRef = mSurface->DrawableRef(); + } else { + mDrawableRef.reset(); + } + } + + bool IsLocked() const { return bool(mDrawableRef); } + ImageKey GetImageKey() const { return mImageKey; } SurfaceKey GetSurfaceKey() const { return mSurfaceKey; } CostEntry GetCostEntry() { return image::CostEntry(this, mCost); } nsExpirationState* GetExpirationState() { return &mExpirationState; } + Lifetime GetLifetime() const { return mLifetime; } private: nsExpirationState mExpirationState; nsRefPtr mSurface; - const IntSize mTargetSize; + DrawableFrameRef mDrawableRef; const Cost mCost; const ImageKey mImageKey; const SurfaceKey mSurfaceKey; + const Lifetime mLifetime; }; /* @@ -157,11 +173,16 @@ private: * able to remove all surfaces associated with an image when the image is * destroyed or invalidated. Since this will happen frequently, it makes sense * to make it cheap by storing the surfaces for each image separately. + * + * ImageSurfaceCache also keeps track of whether its associated image is locked + * or unlocked. */ class ImageSurfaceCache { - ~ImageSurfaceCache() {} + ~ImageSurfaceCache() { } public: + ImageSurfaceCache() : mLocked(false) { } + NS_INLINE_DECL_REFCOUNTING(ImageSurfaceCache) typedef nsRefPtrHashtable, CachedSurface> SurfaceTable; @@ -171,6 +192,9 @@ public: void Insert(const SurfaceKey& aKey, CachedSurface* aSurface) { MOZ_ASSERT(aSurface, "Should have a surface"); + MOZ_ASSERT(!mLocked || aSurface->GetLifetime() != Lifetime::Persistent || + aSurface->IsLocked(), + "Inserting an unlocked persistent surface for a locked image"); mSurfaces.Put(aKey, aSurface); } @@ -195,8 +219,12 @@ public: mSurfaces.EnumerateRead(aFunction, aData); } + void SetLocked(bool aLocked) { mLocked = aLocked; } + bool IsLocked() const { return mLocked; } + private: SurfaceTable mSurfaces; + bool mLocked; }; /* @@ -218,6 +246,7 @@ public: , mMemoryPressureObserver(new MemoryPressureObserver) , mMaxCost(aSurfaceCacheSize) , mAvailableCost(aSurfaceCacheSize) + , mLockedCost(0) { nsCOMPtr os = services::GetObserverService(); if (os) @@ -239,23 +268,22 @@ public: RegisterWeakMemoryReporter(this); } - void Insert(imgFrame* aSurface, - IntSize aTargetSize, + bool Insert(imgFrame* aSurface, const Cost aCost, const ImageKey aImageKey, - const SurfaceKey& aSurfaceKey) + const SurfaceKey& aSurfaceKey, + Lifetime aLifetime) { MOZ_ASSERT(!Lookup(aImageKey, aSurfaceKey), "Inserting a duplicate surface into the SurfaceCache"); - // If this is bigger than the maximum cache size, refuse to cache it. - if (!CanHold(aCost)) - return; + // If this is bigger than we can hold after discarding everything we can, + // refuse to cache it. + if (!CanHoldAfterDiscarding(aCost)) + return false; - nsRefPtr surface = - new CachedSurface(aSurface, aTargetSize, aCost, aImageKey, aSurfaceKey); - - // Remove elements in order of cost until we can fit this in the cache. + // Remove elements in order of cost until we can fit this in the cache. Note + // that locked surfaces aren't in mCosts, so we never remove them here. while (aCost > mAvailableCost) { MOZ_ASSERT(!mCosts.IsEmpty(), "Removed everything and it still won't fit"); Remove(mCosts.LastElement().GetSurface()); @@ -269,10 +297,24 @@ public: mImageCaches.Put(aImageKey, cache); } + nsRefPtr surface = + new CachedSurface(aSurface, aCost, aImageKey, aSurfaceKey, aLifetime); + + // We require that locking succeed if the image is locked and the surface is + // persistent; the caller may need to know this to handle errors correctly. + if (cache->IsLocked() && aLifetime == Lifetime::Persistent) { + surface->SetLocked(true); + if (!surface->IsLocked()) { + return false; + } + } + // Insert. MOZ_ASSERT(aCost <= mAvailableCost, "Inserting despite too large a cost"); cache->Insert(aSurfaceKey, surface); StartTracking(surface); + + return true; } void Remove(CachedSurface* aSurface) @@ -286,8 +328,9 @@ public: StopTracking(aSurface); cache->Remove(aSurface); - // Remove the per-image cache if it's unneeded now. - if (cache->IsEmpty()) { + // Remove the per-image cache if it's unneeded now. (Keep it if the image is + // locked, since the per-image cache is where we store that state.) + if (cache->IsEmpty() && !cache->IsLocked()) { mImageCaches.Remove(imageKey); } } @@ -299,8 +342,14 @@ public: "Cost too large and the caller didn't catch it"); mAvailableCost -= costEntry.GetCost(); - mCosts.InsertElementSorted(costEntry); - mExpirationTracker.AddObject(aSurface); + + if (aSurface->IsLocked()) { + mLockedCost += costEntry.GetCost(); + MOZ_ASSERT(mLockedCost <= mMaxCost, "Locked more than we can hold?"); + } else { + mCosts.InsertElementSorted(costEntry); + mExpirationTracker.AddObject(aSurface); + } } void StopTracking(CachedSurface* aSurface) @@ -308,12 +357,21 @@ public: MOZ_ASSERT(aSurface, "Should have a surface"); CostEntry costEntry = aSurface->GetCostEntry(); - mExpirationTracker.RemoveObject(aSurface); - DebugOnly foundInCosts = mCosts.RemoveElementSorted(costEntry); - mAvailableCost += costEntry.GetCost(); + if (aSurface->IsLocked()) { + MOZ_ASSERT(mLockedCost >= costEntry.GetCost(), "Costs don't balance"); + mLockedCost -= costEntry.GetCost(); + // XXX(seth): It'd be nice to use an O(log n) lookup here. This is O(n). + MOZ_ASSERT(!mCosts.Contains(costEntry), + "Shouldn't have a cost entry for a locked surface"); + } else { + mExpirationTracker.RemoveObject(aSurface); + DebugOnly foundInCosts = mCosts.RemoveElementSorted(costEntry); + MOZ_ASSERT(foundInCosts, "Lost track of costs for this surface"); + } - MOZ_ASSERT(foundInCosts, "Lost track of costs for this surface"); - MOZ_ASSERT(mAvailableCost <= mMaxCost, "More available cost than we started with"); + mAvailableCost += costEntry.GetCost(); + MOZ_ASSERT(mAvailableCost <= mMaxCost, + "More available cost than we started with"); } DrawableFrameRef Lookup(const ImageKey aImageKey, @@ -335,12 +393,15 @@ public: return DrawableFrameRef(); } - mExpirationTracker.MarkUsed(surface); + if (!surface->IsLocked()) { + mExpirationTracker.MarkUsed(surface); + } + return ref; } - void RemoveIfPresent(const ImageKey aImageKey, - const SurfaceKey& aSurfaceKey) + void RemoveSurface(const ImageKey aImageKey, + const SurfaceKey& aSurfaceKey) { nsRefPtr cache = GetImageCache(aImageKey); if (!cache) @@ -358,7 +419,33 @@ public: return aCost <= mMaxCost; } - void Discard(const ImageKey aImageKey) + void LockImage(const ImageKey aImageKey) + { + nsRefPtr cache = GetImageCache(aImageKey); + if (!cache) { + cache = new ImageSurfaceCache; + mImageCaches.Put(aImageKey, cache); + } + + cache->SetLocked(true); + + // Try to lock all the surfaces the per-image cache is holding. + cache->ForEach(DoLockSurface, this); + } + + void UnlockImage(const ImageKey aImageKey) + { + nsRefPtr cache = GetImageCache(aImageKey); + if (!cache) + return; // Already unlocked and removed. + + cache->SetLocked(false); + + // Unlock all the surfaces the per-image cache is holding. + cache->ForEach(DoUnlockSurface, this); + } + + void RemoveImage(const ImageKey aImageKey) { nsRefPtr cache = GetImageCache(aImageKey); if (!cache) @@ -372,13 +459,16 @@ public: cache->ForEach(DoStopTracking, this); // The per-image cache isn't needed anymore, so remove it as well. + // This implicitly unlocks the image if it was locked. mImageCaches.Remove(aImageKey); } void DiscardAll() { // Remove in order of cost because mCosts is an array and the other data - // structures are all hash tables. + // structures are all hash tables. Note that locked surfaces (persistent + // surfaces belonging to locked images) are not removed, since they aren't + // present in mCosts. while (!mCosts.IsEmpty()) { Remove(mCosts.LastElement().GetSurface()); } @@ -392,14 +482,64 @@ public: return PL_DHASH_NEXT; } - NS_IMETHOD - CollectReports(nsIHandleReportCallback* aHandleReport, nsISupports* aData, - bool aAnonymize) + static PLDHashOperator DoLockSurface(const SurfaceKey&, + CachedSurface* aSurface, + void* aCache) { - return MOZ_COLLECT_REPORT( - "imagelib-surface-cache", KIND_OTHER, UNITS_BYTES, - SizeOfSurfacesEstimate(), - "Memory used by the imagelib temporary surface cache."); + if (aSurface->GetLifetime() == Lifetime::Transient || + aSurface->IsLocked()) { + return PL_DHASH_NEXT; + } + + auto cache = static_cast(aCache); + cache->StopTracking(aSurface); + + // Lock the surface. This can fail. + aSurface->SetLocked(true); + cache->StartTracking(aSurface); + + return PL_DHASH_NEXT; + } + + static PLDHashOperator DoUnlockSurface(const SurfaceKey&, + CachedSurface* aSurface, + void* aCache) + { + if (aSurface->GetLifetime() == Lifetime::Transient || + !aSurface->IsLocked()) { + return PL_DHASH_NEXT; + } + + auto cache = static_cast(aCache); + cache->StopTracking(aSurface); + + aSurface->SetLocked(false); + cache->StartTracking(aSurface); + + return PL_DHASH_NEXT; + } + + NS_IMETHOD + CollectReports(nsIHandleReportCallback* aHandleReport, + nsISupports* aData, + bool aAnonymize) + { + nsresult rv; + + rv = MOZ_COLLECT_REPORT("imagelib-surface-cache-total", + KIND_OTHER, UNITS_BYTES, + SizeOfSurfacesEstimate(), + "Total memory used by the imagelib surface cache."); + NS_ENSURE_SUCCESS(rv, rv); + + rv = MOZ_COLLECT_REPORT("imagelib-surface-cache-locked", + KIND_OTHER, UNITS_BYTES, + SizeOfLockedSurfacesEstimate(), + "Memory used by locked surfaces in the imagelib " + "surface cache."); + NS_ENSURE_SUCCESS(rv, rv); + + return NS_OK; } // XXX(seth): This is currently only an estimate and, since we don't know @@ -411,6 +551,11 @@ public: return mMaxCost - mAvailableCost; } + Cost SizeOfLockedSurfacesEstimate() const + { + return mLockedCost; + } + private: already_AddRefed GetImageCache(const ImageKey aImageKey) { @@ -419,6 +564,16 @@ private: return imageCache.forget(); } + // This is similar to CanHold() except that it takes into account the costs of + // locked surfaces. It's used internally in Insert(), but it's not exposed + // publicly because if we start permitting multithreaded access to the surface + // cache, which seems likely, then the result would be meaningless: another + // thread could insert a persistent surface or lock an image at any time. + bool CanHoldAfterDiscarding(const Cost aCost) const + { + return aCost <= mMaxCost - mLockedCost; + } + struct SurfaceTracker : public nsExpirationTracker { SurfaceTracker(SurfaceCacheImpl* aCache, uint32_t aSurfaceCacheExpirationTimeMS) @@ -461,6 +616,7 @@ private: nsRefPtr mMemoryPressureObserver; const Cost mMaxCost; Cost mAvailableCost; + Cost mLockedCost; }; NS_IMPL_ISUPPORTS(SurfaceCacheImpl, nsIMemoryReporter) @@ -476,35 +632,39 @@ SurfaceCache::Initialize() // Initialize preferences. MOZ_ASSERT(!sInstance, "Shouldn't initialize more than once"); - // See gfxPrefs for the default values + // See gfxPrefs for the default values of these preferences. - // Length of time before an unused surface is removed from the cache, in milliseconds. - uint32_t surfaceCacheExpirationTimeMS = gfxPrefs::ImageMemSurfaceCacheMinExpirationMS(); + // Length of time before an unused surface is removed from the cache, in + // milliseconds. + uint32_t surfaceCacheExpirationTimeMS = + gfxPrefs::ImageMemSurfaceCacheMinExpirationMS(); // Maximum size of the surface cache, in kilobytes. - uint32_t surfaceCacheMaxSizeKB = gfxPrefs::ImageMemSurfaceCacheMaxSizeKB(); + uint64_t surfaceCacheMaxSizeKB = gfxPrefs::ImageMemSurfaceCacheMaxSizeKB(); // A knob determining the actual size of the surface cache. Currently the // cache is (size of main memory) / (surface cache size factor) KB // or (surface cache max size) KB, whichever is smaller. The formula // may change in the future, though. - // For example, a value of 64 would yield a 64MB cache on a 4GB machine. + // For example, a value of 4 would yield a 256MB cache on a 1GB machine. // The smallest machines we are likely to run this code on have 256MB - // of memory, which would yield a 4MB cache on the default setting. + // of memory, which would yield a 64MB cache on this setting. uint32_t surfaceCacheSizeFactor = gfxPrefs::ImageMemSurfaceCacheSizeFactor(); // Clamp to avoid division by zero below. surfaceCacheSizeFactor = max(surfaceCacheSizeFactor, 1u); // Compute the size of the surface cache. - uint32_t proposedSize = PR_GetPhysicalMemorySize() / surfaceCacheSizeFactor; - uint32_t surfaceCacheSizeBytes = min(proposedSize, surfaceCacheMaxSizeKB * 1024); + uint64_t proposedSize = PR_GetPhysicalMemorySize() / surfaceCacheSizeFactor; + uint64_t surfaceCacheSizeBytes = min(proposedSize, surfaceCacheMaxSizeKB * 1024); + uint32_t finalSurfaceCacheSizeBytes = + min(surfaceCacheSizeBytes, uint64_t(UINT32_MAX)); // Create the surface cache singleton with the requested expiration time and // size. Note that the size is a limit that the cache may not grow beyond, but // we do not actually allocate any storage for surfaces at this time. sInstance = new SurfaceCacheImpl(surfaceCacheExpirationTimeMS, - surfaceCacheSizeBytes); + finalSurfaceCacheSizeBytes); sInstance->InitMemoryReporter(); } @@ -527,17 +687,19 @@ SurfaceCache::Lookup(const ImageKey aImageKey, return sInstance->Lookup(aImageKey, aSurfaceKey); } -/* static */ void +/* static */ bool SurfaceCache::Insert(imgFrame* aSurface, const ImageKey aImageKey, - const SurfaceKey& aSurfaceKey) + const SurfaceKey& aSurfaceKey, + Lifetime aLifetime) { MOZ_ASSERT(NS_IsMainThread()); - if (sInstance) { - Cost cost = ComputeCost(aSurfaceKey.Size()); - sInstance->Insert(aSurface, aSurfaceKey.Size(), cost, aImageKey, - aSurfaceKey); + if (!sInstance) { + return false; } + + Cost cost = ComputeCost(aSurfaceKey.Size()); + return sInstance->Insert(aSurface, cost, aImageKey, aSurfaceKey, aLifetime); } /* static */ bool @@ -553,21 +715,39 @@ SurfaceCache::CanHold(const IntSize& aSize) } /* static */ void -SurfaceCache::RemoveIfPresent(const ImageKey aImageKey, - const SurfaceKey& aSurfaceKey) +SurfaceCache::LockImage(Image* aImageKey) { MOZ_ASSERT(NS_IsMainThread()); if (sInstance) { - sInstance->RemoveIfPresent(aImageKey, aSurfaceKey); + return sInstance->LockImage(aImageKey); } } /* static */ void -SurfaceCache::Discard(Image* aImageKey) +SurfaceCache::UnlockImage(Image* aImageKey) { MOZ_ASSERT(NS_IsMainThread()); if (sInstance) { - sInstance->Discard(aImageKey); + return sInstance->UnlockImage(aImageKey); + } +} + +/* static */ void +SurfaceCache::RemoveSurface(const ImageKey aImageKey, + const SurfaceKey& aSurfaceKey) +{ + MOZ_ASSERT(NS_IsMainThread()); + if (sInstance) { + sInstance->RemoveSurface(aImageKey, aSurfaceKey); + } +} + +/* static */ void +SurfaceCache::RemoveImage(Image* aImageKey) +{ + MOZ_ASSERT(NS_IsMainThread()); + if (sInstance) { + sInstance->RemoveImage(aImageKey); } } diff --git a/image/src/SurfaceCache.h b/image/src/SurfaceCache.h index 29231a97d901..3a2a54b66ec8 100644 --- a/image/src/SurfaceCache.h +++ b/image/src/SurfaceCache.h @@ -109,16 +109,33 @@ VectorSurfaceKey(const gfx::IntSize& aSize, return SurfaceKey(aSize, aSVGContext, aAnimationTime, 0); } +MOZ_BEGIN_ENUM_CLASS(Lifetime, uint8_t) + Transient, + Persistent +MOZ_END_ENUM_CLASS(Lifetime) + /** * SurfaceCache is an imagelib-global service that allows caching of temporary - * surfaces. Surfaces expire from the cache automatically if they go too long - * without being accessed. + * surfaces. Surfaces normally expire from the cache automatically if they go + * too long without being accessed. * * SurfaceCache does not hold surfaces directly; instead, it holds imgFrame * objects, which hold surfaces but also layer on additional features specific * to imagelib's needs like animation, padding support, and transparent support * for volatile buffers. * + * Sometime it's useful to temporarily prevent surfaces from expiring from the + * cache. This is most often because losing the data could harm the user + * experience (for example, we often don't want to allow surfaces that are + * currently visible to expire) or because it's not possible to rematerialize + * the surface. SurfaceCache supports this through the use of image locking and + * surface lifetimes; see the comments for Insert() and LockImage() for more + * details. + * + * Any image which stores surfaces in the SurfaceCache *must* ensure that it + * calls RemoveImage() before it is destroyed. See the comments for + * RemoveImage() for more details. + * * SurfaceCache is not thread-safe; it should only be accessed from the main * thread. */ @@ -126,23 +143,25 @@ struct SurfaceCache { typedef gfx::IntSize IntSize; - /* + /** * Initialize static data. Called during imagelib module initialization. */ static void Initialize(); - /* + /** * Release static data. Called during imagelib module shutdown. */ static void Shutdown(); - /* + /** * Look up the imgFrame containing a surface in the cache and returns a * drawable reference to that imgFrame. * * If the imgFrame was found in the cache, but had stored its surface in a * volatile buffer which was discarded by the OS, then it is automatically - * removed from the cache and an empty DrawableFrameRef is returned. + * removed from the cache and an empty DrawableFrameRef is returned. Note that + * this will never happen to persistent surfaces associated with a locked + * image; the cache keeps a strong reference to such surfaces internally. * * @param aImageKey Key data identifying which image the surface belongs to. * @param aSurfaceKey Key data which uniquely identifies the requested surface. @@ -153,21 +172,46 @@ struct SurfaceCache static DrawableFrameRef Lookup(const ImageKey aImageKey, const SurfaceKey& aSurfaceKey); - /* + /** * Insert a surface into the cache. It is an error to call this function * without first calling Lookup to verify that the surface is not already in * the cache. * + * Each surface in the cache has a lifetime, either Transient or Persistent. + * Transient surfaces can expire from the cache at any time. Persistent + * surfaces can ordinarily also expire from the cache at any time, but if the + * image they're associated with is locked, then these surfaces will never + * expire. This means that surfaces which cannot be rematerialized should be + * inserted with a persistent lifetime *after* the image is locked with + * LockImage(); if you use the other order, the surfaces might expire before + * LockImage() gets called. + * + * If a surface cannot be rematerialized, it may be important to know whether + * it was inserted into the cache successfully. Insert() returns false if it + * failed to insert the surface, which could happen because of capacity + * reasons, or because it was already freed by the OS. If you aren't inserting + * a surface with persistent lifetime, or if the surface isn't associated with + * a locked image, the return value is useless: the surface might expire + * immediately after being inserted, even though Insert() returned true. Thus, + * most callers do not need to check the return value. + * * @param aTarget The new surface (wrapped in an imgFrame) to insert into * the cache. * @param aImageKey Key data identifying which image the surface belongs to. * @param aSurfaceKey Key data which uniquely identifies the requested surface. + * @param aLifetime Whether this is a transient surface that can always be + * allowed to expire, or a persistent surface that + * shouldn't expire if the image is locked. + * @return false if the surface could not be inserted. Only check this if + * inserting a persistent surface associated with a locked image (see + * above for more information). */ - static void Insert(imgFrame* aSurface, + static bool Insert(imgFrame* aSurface, const ImageKey aImageKey, - const SurfaceKey& aSurfaceKey); + const SurfaceKey& aSurfaceKey, + Lifetime aLifetime); - /* + /** * Checks if a surface of a given size could possibly be stored in the cache. * If CanHold() returns false, Insert() will always fail to insert the * surface, but the inverse is not true: Insert() may take more information @@ -183,30 +227,69 @@ struct SurfaceCache */ static bool CanHold(const IntSize& aSize); - /* - * Removes a surface from the cache, if it's present. + /** + * Locks an image, preventing any of that image's surfaces from expiring + * unless they have a transient lifetime. + * + * Regardless of locking, any of an image's surfaces may be removed using + * RemoveSurface(), and all of an image's surfaces are removed by + * RemoveImage(), whether the image is locked or not. + * + * It's safe to call LockImage() on an image that's already locked; this has + * no effect. + * + * You must always unlock any image you lock. You may do this explicitly by + * calling UnlockImage(), or implicitly by calling RemoveImage(). Since you're + * required to call RemoveImage() when you destroy an image, this doesn't + * impose any additional requirements, but it's preferable to call + * UnlockImage() earlier if it's possible. + * + * @param aImageKey The image to lock. + */ + static void LockImage(const ImageKey aImageKey); + + /** + * Unlocks an image, allowing any of its surfaces to expire at any time. + * + * It's OK to call UnlockImage() on an image that's already unlocked; this has + * no effect. + * + * @param aImageKey The image to lock. + */ + static void UnlockImage(const ImageKey aImageKey); + + /** + * Removes a surface from the cache, if it's present. If it's not present, + * RemoveSurface() has no effect. * * Use this function to remove individual surfaces that have become invalid. - * Prefer Discard() or DiscardAll() when they're applicable, as they have much - * better performance than calling this function repeatedly. + * Prefer RemoveImage() or DiscardAll() when they're applicable, as they have + * much better performance than calling this function repeatedly. * * @param aImageKey Key data identifying which image the surface belongs to. * @param aSurfaceKey Key data which uniquely identifies the requested surface. */ - static void RemoveIfPresent(const ImageKey aImageKey, - const SurfaceKey& aSurfaceKey); - /* - * Evicts any cached surfaces associated with the given image from the cache. - * This MUST be called, at a minimum, when the image is destroyed. If - * another image were allocated at the same address it could result in - * subtle, difficult-to-reproduce bugs. + static void RemoveSurface(const ImageKey aImageKey, + const SurfaceKey& aSurfaceKey); + + /** + * Removes all cached surfaces associated with the given image from the cache. + * If the image is locked, it is automatically unlocked. + * + * This MUST be called, at a minimum, when an Image which could be storing + * surfaces in the surface cache is destroyed. If another image were allocated + * at the same address it could result in subtle, difficult-to-reproduce bugs. * * @param aImageKey The image which should be removed from the cache. */ - static void Discard(const ImageKey aImageKey); + static void RemoveImage(const ImageKey aImageKey); - /* - * Evicts all caches surfaces from ths cache. + /** + * Evicts all evictable surfaces from the cache. + * + * All surfaces are evictable except for persistent surfaces associated with + * locked images. Non-evictable surfaces can only be removed by + * RemoveSurface() or RemoveImage(). */ static void DiscardAll(); diff --git a/image/src/VectorImage.cpp b/image/src/VectorImage.cpp index 42fb26a7e057..81f5475ed101 100644 --- a/image/src/VectorImage.cpp +++ b/image/src/VectorImage.cpp @@ -337,7 +337,7 @@ VectorImage::VectorImage(ProgressTracker* aProgressTracker, VectorImage::~VectorImage() { CancelAllListeners(); - SurfaceCache::Discard(this); + SurfaceCache::RemoveImage(ImageKey(this)); } //------------------------------------------------------------------------------ @@ -565,7 +565,7 @@ VectorImage::SendInvalidationNotifications() // notifications directly in |InvalidateObservers...|. if (mProgressTracker) { - SurfaceCache::Discard(this); + SurfaceCache::RemoveImage(ImageKey(this)); mProgressTracker->SyncNotifyProgress(FLAG_FRAME_COMPLETE, nsIntRect::GetMaxSizedIntRect()); } @@ -903,7 +903,8 @@ VectorImage::CreateSurfaceAndShow(const SVGDrawingParameters& aParams) SurfaceCache::Insert(frame, ImageKey(this), VectorSurfaceKey(aParams.size, aParams.svgContext, - aParams.animationTime)); + aParams.animationTime), + Lifetime::Transient); // Draw. nsRefPtr drawable = @@ -971,7 +972,7 @@ VectorImage::UnlockImage() NS_IMETHODIMP VectorImage::RequestDiscard() { - SurfaceCache::Discard(this); + SurfaceCache::RemoveImage(ImageKey(this)); return NS_OK; } From fc5233fbbd2741551fe54a5bfd1da5e47c3f71d9 Mon Sep 17 00:00:00 2001 From: Seth Fowler Date: Wed, 26 Nov 2014 13:22:10 -0800 Subject: [PATCH 04/64] Bug 1060869 (Part 2) - Store the first frame of a RasterImage in the SurfaceCache. r=tn --- image/decoders/nsICODecoder.cpp | 17 +- image/decoders/nsICODecoder.h | 2 + image/src/Decoder.cpp | 75 ++--- image/src/Decoder.h | 45 ++- image/src/ImageMetadata.cpp | 4 - image/src/ImageMetadata.h | 10 +- image/src/RasterImage.cpp | 536 ++++++++++++++++---------------- image/src/RasterImage.h | 81 +++-- image/src/imgFrame.cpp | 77 ++--- image/src/imgFrame.h | 12 +- 10 files changed, 409 insertions(+), 450 deletions(-) diff --git a/image/decoders/nsICODecoder.cpp b/image/decoders/nsICODecoder.cpp index 6313ffb984db..62075c79a1b7 100644 --- a/image/decoders/nsICODecoder.cpp +++ b/image/decoders/nsICODecoder.cpp @@ -9,6 +9,7 @@ #include #include "mozilla/Endian.h" +#include "mozilla/Move.h" #include "nsICODecoder.h" #include "RasterImage.h" @@ -344,7 +345,7 @@ nsICODecoder::WriteInternal(const char* aBuffer, uint32_t aCount, mContainedDecoder->SetSizeDecode(IsSizeDecode()); mContainedDecoder->InitSharedDecoder(mImageData, mImageDataLength, mColormap, mColormapSize, - mCurrentFrame); + Move(mRefForContainedDecoder)); if (!WriteToContainedDecoder(mSignature, PNGSIGNATURESIZE, aStrategy)) { return; } @@ -422,7 +423,7 @@ nsICODecoder::WriteInternal(const char* aBuffer, uint32_t aCount, mContainedDecoder->SetSizeDecode(IsSizeDecode()); mContainedDecoder->InitSharedDecoder(mImageData, mImageDataLength, mColormap, mColormapSize, - mCurrentFrame); + Move(mRefForContainedDecoder)); // The ICO format when containing a BMP does not include the 14 byte // bitmap file header. To use the code of the BMP decoder we need to @@ -640,15 +641,21 @@ nsICODecoder::NeedsNewFrame() const nsresult nsICODecoder::AllocateFrame() { + nsresult rv; + if (mContainedDecoder) { - nsresult rv = mContainedDecoder->AllocateFrame(); - mCurrentFrame = mContainedDecoder->GetCurrentFrame(); + rv = mContainedDecoder->AllocateFrame(); + mCurrentFrame = mContainedDecoder->GetCurrentFrameRef(); mProgress |= mContainedDecoder->TakeProgress(); mInvalidRect.Union(mContainedDecoder->TakeInvalidRect()); return rv; } - return Decoder::AllocateFrame(); + // Grab a strong ref that we'll later hand over to the contained decoder. This + // lets us avoid creating a RawAccessFrameRef off-main-thread. + rv = Decoder::AllocateFrame(); + mRefForContainedDecoder = GetCurrentFrameRef(); + return rv; } } // namespace image diff --git a/image/decoders/nsICODecoder.h b/image/decoders/nsICODecoder.h index 8d5614fc9a3b..080e0ae70d78 100644 --- a/image/decoders/nsICODecoder.h +++ b/image/decoders/nsICODecoder.h @@ -9,6 +9,7 @@ #include "nsAutoPtr.h" #include "Decoder.h" +#include "imgFrame.h" #include "nsBMPDecoder.h" #include "nsPNGDecoder.h" #include "ICOFileHeaders.h" @@ -82,6 +83,7 @@ private: uint32_t mRowBytes; // How many bytes of the row were already received int32_t mOldLine; // Previous index of the line nsRefPtr mContainedDecoder; // Contains either a BMP or PNG resource + RawAccessFrameRef mRefForContainedDecoder; // Avoid locking off-main-thread char mDirEntryArray[ICODIRENTRYSIZE]; // Holds the current dir entry buffer IconDirEntry mDirEntry; // Holds a decoded dir entry diff --git a/image/src/Decoder.cpp b/image/src/Decoder.cpp index ee6a9a19a563..58fcd401ec9b 100644 --- a/image/src/Decoder.cpp +++ b/image/src/Decoder.cpp @@ -16,7 +16,6 @@ namespace image { Decoder::Decoder(RasterImage &aImage) : mImage(aImage) - , mCurrentFrame(nullptr) , mProgress(NoProgress) , mImageData(nullptr) , mColormap(nullptr) @@ -68,18 +67,19 @@ Decoder::Init() // Initializes a decoder whose image and observer is already being used by a // parent decoder void -Decoder::InitSharedDecoder(uint8_t* imageData, uint32_t imageDataLength, - uint32_t* colormap, uint32_t colormapSize, - imgFrame* currentFrame) +Decoder::InitSharedDecoder(uint8_t* aImageData, uint32_t aImageDataLength, + uint32_t* aColormap, uint32_t aColormapSize, + RawAccessFrameRef&& aFrameRef) { // No re-initializing NS_ABORT_IF_FALSE(!mInitialized, "Can't re-initialize a decoder!"); - mImageData = imageData; - mImageDataLength = imageDataLength; - mColormap = colormap; - mColormapSize = colormapSize; - mCurrentFrame = currentFrame; + mImageData = aImageData; + mImageDataLength = aImageDataLength; + mColormap = aColormap; + mColormapSize = aColormapSize; + mCurrentFrame = Move(aFrameRef); + // We have all the frame data, so we've started the frame. if (!IsSizeDecode()) { PostFrameStart(); @@ -206,11 +206,13 @@ Decoder::Finish(ShutdownReason aReason) } } - // Set image metadata before calling DecodingComplete, because DecodingComplete calls Optimize(). + // Set image metadata before calling DecodingComplete, because + // DecodingComplete calls Optimize(). mImageMetadata.SetOnImage(&mImage); if (mDecodeDone) { - mImage.DecodingComplete(); + MOZ_ASSERT(HasError() || mCurrentFrame, "Should have an error or a frame"); + mImage.DecodingComplete(mCurrentFrame.get()); } } @@ -230,34 +232,22 @@ Decoder::AllocateFrame() MOZ_ASSERT(mNeedsNewFrame); MOZ_ASSERT(NS_IsMainThread()); - nsresult rv; - nsRefPtr frame; - if (mNewFrameData.mPaletteDepth) { - rv = mImage.EnsureFrame(mNewFrameData.mFrameNum, mNewFrameData.mOffsetX, - mNewFrameData.mOffsetY, mNewFrameData.mWidth, - mNewFrameData.mHeight, mNewFrameData.mFormat, - mNewFrameData.mPaletteDepth, - &mImageData, &mImageDataLength, - &mColormap, &mColormapSize, - getter_AddRefs(frame)); - } else { - rv = mImage.EnsureFrame(mNewFrameData.mFrameNum, mNewFrameData.mOffsetX, - mNewFrameData.mOffsetY, mNewFrameData.mWidth, - mNewFrameData.mHeight, mNewFrameData.mFormat, - &mImageData, &mImageDataLength, - getter_AddRefs(frame)); - } + mCurrentFrame = mImage.EnsureFrame(mNewFrameData.mFrameNum, + mNewFrameData.mFrameRect, + mDecodeFlags, + mNewFrameData.mFormat, + mNewFrameData.mPaletteDepth, + mCurrentFrame.get()); - if (NS_SUCCEEDED(rv)) { - mCurrentFrame = frame; - } else { - mCurrentFrame = nullptr; - } + if (mCurrentFrame) { + // Gather the raw pointers the decoders will use. + mCurrentFrame->GetImageData(&mImageData, &mImageDataLength); + mCurrentFrame->GetPaletteData(&mColormap, &mColormapSize); - // Notify if appropriate - if (NS_SUCCEEDED(rv) && mNewFrameData.mFrameNum == mFrameCount) { - PostFrameStart(); - } else if (NS_FAILED(rv)) { + if (mNewFrameData.mFrameNum == mFrameCount) { + PostFrameStart(); + } + } else { PostDataError(); } @@ -271,7 +261,7 @@ Decoder::AllocateFrame() mNeedsToFlushData = true; } - return rv; + return mCurrentFrame ? NS_OK : NS_ERROR_FAILURE; } void @@ -338,8 +328,8 @@ Decoder::PostFrameStart() // Decoder implementations should only call this method if they successfully // appended the frame to the image. So mFrameCount should always match that // reported by the Image. - NS_ABORT_IF_FALSE(mFrameCount == mImage.GetNumFrames(), - "Decoder frame count doesn't match image's!"); + MOZ_ASSERT(mFrameCount == mImage.GetNumFrames(), + "Decoder frame count doesn't match image's!"); } void @@ -389,7 +379,6 @@ Decoder::PostDecodeDone(int32_t aLoopCount /* = 0 */) mDecodeDone = true; mImageMetadata.SetLoopCount(aLoopCount); - mImageMetadata.SetIsNonPremultiplied(GetDecodeFlags() & DECODER_NO_PREMULTIPLY_ALPHA); mProgress |= FLAG_DECODE_COMPLETE; } @@ -424,7 +413,9 @@ Decoder::NeedNewFrame(uint32_t framenum, uint32_t x_offset, uint32_t y_offset, // We don't want images going back in time or skipping frames. MOZ_ASSERT(framenum == mFrameCount || framenum == (mFrameCount - 1)); - mNewFrameData = NewFrameData(framenum, x_offset, y_offset, width, height, format, palette_depth); + mNewFrameData = NewFrameData(framenum, + nsIntRect(x_offset, y_offset, width, height), + format, palette_depth); mNeedsNewFrame = true; } diff --git a/image/src/Decoder.h b/image/src/Decoder.h index 0ae05af5408b..544b14e916fd 100644 --- a/image/src/Decoder.h +++ b/image/src/Decoder.h @@ -36,9 +36,9 @@ public: * * Notifications Sent: TODO */ - void InitSharedDecoder(uint8_t* imageData, uint32_t imageDataLength, - uint32_t* colormap, uint32_t colormapSize, - imgFrame* currentFrame); + void InitSharedDecoder(uint8_t* aImageData, uint32_t aImageDataLength, + uint32_t* aColormap, uint32_t aColormapSize, + RawAccessFrameRef&& aFrameRef); /** * Writes data to the decoder. @@ -186,12 +186,17 @@ public: // status code from that attempt. Clears mNewFrameData. virtual nsresult AllocateFrame(); - already_AddRefed GetCurrentFrame() const + already_AddRefed GetCurrentFrame() { - nsRefPtr frame = mCurrentFrame; + nsRefPtr frame = mCurrentFrame.get(); return frame.forget(); } + RawAccessFrameRef GetCurrentFrameRef() + { + return mCurrentFrame->RawAccessRef(); + } + protected: virtual ~Decoder(); @@ -263,7 +268,7 @@ protected: * */ RasterImage &mImage; - nsRefPtr mCurrentFrame; + RawAccessFrameRef mCurrentFrame; ImageMetadata mImageMetadata; nsIntRect mInvalidRect; // Tracks an invalidation region in the current frame. Progress mProgress; @@ -289,28 +294,22 @@ private: struct NewFrameData { - NewFrameData() - {} + NewFrameData() { } + + NewFrameData(uint32_t aFrameNum, const nsIntRect& aFrameRect, + gfx::SurfaceFormat aFormat, uint8_t aPaletteDepth) + : mFrameNum(aFrameNum) + , mFrameRect(aFrameRect) + , mFormat(aFormat) + , mPaletteDepth(aPaletteDepth) + { } - NewFrameData(uint32_t num, uint32_t offsetx, uint32_t offsety, - uint32_t width, uint32_t height, - gfx::SurfaceFormat format, uint8_t paletteDepth) - : mFrameNum(num) - , mOffsetX(offsetx) - , mOffsetY(offsety) - , mWidth(width) - , mHeight(height) - , mFormat(format) - , mPaletteDepth(paletteDepth) - {} uint32_t mFrameNum; - uint32_t mOffsetX; - uint32_t mOffsetY; - uint32_t mWidth; - uint32_t mHeight; + nsIntRect mFrameRect; gfx::SurfaceFormat mFormat; uint8_t mPaletteDepth; }; + NewFrameData mNewFrameData; bool mNeedsNewFrame; bool mNeedsToFlushData; diff --git a/image/src/ImageMetadata.cpp b/image/src/ImageMetadata.cpp index cb74600802d1..03bd48965e3f 100644 --- a/image/src/ImageMetadata.cpp +++ b/image/src/ImageMetadata.cpp @@ -27,10 +27,6 @@ ImageMetadata::SetOnImage(RasterImage* image) } image->SetLoopCount(mLoopCount); - - for (uint32_t i = 0; i < image->GetNumFrames(); i++) { - image->SetFrameAsNonPremult(i, mIsNonPremultiplied); - } } } // namespace image diff --git a/image/src/ImageMetadata.h b/image/src/ImageMetadata.h index acaeb10dd1a5..e05d9b3c0e65 100644 --- a/image/src/ImageMetadata.h +++ b/image/src/ImageMetadata.h @@ -25,7 +25,6 @@ public: : mHotspotX(-1) , mHotspotY(-1) , mLoopCount(-1) - , mIsNonPremultiplied(false) {} // Set the metadata this object represents on an image. @@ -41,11 +40,6 @@ public: mLoopCount = loopcount; } - void SetIsNonPremultiplied(bool nonPremult) - { - mIsNonPremultiplied = nonPremult; - } - void SetSize(int32_t width, int32_t height, Orientation orientation) { mSize.emplace(nsIntSize(width, height)); @@ -68,9 +62,7 @@ private: int32_t mLoopCount; Maybe mSize; - Maybe mOrientation; - - bool mIsNonPremultiplied; + Maybe mOrientation; }; } // namespace image diff --git a/image/src/RasterImage.cpp b/image/src/RasterImage.cpp index 1e80e667db26..8ad0eb2cc143 100644 --- a/image/src/RasterImage.cpp +++ b/image/src/RasterImage.cpp @@ -233,9 +233,6 @@ public: mDstRef->ImageUpdated(mDstRef->GetRect()); MOZ_ASSERT(mDstRef->ImageComplete(), "Incomplete, but just updated the entire frame"); - if (DiscardingEnabled()) { - mDstRef->SetDiscardable(); - } } // We need to send notifications and release our references on the main @@ -322,7 +319,9 @@ RasterImage::RasterImage(ProgressTracker* aProgressTracker, mDiscardable(false), mHasSourceData(false), mDecoded(false), + mHasFirstFrame(false), mHasBeenDecoded(false), + mPendingAnimation(false), mAnimationFinished(false), mWantFullDecode(false), mPendingError(false) @@ -364,7 +363,7 @@ RasterImage::~RasterImage() mDecoder = nullptr; } - // Release any HQ scaled frames from the surface cache. + // Release all frames from the surface cache. SurfaceCache::RemoveImage(ImageKey(this)); mAnim = nullptr; @@ -419,6 +418,11 @@ RasterImage::Init(const char* aMimeType, discardable_source_bytes += mSourceData.Length(); } + // Lock this image's surfaces in the SurfaceCache if we're not discardable. + if (!mDiscardable) { + SurfaceCache::LockImage(ImageKey(this)); + } + // Instantiate the decoder nsresult rv = InitDecoder(/* aDoSizeDecode = */ true); CONTAINER_ENSURE_SUCCESS(rv); @@ -558,21 +562,33 @@ RasterImage::GetType() return imgIContainer::TYPE_RASTER; } -already_AddRefed -RasterImage::LookupFrameNoDecode(uint32_t aFrameNum) +DrawableFrameRef +RasterImage::LookupFrameInternal(uint32_t aFrameNum, + const nsIntSize& aSize, + uint32_t aFlags) { - if (!mAnim) { - NS_ASSERTION(aFrameNum == 0, "Don't ask for a frame > 0 if we're not animated!"); - return mFrameBlender.GetFrame(0); + if (mAnim) { + MOZ_ASSERT(mFrameBlender, "mAnim but no mFrameBlender?"); + nsRefPtr frame = mFrameBlender->GetFrame(aFrameNum); + return frame->DrawableRef(); } - return mFrameBlender.GetFrame(aFrameNum); + + NS_ASSERTION(aFrameNum == 0, + "Don't ask for a frame > 0 if we're not animated!"); + + return SurfaceCache::Lookup(ImageKey(this), + RasterSurfaceKey(aSize.ToIntSize(), + DecodeFlags(aFlags))); } DrawableFrameRef RasterImage::LookupFrame(uint32_t aFrameNum, + const nsIntSize& aSize, uint32_t aFlags, bool aShouldSyncNotify /* = true */) { + MOZ_ASSERT(NS_IsMainThread()); + if (mMultipart && aFrameNum == GetCurrentFrameIndex() && mMultipartDecodedFrame) { @@ -582,26 +598,18 @@ RasterImage::LookupFrame(uint32_t aFrameNum, return mMultipartDecodedFrame->DrawableRef(); } - // Try our best to start decoding if it's necessary. - nsresult rv = WantDecodedFrames(aFlags, aShouldSyncNotify); - CONTAINER_ENSURE_TRUE(NS_SUCCEEDED(rv), DrawableFrameRef()); + DrawableFrameRef ref = LookupFrameInternal(aFrameNum, aSize, aFlags); - nsRefPtr frame = LookupFrameNoDecode(aFrameNum); - if (!frame) { - return DrawableFrameRef(); - } - - DrawableFrameRef ref = frame->DrawableRef(); if (!ref) { // The OS threw this frame away. We need to discard and redecode. MOZ_ASSERT(!mAnim, "Animated frames should be locked"); if (CanForciblyDiscardAndRedecode()) { - ForceDiscard(); + Discard(/* aForce = */ true, /* aNotify = */ false); + ApplyDecodeFlags(aFlags); WantDecodedFrames(aFlags, aShouldSyncNotify); - // See if we managed to entirely redecode the frame. - frame = LookupFrameNoDecode(aFrameNum); - ref = frame->DrawableRef(); + // See if we managed to redecode enough to get the frame we want. + ref = LookupFrameInternal(aFrameNum, aSize, aFlags); } if (!ref) { @@ -672,9 +680,18 @@ RasterImage::FrameRect(uint32_t aWhichFrame) return nsIntRect(); } - // Get the requested frame. + if (!mHasFirstFrame) { + return nsIntRect(); + } + + if (GetNumFrames() == 1) { + return nsIntRect(0, 0, mSize.width, mSize.height); + } + + // We must be animated, so get the requested frame from our FrameBlender. + MOZ_ASSERT(mFrameBlender, "We should be animated here"); nsRefPtr frame = - LookupFrameNoDecode(GetRequestedFrameIndex(aWhichFrame)); + mFrameBlender->RawGetFrame(GetRequestedFrameIndex(aWhichFrame)); // If we have the frame, use that rectangle. if (frame) { @@ -692,7 +709,10 @@ RasterImage::FrameRect(uint32_t aWhichFrame) uint32_t RasterImage::GetNumFrames() const { - return mFrameBlender.GetNumFrames(); + if (mFrameBlender) { + return mFrameBlender->GetNumFrames(); + } + return mHasFirstFrame ? 1 : 0; } //****************************************************************************** @@ -734,7 +754,8 @@ RasterImage::GetFirstFrameDelay() if (NS_FAILED(GetAnimated(&animated)) || !animated) return -1; - return mFrameBlender.GetTimeoutForFrame(0); + MOZ_ASSERT(mFrameBlender, "Animated images should have a FrameBlender"); + return mFrameBlender->GetTimeoutForFrame(0); } TemporaryRef @@ -755,7 +776,7 @@ RasterImage::CopyFrame(uint32_t aWhichFrame, // not waiting for the data to be loaded from the network or not passing // FLAG_SYNC_DECODE DrawableFrameRef frameRef = LookupFrame(GetRequestedFrameIndex(aWhichFrame), - aFlags, aShouldSyncNotify); + mSize, aFlags, aShouldSyncNotify); if (!frameRef) { // The OS threw this frame away and we couldn't redecode it right now. return nullptr; @@ -832,7 +853,7 @@ RasterImage::GetFrameInternal(uint32_t aWhichFrame, // not waiting for the data to be loaded from the network or not passing // FLAG_SYNC_DECODE DrawableFrameRef frameRef = LookupFrame(GetRequestedFrameIndex(aWhichFrame), - aFlags, aShouldSyncNotify); + mSize, aFlags, aShouldSyncNotify); if (!frameRef) { // The OS threw this frame away and we couldn't redecode it. return nullptr; @@ -960,7 +981,10 @@ size_t RasterImage::SizeOfDecodedWithComputedFallbackIfHeap(gfxMemoryLocation aLocation, MallocSizeOf aMallocSizeOf) const { - return mFrameBlender.SizeOfDecodedWithComputedFallbackIfHeap(aLocation, aMallocSizeOf); + return mFrameBlender + ? mFrameBlender->SizeOfDecodedWithComputedFallbackIfHeap(aLocation, + aMallocSizeOf) + : 0; } size_t @@ -984,115 +1008,114 @@ RasterImage::OutOfProcessSizeOfDecoded() const nullptr); } -void -RasterImage::EnsureAnimExists() -{ - if (!mAnim) { - - // Create the animation context - mAnim = MakeUnique(mFrameBlender, mAnimationMode); - - // We don't support discarding animated images (See bug 414259). - // Lock the image and throw away the key. - // - // Note that this is inefficient, since we could get rid of the source - // data too. However, doing this is actually hard, because we're probably - // calling ensureAnimExists mid-decode, and thus we're decoding out of - // the source buffer. Since we're going to fix this anyway later, and - // since we didn't kill the source data in the old world either, locking - // is acceptable for the moment. - LockImage(); - } -} - -nsresult -RasterImage::InternalAddFrameHelper(uint32_t framenum, imgFrame *aFrame, - uint8_t **imageData, uint32_t *imageLength, - uint32_t **paletteData, uint32_t *paletteLength, - imgFrame** aRetFrame) -{ - NS_ABORT_IF_FALSE(framenum <= GetNumFrames(), "Invalid frame index!"); - if (framenum > GetNumFrames()) - return NS_ERROR_INVALID_ARG; - - nsRefPtr frame = aFrame; - RawAccessFrameRef ref = frame->RawAccessRef(); - if (!ref) { - // Probably the OS discarded the frame. Exceedingly unlikely since we just - // created it, but it could happen. - return NS_ERROR_FAILURE; - } - - if (paletteData && paletteLength) - frame->GetPaletteData(paletteData, paletteLength); - - frame->GetImageData(imageData, imageLength); - - mFrameBlender.InsertFrame(framenum, Move(ref)); - - frame.forget(aRetFrame); - return NS_OK; -} - -nsresult -RasterImage::InternalAddFrame(uint32_t framenum, - int32_t aX, int32_t aY, - int32_t aWidth, int32_t aHeight, +RawAccessFrameRef +RasterImage::InternalAddFrame(uint32_t aFrameNum, + const nsIntRect& aFrameRect, + uint32_t aDecodeFlags, SurfaceFormat aFormat, uint8_t aPaletteDepth, - uint8_t **imageData, - uint32_t *imageLength, - uint32_t **paletteData, - uint32_t *paletteLength, - imgFrame** aRetFrame) + imgFrame* aPreviousFrame) { // We assume that we're in the middle of decoding because we unlock the // previous frame when we create a new frame, and only when decoding do we // lock frames. - NS_ABORT_IF_FALSE(mDecoder, "Only decoders may add frames!"); + MOZ_ASSERT(mDecoder, "Only decoders may add frames!"); - NS_ABORT_IF_FALSE(framenum <= GetNumFrames(), "Invalid frame index!"); - if (framenum > GetNumFrames()) - return NS_ERROR_INVALID_ARG; + MOZ_ASSERT(aFrameNum <= GetNumFrames(), "Invalid frame index!"); + if (aFrameNum > GetNumFrames()) { + return RawAccessFrameRef(); + } - nsRefPtr frame(new imgFrame()); + if (mSize.width <= 0 || mSize.height <= 0) { + NS_WARNING("Trying to add frame with zero or negative size"); + return RawAccessFrameRef(); + } - nsIntRect frameRect(aX, aY, aWidth, aHeight); - nsresult rv = frame->InitForDecoder(frameRect, aFormat, aPaletteDepth); - if (!(mSize.width > 0 && mSize.height > 0)) - NS_WARNING("Shouldn't call InternalAddFrame with zero size"); - if (!NS_SUCCEEDED(rv)) + if (!SurfaceCache::CanHold(mSize.ToIntSize())) { + NS_WARNING("Trying to add frame that's too large for the SurfaceCache"); + return RawAccessFrameRef(); + } + + nsRefPtr frame = new imgFrame(); + if (NS_FAILED(frame->InitForDecoder(mSize, aFrameRect, aFormat, + aPaletteDepth))) { NS_WARNING("imgFrame::Init should succeed"); - NS_ENSURE_SUCCESS(rv, rv); + return RawAccessFrameRef(); + } + frame->SetAsNonPremult(aDecodeFlags & FLAG_DECODE_NO_PREMULTIPLY_ALPHA); + + RawAccessFrameRef ref = frame->RawAccessRef(); + if (!ref) { + return RawAccessFrameRef(); + } if (GetNumFrames() == 0) { - return InternalAddFrameHelper(framenum, frame, imageData, imageLength, - paletteData, paletteLength, aRetFrame); + bool succeeded = + SurfaceCache::Insert(frame, ImageKey(this), + RasterSurfaceKey(mSize.ToIntSize(), aDecodeFlags), + Lifetime::Persistent); + if (!succeeded) { + return RawAccessFrameRef(); + } + mHasFirstFrame = true; + return ref; } if (GetNumFrames() == 1) { - // Since we're about to add our second frame, initialize animation stuff - EnsureAnimExists(); + // We're becoming animated, so initialize animation stuff. + MOZ_ASSERT(!mFrameBlender, "Already have a FrameBlender?"); + MOZ_ASSERT(!mAnim, "Already have animation state?"); + mFrameBlender.emplace(); + mFrameBlender->SetSize(mSize); + mAnim = MakeUnique(*mFrameBlender, mAnimationMode); - // If we dispose of the first frame by clearing it, then the - // First Frame's refresh area is all of itself. - // RESTORE_PREVIOUS is invalid (assumed to be DISPOSE_CLEAR) - nsRefPtr firstFrame = mFrameBlender.RawGetFrame(0); - int32_t frameDisposalMethod = firstFrame->GetFrameDisposalMethod(); + // We don't support discarding animated images (See bug 414259). + // Lock the image and throw away the key. + // + // Note that this is inefficient, since we could get rid of the source data + // too. However, doing this is actually hard, because we're probably + // mid-decode, and thus we're decoding out of the source buffer. Since we're + // going to fix this anyway later, and since we didn't kill the source data + // in the old world either, locking is acceptable for the moment. + LockImage(); + + // Insert the first frame into the FrameBlender. + MOZ_ASSERT(aPreviousFrame, "Must provide a previous frame when animated"); + RawAccessFrameRef ref = aPreviousFrame->RawAccessRef(); + if (!ref) { + return RawAccessFrameRef(); // Let's keep the FrameBlender consistent... + } + mFrameBlender->InsertFrame(0, Move(ref)); + + // Remove it from the SurfaceCache. (It's not really doing any harm there, + // but keeping it there could cause it to be counted twice in our memory + // statistics.) + SurfaceCache::RemoveSurface(ImageKey(this), + RasterSurfaceKey(mSize.ToIntSize(), + aDecodeFlags)); + + // If we dispose of the first frame by clearing it, then the first frame's + // refresh area is all of itself. + // RESTORE_PREVIOUS is invalid (assumed to be DISPOSE_CLEAR). + int32_t frameDisposalMethod = aPreviousFrame->GetFrameDisposalMethod(); if (frameDisposalMethod == FrameBlender::kDisposeClear || - frameDisposalMethod == FrameBlender::kDisposeRestorePrevious) - mAnim->SetFirstFrameRefreshArea(firstFrame->GetRect()); + frameDisposalMethod == FrameBlender::kDisposeRestorePrevious) { + mAnim->SetFirstFrameRefreshArea(aPreviousFrame->GetRect()); + } + + if (mPendingAnimation && ShouldAnimate()) { + StartAnimation(); + } } - // Calculate firstFrameRefreshArea - // Some gifs are huge but only have a small area that they animate - // We only need to refresh that small area when Frame 0 comes around again + // Some GIFs are huge but only have a small area that they animate. We only + // need to refresh that small area when frame 0 comes around again. mAnim->UnionFirstFrameRefreshArea(frame->GetRect()); - rv = InternalAddFrameHelper(framenum, frame, imageData, imageLength, - paletteData, paletteLength, aRetFrame); + MOZ_ASSERT(mFrameBlender, "Should have a FrameBlender by now"); + mFrameBlender->InsertFrame(aFrameNum, frame->RawAccessRef()); - return rv; + return ref; } bool @@ -1162,121 +1185,70 @@ RasterImage::SetSize(int32_t aWidth, int32_t aHeight, Orientation aOrientation) mOrientation = aOrientation; mHasSize = true; - mFrameBlender.SetSize(mSize); - return NS_OK; } -nsresult -RasterImage::EnsureFrame(uint32_t aFrameNum, int32_t aX, int32_t aY, - int32_t aWidth, int32_t aHeight, +RawAccessFrameRef +RasterImage::EnsureFrame(uint32_t aFrameNum, + const nsIntRect& aFrameRect, + uint32_t aDecodeFlags, SurfaceFormat aFormat, uint8_t aPaletteDepth, - uint8_t **imageData, uint32_t *imageLength, - uint32_t **paletteData, uint32_t *paletteLength, - imgFrame** aRetFrame) + imgFrame* aPreviousFrame) { - if (mError) - return NS_ERROR_FAILURE; - - NS_ENSURE_ARG_POINTER(imageData); - NS_ENSURE_ARG_POINTER(imageLength); - NS_ENSURE_ARG_POINTER(aRetFrame); - NS_ABORT_IF_FALSE(aFrameNum <= GetNumFrames(), "Invalid frame index!"); - - if (aPaletteDepth > 0) { - NS_ENSURE_ARG_POINTER(paletteData); - NS_ENSURE_ARG_POINTER(paletteLength); + if (mError) { + return RawAccessFrameRef(); } - if (aFrameNum > GetNumFrames()) - return NS_ERROR_INVALID_ARG; + MOZ_ASSERT(aFrameNum <= GetNumFrames(), "Invalid frame index!"); + if (aFrameNum > GetNumFrames()) { + return RawAccessFrameRef(); + } - // Adding a frame that doesn't already exist. + // Adding a frame that doesn't already exist. This is the normal case. if (aFrameNum == GetNumFrames()) { - return InternalAddFrame(aFrameNum, aX, aY, aWidth, aHeight, aFormat, - aPaletteDepth, imageData, imageLength, - paletteData, paletteLength, aRetFrame); + return InternalAddFrame(aFrameNum, aFrameRect, aDecodeFlags, aFormat, + aPaletteDepth, aPreviousFrame); } - nsRefPtr frame = mFrameBlender.RawGetFrame(aFrameNum); - if (!frame) { - return InternalAddFrame(aFrameNum, aX, aY, aWidth, aHeight, aFormat, - aPaletteDepth, imageData, imageLength, - paletteData, paletteLength, aRetFrame); + // We're replacing a frame. It must be the first frame; there's no reason to + // ever replace any other frame, since the first frame is the only one we + // speculatively allocate without knowing what the decoder really needs. + // XXX(seth): I'm not convinced there's any reason to support this at all. We + // should figure out how to avoid triggering this and rip it out. + MOZ_ASSERT(mHasFirstFrame, "Should have the first frame"); + MOZ_ASSERT(aFrameNum == 0, "Replacing a frame other than the first?"); + MOZ_ASSERT(GetNumFrames() == 1, "Should have only one frame"); + MOZ_ASSERT(aPreviousFrame, "Need the previous frame to replace"); + MOZ_ASSERT(!mFrameBlender && !mAnim, "Shouldn't be animated"); + if (aFrameNum != 0 || !aPreviousFrame || GetNumFrames() != 1) { + return RawAccessFrameRef(); } - // See if we can re-use the frame that already exists. - nsIntRect rect = frame->GetRect(); - if (rect.x == aX && rect.y == aY && rect.width == aWidth && - rect.height == aHeight && frame->GetFormat() == aFormat && - frame->GetPaletteDepth() == aPaletteDepth) { - frame->GetImageData(imageData, imageLength); - if (paletteData) { - frame->GetPaletteData(paletteData, paletteLength); - } + MOZ_ASSERT(!aPreviousFrame->GetRect().IsEqualEdges(aFrameRect) || + aPreviousFrame->GetFormat() != aFormat || + aPreviousFrame->GetPaletteDepth() != aPaletteDepth, + "Replacing first frame with the same kind of frame?"); - // We can re-use the frame if it has image data. - if (*imageData && paletteData && *paletteData) { - frame.forget(aRetFrame); - return NS_OK; - } - if (*imageData && !paletteData) { - frame.forget(aRetFrame); - return NS_OK; - } - } + // Remove the old frame from the SurfaceCache. + IntSize prevFrameSize = aPreviousFrame->GetImageSize(); + SurfaceCache::RemoveSurface(ImageKey(this), + RasterSurfaceKey(prevFrameSize, aDecodeFlags)); + mHasFirstFrame = false; - // Not reusable, so replace the frame directly. - mFrameBlender.RemoveFrame(aFrameNum); - nsRefPtr newFrame(new imgFrame()); - nsIntRect frameRect(aX, aY, aWidth, aHeight); - nsresult rv = newFrame->InitForDecoder(frameRect, aFormat, aPaletteDepth); - NS_ENSURE_SUCCESS(rv, rv); - return InternalAddFrameHelper(aFrameNum, newFrame, imageData, imageLength, - paletteData, paletteLength, aRetFrame); + // Add the new frame as usual. + return InternalAddFrame(aFrameNum, aFrameRect, aDecodeFlags, aFormat, + aPaletteDepth, nullptr); } -nsresult -RasterImage::EnsureFrame(uint32_t aFramenum, int32_t aX, int32_t aY, - int32_t aWidth, int32_t aHeight, - SurfaceFormat aFormat, - uint8_t** imageData, uint32_t* imageLength, - imgFrame** aFrame) -{ - return EnsureFrame(aFramenum, aX, aY, aWidth, aHeight, aFormat, - /* aPaletteDepth = */ 0, imageData, imageLength, - /* aPaletteData = */ nullptr, - /* aPaletteLength = */ nullptr, - aFrame); -} - -nsresult -RasterImage::SetFrameAsNonPremult(uint32_t aFrameNum, bool aIsNonPremult) -{ - if (mError) - return NS_ERROR_FAILURE; - - NS_ABORT_IF_FALSE(aFrameNum < GetNumFrames(), "Invalid frame index!"); - if (aFrameNum >= GetNumFrames()) - return NS_ERROR_INVALID_ARG; - - nsRefPtr frame = mFrameBlender.RawGetFrame(aFrameNum); - NS_ABORT_IF_FALSE(frame, "Calling SetFrameAsNonPremult on frame that doesn't exist!"); - NS_ENSURE_TRUE(frame, NS_ERROR_FAILURE); - - frame->SetAsNonPremult(aIsNonPremult); - - return NS_OK; -} - -nsresult -RasterImage::DecodingComplete() +void +RasterImage::DecodingComplete(imgFrame* aFinalFrame) { MOZ_ASSERT(NS_IsMainThread()); - if (mError) - return NS_ERROR_FAILURE; + if (mError) { + return; + } // Flag that we're done decoding. // XXX - these should probably be combined when we fix animated image @@ -1284,48 +1256,42 @@ RasterImage::DecodingComplete() mDecoded = true; mHasBeenDecoded = true; - nsresult rv; - // We now have one of the qualifications for discarding. Re-evaluate. if (CanDiscard()) { NS_ABORT_IF_FALSE(!DiscardingActive(), "We shouldn't have been discardable before this"); - rv = DiscardTracker::Reset(&mDiscardTrackerNode); - CONTAINER_ENSURE_SUCCESS(rv); + DiscardTracker::Reset(&mDiscardTrackerNode); } + bool singleFrame = GetNumFrames() == 1; + // If there's only 1 frame, mark it as optimizable. Optimizing animated images // is not supported. // // We don't optimize the frame for multipart images because we reuse // the frame. - if ((GetNumFrames() == 1) && !mMultipart) { - nsRefPtr firstFrame = mFrameBlender.RawGetFrame(0); - firstFrame->SetOptimizable(); - if (DiscardingEnabled() && CanForciblyDiscard()) { - firstFrame->SetDiscardable(); - } + if (singleFrame && !mMultipart && aFinalFrame) { + aFinalFrame->SetOptimizable(); } // Double-buffer our frame in the multipart case, since we'll start decoding // into the first frame again immediately and this produces severe tearing. if (mMultipart) { - if (GetNumFrames() == 1) { - mMultipartDecodedFrame = mFrameBlender.GetFrame(GetCurrentFrameIndex()); + if (singleFrame && aFinalFrame) { + // aFinalFrame must be the first frame since we only have one. + mMultipartDecodedFrame = aFinalFrame->DrawableRef(); } else { // Don't double buffer for animated multipart images. It entails more // complexity and it's not really needed since we already are smart about // not displaying the still-decoding frame of an animated image. We may // have already stored an extra frame, though, so we'll release it here. - mMultipartDecodedFrame = nullptr; + mMultipartDecodedFrame.reset(); } } if (mAnim) { mAnim->SetDoneDecoding(true); } - - return NS_OK; } NS_IMETHODIMP @@ -1347,12 +1313,17 @@ RasterImage::StartAnimation() NS_ABORT_IF_FALSE(ShouldAnimate(), "Should not animate!"); - EnsureAnimExists(); + // If we don't have mAnim yet, then we're not ready to animate. Setting + // mPendingAnimation will cause us to start animating as soon as we have a + // second frame, which causes mAnim to be constructed. + mPendingAnimation = !mAnim; + if (mPendingAnimation) { + return NS_OK; + } - nsRefPtr currentFrame = LookupFrameNoDecode(GetCurrentFrameIndex()); // A timeout of -1 means we should display this frame forever. - if (currentFrame && - mFrameBlender.GetTimeoutForFrame(GetCurrentFrameIndex()) < 0) { + MOZ_ASSERT(mFrameBlender, "Have an animation but no FrameBlender?"); + if (mFrameBlender->GetTimeoutForFrame(GetCurrentFrameIndex()) < 0) { mAnimationFinished = true; return NS_ERROR_ABORT; } @@ -1392,16 +1363,20 @@ RasterImage::ResetAnimation() if (mError) return NS_ERROR_FAILURE; - if (mAnimationMode == kDontAnimMode || - !mAnim || mAnim->GetCurrentAnimationFrameIndex() == 0) + mPendingAnimation = false; + + if (mAnimationMode == kDontAnimMode || !mAnim || + mAnim->GetCurrentAnimationFrameIndex() == 0) { return NS_OK; + } mAnimationFinished = false; if (mAnimating) StopAnimation(); - mFrameBlender.ResetAnimation(); + MOZ_ASSERT(mFrameBlender, "Should have a FrameBlender"); + mFrameBlender->ResetAnimation(); mAnim->ResetAnimation(); UpdateImageContainer(); @@ -1450,7 +1425,8 @@ RasterImage::SetLoopCount(int32_t aLoopCount) if (mAnim) { // No need to set this if we're not an animation - mFrameBlender.SetLoopCount(aLoopCount); + MOZ_ASSERT(mFrameBlender, "Should have a FrameBlender"); + mFrameBlender->SetLoopCount(aLoopCount); } } @@ -1489,18 +1465,26 @@ RasterImage::AddSourceData(const char *aBuffer, uint32_t aCount) // This needs to happen just before we start getting EnsureFrame() call(s), // so that there's no gap for anything to miss us. if (mMultipart && (!mDecoder || mDecoder->BytesDecoded() == 0)) { - // Our previous state may have been animated, so let's clean up - if (mAnimating) + // Our previous state may have been animated, so let's clean up. + if (mAnimating) { StopAnimation(); + } mAnimationFinished = false; + mPendingAnimation = false; if (mAnim) { mAnim = nullptr; } - // If there's only one frame, this could cause flickering - int old_frame_count = GetNumFrames(); - if (old_frame_count > 1) { - mFrameBlender.ClearFrames(); + + // If we had a FrameBlender, clean it up. We'll hold on to the first frame + // so we have something to draw until the next frame is decoded. + if (mFrameBlender) { + nsRefPtr firstFrame = mFrameBlender->RawGetFrame(0); + mMultipartDecodedFrame = firstFrame->DrawableRef(); + mFrameBlender.reset(); } + + // Remove everything stored in the surface cache for this image. + SurfaceCache::RemoveImage(ImageKey(this)); } // If we're not storing source data and we've previously gotten the size, @@ -1693,6 +1677,7 @@ RasterImage::OnNewSourceData() mDecoded = false; mHasSourceData = false; mHasSize = false; + mHasFirstFrame = false; mWantFullDecode = true; mDecodeStatus = DecodeStatus::INACTIVE; @@ -1771,12 +1756,12 @@ RasterImage::GetKeys(uint32_t *count, char ***keys) } void -RasterImage::Discard(bool force) +RasterImage::Discard(bool aForce, bool aNotify) { MOZ_ASSERT(NS_IsMainThread()); // We should be ok for discard - NS_ABORT_IF_FALSE(force ? CanForciblyDiscard() : CanDiscard(), "Asked to discard but can't!"); + NS_ABORT_IF_FALSE(aForce ? CanForciblyDiscard() : CanDiscard(), "Asked to discard but can't!"); // We should never discard when we have an active decoder NS_ABORT_IF_FALSE(!mDecoder, "Asked to discard with open decoder!"); @@ -1789,22 +1774,26 @@ RasterImage::Discard(bool force) int old_frame_count = GetNumFrames(); // Delete all the decoded frames - mFrameBlender.Discard(); + mFrameBlender.reset(); + SurfaceCache::RemoveImage(ImageKey(this)); // Clear the last decoded multipart frame. - mMultipartDecodedFrame = nullptr; + mMultipartDecodedFrame.reset(); // Flag that we no longer have decoded frames for this image mDecoded = false; + mHasFirstFrame = false; // Notify that we discarded - if (mProgressTracker) + if (aNotify && mProgressTracker) { mProgressTracker->OnDiscard(); + } mDecodeStatus = DecodeStatus::INACTIVE; - if (force) + if (aForce) { DiscardTracker::Remove(&mDiscardTrackerNode); + } // Log PR_LOG(GetCompressedImageAccountingLog(), PR_LOG_DEBUG, @@ -1834,14 +1823,12 @@ RasterImage::CanDiscard() { bool RasterImage::CanForciblyDiscard() { - return mDiscardable && // ...Enabled at creation time... - mHasSourceData; // ...have the source data... + return mHasSourceData; // ...have the source data... } bool RasterImage::CanForciblyDiscardAndRedecode() { - return mDiscardable && // ...Enabled at creation time... - mHasSourceData && // ...have the source data... + return mHasSourceData && // ...have the source data... !mDecoder && // Can't discard with an open decoder !mAnim; // Can never discard animated images } @@ -1857,7 +1844,7 @@ RasterImage::DiscardingActive() { // or just writing it directly to the decoder bool RasterImage::StoringSourceData() const { - return (mDecodeOnDraw || mDiscardable); + return !mMultipart; } @@ -2431,26 +2418,15 @@ RasterImage::DrawWithPreDownscaleIfNeeded(DrawableFrameRef&& aFrameRef, // By now we may have a frame with the requested size. If not, we need to // adjust the drawing parameters accordingly. - nsIntRect finalFrameRect = frameRef->GetRect(); - if (finalFrameRect.Size() != aSize) { - gfx::Size scale(double(aSize.width) / mSize.width, - double(aSize.height) / mSize.height); + IntSize finalSize = frameRef->GetImageSize(); + if (ThebesIntSize(finalSize) != aSize) { + gfx::Size scale(double(aSize.width) / finalSize.width, + double(aSize.height) / finalSize.height); aContext->Multiply(gfxMatrix::Scaling(scale.width, scale.height)); region.Scale(1.0 / scale.width, 1.0 / scale.height); } - // We can only use padding if we're using the original |aFrameRef|, unscaled. - // (If so, we moved it into |frameRef|, so |aFrameRef| is empty.) Because of - // this restriction, we don't scale frames that require padding. - nsIntMargin padding(0, 0, 0, 0); - if (!aFrameRef) { - padding = nsIntMargin(finalFrameRect.y, - mSize.width - finalFrameRect.XMost(), - mSize.height - finalFrameRect.YMost(), - finalFrameRect.x); - } - - frameRef->Draw(aContext, region, padding, aFilter, aFlags); + frameRef->Draw(aContext, region, aFilter, aFlags); } //****************************************************************************** @@ -2528,13 +2504,20 @@ RasterImage::Draw(gfxContext* aContext, NS_ENSURE_SUCCESS(rv, rv); } + // XXX(seth): For now, we deliberately don't look up a frame of size aSize + // (though DrawWithPreDownscaleIfNeeded will do so later). It doesn't make + // sense to do so until we support downscale-during-decode. Right now we need + // to make sure that we always touch an mSize-sized frame so that we have + // something to HQ scale. DrawableFrameRef ref = LookupFrame(GetRequestedFrameIndex(aWhichFrame), - aFlags); + mSize, aFlags); if (!ref) { - return NS_OK; // Getting the frame (above) touches the image and kicks off decoding + // Getting the frame (above) touches the image and kicks off decoding. + return NS_OK; } - DrawWithPreDownscaleIfNeeded(Move(ref), aContext, aSize, aRegion, aFilter, aFlags); + DrawWithPreDownscaleIfNeeded(Move(ref), aContext, aSize, + aRegion, aFilter, aFlags); if (mDecoded && !mDrawStartTime.IsNull()) { TimeDuration drawLatency = TimeStamp::Now() - mDrawStartTime; @@ -2562,6 +2545,11 @@ RasterImage::LockImage() // Increment the lock count mLockCount++; + // Lock this image's surfaces in the SurfaceCache. + if (mLockCount == 1) { + SurfaceCache::LockImage(ImageKey(this)); + } + return NS_OK; } @@ -2587,6 +2575,11 @@ RasterImage::UnlockImage() // Decrement our lock count mLockCount--; + // Unlock this image's surfaces in the SurfaceCache. + if (mLockCount == 0) { + SurfaceCache::UnlockImage(ImageKey(this)); + } + // If we've decoded this image once before, we're currently decoding again, // and our lock count is now zero (so nothing is forcing us to keep the // decoded data around), try to cancel the decode and throw away whatever @@ -2974,7 +2967,8 @@ RasterImage::OptimalImageSizeForDest(const gfxSize& aDest, uint32_t aWhichFrame, } if (!frameRef) { // We could HQ scale to this size, but we haven't. Request a scale now. - frameRef = LookupFrame(GetRequestedFrameIndex(aWhichFrame), aFlags); + frameRef = LookupFrame(GetRequestedFrameIndex(aWhichFrame), + mSize, aFlags); if (frameRef) { RequestScale(frameRef.get(), aFlags, destSize); } diff --git a/image/src/RasterImage.h b/image/src/RasterImage.h index 5d4e974032dd..f4b017dc88b6 100644 --- a/image/src/RasterImage.h +++ b/image/src/RasterImage.h @@ -29,6 +29,7 @@ #include "DiscardTracker.h" #include "Orientation.h" #include "nsIObserver.h" +#include "mozilla/Maybe.h" #include "mozilla/MemoryReporting.h" #include "mozilla/ReentrantMonitor.h" #include "mozilla/TimeStamp.h" @@ -180,12 +181,10 @@ public: } /* Triggers discarding. */ - void Discard(bool force = false); - void ForceDiscard() { Discard(/* force = */ true); } + void Discard(bool aForce = false, bool aNotify = true); + void ForceDiscard() { Discard(/* aForce = */ true); } /* Callbacks for decoders */ - nsresult SetFrameAsNonPremult(uint32_t aFrameNum, bool aIsNonPremult); - /** Sets the size and inherent orientation of the container. This should only * be called by the decoder. This function may be called multiple times, but * will throw an error if subsequent calls do not match the first. @@ -194,33 +193,21 @@ public: /** * Ensures that a given frame number exists with the given parameters, and - * returns pointers to the data storage for that frame. + * returns a RawAccessFrameRef for that frame. * It is not possible to create sparse frame arrays; you can only append - * frames to the current frame array. + * frames to the current frame array, or if there is only one frame in the + * array, replace that frame. + * If a non-paletted frame is desired, pass 0 for aPaletteDepth. */ - nsresult EnsureFrame(uint32_t aFramenum, int32_t aX, int32_t aY, - int32_t aWidth, int32_t aHeight, - gfx::SurfaceFormat aFormat, - uint8_t aPaletteDepth, - uint8_t** imageData, - uint32_t* imageLength, - uint32_t** paletteData, - uint32_t* paletteLength, - imgFrame** aFrame); - - /** - * A shorthand for EnsureFrame, above, with aPaletteDepth = 0 and paletteData - * and paletteLength set to null. - */ - nsresult EnsureFrame(uint32_t aFramenum, int32_t aX, int32_t aY, - int32_t aWidth, int32_t aHeight, - gfx::SurfaceFormat aFormat, - uint8_t** imageData, - uint32_t* imageLength, - imgFrame** aFrame); + RawAccessFrameRef EnsureFrame(uint32_t aFrameNum, + const nsIntRect& aFrameRect, + uint32_t aDecodeFlags, + gfx::SurfaceFormat aFormat, + uint8_t aPaletteDepth, + imgFrame* aPreviousFrame); /* notification that the entire image has been decoded */ - nsresult DecodingComplete(); + void DecodingComplete(imgFrame* aFinalFrame); /** * Number of times to loop the image. @@ -314,8 +301,13 @@ private: uint32_t aFlags, bool aShouldSyncNotify = true); - already_AddRefed LookupFrameNoDecode(uint32_t aFrameNum); - DrawableFrameRef LookupFrame(uint32_t aFrameNum, uint32_t aFlags, bool aShouldSyncNotify = true); + DrawableFrameRef LookupFrameInternal(uint32_t aFrameNum, + const nsIntSize& aSize, + uint32_t aFlags); + DrawableFrameRef LookupFrame(uint32_t aFrameNum, + const nsIntSize& aSize, + uint32_t aFlags, + bool aShouldSyncNotify = true); uint32_t GetCurrentFrameIndex() const; uint32_t GetRequestedFrameIndex(uint32_t aWhichFrame) const; @@ -324,18 +316,12 @@ private: size_t SizeOfDecodedWithComputedFallbackIfHeap(gfxMemoryLocation aLocation, MallocSizeOf aMallocSizeOf) const; - void EnsureAnimExists(); - - nsresult InternalAddFrameHelper(uint32_t framenum, imgFrame *frame, - uint8_t **imageData, uint32_t *imageLength, - uint32_t **paletteData, uint32_t *paletteLength, - imgFrame** aRetFrame); - nsresult InternalAddFrame(uint32_t framenum, int32_t aX, int32_t aY, int32_t aWidth, int32_t aHeight, - gfx::SurfaceFormat aFormat, uint8_t aPaletteDepth, - uint8_t **imageData, uint32_t *imageLength, - uint32_t **paletteData, uint32_t *paletteLength, - imgFrame** aRetFrame); - + RawAccessFrameRef InternalAddFrame(uint32_t aFrameNum, + const nsIntRect& aFrameRect, + uint32_t aDecodeFlags, + gfx::SurfaceFormat aFormat, + uint8_t aPaletteDepth, + imgFrame* aPreviousFrame); nsresult DoImageDataComplete(); bool ApplyDecodeFlags(uint32_t aNewFlags); @@ -370,11 +356,11 @@ private: // data // and imgIContainer::FLAG_DECODE_NO_COLORSPACE_CONVERSION. uint32_t mFrameDecodeFlags; - //! All the frames of the image - FrameBlender mFrameBlender; + //! All the frames of the image. + Maybe mFrameBlender; - // The last frame we decoded for multipart images. - nsRefPtr mMultipartDecodedFrame; + //! The last frame we decoded for multipart images. + DrawableFrameRef mMultipartDecodedFrame; nsCOMPtr mProperties; @@ -439,8 +425,13 @@ private: // data // Do we have the frames in decoded form? bool mDecoded:1; + bool mHasFirstFrame:1; bool mHasBeenDecoded:1; + // Whether we're waiting to start animation. If we get a StartAnimation() call + // but we don't yet have more than one frame, mPendingAnimation is set so that + // we know to start animation later if/when we have more frames. + bool mPendingAnimation:1; // Whether the animation can stop, due to running out // of frames, or no more owning request diff --git a/image/src/imgFrame.cpp b/image/src/imgFrame.cpp index fcc0015b8050..094f698a974a 100644 --- a/image/src/imgFrame.cpp +++ b/image/src/imgFrame.cpp @@ -111,6 +111,23 @@ static bool AllowedImageSize(int32_t aWidth, int32_t aHeight) return true; } +static bool AllowedImageAndFrameDimensions(const nsIntSize& aImageSize, + const nsIntRect& aFrameRect) +{ + if (!AllowedImageSize(aImageSize.width, aImageSize.height)) { + return false; + } + if (!AllowedImageSize(aFrameRect.width, aFrameRect.height)) { + return false; + } + nsIntRect imageRect(0, 0, aImageSize.width, aImageSize.height); + if (!imageRect.Contains(aFrameRect)) { + return false; + } + return true; +} + + imgFrame::imgFrame() : mDecoded(0, 0, 0, 0), mDecodedMutex("imgFrame::mDecoded"), @@ -123,7 +140,6 @@ imgFrame::imgFrame() : mCompositingFailed(false), mHasNoAlpha(false), mNonPremult(false), - mDiscardable(false), mOptimizable(false), mInformedDiscardTracker(false) { @@ -147,17 +163,19 @@ imgFrame::~imgFrame() } nsresult -imgFrame::InitForDecoder(const nsIntRect& aRect, +imgFrame::InitForDecoder(const nsIntSize& aImageSize, + const nsIntRect& aRect, SurfaceFormat aFormat, uint8_t aPaletteDepth /* = 0 */) { // Assert for properties that should be verified by decoders, // warn for properties related to bad content. - if (!AllowedImageSize(aRect.width, aRect.height)) { + if (!AllowedImageAndFrameDimensions(aImageSize, aRect)) { NS_WARNING("Should have legal image size"); return NS_ERROR_FAILURE; } + mImageSize = aImageSize.ToIntSize(); mOffset.MoveTo(aRect.x, aRect.y); mSize.SizeTo(aRect.width, aRect.height); @@ -221,6 +239,7 @@ imgFrame::InitWithDrawable(gfxDrawable* aDrawable, return NS_ERROR_FAILURE; } + mImageSize = aSize.ToIntSize(); mOffset.MoveTo(0, 0); mSize.SizeTo(aSize.width, aSize.height); @@ -415,9 +434,7 @@ nsresult imgFrame::Optimize() // allows the operating system to free our volatile buffer. // XXX(seth): We'd eventually like to do this on all platforms, but right now // converting raw memory to a SourceSurface is expensive on some backends. - if (mDiscardable) { - mImageSurface = nullptr; - } + mImageSurface = nullptr; #endif return NS_OK; @@ -492,8 +509,7 @@ imgFrame::SurfaceForDrawing(bool aDoPadding, } bool imgFrame::Draw(gfxContext* aContext, const ImageRegion& aRegion, - const nsIntMargin& aPadding, GraphicsFilter aFilter, - uint32_t aImageFlags) + GraphicsFilter aFilter, uint32_t aImageFlags) { PROFILER_LABEL("imgFrame", "Draw", js::ProfileEntry::Category::GRAPHICS); @@ -504,7 +520,12 @@ bool imgFrame::Draw(gfxContext* aContext, const ImageRegion& aRegion, "We must be allowed to sample *some* source pixels!"); NS_ASSERTION(!mPalettedImageData, "Directly drawing a paletted image!"); - bool doPadding = aPadding != nsIntMargin(0,0,0,0); + nsIntMargin padding(mOffset.y, + mImageSize.width - (mOffset.x + mSize.width), + mImageSize.height - (mOffset.y + mSize.height), + mOffset.x); + + bool doPadding = padding != nsIntMargin(0,0,0,0); bool doPartialDecode = !ImageComplete(); if (mSinglePixel && !doPadding && !doPartialDecode) { @@ -519,14 +540,12 @@ bool imgFrame::Draw(gfxContext* aContext, const ImageRegion& aRegion, return true; } - gfxRect imageRect(0, 0, mSize.width + aPadding.LeftRight(), - mSize.height + aPadding.TopBottom()); - RefPtr surf = GetSurface(); if (!surf && !mSinglePixel) { return false; } + gfxRect imageRect(0, 0, mImageSize.width, mImageSize.height); bool doTile = !imageRect.Contains(aRegion.Rect()) && !(aImageFlags & imgIContainer::FLAG_CLAMP); ImageRegion region(aRegion); @@ -539,7 +558,7 @@ bool imgFrame::Draw(gfxContext* aContext, const ImageRegion& aRegion, gfxContextMatrixAutoSaveRestore autoSR(aContext); SurfaceWithFormat surfaceResult = SurfaceForDrawing(doPadding, doPartialDecode, doTile, aContext, - aPadding, imageRect, region, surf); + padding, imageRect, region, surf); if (surfaceResult.IsValid()) { gfxUtils::DrawPixelSnapped(aContext, surfaceResult.mDrawable, @@ -579,34 +598,9 @@ imgFrame::GetStride() const return VolatileSurfaceStride(mSize, mFormat); } -<<<<<<< found SurfaceFormat imgFrame::GetFormat() const { -||||||| expected -bool imgFrame::GetNeedsBackground() const -{ - // We need a background painted if we have alpha or we're incomplete. -======= -bool imgFrame::GetNeedsBackground() const -{ - // We need a background painted if we're incomplete. - if (!ImageComplete()) { - return true; - } - - // We need a background painted if we might not be opaque. ->>>>>>> replacement -<<<<<<< found return mFormat; -||||||| expected - return (mFormat == SurfaceFormat::B8G8R8A8 || !ImageComplete()); -======= - if (mFormat == SurfaceFormat::B8G8R8A8 && !mHasNoAlpha) { - return true; - } - - return false; ->>>>>>> replacement } uint32_t imgFrame::GetImageBytesPerRow() const @@ -804,13 +798,6 @@ nsresult imgFrame::UnlockImageData() return NS_OK; } -void -imgFrame::SetDiscardable() -{ - MOZ_ASSERT(mLockCount, "Expected to be locked when SetDiscardable is called"); - mDiscardable = true; -} - void imgFrame::SetOptimizable() { diff --git a/image/src/imgFrame.h b/image/src/imgFrame.h index 1014071b4dec..8c61039ff001 100644 --- a/image/src/imgFrame.h +++ b/image/src/imgFrame.h @@ -44,7 +44,8 @@ public: * when drawing content into an imgFrame, as it may use a different graphics * backend than normal content drawing. */ - nsresult InitForDecoder(const nsIntRect& aRect, + nsresult InitForDecoder(const nsIntSize& aImageSize, + const nsIntRect& aRect, SurfaceFormat aFormat, uint8_t aPaletteDepth = 0); @@ -52,7 +53,7 @@ public: SurfaceFormat aFormat, uint8_t aPaletteDepth = 0) { - return InitForDecoder(nsIntRect(0, 0, aSize.width, aSize.height), + return InitForDecoder(aSize, nsIntRect(0, 0, aSize.width, aSize.height), aFormat, aPaletteDepth); } @@ -77,11 +78,11 @@ public: RawAccessFrameRef RawAccessRef(); bool Draw(gfxContext* aContext, const ImageRegion& aRegion, - const nsIntMargin& aPadding, GraphicsFilter aFilter, - uint32_t aImageFlags); + GraphicsFilter aFilter, uint32_t aImageFlags); nsresult ImageUpdated(const nsIntRect &aUpdateRect); + IntSize GetImageSize() { return mImageSize; } nsIntRect GetRect() const; IntSize GetSize() const { return mSize; } bool NeedsPadding() const { return mOffset != nsIntPoint(0, 0); } @@ -112,7 +113,6 @@ public: bool GetCompositingFailed() const; void SetCompositingFailed(bool val); - void SetDiscardable(); void SetOptimizable(); TemporaryRef GetSurface(); @@ -173,6 +173,7 @@ private: // data RefPtr mImageSurface; RefPtr mOptSurface; + IntSize mImageSize; IntSize mSize; nsIntPoint mOffset; @@ -205,7 +206,6 @@ private: // data bool mCompositingFailed; bool mHasNoAlpha; bool mNonPremult; - bool mDiscardable; bool mOptimizable; /** Have we called DiscardTracker::InformAllocation()? */ From 841625f805858853bd8364d7953b7702ab5e5255 Mon Sep 17 00:00:00 2001 From: Seth Fowler Date: Wed, 26 Nov 2014 13:22:10 -0800 Subject: [PATCH 05/64] Bug 1060869 (Part 3) - Make the SurfaceCache free only a fraction of its data on memory pressure. r=dholbert --- gfx/thebes/gfxPrefs.h | 1 + image/src/SurfaceCache.cpp | 52 +++++++++++++++++++++++++++++++------ modules/libpref/init/all.js | 8 ++++++ 3 files changed, 53 insertions(+), 8 deletions(-) diff --git a/gfx/thebes/gfxPrefs.h b/gfx/thebes/gfxPrefs.h index bd7969705292..41f18d05c38c 100644 --- a/gfx/thebes/gfxPrefs.h +++ b/gfx/thebes/gfxPrefs.h @@ -239,6 +239,7 @@ private: DECL_GFX_PREF(Live, "image.mem.hard_limit_decoded_image_kb", ImageMemHardLimitDecodedImageKB, uint32_t, 0); DECL_GFX_PREF(Live, "image.mem.max_decoded_image_kb", ImageMemMaxDecodedImageKB, uint32_t, 50*1024); DECL_GFX_PREF(Live, "image.mem.max_ms_before_yield", ImageMemMaxMSBeforeYield, uint32_t, 400); + DECL_GFX_PREF(Once, "image.mem.surfacecache.discard_factor", ImageMemSurfaceCacheDiscardFactor, uint32_t, 1); DECL_GFX_PREF(Once, "image.mem.surfacecache.max_size_kb", ImageMemSurfaceCacheMaxSizeKB, uint32_t, 100 * 1024); DECL_GFX_PREF(Once, "image.mem.surfacecache.min_expiration_ms", ImageMemSurfaceCacheMinExpirationMS, uint32_t, 60*1000); DECL_GFX_PREF(Once, "image.mem.surfacecache.size_factor", ImageMemSurfaceCacheSizeFactor, uint32_t, 64); diff --git a/image/src/SurfaceCache.cpp b/image/src/SurfaceCache.cpp index f6e4914fdade..76f15dba69ab 100644 --- a/image/src/SurfaceCache.cpp +++ b/image/src/SurfaceCache.cpp @@ -240,10 +240,12 @@ public: NS_DECL_ISUPPORTS SurfaceCacheImpl(uint32_t aSurfaceCacheExpirationTimeMS, + uint32_t aSurfaceCacheDiscardFactor, uint32_t aSurfaceCacheSize) : mExpirationTracker(MOZ_THIS_IN_INITIALIZER_LIST(), aSurfaceCacheExpirationTimeMS) , mMemoryPressureObserver(new MemoryPressureObserver) + , mDiscardFactor(aSurfaceCacheDiscardFactor) , mMaxCost(aSurfaceCacheSize) , mAvailableCost(aSurfaceCacheSize) , mLockedCost(0) @@ -474,6 +476,32 @@ public: } } + void DiscardForMemoryPressure() + { + // Compute our discardable cost. Since locked surfaces aren't discardable, + // we exclude them. + const Cost discardableCost = (mMaxCost - mAvailableCost) - mLockedCost; + MOZ_ASSERT(discardableCost <= mMaxCost, "Discardable cost doesn't add up"); + + // Our target is to raise our available cost by (1 / mDiscardFactor) of our + // discardable cost - in other words, we want to end up with about + // (discardableCost / mDiscardFactor) fewer bytes stored in the surface + // cache after we're done. + const Cost targetCost = mAvailableCost + (discardableCost / mDiscardFactor); + + if (targetCost > mMaxCost - mLockedCost) { + MOZ_ASSERT_UNREACHABLE("Target cost is more than we can discard"); + DiscardAll(); + return; + } + + // Discard surfaces until we've reduced our cost to our target cost. + while (mAvailableCost < targetCost) { + MOZ_ASSERT(!mCosts.IsEmpty(), "Removed everything and still not done"); + Remove(mCosts.LastElement().GetSurface()); + } + } + static PLDHashOperator DoStopTracking(const SurfaceKey&, CachedSurface* aSurface, void* aCache) @@ -600,7 +628,7 @@ private: NS_IMETHOD Observe(nsISupports*, const char* aTopic, const char16_t*) { if (sInstance && strcmp(aTopic, "memory-pressure") == 0) { - sInstance->DiscardAll(); + sInstance->DiscardForMemoryPressure(); } return NS_OK; } @@ -614,6 +642,7 @@ private: nsRefPtrHashtable, ImageSurfaceCache> mImageCaches; SurfaceTracker mExpirationTracker; nsRefPtr mMemoryPressureObserver; + const uint32_t mDiscardFactor; const Cost mMaxCost; Cost mAvailableCost; Cost mLockedCost; @@ -639,6 +668,13 @@ SurfaceCache::Initialize() uint32_t surfaceCacheExpirationTimeMS = gfxPrefs::ImageMemSurfaceCacheMinExpirationMS(); + // What fraction of the memory used by the surface cache we should discard + // when we get a memory pressure notification. This value is interpreted as + // 1/N, so 1 means to discard everything, 2 means to discard about half of the + // memory we're using, and so forth. We clamp it to avoid division by zero. + uint32_t surfaceCacheDiscardFactor = + max(gfxPrefs::ImageMemSurfaceCacheDiscardFactor(), 1u); + // Maximum size of the surface cache, in kilobytes. uint64_t surfaceCacheMaxSizeKB = gfxPrefs::ImageMemSurfaceCacheMaxSizeKB(); @@ -649,10 +685,9 @@ SurfaceCache::Initialize() // For example, a value of 4 would yield a 256MB cache on a 1GB machine. // The smallest machines we are likely to run this code on have 256MB // of memory, which would yield a 64MB cache on this setting. - uint32_t surfaceCacheSizeFactor = gfxPrefs::ImageMemSurfaceCacheSizeFactor(); - - // Clamp to avoid division by zero below. - surfaceCacheSizeFactor = max(surfaceCacheSizeFactor, 1u); + // We clamp this value to avoid division by zero. + uint32_t surfaceCacheSizeFactor = + max(gfxPrefs::ImageMemSurfaceCacheSizeFactor(), 1u); // Compute the size of the surface cache. uint64_t proposedSize = PR_GetPhysicalMemorySize() / surfaceCacheSizeFactor; @@ -660,10 +695,11 @@ SurfaceCache::Initialize() uint32_t finalSurfaceCacheSizeBytes = min(surfaceCacheSizeBytes, uint64_t(UINT32_MAX)); - // Create the surface cache singleton with the requested expiration time and - // size. Note that the size is a limit that the cache may not grow beyond, but - // we do not actually allocate any storage for surfaces at this time. + // Create the surface cache singleton with the requested settings. Note that + // the size is a limit that the cache may not grow beyond, but we do not + // actually allocate any storage for surfaces at this time. sInstance = new SurfaceCacheImpl(surfaceCacheExpirationTimeMS, + surfaceCacheDiscardFactor, finalSurfaceCacheSizeBytes); sInstance->InitMemoryReporter(); } diff --git a/modules/libpref/init/all.js b/modules/libpref/init/all.js index 6aa3581f83b9..748db4d03010 100644 --- a/modules/libpref/init/all.js +++ b/modules/libpref/init/all.js @@ -3808,6 +3808,14 @@ pref("image.mem.surfacecache.max_size_kb", 102400); // 100MB // systems. pref("image.mem.surfacecache.size_factor", 64); +// How much of the data in the surface cache is discarded when we get a memory +// pressure notification, as a fraction. The discard factor is interpreted as a +// reciprocal, so a discard factor of 1 means to discard everything in the +// surface cache on memory pressure, a discard factor of 2 means to discard half +// of the data, and so forth. The default should be a good balance for desktop +// and laptop systems, where we never discard visible images. +pref("image.mem.surfacecache.discard_factor", 1); + // Whether we decode images on multiple background threads rather than the // foreground thread. pref("image.multithreaded_decoding.enabled", true); From b8c1e93d1d48df0a447b5dfbff745cc71e4244b2 Mon Sep 17 00:00:00 2001 From: Seth Fowler Date: Wed, 26 Nov 2014 13:22:10 -0800 Subject: [PATCH 06/64] Bug 1060869 (Part 4) - Update SurfaceCache prefs to increase the cache size. r=dholbert,tn --- b2g/app/b2g.js | 19 ++++++++++++++++--- dom/base/test/mochitest.ini | 2 +- dom/html/reftests/reftest.list | 2 +- image/test/mochitest/chrome.ini | 1 + image/test/mochitest/mochitest.ini | 3 ++- layout/reftests/bugs/reftest.list | 4 ++-- modules/libpref/init/all.js | 11 +++++------ 7 files changed, 28 insertions(+), 14 deletions(-) diff --git a/b2g/app/b2g.js b/b2g/app/b2g.js index ef5a5f2e1341..3cf73a09c6ff 100644 --- a/b2g/app/b2g.js +++ b/b2g/app/b2g.js @@ -330,9 +330,22 @@ pref("media.video-queue.default-size", 3); pref("image.mem.decodeondraw", true); pref("image.mem.allow_locking_in_content_processes", false); /* don't allow image locking */ pref("image.mem.min_discard_timeout_ms", 86400000); /* 24h, we rely on the out of memory hook */ -pref("image.mem.max_decoded_image_kb", 30000); /* 30MB seems reasonable */ -// 65MB seems reasonable and layout/reftests/bugs/370629-1.html requires more than 62MB -pref("image.mem.hard_limit_decoded_image_kb", 66560); +// At this point 'max_decoded_image_kb' only applies to animated images. They're +// unfortunately fairly large, so this pref still needs to be somewhat generous, +// but it makes sense to reduce it since most types of images are now in the +// surface cache. Once animated images are stored in the surface cache too, this +// pref will go away; see bug 977459. The same goes for +// 'hard_limit_decoded_image_kb'; the surface cache limits are all hard. +pref("image.mem.max_decoded_image_kb", 16384); // 16MB +pref("image.mem.hard_limit_decoded_image_kb", 16384); // 16MB +// Limit the surface cache to 1/8 of main memory or 128MB, whichever is smaller. +// Almost everything that was factored into 'max_decoded_image_kb' is now stored +// in the surface cache. 1/8 of main memory is 32MB on a 256MB device, which is +// about the same as the old 'max_decoded_image_kb'. +pref("image.mem.surfacecache.max_size_kb", 131072); // 128MB +pref("image.mem.surfacecache.size_factor", 8); // 1/8 of main memory +pref("image.mem.surfacecache.discard_factor", 2); // Discard 1/2 of the surface cache at a time. +pref("image.mem.surfacecache.min_expiration_ms", 86400000); // 24h, we rely on the out of memory hook pref("image.onload.decode.limit", 24); /* don't decode more than 24 images eagerly */ // XXX this isn't a good check for "are touch events supported", but diff --git a/dom/base/test/mochitest.ini b/dom/base/test/mochitest.ini index 0d002888f36e..db57586d69dd 100644 --- a/dom/base/test/mochitest.ini +++ b/dom/base/test/mochitest.ini @@ -674,7 +674,7 @@ skip-if = buildapp == 'b2g' || toolkit == 'android' #bug 904183 # b2g(bug 904183 [test_fileapi.html] skip-if = e10s [test_fileapi_slice.html] -skip-if = buildapp == 'b2g' || toolkit == 'android' || e10s #bug 775227 +disabled = Busted on B2G, Android, E10S and now Mulet. Bug 775227. [test_getElementById.html] [test_html_colors_quirks.html] [test_html_colors_standards.html] diff --git a/dom/html/reftests/reftest.list b/dom/html/reftests/reftest.list index 6bb3f44aa9cd..47570e403178 100644 --- a/dom/html/reftests/reftest.list +++ b/dom/html/reftests/reftest.list @@ -39,7 +39,7 @@ skip-if(Android||B2G) == 649134-2.html 649134-2-ref.html # (Fuzzy necessary due to pixel-wise comparison of different JPEGs. # The vast majority of the fuzziness comes from Linux and WinXP.) fuzzy(1,149) == bug917595-iframe-1.html bug917595-1-ref.html -fuzzy(3,640) == bug917595-exif-rotated.jpg bug917595-pixel-rotated.jpg +skip-if(B2G) fuzzy-if(!B2G,3,640) == bug917595-exif-rotated.jpg bug917595-pixel-rotated.jpg # bug 1060869 == href-attr-change-restyles.html href-attr-change-restyles-ref.html == figure.html figure-ref.html diff --git a/image/test/mochitest/chrome.ini b/image/test/mochitest/chrome.ini index 783ab899ffae..70b48ff811d3 100644 --- a/image/test/mochitest/chrome.ini +++ b/image/test/mochitest/chrome.ini @@ -47,4 +47,5 @@ skip-if = true # bug 1100497 [test_svg_filter_animation.html] [test_synchronized_animation.html] [test_undisplayed_iframe.html] +skip-if = true # bug 1060869 [test_xultree_animation.xhtml] diff --git a/image/test/mochitest/mochitest.ini b/image/test/mochitest/mochitest.ini index a81a5faaa78c..22c7d4b187af 100644 --- a/image/test/mochitest/mochitest.ini +++ b/image/test/mochitest/mochitest.ini @@ -93,4 +93,5 @@ skip-if = toolkit == "gonk" #Bug 997034 - canvas.toDataURL() often causes lost c [test_error_events.html] [test_short_gif_header.html] [test_image_buffer_limit.html] -run-if = toolkit == "gonk" #Image buffer limit is only set for Firefox OS currently. +#run-if = toolkit == "gonk" #Image buffer limit is only set for Firefox OS currently. +skip-if = true # bug 1060869 diff --git a/layout/reftests/bugs/reftest.list b/layout/reftests/bugs/reftest.list index c805de68dd62..ca7511fb0cc4 100644 --- a/layout/reftests/bugs/reftest.list +++ b/layout/reftests/bugs/reftest.list @@ -637,7 +637,7 @@ skip-if(B2G&&browserIsRemote) == 369882.xul 369882-ref.xul # bug 974780 == 370525-rowspan-4.html 370525-rowspan-4-ref.html == 370525-sib.html 370525-sib-ref.html == 370586-1.xhtml 370586-1-ref.xhtml -== 370629-1.html 370629-1-ref.html +skip-if(B2G) == 370629-1.html 370629-1-ref.html # bug 1060869 skip-if(B2G) == 370629-2.html 370629-2-ref.html == 370692-1.xhtml 370692-1-ref.xhtml == 371041-1.html 371041-1-ref.html @@ -1844,4 +1844,4 @@ test-pref(dom.webcomponents.enabled,true) == 1066554-1.html 1066554-1-ref.html == 1078262-1.html about:blank test-pref(layout.testing.overlay-scrollbars.always-visible,false) == 1081072-1.html 1081072-1-ref.html fuzzy-if(winWidget&&!layersGPUAccelerated,1,31) == 1081185-1.html 1081185-1-ref.html -== 1097437-1.html 1097437-1-ref.html \ No newline at end of file +== 1097437-1.html 1097437-1-ref.html diff --git a/modules/libpref/init/all.js b/modules/libpref/init/all.js index 748db4d03010..6f18beeaa91e 100644 --- a/modules/libpref/init/all.js +++ b/modules/libpref/init/all.js @@ -3799,14 +3799,13 @@ pref("image.mem.hard_limit_decoded_image_kb", 0); pref("image.mem.surfacecache.min_expiration_ms", 60000); // 60ms // Maximum size for the surface cache, in kilobytes. -pref("image.mem.surfacecache.max_size_kb", 102400); // 100MB +pref("image.mem.surfacecache.max_size_kb", 1048576); // 1GB // The surface cache's size, within the constraints of the maximum size set -// above, is determined using a formula based on system capabilities like memory -// size. The size factor is used to tune this formula. Larger size factors -// result in smaller caches. The default should be a good balance for most -// systems. -pref("image.mem.surfacecache.size_factor", 64); +// above, is determined as a fraction of main memory size. The size factor is +// interpreted as a reciprocal, so a size factor of 4 means to use no more than +// 1/4 of main memory. The default should be a good balance for most systems. +pref("image.mem.surfacecache.size_factor", 4); // How much of the data in the surface cache is discarded when we get a memory // pressure notification, as a fraction. The discard factor is interpreted as a From 100f7e8eafd7bc4c99d7b63efe353c5e58134879 Mon Sep 17 00:00:00 2001 From: Seth Fowler Date: Wed, 26 Nov 2014 13:22:11 -0800 Subject: [PATCH 07/64] Bug 923302 - Add explicit memory reporting for SurfaceCache. r=njn,dholbert --- image/src/RasterImage.cpp | 11 ++-- image/src/SurfaceCache.cpp | 104 +++++++++++++++++++++++++++++-------- image/src/SurfaceCache.h | 33 +++++++++--- image/src/VectorImage.cpp | 23 ++++---- 4 files changed, 129 insertions(+), 42 deletions(-) diff --git a/image/src/RasterImage.cpp b/image/src/RasterImage.cpp index 8ad0eb2cc143..b468537987af 100644 --- a/image/src/RasterImage.cpp +++ b/image/src/RasterImage.cpp @@ -981,10 +981,13 @@ size_t RasterImage::SizeOfDecodedWithComputedFallbackIfHeap(gfxMemoryLocation aLocation, MallocSizeOf aMallocSizeOf) const { - return mFrameBlender - ? mFrameBlender->SizeOfDecodedWithComputedFallbackIfHeap(aLocation, - aMallocSizeOf) - : 0; + size_t n = 0; + n += SurfaceCache::SizeOfSurfaces(ImageKey(this), aLocation, aMallocSizeOf); + if (mFrameBlender) { + n += mFrameBlender->SizeOfDecodedWithComputedFallbackIfHeap(aLocation, + aMallocSizeOf); + } + return n; } size_t diff --git a/image/src/SurfaceCache.cpp b/image/src/SurfaceCache.cpp index 76f15dba69ab..ec94dae7e85f 100644 --- a/image/src/SurfaceCache.cpp +++ b/image/src/SurfaceCache.cpp @@ -54,7 +54,7 @@ static StaticRefPtr sInstance; // SurfaceCache Implementation /////////////////////////////////////////////////////////////////////////////// -/* +/** * Cost models the cost of storing a surface in the cache. Right now, this is * simply an estimate of the size of the surface in bytes, but in the future it * may be worth taking into account the cost of rematerializing the surface as @@ -67,7 +67,7 @@ static Cost ComputeCost(const IntSize& aSize) return aSize.width * aSize.height * 4; // width * height * 4 bytes (32bpp) } -/* +/** * Since we want to be able to make eviction decisions based on cost, we need to * be able to look up the CachedSurface which has a certain cost as well as the * cost associated with a certain CachedSurface. To make this possible, in data @@ -108,7 +108,7 @@ private: Cost mCost; }; -/* +/** * A CachedSurface associates a surface with a key that uniquely identifies that * surface. */ @@ -158,6 +158,36 @@ public: nsExpirationState* GetExpirationState() { return &mExpirationState; } Lifetime GetLifetime() const { return mLifetime; } + // A helper type used by SurfaceCacheImpl::SizeOfSurfacesSum. + struct SizeOfSurfacesSum + { + SizeOfSurfacesSum(gfxMemoryLocation aLocation, + MallocSizeOf aMallocSizeOf) + : mLocation(aLocation) + , mMallocSizeOf(aMallocSizeOf) + , mSum(0) + { } + + void Add(CachedSurface* aCachedSurface) + { + MOZ_ASSERT(aCachedSurface, "Should have a CachedSurface"); + + if (!aCachedSurface->mSurface) { + return; + } + + mSum += aCachedSurface->mSurface-> + SizeOfExcludingThisWithComputedFallbackIfHeap(mLocation, mMallocSizeOf); + } + + size_t Result() const { return mSum; } + + private: + gfxMemoryLocation mLocation; + MallocSizeOf mMallocSizeOf; + size_t mSum; + }; + private: nsExpirationState mExpirationState; nsRefPtr mSurface; @@ -168,7 +198,7 @@ private: const Lifetime mLifetime; }; -/* +/** * An ImageSurfaceCache is a per-image surface cache. For correctness we must be * able to remove all surfaces associated with an image when the image is * destroyed or invalidated. Since this will happen frequently, it makes sense @@ -227,7 +257,7 @@ private: bool mLocked; }; -/* +/** * SurfaceCacheImpl is responsible for determining which surfaces will be cached * and managing the surface cache data structures. Rather than interact with * SurfaceCacheImpl directly, client code interacts with SurfaceCache, which @@ -550,38 +580,53 @@ public: NS_IMETHOD CollectReports(nsIHandleReportCallback* aHandleReport, nsISupports* aData, - bool aAnonymize) + bool aAnonymize) MOZ_OVERRIDE { + // We have explicit memory reporting for the surface cache which is more + // accurate than the cost metrics we report here, but these metrics are + // still useful to report, since they control the cache's behavior. nsresult rv; - rv = MOZ_COLLECT_REPORT("imagelib-surface-cache-total", + rv = MOZ_COLLECT_REPORT("imagelib-surface-cache-estimated-total", KIND_OTHER, UNITS_BYTES, - SizeOfSurfacesEstimate(), - "Total memory used by the imagelib surface cache."); + (mMaxCost - mAvailableCost), + "Estimated total memory used by the imagelib " + "surface cache."); NS_ENSURE_SUCCESS(rv, rv); - rv = MOZ_COLLECT_REPORT("imagelib-surface-cache-locked", + rv = MOZ_COLLECT_REPORT("imagelib-surface-cache-estimated-locked", KIND_OTHER, UNITS_BYTES, - SizeOfLockedSurfacesEstimate(), - "Memory used by locked surfaces in the imagelib " - "surface cache."); + mLockedCost, + "Estimated memory used by locked surfaces in the " + "imagelib surface cache."); NS_ENSURE_SUCCESS(rv, rv); return NS_OK; } - // XXX(seth): This is currently only an estimate and, since we don't know - // which surfaces are in GPU memory and which aren't, it's reported as - // KIND_OTHER and will also show up in heap-unclassified. Bug 923302 will - // make this nicer. - Cost SizeOfSurfacesEstimate() const + size_t SizeOfSurfaces(const ImageKey aImageKey, + gfxMemoryLocation aLocation, + MallocSizeOf aMallocSizeOf) { - return mMaxCost - mAvailableCost; + nsRefPtr cache = GetImageCache(aImageKey); + if (!cache) { + return 0; // No surfaces for this image. + } + + // Sum the size of all surfaces in the per-image cache. + CachedSurface::SizeOfSurfacesSum sum(aLocation, aMallocSizeOf); + cache->ForEach(DoSizeOfSurfacesSum, &sum); + + return sum.Result(); } - Cost SizeOfLockedSurfacesEstimate() const + static PLDHashOperator DoSizeOfSurfacesSum(const SurfaceKey&, + CachedSurface* aSurface, + void* aSum) { - return mLockedCost; + auto sum = static_cast(aSum); + sum->Add(aSurface); + return PL_DHASH_NEXT; } private: @@ -625,7 +670,9 @@ private: { NS_DECL_ISUPPORTS - NS_IMETHOD Observe(nsISupports*, const char* aTopic, const char16_t*) + NS_IMETHOD Observe(nsISupports*, + const char* aTopic, + const char16_t*) MOZ_OVERRIDE { if (sInstance && strcmp(aTopic, "memory-pressure") == 0) { sInstance->DiscardForMemoryPressure(); @@ -796,5 +843,18 @@ SurfaceCache::DiscardAll() } } +/* static */ size_t +SurfaceCache::SizeOfSurfaces(const ImageKey aImageKey, + gfxMemoryLocation aLocation, + MallocSizeOf aMallocSizeOf) +{ + MOZ_ASSERT(NS_IsMainThread()); + if (!sInstance) { + return 0; + } + + return sInstance->SizeOfSurfaces(aImageKey, aLocation, aMallocSizeOf); +} + } // namespace image } // namespace mozilla diff --git a/image/src/SurfaceCache.h b/image/src/SurfaceCache.h index 3a2a54b66ec8..a0e8c66e6684 100644 --- a/image/src/SurfaceCache.h +++ b/image/src/SurfaceCache.h @@ -11,13 +11,15 @@ #ifndef MOZILLA_IMAGELIB_SURFACECACHE_H_ #define MOZILLA_IMAGELIB_SURFACECACHE_H_ -#include "mozilla/Maybe.h" // for Maybe -#include "mozilla/HashFunctions.h" // for HashGeneric and AddToHash -#include "gfxPoint.h" // for gfxSize -#include "nsCOMPtr.h" // for already_AddRefed -#include "mozilla/gfx/Point.h" // for mozilla::gfx::IntSize -#include "mozilla/gfx/2D.h" // for SourceSurface -#include "SVGImageContext.h" // for SVGImageContext +#include "mozilla/Maybe.h" // for Maybe +#include "mozilla/MemoryReporting.h" // for MallocSizeOf +#include "mozilla/HashFunctions.h" // for HashGeneric and AddToHash +#include "gfx2DGlue.h" // for gfxMemoryLocation +#include "gfxPoint.h" // for gfxSize +#include "nsCOMPtr.h" // for already_AddRefed +#include "mozilla/gfx/Point.h" // for mozilla::gfx::IntSize +#include "mozilla/gfx/2D.h" // for SourceSurface +#include "SVGImageContext.h" // for SVGImageContext namespace mozilla { namespace image { @@ -293,6 +295,23 @@ struct SurfaceCache */ static void DiscardAll(); + /** + * Computes the size of the surfaces stored for the given image at the given + * memory location. + * + * This is intended for use with memory reporting. + * + * @param aImageKey The image to report memory usage for. + * @param aLocation The location (heap, nonheap, etc.) of the memory to + * report on. + * @param aMallocSizeOf A fallback malloc memory reporting function. This + * should be null unless we're reporting on in-process + * heap memory. + */ + static size_t SizeOfSurfaces(const ImageKey aImageKey, + gfxMemoryLocation aLocation, + MallocSizeOf aMallocSizeOf); + private: virtual ~SurfaceCache() = 0; // Forbid instantiation. }; diff --git a/image/src/VectorImage.cpp b/image/src/VectorImage.cpp index 81f5475ed101..2eeda34ee551 100644 --- a/image/src/VectorImage.cpp +++ b/image/src/VectorImage.cpp @@ -383,25 +383,30 @@ VectorImage::HeapSizeOfDecodedWithComputedFallback(MallocSizeOf aMallocSizeOf) c // If implementing this, we'll need to restructure our callers to make sure // any amount we return is attributed to the vector images measure (i.e. // "explicit/images/{content,chrome}/vector/{used,unused}/...") - return 0; + // XXX(seth): Same goes for the other *SizeOfDecoded() methods. We'll do this + // in bug 921300 or one of its blockers. For now it seems worthwhile to get + // this memory accounted for, even if it gets listed under 'raster'. It does + // make some perverse sense, since we are after all reporting on raster data + // here - it just happens to be computed from a vector document. + return SurfaceCache::SizeOfSurfaces(ImageKey(this), + gfxMemoryLocation::IN_PROCESS_HEAP, + aMallocSizeOf); } size_t VectorImage::NonHeapSizeOfDecoded() const { - // If implementing this, we'll need to restructure our callers to make sure - // any amount we return is attributed to the vector images measure (i.e. - // "explicit/images/{content,chrome}/vector/{used,unused}/...") - return 0; + return SurfaceCache::SizeOfSurfaces(ImageKey(this), + gfxMemoryLocation::IN_PROCESS_NONHEAP, + nullptr); } size_t VectorImage::OutOfProcessSizeOfDecoded() const { - // If implementing this, we'll need to restructure our callers to make sure - // any amount we return is attributed to the vector images measure (i.e. - // "explicit/images/{content,chrome}/vector/{used,unused}/...") - return 0; + return SurfaceCache::SizeOfSurfaces(ImageKey(this), + gfxMemoryLocation::OUT_OF_PROCESS, + nullptr); } MOZ_DEFINE_MALLOC_SIZE_OF(WindowsMallocSizeOf); From ff5ac4a822ddbac75e1dff863b7f759bce7f0f53 Mon Sep 17 00:00:00 2001 From: James Willcox Date: Wed, 26 Nov 2014 15:16:07 -0600 Subject: [PATCH 08/64] Bug 1097116 - Add fencing and better lifetime management for EGLImage Images r=jgilbert --HG-- extra : rebase_source : 8da8c1e9e5ded06c8735ee5d30f8333f829064c5 --- gfx/layers/GLImages.cpp | 18 ++++++++++++++++++ gfx/layers/GLImages.h | 5 +++++ gfx/layers/client/ImageClient.cpp | 7 +++---- gfx/layers/ipc/LayersSurfaces.ipdlh | 1 + gfx/layers/opengl/TextureClientOGL.cpp | 17 ++++++----------- gfx/layers/opengl/TextureClientOGL.h | 10 ++++------ gfx/layers/opengl/TextureHostOGL.cpp | 8 ++++++++ gfx/layers/opengl/TextureHostOGL.h | 2 ++ 8 files changed, 47 insertions(+), 21 deletions(-) diff --git a/gfx/layers/GLImages.cpp b/gfx/layers/GLImages.cpp index 6a30b3749dd5..3a7bb73e9f68 100644 --- a/gfx/layers/GLImages.cpp +++ b/gfx/layers/GLImages.cpp @@ -8,6 +8,7 @@ #include "GLBlitHelper.h" #include "GLReadTexImageHelper.h" #include "AndroidSurfaceTexture.h" +#include "GLLibraryEGL.h" using namespace mozilla; using namespace mozilla::gl; @@ -17,6 +18,23 @@ namespace layers { static nsRefPtr sSnapshotContext; +EGLImageImage::~EGLImageImage() +{ + if (!mData.mOwns) { + return; + } + + if (mData.mImage) { + sEGLLibrary.fDestroyImage(EGL_DISPLAY(), mData.mImage); + mData.mImage = nullptr; + } + + if (mData.mSync) { + sEGLLibrary.fDestroySync(EGL_DISPLAY(), mData.mSync); + mData.mSync = nullptr; + } +} + TemporaryRef SurfaceTextureImage::GetAsSourceSurface() { diff --git a/gfx/layers/GLImages.h b/gfx/layers/GLImages.h index add2d55644a8..4928d4b9e09f 100644 --- a/gfx/layers/GLImages.h +++ b/gfx/layers/GLImages.h @@ -22,8 +22,10 @@ class EGLImageImage : public Image { public: struct Data { EGLImage mImage; + EGLSync mSync; gfx::IntSize mSize; bool mInverted; + bool mOwns; }; void SetData(const Data& aData) { mData = aData; } @@ -38,6 +40,9 @@ public: EGLImageImage() : Image(nullptr, ImageFormat::EGLIMAGE) {} +protected: + virtual ~EGLImageImage(); + private: Data mData; }; diff --git a/gfx/layers/client/ImageClient.cpp b/gfx/layers/client/ImageClient.cpp index 83d9f7a7cd75..9c68981ad084 100644 --- a/gfx/layers/client/ImageClient.cpp +++ b/gfx/layers/client/ImageClient.cpp @@ -192,10 +192,9 @@ ImageClientSingle::UpdateImage(ImageContainer* aContainer, uint32_t aContentFlag if (image->GetFormat() == ImageFormat::EGLIMAGE) { EGLImageImage* typedImage = static_cast(image); - const EGLImageImage::Data* data = typedImage->GetData(); - - texture = new EGLImageTextureClient(mTextureFlags, data->mImage, - size, data->mInverted); + texture = new EGLImageTextureClient(mTextureFlags, + typedImage, + size); #ifdef MOZ_WIDGET_ANDROID } else if (image->GetFormat() == ImageFormat::SURFACE_TEXTURE) { SurfaceTextureImage* typedImage = static_cast(image); diff --git a/gfx/layers/ipc/LayersSurfaces.ipdlh b/gfx/layers/ipc/LayersSurfaces.ipdlh index 6d3a103d5165..a85284f61beb 100644 --- a/gfx/layers/ipc/LayersSurfaces.ipdlh +++ b/gfx/layers/ipc/LayersSurfaces.ipdlh @@ -63,6 +63,7 @@ struct SurfaceTextureDescriptor { struct EGLImageDescriptor { uintptr_t image; // `EGLImage` is a `void*`. + uintptr_t fence; IntSize size; }; diff --git a/gfx/layers/opengl/TextureClientOGL.cpp b/gfx/layers/opengl/TextureClientOGL.cpp index 12ef1c0dba3e..c37a3ffa5ebe 100644 --- a/gfx/layers/opengl/TextureClientOGL.cpp +++ b/gfx/layers/opengl/TextureClientOGL.cpp @@ -8,6 +8,7 @@ #include "mozilla/layers/ISurfaceAllocator.h" #include "mozilla/layers/TextureClientOGL.h" #include "nsSize.h" // for nsIntSize +#include "GLLibraryEGL.h" using namespace mozilla::gl; @@ -20,9 +21,8 @@ class CompositableForwarder; // EGLImageTextureClient EGLImageTextureClient::EGLImageTextureClient(TextureFlags aFlags, - EGLImage aImage, - gfx::IntSize aSize, - bool aInverted) + EGLImageImage* aImage, + gfx::IntSize aSize) : TextureClient(aFlags) , mImage(aImage) , mSize(aSize) @@ -31,26 +31,21 @@ EGLImageTextureClient::EGLImageTextureClient(TextureFlags aFlags, MOZ_ASSERT(XRE_GetProcessType() == GeckoProcessType_Default, "Can't pass an `EGLImage` between processes."); - // Our data is always owned externally. AddFlags(TextureFlags::DEALLOCATE_CLIENT); - if (aInverted) { + if (aImage->GetData()->mInverted) { AddFlags(TextureFlags::NEEDS_Y_FLIP); } } -EGLImageTextureClient::~EGLImageTextureClient() -{ - // Our data is always owned externally. -} - bool EGLImageTextureClient::ToSurfaceDescriptor(SurfaceDescriptor& aOutDescriptor) { MOZ_ASSERT(IsValid()); MOZ_ASSERT(IsAllocated()); - aOutDescriptor = EGLImageDescriptor((uintptr_t)mImage, mSize); + const EGLImageImage::Data* data = mImage->GetData(); + aOutDescriptor = EGLImageDescriptor((uintptr_t)data->mImage, (uintptr_t)data->mSync, mSize); return true; } diff --git a/gfx/layers/opengl/TextureClientOGL.h b/gfx/layers/opengl/TextureClientOGL.h index cde0580a6dd1..d54f520ae1ad 100644 --- a/gfx/layers/opengl/TextureClientOGL.h +++ b/gfx/layers/opengl/TextureClientOGL.h @@ -7,6 +7,7 @@ #define MOZILLA_GFX_TEXTURECLIENTOGL_H #include "GLContextTypes.h" // for SharedTextureHandle, etc +#include "GLImages.h" #include "gfxTypes.h" #include "mozilla/Attributes.h" // for MOZ_OVERRIDE #include "mozilla/gfx/Point.h" // for IntSize @@ -25,11 +26,8 @@ class EGLImageTextureClient : public TextureClient { public: EGLImageTextureClient(TextureFlags aFlags, - EGLImage aImage, - gfx::IntSize aSize, - bool aInverted); - - ~EGLImageTextureClient(); + EGLImageImage* aImage, + gfx::IntSize aSize); virtual bool IsAllocated() const MOZ_OVERRIDE { return true; } @@ -64,7 +62,7 @@ public: } protected: - const EGLImage mImage; + RefPtr mImage; const gfx::IntSize mSize; bool mIsLocked; }; diff --git a/gfx/layers/opengl/TextureHostOGL.cpp b/gfx/layers/opengl/TextureHostOGL.cpp index 8d053bf460cf..743fecedbf3d 100644 --- a/gfx/layers/opengl/TextureHostOGL.cpp +++ b/gfx/layers/opengl/TextureHostOGL.cpp @@ -68,6 +68,7 @@ CreateTextureHostOGL(const SurfaceDescriptor& aDesc, const EGLImageDescriptor& desc = aDesc.get_EGLImageDescriptor(); result = new EGLImageTextureHost(aFlags, (EGLImage)desc.image(), + (EGLSync)desc.fence(), desc.size()); break; } @@ -633,9 +634,11 @@ EGLImageTextureSource::GetTextureTransform() EGLImageTextureHost::EGLImageTextureHost(TextureFlags aFlags, EGLImage aImage, + EGLSync aSync, gfx::IntSize aSize) : TextureHost(aFlags) , mImage(aImage) + , mSync(aSync) , mSize(aSize) , mCompositor(nullptr) { @@ -658,6 +661,11 @@ EGLImageTextureHost::Lock() return false; } + EGLint status = sEGLLibrary.fClientWaitSync(EGL_DISPLAY(), mSync, 0, LOCAL_EGL_FOREVER); + if (status != LOCAL_EGL_CONDITION_SATISFIED) { + return false; + } + if (!mTextureSource) { gfx::SurfaceFormat format = gfx::SurfaceFormat::R8G8B8A8; GLenum target = LOCAL_GL_TEXTURE_2D; diff --git a/gfx/layers/opengl/TextureHostOGL.h b/gfx/layers/opengl/TextureHostOGL.h index 9f8f62851c01..e46a9d115179 100644 --- a/gfx/layers/opengl/TextureHostOGL.h +++ b/gfx/layers/opengl/TextureHostOGL.h @@ -476,6 +476,7 @@ class EGLImageTextureHost : public TextureHost public: EGLImageTextureHost(TextureFlags aFlags, EGLImage aImage, + EGLSync aSync, gfx::IntSize aSize); virtual ~EGLImageTextureHost(); @@ -509,6 +510,7 @@ public: protected: const EGLImage mImage; + const EGLSync mSync; const gfx::IntSize mSize; RefPtr mCompositor; RefPtr mTextureSource; From fe1117609c8d8f07af7aa4c5f2d6d8042b904ce0 Mon Sep 17 00:00:00 2001 From: James Willcox Date: Wed, 26 Nov 2014 15:16:07 -0600 Subject: [PATCH 09/64] Bug 1097116 - Copy the decoded SurfaceTexture into an EGLImage to allow accurate presentation r=jgilbert --HG-- extra : rebase_source : d3165eb2d9534f82c84e3399e744e0c31b64c2dd --- .../fmp4/android/AndroidDecoderModule.cpp | 94 +++++++++++++++++-- dom/media/fmp4/android/AndroidDecoderModule.h | 1 + gfx/layers/GLImages.h | 4 + 3 files changed, 91 insertions(+), 8 deletions(-) diff --git a/dom/media/fmp4/android/AndroidDecoderModule.cpp b/dom/media/fmp4/android/AndroidDecoderModule.cpp index af3c01457e8f..c5d8309cc222 100644 --- a/dom/media/fmp4/android/AndroidDecoderModule.cpp +++ b/dom/media/fmp4/android/AndroidDecoderModule.cpp @@ -4,7 +4,12 @@ #include "AndroidDecoderModule.h" #include "AndroidBridge.h" +#include "GLBlitHelper.h" +#include "GLContext.h" +#include "GLContextEGL.h" +#include "GLContextProvider.h" #include "GLImages.h" +#include "GLLibraryEGL.h" #include "MediaData.h" @@ -56,18 +61,18 @@ public: return InitDecoder(mSurfaceTexture->JavaSurface()); } + void Cleanup() MOZ_OVERRIDE { + mGLContext = nullptr; + } + virtual nsresult Input(mp4_demuxer::MP4Sample* aSample) MOZ_OVERRIDE { mp4_demuxer::AnnexB::ConvertSample(aSample); return MediaCodecDataDecoder::Input(aSample); } - virtual nsresult PostOutput(BufferInfo* aInfo, MediaFormat* aFormat, Microseconds aDuration) MOZ_OVERRIDE { - VideoInfo videoInfo; - videoInfo.mDisplay = nsIntSize(mConfig.display_width, mConfig.display_height); - - bool isSync = false; - if (MediaCodec::getBUFFER_FLAG_SYNC_FRAME() & aInfo->getFlags()) { - isSync = true; + EGLImage CopySurface() { + if (!EnsureGLContext()) { + return nullptr; } nsRefPtr img = mImageContainer->CreateImage(ImageFormat::SURFACE_TEXTURE); @@ -76,9 +81,70 @@ public: data.mSize = gfx::IntSize(mConfig.display_width, mConfig.display_height); data.mInverted = true; - layers::SurfaceTextureImage* typedImg = static_cast(img.get()); + layers::SurfaceTextureImage* stImg = static_cast(img.get()); + stImg->SetData(data); + + mGLContext->MakeCurrent(); + + GLuint tex = CreateTextureForOffscreen(mGLContext, mGLContext->GetGLFormats(), data.mSize); + + GLBlitHelper helper(mGLContext); + if (!helper.BlitImageToTexture(img, data.mSize, tex, LOCAL_GL_TEXTURE_2D)) { + mGLContext->fDeleteTextures(1, &tex); + return nullptr; + } + + EGLint attribs[] = { + LOCAL_EGL_IMAGE_PRESERVED_KHR, LOCAL_EGL_TRUE, + LOCAL_EGL_NONE, LOCAL_EGL_NONE + }; + + EGLContext eglContext = static_cast(mGLContext.get())->GetEGLContext(); + EGLImage eglImage = sEGLLibrary.fCreateImage(EGL_DISPLAY(), eglContext, + LOCAL_EGL_GL_TEXTURE_2D_KHR, + (EGLClientBuffer)tex, attribs); + mGLContext->fDeleteTextures(1, &tex); + + return eglImage; + } + + virtual nsresult PostOutput(BufferInfo* aInfo, MediaFormat* aFormat, Microseconds aDuration) MOZ_OVERRIDE { + VideoInfo videoInfo; + videoInfo.mDisplay = nsIntSize(mConfig.display_width, mConfig.display_height); + + EGLImage eglImage = CopySurface(); + if (!eglImage) { + return NS_ERROR_FAILURE; + } + + EGLSync eglSync = nullptr; + if (sEGLLibrary.IsExtensionSupported(GLLibraryEGL::KHR_fence_sync) && + mGLContext->IsExtensionSupported(GLContext::OES_EGL_sync)) + { + MOZ_ASSERT(mGLContext->IsCurrent()); + eglSync = sEGLLibrary.fCreateSync(EGL_DISPLAY(), + LOCAL_EGL_SYNC_FENCE, + nullptr); + if (eglSync) { + mGLContext->fFlush(); + } + } else { + NS_WARNING("No EGL fence support detected, rendering artifacts may occur!"); + } + + nsRefPtr img = mImageContainer->CreateImage(ImageFormat::EGLIMAGE); + layers::EGLImageImage::Data data; + data.mImage = eglImage; + data.mSync = eglSync; + data.mOwns = true; + data.mSize = gfx::IntSize(mConfig.display_width, mConfig.display_height); + data.mInverted = false; + + layers::EGLImageImage* typedImg = static_cast(img.get()); typedImg->SetData(data); + bool isSync = !!(MediaCodec::getBUFFER_FLAG_SYNC_FRAME() & aInfo->getFlags()); + nsRefPtr v = VideoData::CreateFromImage(videoInfo, mImageContainer, aInfo->getOffset(), aInfo->getPresentationTimeUs(), aDuration, @@ -92,9 +158,19 @@ public: } protected: + bool EnsureGLContext() { + if (mGLContext) { + return true; + } + + mGLContext = GLContextProvider::CreateHeadless(); + return mGLContext; + } + layers::ImageContainer* mImageContainer; const mp4_demuxer::VideoDecoderConfig& mConfig; RefPtr mSurfaceTexture; + nsRefPtr mGLContext; }; class AudioDataDecoder : public MediaCodecDataDecoder { @@ -454,6 +530,8 @@ void MediaCodecDataDecoder::DecoderLoop() } } + Cleanup(); + // We're done mMonitor.Lock(); mStopping = false; diff --git a/dom/media/fmp4/android/AndroidDecoderModule.h b/dom/media/fmp4/android/AndroidDecoderModule.h index 343630fe143c..e2d4dd0c5d27 100644 --- a/dom/media/fmp4/android/AndroidDecoderModule.h +++ b/dom/media/fmp4/android/AndroidDecoderModule.h @@ -98,6 +98,7 @@ protected: virtual nsresult Output(mozilla::widget::android::sdk::BufferInfo* aInfo, void* aBuffer, mozilla::widget::android::sdk::MediaFormat* aFormat, Microseconds aDuration) { return NS_OK; } virtual nsresult PostOutput(mozilla::widget::android::sdk::BufferInfo* aInfo, mozilla::widget::android::sdk::MediaFormat* aFormat, Microseconds aDuration) { return NS_OK; } + virtual void Cleanup() {}; nsresult ResetInputBuffers(); nsresult ResetOutputBuffers(); diff --git a/gfx/layers/GLImages.h b/gfx/layers/GLImages.h index 4928d4b9e09f..33b3a7f29f64 100644 --- a/gfx/layers/GLImages.h +++ b/gfx/layers/GLImages.h @@ -26,6 +26,10 @@ public: gfx::IntSize mSize; bool mInverted; bool mOwns; + + Data() : mImage(nullptr), mSync(nullptr), mSize(0, 0), mInverted(false), mOwns(false) + { + } }; void SetData(const Data& aData) { mData = aData; } From 54b19cef8914f6db205c9cde33280c6c5faabf91 Mon Sep 17 00:00:00 2001 From: James Willcox Date: Wed, 26 Nov 2014 15:16:08 -0600 Subject: [PATCH 10/64] Bug 1097116 - Fix readback for EGLImageImage r=jgilbert --HG-- extra : rebase_source : 038ddc25801541512a4e8231e4a6b586ed02c02b --- gfx/gl/GLBlitHelper.cpp | 72 +++++++++++++++++++++++++++++++++-------- gfx/gl/GLBlitHelper.h | 9 ++++-- gfx/layers/GLImages.cpp | 20 ++++++------ gfx/layers/GLImages.h | 22 ++++++------- 4 files changed, 84 insertions(+), 39 deletions(-) diff --git a/gfx/gl/GLBlitHelper.cpp b/gfx/gl/GLBlitHelper.cpp index fa44819869ad..46b568f0f8ec 100644 --- a/gfx/gl/GLBlitHelper.cpp +++ b/gfx/gl/GLBlitHelper.cpp @@ -305,6 +305,7 @@ GLBlitHelper::InitTexQuadProgram(BlitType target) GLuint *fragShaderPtr; const char* fragShaderSource; switch (target) { + case ConvertEGLImage: case BlitTex2D: programPtr = &mTex2DBlit_Program; fragShaderPtr = &mTex2DBlit_FragShader; @@ -451,6 +452,7 @@ GLBlitHelper::InitTexQuadProgram(BlitType target) switch (target) { case BlitTex2D: case BlitTexRect: + case ConvertEGLImage: case ConvertSurfaceTexture: case ConvertGralloc: { #ifdef ANDROID @@ -666,25 +668,26 @@ GLBlitHelper::BindAndUploadYUVTexture(Channel which, } } -#ifdef MOZ_WIDGET_GONK void -GLBlitHelper::BindAndUploadExternalTexture(EGLImage image) +GLBlitHelper::BindAndUploadEGLImage(EGLImage image, GLuint target) { MOZ_ASSERT(image != EGL_NO_IMAGE, "Bad EGLImage"); if (!mSrcTexEGL) { mGL->fGenTextures(1, &mSrcTexEGL); - mGL->fBindTexture(LOCAL_GL_TEXTURE_EXTERNAL_OES, mSrcTexEGL); - mGL->fTexParameteri(LOCAL_GL_TEXTURE_EXTERNAL_OES, LOCAL_GL_TEXTURE_WRAP_S, LOCAL_GL_CLAMP_TO_EDGE); - mGL->fTexParameteri(LOCAL_GL_TEXTURE_EXTERNAL_OES, LOCAL_GL_TEXTURE_WRAP_T, LOCAL_GL_CLAMP_TO_EDGE); - mGL->fTexParameteri(LOCAL_GL_TEXTURE_EXTERNAL_OES, LOCAL_GL_TEXTURE_MAG_FILTER, LOCAL_GL_NEAREST); - mGL->fTexParameteri(LOCAL_GL_TEXTURE_EXTERNAL_OES, LOCAL_GL_TEXTURE_MIN_FILTER, LOCAL_GL_NEAREST); + mGL->fBindTexture(target, mSrcTexEGL); + mGL->fTexParameteri(target, LOCAL_GL_TEXTURE_WRAP_S, LOCAL_GL_CLAMP_TO_EDGE); + mGL->fTexParameteri(target, LOCAL_GL_TEXTURE_WRAP_T, LOCAL_GL_CLAMP_TO_EDGE); + mGL->fTexParameteri(target, LOCAL_GL_TEXTURE_MAG_FILTER, LOCAL_GL_NEAREST); + mGL->fTexParameteri(target, LOCAL_GL_TEXTURE_MIN_FILTER, LOCAL_GL_NEAREST); } else { - mGL->fBindTexture(LOCAL_GL_TEXTURE_EXTERNAL_OES, mSrcTexEGL); + mGL->fBindTexture(target, mSrcTexEGL); } - mGL->fEGLImageTargetTexture2D(LOCAL_GL_TEXTURE_EXTERNAL_OES, image); + mGL->fEGLImageTargetTexture2D(target, image); } +#ifdef MOZ_WIDGET_GONK + bool GLBlitHelper::BlitGrallocImage(layers::GrallocImage* grallocImage, bool yFlip) { @@ -705,7 +708,7 @@ GLBlitHelper::BlitGrallocImage(layers::GrallocImage* grallocImage, bool yFlip) int oldBinding = 0; mGL->fGetIntegerv(LOCAL_GL_TEXTURE_BINDING_EXTERNAL_OES, &oldBinding); - BindAndUploadExternalTexture(image); + BindAndUploadEGLImage(image, LOCAL_GL_TEXTURE_EXTERNAL_OES); mGL->fUniform1f(mYFlipLoc, yFlip ? (float)1.0f : (float)0.0f); @@ -720,13 +723,14 @@ GLBlitHelper::BlitGrallocImage(layers::GrallocImage* grallocImage, bool yFlip) #ifdef MOZ_WIDGET_ANDROID bool -GLBlitHelper::BlitSurfaceTextureImage(layers::SurfaceTextureImage* stImage) +GLBlitHelper::BlitSurfaceTextureImage(layers::SurfaceTextureImage* stImage, bool yFlip) { AndroidSurfaceTexture* surfaceTexture = stImage->GetData()->mSurfTex; - bool yFlip = stImage->GetData()->mInverted; + if (stImage->GetData()->mInverted) { + yFlip = !yFlip; + } ScopedBindTextureUnit boundTU(mGL, LOCAL_GL_TEXTURE0); - mGL->fClear(LOCAL_GL_COLOR_BUFFER_BIT); if (NS_FAILED(surfaceTexture->Attach(mGL))) { return false; @@ -751,6 +755,39 @@ GLBlitHelper::BlitSurfaceTextureImage(layers::SurfaceTextureImage* stImage) mGL->fBindTexture(LOCAL_GL_TEXTURE_EXTERNAL, oldBinding); return true; } + +bool +GLBlitHelper::BlitEGLImageImage(layers::EGLImageImage* image, bool yFlip) +{ + EGLImage eglImage = image->GetData()->mImage; + EGLSync eglSync = image->GetData()->mSync; + + if (image->GetData()->mInverted) { + yFlip = !yFlip; + } + + if (eglSync) { + EGLint status = sEGLLibrary.fClientWaitSync(EGL_DISPLAY(), eglSync, 0, LOCAL_EGL_FOREVER); + if (status != LOCAL_EGL_CONDITION_SATISFIED) { + return false; + } + } + + ScopedBindTextureUnit boundTU(mGL, LOCAL_GL_TEXTURE0); + + int oldBinding = 0; + mGL->fGetIntegerv(LOCAL_GL_TEXTURE_BINDING_2D, &oldBinding); + + BindAndUploadEGLImage(eglImage, LOCAL_GL_TEXTURE_2D); + + mGL->fUniform1f(mYFlipLoc, yFlip ? 1.0f : 0.0f); + + mGL->fDrawArrays(LOCAL_GL_TRIANGLE_STRIP, 0, 4); + + mGL->fBindTexture(LOCAL_GL_TEXTURE_EXTERNAL_OES, oldBinding); + return true; +} + #endif bool @@ -816,6 +853,9 @@ GLBlitHelper::BlitImageToFramebuffer(layers::Image* srcImage, case ImageFormat::SURFACE_TEXTURE: type = ConvertSurfaceTexture; break; + case ImageFormat::EGLIMAGE: + type = ConvertEGLImage; + break; #endif default: return false; @@ -848,7 +888,11 @@ GLBlitHelper::BlitImageToFramebuffer(layers::Image* srcImage, #ifdef MOZ_WIDGET_ANDROID if (type == ConvertSurfaceTexture) { layers::SurfaceTextureImage* stImage = static_cast(srcImage); - return BlitSurfaceTextureImage(stImage); + return BlitSurfaceTextureImage(stImage, yFlip); + } + if (type == ConvertEGLImage) { + layers::EGLImageImage* eglImage = static_cast(srcImage); + return BlitEGLImageImage(eglImage, yFlip); } #endif diff --git a/gfx/gl/GLBlitHelper.h b/gfx/gl/GLBlitHelper.h index a5e42acad23a..4df7a0089aab 100644 --- a/gfx/gl/GLBlitHelper.h +++ b/gfx/gl/GLBlitHelper.h @@ -20,6 +20,7 @@ class Image; class PlanarYCbCrImage; class GrallocImage; class SurfaceTextureImage; +class EGLImageImage; } namespace gl { @@ -98,7 +99,8 @@ class GLBlitHelper MOZ_FINAL BlitTexRect, ConvertGralloc, ConvertPlanarYCbCr, - ConvertSurfaceTexture + ConvertSurfaceTexture, + ConvertEGLImage }; // The GLContext is the sole owner of the GLBlitHelper. GLContext* mGL; @@ -140,14 +142,15 @@ class GLBlitHelper MOZ_FINAL bool InitTexQuadProgram(BlitType target = BlitTex2D); void DeleteTexBlitProgram(); void BindAndUploadYUVTexture(Channel which, uint32_t width, uint32_t height, void* data, bool allocation); + void BindAndUploadEGLImage(EGLImage image, GLuint target); #ifdef MOZ_WIDGET_GONK - void BindAndUploadExternalTexture(EGLImage image); bool BlitGrallocImage(layers::GrallocImage* grallocImage, bool yFlip = false); #endif bool BlitPlanarYCbCrImage(layers::PlanarYCbCrImage* yuvImage, bool yFlip = false); #ifdef MOZ_WIDGET_ANDROID - bool BlitSurfaceTextureImage(layers::SurfaceTextureImage* stImage); + bool BlitSurfaceTextureImage(layers::SurfaceTextureImage* stImage, bool yFlip = false); + bool BlitEGLImageImage(layers::EGLImageImage* eglImage, bool yFlip = false); #endif public: diff --git a/gfx/layers/GLImages.cpp b/gfx/layers/GLImages.cpp index 3a7bb73e9f68..9b65bb1f2a41 100644 --- a/gfx/layers/GLImages.cpp +++ b/gfx/layers/GLImages.cpp @@ -1,4 +1,3 @@ -#ifdef MOZ_WIDGET_ANDROID #include "GLImages.h" #include "GLContext.h" @@ -7,7 +6,6 @@ #include "GLImages.h" #include "GLBlitHelper.h" #include "GLReadTexImageHelper.h" -#include "AndroidSurfaceTexture.h" #include "GLLibraryEGL.h" using namespace mozilla; @@ -35,16 +33,16 @@ EGLImageImage::~EGLImageImage() } } -TemporaryRef -SurfaceTextureImage::GetAsSourceSurface() +TemporaryRef +GLImage::GetAsSourceSurface() { MOZ_ASSERT(NS_IsMainThread(), "Should be on the main thread"); if (!sSnapshotContext) { - SurfaceCaps caps = SurfaceCaps::ForRGBA(); - sSnapshotContext = GLContextProvider::CreateOffscreen(gfxIntSize(16, 16), caps); + sSnapshotContext = GLContextProvider::CreateHeadless(); if (!sSnapshotContext) { + NS_WARNING("Failed to create snapshot GLContext"); return nullptr; } } @@ -52,8 +50,10 @@ SurfaceTextureImage::GetAsSourceSurface() sSnapshotContext->MakeCurrent(); ScopedTexture scopedTex(sSnapshotContext); ScopedBindTexture boundTex(sSnapshotContext, scopedTex.Texture()); + + gfx::IntSize size = GetSize(); sSnapshotContext->fTexImage2D(LOCAL_GL_TEXTURE_2D, 0, LOCAL_GL_RGBA, - mData.mSize.width, mData.mSize.height, 0, + size.width, size.height, 0, LOCAL_GL_RGBA, LOCAL_GL_UNSIGNED_BYTE, nullptr); @@ -62,11 +62,11 @@ SurfaceTextureImage::GetAsSourceSurface() GLBlitHelper helper(sSnapshotContext); - helper.BlitImageToFramebuffer(this, mData.mSize, fb.FB(), false); + helper.BlitImageToFramebuffer(this, size, fb.FB(), false); ScopedBindFramebuffer bind(sSnapshotContext, fb.FB()); RefPtr source = - gfx::Factory::CreateDataSourceSurface(mData.mSize, gfx::SurfaceFormat::B8G8R8A8); + gfx::Factory::CreateDataSourceSurface(size, gfx::SurfaceFormat::B8G8R8A8); if (NS_WARN_IF(!source)) { return nullptr; } @@ -77,5 +77,3 @@ SurfaceTextureImage::GetAsSourceSurface() } // layers } // mozilla - -#endif diff --git a/gfx/layers/GLImages.h b/gfx/layers/GLImages.h index 33b3a7f29f64..92bdc307cf83 100644 --- a/gfx/layers/GLImages.h +++ b/gfx/layers/GLImages.h @@ -18,7 +18,14 @@ class AndroidSurfaceTexture; } namespace layers { -class EGLImageImage : public Image { +class GLImage : public Image { +public: + GLImage(ImageFormat aFormat) : Image(nullptr, aFormat){} + + virtual TemporaryRef GetAsSourceSurface() MOZ_OVERRIDE; +}; + +class EGLImageImage : public GLImage { public: struct Data { EGLImage mImage; @@ -37,12 +44,7 @@ public: gfx::IntSize GetSize() { return mData.mSize; } - virtual TemporaryRef GetAsSourceSurface() MOZ_OVERRIDE - { - return nullptr; - } - - EGLImageImage() : Image(nullptr, ImageFormat::EGLIMAGE) {} + EGLImageImage() : GLImage(ImageFormat::EGLIMAGE) {} protected: virtual ~EGLImageImage(); @@ -53,7 +55,7 @@ private: #ifdef MOZ_WIDGET_ANDROID -class SurfaceTextureImage : public Image { +class SurfaceTextureImage : public GLImage { public: struct Data { mozilla::gl::AndroidSurfaceTexture* mSurfTex; @@ -66,9 +68,7 @@ public: gfx::IntSize GetSize() { return mData.mSize; } - virtual TemporaryRef GetAsSourceSurface() MOZ_OVERRIDE; - - SurfaceTextureImage() : Image(nullptr, ImageFormat::SURFACE_TEXTURE) {} + SurfaceTextureImage() : GLImage(ImageFormat::SURFACE_TEXTURE) {} private: Data mData; From 2af96740015cb2d88fd8e60f2a99d325f12a6a9b Mon Sep 17 00:00:00 2001 From: James Willcox Date: Wed, 26 Nov 2014 15:16:08 -0600 Subject: [PATCH 11/64] Bug 1097116 - Disable Android MediaCodec on PowerVR devices r=cpearce --HG-- extra : rebase_source : 8c852f321f5755f4af702011f6cf72ba9c605104 --- dom/media/fmp4/MP4Decoder.cpp | 27 +++++++++++++++++++++++---- 1 file changed, 23 insertions(+), 4 deletions(-) diff --git a/dom/media/fmp4/MP4Decoder.cpp b/dom/media/fmp4/MP4Decoder.cpp index c81f4fc9b5af..9f8dcbb8523e 100644 --- a/dom/media/fmp4/MP4Decoder.cpp +++ b/dom/media/fmp4/MP4Decoder.cpp @@ -24,6 +24,7 @@ #include "apple/AppleDecoderModule.h" #endif #ifdef MOZ_WIDGET_ANDROID +#include "nsIGfxInfo.h" #include "AndroidBridge.h" #endif @@ -180,6 +181,27 @@ IsAppleAvailable() #endif } +static bool +IsAndroidAvailable() +{ +#ifndef MOZ_WIDGET_ANDROID + return false; +#else + // PowerVR is very slow at texture allocation for some reason, which causes poor performance. + nsCOMPtr gfxInfo = do_GetService("@mozilla.org/gfx/info;1"); + + nsString vendor; + if (NS_FAILED(gfxInfo->GetAdapterVendorID(vendor)) || + vendor.Find("Imagination") == 0) { + printf_stderr("SNORP: not doing video for PowerVR\n"); + return nullptr; + } + + // We need android.media.MediaCodec which exists in API level 16 and higher. + return AndroidBridge::Bridge()->GetAPIVersion() >= 16; +#endif +} + static bool IsGonkMP4DecoderAvailable() { @@ -194,10 +216,7 @@ HavePlatformMPEGDecoders() // We have H.264/AAC platform decoders on Windows Vista and up. IsVistaOrLater() || #endif -#ifdef MOZ_WIDGET_ANDROID - // We need android.media.MediaCodec which exists in API level 16 and higher. - (AndroidBridge::Bridge()->GetAPIVersion() >= 16) || -#endif + IsAndroidAvailable() || IsFFmpegAvailable() || IsAppleAvailable() || IsGonkMP4DecoderAvailable() || From 90ad2ed95546f22347d0936e118f72273a23b709 Mon Sep 17 00:00:00 2001 From: James Willcox Date: Wed, 26 Nov 2014 15:19:57 -0600 Subject: [PATCH 12/64] Bug 1085742 - Bail out of XPCOM init early if we're already initialized r=bsmedberg --HG-- extra : rebase_source : 6029756f6c910d1d201f067379ad2c2838b73b8d --- xpcom/build/XPCOMInit.cpp | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/xpcom/build/XPCOMInit.cpp b/xpcom/build/XPCOMInit.cpp index fec664c68ed2..a4f152b4edc8 100644 --- a/xpcom/build/XPCOMInit.cpp +++ b/xpcom/build/XPCOMInit.cpp @@ -481,6 +481,13 @@ NS_InitXPCOM2(nsIServiceManager** aResult, nsIFile* aBinDirectory, nsIDirectoryServiceProvider* aAppFileLocationProvider) { + static bool sInitialized = false; + if (sInitialized) { + return NS_ERROR_FAILURE; + } + + sInitialized = true; + mozPoisonValueInit(); char aLocal; From 9496c78f681baf26f52fd4540f881c681c366d0c Mon Sep 17 00:00:00 2001 From: James Willcox Date: Wed, 26 Nov 2014 15:16:08 -0600 Subject: [PATCH 13/64] Bug 1099345 - Add more descriptive debugging output to the Android SDK code generator r=nalexander --HG-- extra : rebase_source : 47d675ebe19db1a488498a19834674fe2fd8dc4f --- build/annotationProcessors/SDKProcessor.java | 16 +++++----------- widget/android/bindings/Makefile.in | 2 +- 2 files changed, 6 insertions(+), 12 deletions(-) diff --git a/build/annotationProcessors/SDKProcessor.java b/build/annotationProcessors/SDKProcessor.java index 10393ff58fd9..2011ebec68db 100644 --- a/build/annotationProcessors/SDKProcessor.java +++ b/build/annotationProcessors/SDKProcessor.java @@ -43,7 +43,7 @@ public class SDKProcessor { private static ApiLookup sApiLookup; private static int sMaxSdkVersion; - public static void main(String[] args) { + public static void main(String[] args) throws Exception { // We expect a list of jars on the commandline. If missing, whinge about it. if (args.length < 5) { System.err.println("Usage: java SDKProcessor sdkjar classlistfile outdir fileprefix max-sdk-version"); @@ -106,16 +106,10 @@ public class SDKProcessor { String className = i.next(); System.out.println("Looking up: " + className); - try { - Class c = Class.forName(className, true, loader); - - generateClass(Class.forName(className, true, loader), - stubInitializer, - implementationFile, - headerFile); - } catch (Exception e) { - System.out.println("Failed to generate class " + className + ": " + e); - } + generateClass(Class.forName(className, true, loader), + stubInitializer, + implementationFile, + headerFile); } implementationFile.append('\n'); diff --git a/widget/android/bindings/Makefile.in b/widget/android/bindings/Makefile.in index e285f45a23d5..348f847299a0 100644 --- a/widget/android/bindings/Makefile.in +++ b/widget/android/bindings/Makefile.in @@ -15,7 +15,7 @@ sdk_processor := \ # MediaCodec-classes.txt. This formulation invokes the SDK processor # at most once. -%.cpp %.h: $(ANDROID_SDK)/android.jar %-classes.txt +%.cpp %.h: $(ANDROID_SDK)/android.jar %-classes.txt FORCE $(sdk_processor) $(ANDROID_SDK)/android.jar $(srcdir)/$*-classes.txt $(CURDIR) $* 16 # We'd like these to be defined in a future GENERATED_EXPORTS list. From b29e662209a0676118505fae0f7e902dfd3775c5 Mon Sep 17 00:00:00 2001 From: Chris Manchester Date: Wed, 26 Nov 2014 16:25:55 -0500 Subject: [PATCH 14/64] Bug 1105082 - Send the correct error when attempting to navigate with marionette in chrome scope.;r=ato --- .../marionette/client/marionette/tests/unit/test_navigation.py | 3 ++- testing/marionette/marionette-server.js | 2 +- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/testing/marionette/client/marionette/tests/unit/test_navigation.py b/testing/marionette/client/marionette/tests/unit/test_navigation.py index c335f89ca061..aaa1322c36e8 100644 --- a/testing/marionette/client/marionette/tests/unit/test_navigation.py +++ b/testing/marionette/client/marionette/tests/unit/test_navigation.py @@ -16,7 +16,8 @@ class TestNavigate(MarionetteTestCase): def test_navigate_chrome_error(self): with self.marionette.using_context("chrome"): - self.assertRaises(MarionetteException, self.marionette.navigate, "about:blank") + self.assertRaisesRegexp(MarionetteException, "Cannot navigate in chrome context", + self.marionette.navigate, "about:blank") def test_getUrl(self): test_html = self.marionette.absolute_url("test.html") diff --git a/testing/marionette/marionette-server.js b/testing/marionette/marionette-server.js index 4fe12e2456e4..ee7c3f5cfb8c 100644 --- a/testing/marionette/marionette-server.js +++ b/testing/marionette/marionette-server.js @@ -1211,7 +1211,7 @@ MarionetteServerConnection.prototype = { // TODO: Error codes need to be refined as a part of bug 1100545 and // bug 945729. if (appName == "Firefox") { - sendError("Cannot navigate in chrome context", 13, null, command_id); + this.sendError("Cannot navigate in chrome context", 13, null, command_id); return; } From 1215625738b04b943a55216c06f1f73611e2aa42 Mon Sep 17 00:00:00 2001 From: Paul Adenot Date: Wed, 19 Nov 2014 11:38:39 +0100 Subject: [PATCH 15/64] Bug 1087944 - Implement the promise version of OfflineAudioContext. r=ehsan,smaug --HG-- extra : rebase_source : 1ede286a68f592038320ed5b82051bb9dd3cc0db --- dom/media/webaudio/AudioContext.cpp | 10 +++-- dom/media/webaudio/AudioContext.h | 2 +- dom/media/webaudio/AudioDestinationNode.cpp | 46 ++++++++++++++++++--- dom/media/webaudio/AudioDestinationNode.h | 4 +- dom/webidl/OfflineAudioContext.webidl | 2 +- 5 files changed, 52 insertions(+), 12 deletions(-) diff --git a/dom/media/webaudio/AudioContext.cpp b/dom/media/webaudio/AudioContext.cpp index 8f348b242bb7..8dd4f5cf6c3b 100644 --- a/dom/media/webaudio/AudioContext.cpp +++ b/dom/media/webaudio/AudioContext.cpp @@ -632,17 +632,21 @@ AudioContext::GetGlobalJSObject() const return parentObject->GetGlobalJSObject(); } -void +already_AddRefed AudioContext::StartRendering(ErrorResult& aRv) { + nsCOMPtr parentObject = do_QueryInterface(GetParentObject()); + MOZ_ASSERT(mIsOffline, "This should only be called on OfflineAudioContext"); if (mIsStarted) { aRv.Throw(NS_ERROR_DOM_INVALID_STATE_ERR); - return; + return nullptr; } mIsStarted = true; - mDestination->StartRendering(); + nsRefPtr promise = Promise::Create(parentObject, aRv); + mDestination->StartRendering(promise); + return promise.forget(); } void diff --git a/dom/media/webaudio/AudioContext.h b/dom/media/webaudio/AudioContext.h index c34f2dac0324..2b1ba5e7174e 100644 --- a/dom/media/webaudio/AudioContext.h +++ b/dom/media/webaudio/AudioContext.h @@ -191,7 +191,7 @@ public: const Optional >& aFailureCallback); // OfflineAudioContext methods - void StartRendering(ErrorResult& aRv); + already_AddRefed StartRendering(ErrorResult& aRv); IMPL_EVENT_HANDLER(complete) bool IsOffline() const { return mIsOffline; } diff --git a/dom/media/webaudio/AudioDestinationNode.cpp b/dom/media/webaudio/AudioDestinationNode.cpp index 7c6f3bbbf8d6..c0dd1d31f74c 100644 --- a/dom/media/webaudio/AudioDestinationNode.cpp +++ b/dom/media/webaudio/AudioDestinationNode.cpp @@ -22,6 +22,7 @@ #include "nsServiceManagerUtils.h" #include "nsIAppShell.h" #include "nsWidgetsCID.h" +#include "mozilla/dom/Promise.h" namespace mozilla { namespace dom { @@ -126,6 +127,28 @@ public: } } + class OnCompleteTask MOZ_FINAL : public nsRunnable + { + public: + OnCompleteTask(AudioContext* aAudioContext, AudioBuffer* aRenderedBuffer) + : mAudioContext(aAudioContext) + , mRenderedBuffer(aRenderedBuffer) + {} + + NS_IMETHOD Run() + { + nsRefPtr event = + new OfflineAudioCompletionEvent(mAudioContext, nullptr, nullptr); + event->InitEvent(mRenderedBuffer); + mAudioContext->DispatchTrustedEvent(event); + + return NS_OK; + } + private: + nsRefPtr mAudioContext; + nsRefPtr mRenderedBuffer; + }; + void FireOfflineCompletionEvent(AudioDestinationNode* aNode) { AudioContext* context = aNode->Context(); @@ -152,10 +175,11 @@ public: renderedBuffer->SetRawChannelContents(i, mInputChannels[i]); } - nsRefPtr event = - new OfflineAudioCompletionEvent(context, nullptr, nullptr); - event->InitEvent(renderedBuffer); - context->DispatchTrustedEvent(event); + aNode->ResolvePromise(renderedBuffer); + + nsRefPtr task = + new OnCompleteTask(context, renderedBuffer); + NS_DispatchToMainThread(task); } virtual size_t SizeOfExcludingThis(MallocSizeOf aMallocSizeOf) const MOZ_OVERRIDE @@ -301,7 +325,8 @@ private: NS_IMPL_ISUPPORTS(EventProxyHandler, nsIDOMEventListener) NS_IMPL_CYCLE_COLLECTION_INHERITED(AudioDestinationNode, AudioNode, - mAudioChannelAgent, mEventProxyHelper) + mAudioChannelAgent, mEventProxyHelper, + mOfflineRenderingPromise) NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION_INHERITED(AudioDestinationNode) NS_INTERFACE_MAP_ENTRY(nsIDOMEventListener) @@ -415,6 +440,14 @@ AudioDestinationNode::FireOfflineCompletionEvent() engine->FireOfflineCompletionEvent(this); } +void +AudioDestinationNode::ResolvePromise(AudioBuffer* aRenderedBuffer) +{ + MOZ_ASSERT(NS_IsMainThread()); + MOZ_ASSERT(mIsOffline); + mOfflineRenderingPromise->MaybeResolve(aRenderedBuffer); +} + uint32_t AudioDestinationNode::MaxChannelCount() const { @@ -463,8 +496,9 @@ AudioDestinationNode::WrapObject(JSContext* aCx) } void -AudioDestinationNode::StartRendering() +AudioDestinationNode::StartRendering(Promise* aPromise) { + mOfflineRenderingPromise = aPromise; mOfflineRenderingRef.Take(this); mStream->Graph()->StartNonRealtimeProcessing(mFramesToProduce); } diff --git a/dom/media/webaudio/AudioDestinationNode.h b/dom/media/webaudio/AudioDestinationNode.h index 478abc8f2c2b..c893b0f8339c 100644 --- a/dom/media/webaudio/AudioDestinationNode.h +++ b/dom/media/webaudio/AudioDestinationNode.h @@ -54,7 +54,7 @@ public: void Mute(); void Unmute(); - void StartRendering(); + void StartRendering(Promise* aPromise); void OfflineShutdown(); @@ -85,6 +85,7 @@ public: virtual size_t SizeOfIncludingThis(MallocSizeOf aMallocSizeOf) const MOZ_OVERRIDE; void InputMuted(bool aInputMuted); + void ResolvePromise(AudioBuffer* aRenderedBuffer); protected: virtual ~AudioDestinationNode(); @@ -103,6 +104,7 @@ private: nsCOMPtr mAudioChannelAgent; nsRefPtr mEventProxyHelper; + nsRefPtr mOfflineRenderingPromise; // Audio Channel Type. AudioChannel mAudioChannel; diff --git a/dom/webidl/OfflineAudioContext.webidl b/dom/webidl/OfflineAudioContext.webidl index d987370cfbe8..7e6ebeb00d6e 100644 --- a/dom/webidl/OfflineAudioContext.webidl +++ b/dom/webidl/OfflineAudioContext.webidl @@ -16,7 +16,7 @@ callback OfflineRenderSuccessCallback = void (AudioBuffer renderedData); interface OfflineAudioContext : AudioContext { [Throws] - void startRendering(); + Promise startRendering(); attribute EventHandler oncomplete; From d4eb8e50b272e5a8d6181969dbd8ec300fd5c02f Mon Sep 17 00:00:00 2001 From: Paul Adenot Date: Wed, 19 Nov 2014 18:18:24 +0100 Subject: [PATCH 16/64] Bug 1087944 - Test for the promise returned by OfflineAudioContext.startRendering(). r=ehsan --HG-- extra : rebase_source : 351f66c2cd7f2c269d7f2c05214d0f291488cf23 --- .../test/test_OfflineAudioContext.html | 36 +++++++++++++++---- 1 file changed, 30 insertions(+), 6 deletions(-) diff --git a/dom/media/webaudio/test/test_OfflineAudioContext.html b/dom/media/webaudio/test/test_OfflineAudioContext.html index 4fb5d7da141f..ff4e18766239 100644 --- a/dom/media/webaudio/test/test_OfflineAudioContext.html +++ b/dom/media/webaudio/test/test_OfflineAudioContext.html @@ -10,6 +10,17 @@
 

From 60090efcab065f50f7b27b9e7648891ce6e4b1e9 Mon Sep 17 00:00:00 2001
From: Shu-yu Guo 
Date: Wed, 26 Nov 2014 13:35:57 -0800
Subject: [PATCH 17/64] Bug 1103027 - Handle bailed-out-in-place Baseline
 frames in debug mode OSR. (r=jandem)

---
 .../tests/debug/onExceptionUnwind-13.js       | 16 ++++
 js/src/jit/BaselineDebugModeOSR.cpp           | 81 +++++++++++++++----
 js/src/jit/BaselineFrame-inl.h                |  9 +++
 js/src/jit/BaselineFrame.h                    | 23 ++++--
 js/src/jit/BaselineIC.h                       |  5 +-
 js/src/jit/JitFrames.cpp                      | 17 ++++
 6 files changed, 131 insertions(+), 20 deletions(-)
 create mode 100644 js/src/jit-test/tests/debug/onExceptionUnwind-13.js

diff --git a/js/src/jit-test/tests/debug/onExceptionUnwind-13.js b/js/src/jit-test/tests/debug/onExceptionUnwind-13.js
new file mode 100644
index 000000000000..611bf4c9dd37
--- /dev/null
+++ b/js/src/jit-test/tests/debug/onExceptionUnwind-13.js
@@ -0,0 +1,16 @@
+// |jit-test| error: 4
+//
+// Test that we can handle doing debug mode OSR from onExceptionUnwind when
+// settling on a pc without a Baseline ICEntry.
+
+var g = newGlobal();
+var dbg = new Debugger(g);
+dbg.onExceptionUnwind = function () {};
+
+g.eval("" + function f(y) {
+  if (y > 0) {
+    throw 4;
+  }
+});
+g.eval("f(0)");
+g.eval("f(1)");
diff --git a/js/src/jit/BaselineDebugModeOSR.cpp b/js/src/jit/BaselineDebugModeOSR.cpp
index a34228de280d..8270795aa447 100644
--- a/js/src/jit/BaselineDebugModeOSR.cpp
+++ b/js/src/jit/BaselineDebugModeOSR.cpp
@@ -37,7 +37,17 @@ struct DebugModeOSREntry
         newStub(nullptr),
         recompInfo(nullptr),
         pcOffset(uint32_t(-1)),
-        frameKind(ICEntry::Kind_NonOp)
+        frameKind(ICEntry::Kind_Invalid)
+    { }
+
+    DebugModeOSREntry(JSScript *script, uint32_t pcOffset)
+      : script(script),
+        oldBaselineScript(script->baselineScript()),
+        oldStub(nullptr),
+        newStub(nullptr),
+        recompInfo(nullptr),
+        pcOffset(pcOffset),
+        frameKind(ICEntry::Kind_Invalid)
     { }
 
     DebugModeOSREntry(JSScript *script, const ICEntry &icEntry)
@@ -194,11 +204,23 @@ CollectJitStackScripts(JSContext *cx, const Debugger::ExecutionObservableSet &ob
                 if (!entries.append(DebugModeOSREntry(script, info)))
                     return false;
             } else {
-                // Otherwise, use the return address to look up the ICEntry.
                 uint8_t *retAddr = iter.returnAddressToFp();
-                ICEntry &entry = script->baselineScript()->icEntryFromReturnAddress(retAddr);
-                if (!entries.append(DebugModeOSREntry(script, entry)))
-                    return false;
+                ICEntry *icEntry = script->baselineScript()->maybeICEntryFromReturnAddress(retAddr);
+                if (icEntry) {
+                    // Normally, the frame is settled on a pc with an ICEntry.
+                    if (!entries.append(DebugModeOSREntry(script, *icEntry)))
+                        return false;
+                } else {
+                    // Otherwise, we are in the middle of handling an
+                    // exception. This happens since we could have bailed out
+                    // in place from Ion after a throw, settling on the pc
+                    // *after* the bytecode that threw the exception, which
+                    // may have no ICEntry.
+                    MOZ_ASSERT(iter.baselineFrame()->isDebuggerHandlingException());
+                    jsbytecode *pc = script->baselineScript()->pcForReturnAddress(script, retAddr);
+                    if (!entries.append(DebugModeOSREntry(script, script->pcToOffset(pc))))
+                        return false;
+                }
             }
 
             if (entries.back().needsRecompileInfo()) {
@@ -296,6 +318,16 @@ SpewPatchBaselineFrame(uint8_t *oldReturnAddress, uint8_t *newReturnAddress,
             ICEntryKindToString(frameKind), js_CodeName[(JSOp)*pc]);
 }
 
+static void
+SpewPatchBaselineFrameFromExceptionHandler(uint8_t *oldReturnAddress, uint8_t *newReturnAddress,
+                                           JSScript *script, jsbytecode *pc)
+{
+    JitSpew(JitSpew_BaselineDebugModeOSR,
+            "Patch return %p -> %p on BaselineJS frame (%s:%d) from exception handler at %s",
+            oldReturnAddress, newReturnAddress, script->filename(), script->lineno(),
+            js_CodeName[(JSOp)*pc]);
+}
+
 static void
 SpewPatchStubFrame(ICStub *oldStub, ICStub *newStub)
 {
@@ -320,6 +352,7 @@ PatchBaselineFramesForDebugMode(JSContext *cx, const Debugger::ExecutionObservab
     //  A. From a "can call" stub.
     //  B. From a VM call (interrupt handler, debugger statement handler,
     //                     throw).
+    //  H. From inside HandleExceptionBaseline.
     //
     // On to Off:
     //  - All the ways above.
@@ -386,6 +419,29 @@ PatchBaselineFramesForDebugMode(JSContext *cx, const Debugger::ExecutionObservab
                 break;
             }
 
+            if (kind == ICEntry::Kind_Invalid) {
+                // Case H above.
+                //
+                // We are recompiling on-stack scripts from inside the
+                // exception handler, by way of an onExceptionUnwind
+                // invocation, on a pc without an ICEntry. Since execution
+                // cannot continue after the exception anyways, it doesn't
+                // matter what we patch the resume address with, nor do we
+                // need to fix up the stack and register state.
+                //
+                // So that frame iterators may continue working, we patch the
+                // resume address.
+                MOZ_ASSERT(iter.baselineFrame()->isDebuggerHandlingException());
+                uint8_t *retAddr = bl->nativeCodeForPC(script, pc);
+                SpewPatchBaselineFrameFromExceptionHandler(prev->returnAddress(), retAddr,
+                                                           script, pc);
+                DebugModeOSRVolatileJitFrameIterator::forwardLiveIterators(
+                    cx, prev->returnAddress(), retAddr);
+                prev->setReturnAddress(retAddr);
+                entryIndex++;
+                break;
+            }
+
             // Cases F and G above.
             //
             // We undo a previous recompile by handling cases B, C, D, and E
@@ -426,15 +482,12 @@ PatchBaselineFramesForDebugMode(JSContext *cx, const Debugger::ExecutionObservab
                 //
                 // Throws are treated differently, as patching a throw means
                 // we are recompiling on-stack scripts from inside an
-                // onExceptionUnwind invocation. The Baseline compiler
-                // considers all bytecode after the throw to be unreachable
-                // and does not compile them, so we cannot patch the resume
-                // address to be the next pc. Since execution cannot continue
-                // after the throw anyways, it doesn't matter what we patch
-                // the resume address with. So that frame iterators may
-                // continue working, we patch the resume address to be right
-                // at the throw.
-                if (JSOp(*pc) != JSOP_THROW)
+                // onExceptionUnwind invocation. The resume address must be
+                // settled on the throwing pc and not its successor, so that
+                // Debugger.Frame may report the correct offset. Note we never
+                // actually resume execution there, and it is set for the sake
+                // of frame iterators.
+                if (!iter.baselineFrame()->isDebuggerHandlingException())
                     pc += GetBytecodeLength(pc);
                 recompInfo->resumeAddr = bl->nativeCodeForPC(script, pc, &recompInfo->slotInfo);
                 popFrameReg = true;
diff --git a/js/src/jit/BaselineFrame-inl.h b/js/src/jit/BaselineFrame-inl.h
index 3ec2656a0c76..433d7639e651 100644
--- a/js/src/jit/BaselineFrame-inl.h
+++ b/js/src/jit/BaselineFrame-inl.h
@@ -14,6 +14,8 @@
 
 #include "vm/ScopeObject.h"
 
+#include "jsscriptinlines.h"
+
 namespace js {
 namespace jit {
 
@@ -74,6 +76,13 @@ BaselineFrame::callObj() const
     return obj->as();
 }
 
+inline void
+BaselineFrame::unsetIsDebuggee()
+{
+    MOZ_ASSERT(!script()->isDebuggee());
+    flags_ &= ~DEBUGGEE;
+}
+
 } // namespace jit
 } // namespace js
 
diff --git a/js/src/jit/BaselineFrame.h b/js/src/jit/BaselineFrame.h
index dc66316c0603..de22922938c5 100644
--- a/js/src/jit/BaselineFrame.h
+++ b/js/src/jit/BaselineFrame.h
@@ -63,7 +63,7 @@ class BaselineFrame
         OVER_RECURSED    = 1 << 9,
 
         // Frame has a BaselineRecompileInfo stashed in the scratch value
-        // slot. See PatchBaselineFramesForDebugMOde.
+        // slot. See PatchBaselineFramesForDebugMode.
         HAS_DEBUG_MODE_OSR_INFO = 1 << 10,
 
         // Frame has had its scope chain unwound to a pc during exception
@@ -73,7 +73,13 @@ class BaselineFrame
         // the only way to clear it is to pop the frame. Do *not* set this if
         // we will resume execution on the frame, such as in a catch or
         // finally block.
-        HAS_UNWOUND_SCOPE_OVERRIDE_PC = 1 << 11
+        HAS_UNWOUND_SCOPE_OVERRIDE_PC = 1 << 11,
+
+        // Frame has called out to Debugger code from
+        // HandleExceptionBaseline. This is set for debug mode OSR sanity
+        // checking when it handles corner cases which only arise during
+        // exception handling.
+        DEBUGGER_HANDLING_EXCEPTION = 1 << 12
     };
 
   protected: // Silence Clang warning about unused private fields.
@@ -280,9 +286,16 @@ class BaselineFrame
     void setIsDebuggee() {
         flags_ |= DEBUGGEE;
     }
-    void unsetIsDebuggee() {
-        MOZ_ASSERT(!script()->isDebuggee());
-        flags_ &= ~DEBUGGEE;
+    inline void unsetIsDebuggee();
+
+    bool isDebuggerHandlingException() const {
+        return flags_ & DEBUGGER_HANDLING_EXCEPTION;
+    }
+    void setIsDebuggerHandlingException() {
+        flags_ |= DEBUGGER_HANDLING_EXCEPTION;
+    }
+    void unsetIsDebuggerHandlingException() {
+        flags_ &= ~DEBUGGER_HANDLING_EXCEPTION;
     }
 
     JSScript *evalScript() const {
diff --git a/js/src/jit/BaselineIC.h b/js/src/jit/BaselineIC.h
index 726176f4cf65..6e2de5c545c8 100644
--- a/js/src/jit/BaselineIC.h
+++ b/js/src/jit/BaselineIC.h
@@ -229,7 +229,9 @@ class ICEntry
         // A fake IC entry for returning from a callVM to
         // Debug{Prologue,Epilogue}.
         Kind_DebugPrologue,
-        Kind_DebugEpilogue
+        Kind_DebugEpilogue,
+
+        Kind_Invalid
     };
 
   private:
@@ -238,6 +240,7 @@ class ICEntry
 
     // Set the kind and asserts that it's sane.
     void setKind(Kind kind) {
+        MOZ_ASSERT(kind < Kind_Invalid);
         kind_ = kind;
         MOZ_ASSERT(this->kind() == kind);
     }
diff --git a/js/src/jit/JitFrames.cpp b/js/src/jit/JitFrames.cpp
index ebcd237e207a..bdd39ddc75e6 100644
--- a/js/src/jit/JitFrames.cpp
+++ b/js/src/jit/JitFrames.cpp
@@ -548,6 +548,19 @@ HandleClosingGeneratorReturn(JSContext *cx, const JitFrameIterator &frame, jsbyt
     ForcedReturn(cx, frame, pc, rfe, calledDebugEpilogue);
 }
 
+struct AutoDebuggerHandlingException
+{
+    BaselineFrame *frame;
+    AutoDebuggerHandlingException(BaselineFrame *frame)
+      : frame(frame)
+    {
+        frame->setIsDebuggerHandlingException();
+    }
+    ~AutoDebuggerHandlingException() {
+        frame->unsetIsDebuggerHandlingException();
+    }
+};
+
 static void
 HandleExceptionBaseline(JSContext *cx, const JitFrameIterator &frame, ResumeFromException *rfe,
                         jsbytecode **unwoundScopeToPc, bool *calledDebugEpilogue)
@@ -571,6 +584,10 @@ HandleExceptionBaseline(JSContext *cx, const JitFrameIterator &frame, ResumeFrom
     if (cx->isExceptionPending() && cx->compartment()->isDebuggee() &&
         cx->getPendingException(&exception) && !exception.isMagic(JS_GENERATOR_CLOSING))
     {
+        // Set for debug mode OSR. See note concerning
+        // 'isDebuggerHandlingException' in CollectJitStackScripts.
+        AutoDebuggerHandlingException debuggerHandling(frame.baselineFrame());
+
         switch (Debugger::onExceptionUnwind(cx, frame.baselineFrame())) {
           case JSTRAP_ERROR:
             // Uncatchable exception.

From 4c940c33c976bca677f37854044171fb3d388cf8 Mon Sep 17 00:00:00 2001
From: Shu-yu Guo 
Date: Wed, 26 Nov 2014 13:35:57 -0800
Subject: [PATCH 18/64] Bug 1100337 - Cheat when computing resume address for
 propagating exception for debug mode in Ion exception handler. (r=jandem)

---
 .../tests/debug/onExceptionUnwind-14.js       | 23 +++++++++++
 js/src/jit/BaselineBailouts.cpp               | 34 ++++++++++++---
 js/src/jit/BaselineJIT.cpp                    | 41 +++++++++++++++----
 js/src/jit/BaselineJIT.h                      | 12 +++++-
 4 files changed, 95 insertions(+), 15 deletions(-)
 create mode 100644 js/src/jit-test/tests/debug/onExceptionUnwind-14.js

diff --git a/js/src/jit-test/tests/debug/onExceptionUnwind-14.js b/js/src/jit-test/tests/debug/onExceptionUnwind-14.js
new file mode 100644
index 000000000000..121f5728e028
--- /dev/null
+++ b/js/src/jit-test/tests/debug/onExceptionUnwind-14.js
@@ -0,0 +1,23 @@
+var g = newGlobal();
+var dbg = new Debugger(g);
+
+g.eval("" + function f() {
+  throw 42;
+});
+
+g.eval("" + function g() {
+  throw new Error("42");
+});
+
+// Call the functions once. This will compile them in Ion under --ion-eager.
+g.eval("try { f(); } catch (e) { }");
+g.eval("try { g(); } catch (e) { }");
+
+// Now set an onExceptionUnwind hook so that the Ion-compiled functions will
+// try to bail out. The tail of the bytecode for f and g looks like 'throw;
+// retrval', with 'retrval' being unreachable. Since 'throw' is resumeAfter,
+// bailing out for debug mode will attempt to resume at 'retrval'. Test that
+// this case is handled.
+dbg.onExceptionUnwind = function f() { };
+g.eval("try { f(); } catch (e) { }");
+g.eval("try { g(); } catch (e) { }");
diff --git a/js/src/jit/BaselineBailouts.cpp b/js/src/jit/BaselineBailouts.cpp
index 785595b936b5..87a218b804b3 100644
--- a/js/src/jit/BaselineBailouts.cpp
+++ b/js/src/jit/BaselineBailouts.cpp
@@ -1019,21 +1019,45 @@ InitFromBailout(JSContext *cx, HandleScript caller, jsbytecode *callerPC,
         } else {
             // If needed, initialize BaselineBailoutInfo's valueR0 and/or valueR1 with the
             // top stack values.
+            //
+            // Note that we use the 'maybe' variant of nativeCodeForPC because
+            // of exception propagation for debug mode. See note below.
             PCMappingSlotInfo slotInfo;
-            uint8_t *nativeCodeForPC = baselineScript->nativeCodeForPC(script, pc, &slotInfo);
-            unsigned numUnsynced = slotInfo.numUnsynced();
+            uint8_t *nativeCodeForPC = baselineScript->maybeNativeCodeForPC(script, pc, &slotInfo);
+            unsigned numUnsynced;
+
+            if (excInfo && excInfo->propagatingIonExceptionForDebugMode()) {
+                // When propagating an exception for debug mode, set the
+                // return address as the return-from-IC for the throw, so that
+                // Debugger hooks report the correct pc offset of the throwing
+                // op instead of its successor.
+                //
+                // Note that we never resume into this address, it is set for
+                // the sake of frame iterators giving the correct answer.
+                ICEntry &icEntry = baselineScript->anyKindICEntryFromPCOffset(iter.pcOffset());
+                nativeCodeForPC = baselineScript->returnAddressForIC(icEntry);
+
+                // The pc after the throwing PC could be unreachable, in which
+                // case we have no native code for it and no slot info. But in
+                // that case, there are definitely no unsynced slots.
+                numUnsynced = nativeCodeForPC ? slotInfo.numUnsynced() : 0;
+            } else {
+                MOZ_ASSERT(nativeCodeForPC);
+                numUnsynced = slotInfo.numUnsynced();
+            }
+
             MOZ_ASSERT(numUnsynced <= 2);
             PCMappingSlotInfo::SlotLocation loc1, loc2;
             if (numUnsynced > 0) {
                 loc1 = slotInfo.topSlotLocation();
                 JitSpew(JitSpew_BaselineBailouts, "      Popping top stack value into %d.",
-                            (int) loc1);
+                        (int) loc1);
                 builder.popValueInto(loc1);
             }
             if (numUnsynced > 1) {
                 loc2 = slotInfo.nextSlotLocation();
                 JitSpew(JitSpew_BaselineBailouts, "      Popping next stack value into %d.",
-                            (int) loc2);
+                        (int) loc2);
                 MOZ_ASSERT_IF(loc1 != PCMappingSlotInfo::SlotIgnore, loc1 != loc2);
                 builder.popValueInto(loc2);
             }
@@ -1043,7 +1067,7 @@ InitFromBailout(JSContext *cx, HandleScript caller, jsbytecode *callerPC,
             frameSize -= sizeof(Value) * numUnsynced;
             blFrame->setFrameSize(frameSize);
             JitSpew(JitSpew_BaselineBailouts, "      Adjusted framesize -= %d: %d",
-                            int(sizeof(Value) * numUnsynced), int(frameSize));
+                    int(sizeof(Value) * numUnsynced), int(frameSize));
 
             // If scopeChain is nullptr, then bailout is occurring during argument check.
             // In this case, resume into the prologue.
diff --git a/js/src/jit/BaselineJIT.cpp b/js/src/jit/BaselineJIT.cpp
index 89df539598a2..bfad9a32ecfc 100644
--- a/js/src/jit/BaselineJIT.cpp
+++ b/js/src/jit/BaselineJIT.cpp
@@ -554,16 +554,14 @@ BaselineScript::returnAddressForIC(const ICEntry &ent)
     return method()->raw() + ent.returnOffset().offset();
 }
 
-ICEntry &
-BaselineScript::icEntryFromPCOffset(uint32_t pcOffset)
+static inline
+size_t ComputeBinarySearchMid(BaselineScript *baseline, uint32_t pcOffset)
 {
-    // Multiple IC entries can have the same PC offset, but this method only looks for
-    // those which have isForOp() set.
     size_t bottom = 0;
-    size_t top = numICEntries();
+    size_t top = baseline->numICEntries();
     size_t mid = bottom + (top - bottom) / 2;
     while (mid < top) {
-        ICEntry &midEntry = icEntry(mid);
+        ICEntry &midEntry = baseline->icEntry(mid);
         if (midEntry.pcOffset() < pcOffset)
             bottom = mid + 1;
         else if (midEntry.pcOffset() > pcOffset)
@@ -572,6 +570,29 @@ BaselineScript::icEntryFromPCOffset(uint32_t pcOffset)
             break;
         mid = bottom + (top - bottom) / 2;
     }
+    return mid;
+}
+
+ICEntry &
+BaselineScript::anyKindICEntryFromPCOffset(uint32_t pcOffset)
+{
+    size_t mid = ComputeBinarySearchMid(this, pcOffset);
+
+    // Return any IC entry with a matching PC offset.
+    for (size_t i = mid; i < numICEntries() && icEntry(i).pcOffset() == pcOffset; i--)
+            return icEntry(i);
+    for (size_t i = mid+1; i < numICEntries() && icEntry(i).pcOffset() == pcOffset; i++)
+        return icEntry(i);
+    MOZ_CRASH("Invalid PC offset for IC entry.");
+}
+
+ICEntry &
+BaselineScript::icEntryFromPCOffset(uint32_t pcOffset)
+{
+    // Multiple IC entries can have the same PC offset, but this method only looks for
+    // those which have isForOp() set.
+    size_t mid = ComputeBinarySearchMid(this, pcOffset);
+
     // Found an IC entry with a matching PC offset.  Search backward, and then
     // forward from this IC entry, looking for one with the same PC offset which
     // has isForOp() set.
@@ -693,7 +714,7 @@ BaselineScript::copyPCMappingIndexEntries(const PCMappingIndexEntry *entries)
 }
 
 uint8_t *
-BaselineScript::nativeCodeForPC(JSScript *script, jsbytecode *pc, PCMappingSlotInfo *slotInfo)
+BaselineScript::maybeNativeCodeForPC(JSScript *script, jsbytecode *pc, PCMappingSlotInfo *slotInfo)
 {
     MOZ_ASSERT_IF(script->hasBaselineScript(), script->baselineScript() == this);
 
@@ -721,7 +742,7 @@ BaselineScript::nativeCodeForPC(JSScript *script, jsbytecode *pc, PCMappingSlotI
     MOZ_ASSERT(script->containsPC(curPC));
     MOZ_ASSERT(curPC <= pc);
 
-    while (true) {
+    while (reader.more()) {
         // If the high bit is set, the native offset relative to the
         // previous pc != 0 and comes next.
         uint8_t b = reader.readByte();
@@ -736,6 +757,8 @@ BaselineScript::nativeCodeForPC(JSScript *script, jsbytecode *pc, PCMappingSlotI
 
         curPC += GetBytecodeLength(curPC);
     }
+
+    return nullptr;
 }
 
 jsbytecode *
@@ -792,6 +815,8 @@ BaselineScript::pcForNativeOffset(JSScript *script, uint32_t nativeOffset, bool
     if (!isReturn && (curNativeOffset > nativeOffset))
         return script->code();
 
+    mozilla::DebugOnly lastNativeOffset = curNativeOffset;
+    jsbytecode *lastPC = curPC;
     while (true) {
         // If the high bit is set, the native offset relative to the
         // previous pc != 0 and comes next.
diff --git a/js/src/jit/BaselineJIT.h b/js/src/jit/BaselineJIT.h
index 36161630be3b..503aaaa3bc78 100644
--- a/js/src/jit/BaselineJIT.h
+++ b/js/src/jit/BaselineJIT.h
@@ -330,8 +330,8 @@ struct BaselineScript
     ICEntry &icEntry(size_t index);
     ICEntry *maybeICEntryFromReturnOffset(CodeOffsetLabel returnOffset);
     ICEntry &icEntryFromReturnOffset(CodeOffsetLabel returnOffset);
+    ICEntry &anyKindICEntryFromPCOffset(uint32_t pcOffset);
     ICEntry &icEntryFromPCOffset(uint32_t pcOffset);
-    ICEntry &icEntryForDebugModeRecompileFromPCOffset(uint32_t pcOffset);
     ICEntry &icEntryFromPCOffset(uint32_t pcOffset, ICEntry *prevLookedUpEntry);
     ICEntry *maybeICEntryFromReturnAddress(uint8_t *returnAddr);
     ICEntry &icEntryFromReturnAddress(uint8_t *returnAddr);
@@ -356,7 +356,15 @@ struct BaselineScript
     void copyPCMappingIndexEntries(const PCMappingIndexEntry *entries);
 
     void copyPCMappingEntries(const CompactBufferWriter &entries);
-    uint8_t *nativeCodeForPC(JSScript *script, jsbytecode *pc, PCMappingSlotInfo *slotInfo = nullptr);
+    uint8_t *maybeNativeCodeForPC(JSScript *script, jsbytecode *pc,
+                                  PCMappingSlotInfo *slotInfo = nullptr);
+    uint8_t *nativeCodeForPC(JSScript *script, jsbytecode *pc,
+                             PCMappingSlotInfo *slotInfo = nullptr)
+    {
+        uint8_t *code = maybeNativeCodeForPC(script, pc, slotInfo);
+        MOZ_ASSERT(code);
+        return code;
+    }
 
     jsbytecode *pcForReturnOffset(JSScript *script, uint32_t nativeOffset);
     jsbytecode *pcForReturnAddress(JSScript *script, uint8_t *nativeAddress);

From 5a2e922f577a631bc992b3804e42b013c3c498e6 Mon Sep 17 00:00:00 2001
From: Shu-yu Guo 
Date: Wed, 26 Nov 2014 13:35:57 -0800
Subject: [PATCH 19/64] Bug 1100337 - Fix baseline PC mapping for bytecodes
 that generate no native code. (r=djvj)

---
 js/src/jit/BaselineCompiler.cpp |  4 ++++
 js/src/jit/BaselineJIT.cpp      | 19 ++++++++++++++++---
 2 files changed, 20 insertions(+), 3 deletions(-)

diff --git a/js/src/jit/BaselineCompiler.cpp b/js/src/jit/BaselineCompiler.cpp
index fe317633148b..335341e445b7 100644
--- a/js/src/jit/BaselineCompiler.cpp
+++ b/js/src/jit/BaselineCompiler.cpp
@@ -410,6 +410,10 @@ BaselineCompiler::emitPrologue()
     if (!emitSPSPush())
         return false;
 
+    // Pad a nop so that the last non-op ICEntry we pushed does not get
+    // confused with the start address of the first op for PC mapping.
+    masm.nop();
+
     return true;
 }
 
diff --git a/js/src/jit/BaselineJIT.cpp b/js/src/jit/BaselineJIT.cpp
index bfad9a32ecfc..2254923b66fe 100644
--- a/js/src/jit/BaselineJIT.cpp
+++ b/js/src/jit/BaselineJIT.cpp
@@ -824,15 +824,28 @@ BaselineScript::pcForNativeOffset(JSScript *script, uint32_t nativeOffset, bool
         if (b & 0x80)
             curNativeOffset += reader.readUnsigned();
 
-        if (isReturn ? (nativeOffset == curNativeOffset) : (nativeOffset <= curNativeOffset))
-            return curPC;
+        // Return the last PC that matched nativeOffset. Some bytecode
+        // generate no native code (e.g., constant-pushing bytecode like
+        // JSOP_INT8), and so their entries share the same nativeOffset as the
+        // next op that does generate code. Trying to find an entry for a
+        // return address is impossible for bytecodes that generate no code
+        // since calling this method requires VM reentry, so assert an exact
+        // match.
+        if (curNativeOffset > nativeOffset) {
+            MOZ_ASSERT_IF(isReturn, lastNativeOffset == nativeOffset);
+            return lastPC;
+        }
 
         // If this is a raw native lookup (not jsop return addresses), then
         // the native address may lie in-between the last delta-entry in
         // a pcMappingIndexEntry, and the next pcMappingIndexEntry.
-        if (!isReturn && !reader.more())
+        if (!reader.more()) {
+            MOZ_ASSERT_IF(isReturn, curNativeOffset == nativeOffset);
             return curPC;
+        }
 
+        lastNativeOffset = curNativeOffset;
+        lastPC = curPC;
         curPC += GetBytecodeLength(curPC);
     }
 }

From 7dc1d3f41628faea434bb8a3c11512c941ba8c8b Mon Sep 17 00:00:00 2001
From: Shu-yu Guo 
Date: Wed, 26 Nov 2014 13:35:58 -0800
Subject: [PATCH 20/64] Bug 1103048 - Don't track the type of optimized out
 values in CallObjects. (r=bhackett)

---
 js/src/jsinfer.cpp      |  8 ++++----
 js/src/jsinferinlines.h | 14 ++++++++------
 2 files changed, 12 insertions(+), 10 deletions(-)

diff --git a/js/src/jsinfer.cpp b/js/src/jsinfer.cpp
index d888d0e39113..750bda6ad167 100644
--- a/js/src/jsinfer.cpp
+++ b/js/src/jsinfer.cpp
@@ -2963,12 +2963,12 @@ UpdatePropertyType(ExclusiveContext *cx, HeapTypeSet *types, NativeObject *obj,
          * that are not collated into the JSID_VOID property (see propertySet
          * comment).
          *
-         * Also don't add initial uninitialized lexical magic values as
-         * appearing in CallObjects.
+         * Also don't add untracked values (initial uninitialized lexical
+         * magic values and optimized out values) as appearing in CallObjects.
          */
-        MOZ_ASSERT_IF(value.isMagic(JS_UNINITIALIZED_LEXICAL), obj->is());
+        MOZ_ASSERT_IF(IsUntrackedValue(value), obj->is());
         if ((indexed || !value.isUndefined() || !CanHaveEmptyPropertyTypesForOwnProperty(obj)) &&
-            !value.isMagic(JS_UNINITIALIZED_LEXICAL))
+            !IsUntrackedValue(value))
         {
             Type type = GetValueType(value);
             types->TypeSet::addType(type, &cx->typeLifoAlloc());
diff --git a/js/src/jsinferinlines.h b/js/src/jsinferinlines.h
index 12ac5d0572b8..0b42bc9cfc9e 100644
--- a/js/src/jsinferinlines.h
+++ b/js/src/jsinferinlines.h
@@ -154,15 +154,17 @@ GetValueType(const Value &val)
     return Type::PrimitiveType(val.extractNonDoubleType());
 }
 
+inline bool
+IsUntrackedValue(const Value &val)
+{
+    return val.isMagic() && (val.whyMagic() == JS_OPTIMIZED_OUT ||
+                             val.whyMagic() == JS_UNINITIALIZED_LEXICAL);
+}
+
 inline Type
 GetMaybeUntrackedValueType(const Value &val)
 {
-    if (val.isMagic() && (val.whyMagic() == JS_OPTIMIZED_OUT ||
-                          val.whyMagic() == JS_UNINITIALIZED_LEXICAL))
-    {
-        return Type::UnknownType();
-    }
-    return GetValueType(val);
+    return IsUntrackedValue(val) ? Type::UnknownType() : GetValueType(val);
 }
 
 inline TypeFlags

From c1ab6fe191640282a6b809110760bc6d855ffe45 Mon Sep 17 00:00:00 2001
From: Seth Fowler 
Date: Wed, 26 Nov 2014 13:39:30 -0800
Subject: [PATCH 21/64] Bug 1060869 - Followup - Fix mochitest.ini syntax and
 bump back up memory limit prefs on B2G. r=me

--HG--
extra : rebase_source : 1b3a89c0c35e2fc8e1febcba1e4b3b784fa5fcff
---
 b2g/app/b2g.js                     | 4 ++--
 image/test/mochitest/chrome.ini    | 4 ++--
 image/test/mochitest/mochitest.ini | 2 +-
 3 files changed, 5 insertions(+), 5 deletions(-)

diff --git a/b2g/app/b2g.js b/b2g/app/b2g.js
index 3cf73a09c6ff..5cea94468f20 100644
--- a/b2g/app/b2g.js
+++ b/b2g/app/b2g.js
@@ -336,8 +336,8 @@ pref("image.mem.min_discard_timeout_ms", 86400000); /* 24h, we rely on the out o
 // surface cache. Once animated images are stored in the surface cache too, this
 // pref will go away; see bug 977459. The same goes for
 // 'hard_limit_decoded_image_kb'; the surface cache limits are all hard.
-pref("image.mem.max_decoded_image_kb", 16384); // 16MB
-pref("image.mem.hard_limit_decoded_image_kb", 16384); // 16MB
+pref("image.mem.max_decoded_image_kb", 30000);
+pref("image.mem.hard_limit_decoded_image_kb", 66560);
 // Limit the surface cache to 1/8 of main memory or 128MB, whichever is smaller.
 // Almost everything that was factored into 'max_decoded_image_kb' is now stored
 // in the surface cache.  1/8 of main memory is 32MB on a 256MB device, which is
diff --git a/image/test/mochitest/chrome.ini b/image/test/mochitest/chrome.ini
index 70b48ff811d3..3c0970c8e812 100644
--- a/image/test/mochitest/chrome.ini
+++ b/image/test/mochitest/chrome.ini
@@ -32,7 +32,7 @@ support-files =
 [test_animSVGImage.html]
 [test_animSVGImage2.html]
 [test_animation.html]
-skip-if = true # bug 1100497
+disabled = bug 1100497
 [test_animation2.html]
 [test_background_image_anim.html]
 [test_bullet_animation.html]
@@ -47,5 +47,5 @@ skip-if = true # bug 1100497
 [test_svg_filter_animation.html]
 [test_synchronized_animation.html]
 [test_undisplayed_iframe.html]
-skip-if = true # bug 1060869
+disabled = bug 1060869
 [test_xultree_animation.xhtml]
diff --git a/image/test/mochitest/mochitest.ini b/image/test/mochitest/mochitest.ini
index 22c7d4b187af..561e6381e8dc 100644
--- a/image/test/mochitest/mochitest.ini
+++ b/image/test/mochitest/mochitest.ini
@@ -94,4 +94,4 @@ skip-if = toolkit == "gonk" #Bug 997034 - canvas.toDataURL() often causes lost c
 [test_short_gif_header.html]
 [test_image_buffer_limit.html]
 #run-if = toolkit == "gonk" #Image buffer limit is only set for Firefox OS currently.
-skip-if = true # bug 1060869
+disabled = bug 1060869

From e0e268d8b18b347b8b51486e6a4788d752c1ac3c Mon Sep 17 00:00:00 2001
From: James Willcox 
Date: Wed, 26 Nov 2014 15:43:57 -0600
Subject: [PATCH 22/64] Bug 1097116 - Followup for non-unified build breakage
 r=me CLOSED TREE

--HG--
extra : rebase_source : 697dc2f8d1661196ac8bb169fc4797b59af61fa3
extra : amend_source : 2aa014a0dec495466b854aebd5b19d1b5de4279e
---
 gfx/layers/GLImages.cpp | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/gfx/layers/GLImages.cpp b/gfx/layers/GLImages.cpp
index 9b65bb1f2a41..5a6f780fc707 100644
--- a/gfx/layers/GLImages.cpp
+++ b/gfx/layers/GLImages.cpp
@@ -33,7 +33,7 @@ EGLImageImage::~EGLImageImage()
   }
 }
 
-TemporaryRef
+TemporaryRef
 GLImage::GetAsSourceSurface()
 {
   MOZ_ASSERT(NS_IsMainThread(), "Should be on the main thread");

From 01dc7cd769333befa17a07ce11f02286eb133cb3 Mon Sep 17 00:00:00 2001
From: Nicolas Silva 
Date: Wed, 26 Nov 2014 21:05:01 +0100
Subject: [PATCH 23/64] Bug 1086670 - Add more gfxCriticalError logging in the
 D2D backend. r=jrmuizel

---
 gfx/2d/DrawTargetD2D1.cpp         | 16 +++++++---------
 gfx/layers/d3d11/TextureD3D11.cpp |  1 +
 2 files changed, 8 insertions(+), 9 deletions(-)

diff --git a/gfx/2d/DrawTargetD2D1.cpp b/gfx/2d/DrawTargetD2D1.cpp
index 7c27e4e9f49d..4dc3d5bc36b4 100644
--- a/gfx/2d/DrawTargetD2D1.cpp
+++ b/gfx/2d/DrawTargetD2D1.cpp
@@ -652,11 +652,8 @@ DrawTargetD2D1::CreateSourceSurfaceFromData(unsigned char *aData,
                                  D2D1::BitmapProperties1(D2D1_BITMAP_OPTIONS_NONE, D2DPixelFormat(aFormat)),
                                  byRef(bitmap));
 
-  if (FAILED(hr)) {
+  if (FAILED(hr) || !bitmap) {
     gfxCriticalError() << "[D2D1.1] CreateBitmap failure " << aSize << " Code: " << hexa(hr);
-  }
-
-  if (!bitmap) {
     return nullptr;
   }
 
@@ -745,7 +742,7 @@ DrawTargetD2D1::Init(ID3D11Texture2D* aTexture, SurfaceFormat aFormat)
   hr = Factory::GetD2D1Device()->CreateDeviceContext(D2D1_DEVICE_CONTEXT_OPTIONS_ENABLE_MULTITHREADED_OPTIMIZATIONS, byRef(mDC));
 
   if (FAILED(hr)) {
-    gfxWarning() << *this << ": Error " << hexa(hr) << " failed to initialize new DeviceContext.";
+    gfxCriticalError() <<"[D2D1.1] Failed to create a DeviceContext, code: " << hexa(hr);
     return false;
   }
 
@@ -753,6 +750,7 @@ DrawTargetD2D1::Init(ID3D11Texture2D* aTexture, SurfaceFormat aFormat)
   aTexture->QueryInterface(__uuidof(IDXGISurface),
                            (void**)((IDXGISurface**)byRef(dxgiSurface)));
   if (!dxgiSurface) {
+    gfxCriticalError() <<"[D2D1.1] Failed to obtain a DXGI surface.";
     return false;
   }
 
@@ -799,14 +797,14 @@ DrawTargetD2D1::Init(const IntSize &aSize, SurfaceFormat aFormat)
   hr = Factory::GetD2D1Device()->CreateDeviceContext(D2D1_DEVICE_CONTEXT_OPTIONS_ENABLE_MULTITHREADED_OPTIMIZATIONS, byRef(mDC));
 
   if (FAILED(hr)) {
-    gfxWarning() << *this << ": Error " << hexa(hr) << " failed to initialize new DeviceContext.";
+    gfxCriticalError() <<"[D2D1.1] Failed to create a DeviceContext, code: " << hexa(hr);
     return false;
   }
 
   if (mDC->GetMaximumBitmapSize() < UINT32(aSize.width) ||
       mDC->GetMaximumBitmapSize() < UINT32(aSize.height)) {
     // This is 'ok'
-    gfxDebug() << *this << ": Attempt to use unsupported surface size for D2D 1.1.";
+    gfxCriticalError() << "[D2D1.1] Attempt to use unsupported surface size " << aSize;
     return false;
   }
 
@@ -819,7 +817,7 @@ DrawTargetD2D1::Init(const IntSize &aSize, SurfaceFormat aFormat)
   hr = mDC->CreateBitmap(D2DIntSize(aSize), nullptr, 0, props, (ID2D1Bitmap1**)byRef(mBitmap));
 
   if (FAILED(hr)) {
-    gfxCriticalError() << *this << ": Error " << hexa(hr) << " failed to create new Bitmap. Size: " << aSize;
+    gfxCriticalError() << "[D2D1.1] CreateBitmap failure " << aSize << " Code: " << hexa(hr);
     return false;
   }
 
@@ -829,7 +827,7 @@ DrawTargetD2D1::Init(const IntSize &aSize, SurfaceFormat aFormat)
   hr = mDC->CreateBitmap(D2DIntSize(aSize), nullptr, 0, props, (ID2D1Bitmap1**)byRef(mTempBitmap));
 
   if (FAILED(hr)) {
-    gfxCriticalError() << *this << ": Error " << hexa(hr) << " failed to create new TempBitmap. Size: " << aSize;
+    gfxCriticalError() << "[D2D1.1] failed to create new TempBitmap " << aSize << " Code: " << hexa(hr);
     return false;
   }
 
diff --git a/gfx/layers/d3d11/TextureD3D11.cpp b/gfx/layers/d3d11/TextureD3D11.cpp
index 266747f3f17c..7f7e6f37b21f 100644
--- a/gfx/layers/d3d11/TextureD3D11.cpp
+++ b/gfx/layers/d3d11/TextureD3D11.cpp
@@ -317,6 +317,7 @@ TextureClientD3D11::BorrowDrawTarget()
   MOZ_ASSERT(mIsLocked, "Calling TextureClient::BorrowDrawTarget without locking :(");
 
   if (!mIsLocked || (!mTexture && !mTexture10)) {
+    gfxCriticalError() << "Attempted to borrow a DrawTarget without locking the texture.";
     return nullptr;
   }
 

From 0da28b71aa2209fadce273983ea8a4fc8f13b573 Mon Sep 17 00:00:00 2001
From: Patrick Cloke 
Date: Wed, 26 Nov 2014 17:08:41 -0500
Subject: [PATCH 24/64] Bug 1104997 - Fix Thunderbird bustage from Bug 1091668.
 r=mshal

--HG--
extra : rebase_source : 55d97b53e72d29cfada4e656d55a72bc0f700e05
---
 toolkit/mozapps/installer/make-eme.mk | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/toolkit/mozapps/installer/make-eme.mk b/toolkit/mozapps/installer/make-eme.mk
index de50157dfd03..462928b77f83 100644
--- a/toolkit/mozapps/installer/make-eme.mk
+++ b/toolkit/mozapps/installer/make-eme.mk
@@ -6,7 +6,7 @@ include $(MOZILLA_DIR)/toolkit/mozapps/installer/signing.mk
 
 ifdef MOZ_SIGN_CMD
   ifeq ($(OS_ARCH),WINNT)
-    MAKE_SIGN_EME_VOUCHER := $(PYTHON) $(topsrcdir)/python/eme/gen-eme-voucher.py -input $(DIST)/bin/plugin-container.exe -output $(DIST)/$(STAGEPATH)$(MOZ_PKG_DIR)/voucher.bin && \
+    MAKE_SIGN_EME_VOUCHER := $(PYTHON) $(MOZILLA_DIR)/python/eme/gen-eme-voucher.py -input $(DIST)/bin/plugin-container.exe -output $(DIST)/$(STAGEPATH)$(MOZ_PKG_DIR)/voucher.bin && \
       $(MOZ_SIGN_CMD) -f emevoucher "$(DIST)/$(STAGEPATH)$(MOZ_PKG_DIR)/voucher.bin"
   endif
 endif

From 5b9e4409a2032809d82ea5cf7aaeb6f891f8e4ba Mon Sep 17 00:00:00 2001
From: Nicolas Silva 
Date: Wed, 26 Nov 2014 14:11:11 -0800
Subject: [PATCH 25/64] Bug 1036682 - Prevent LayerTransactionChild from
 sending messages after it has been destroyed. r=jrmuizel

---
 gfx/layers/ipc/LayerTransactionChild.cpp | 1 +
 1 file changed, 1 insertion(+)

diff --git a/gfx/layers/ipc/LayerTransactionChild.cpp b/gfx/layers/ipc/LayerTransactionChild.cpp
index ec0a037be0b1..ce10a68a63c0 100644
--- a/gfx/layers/ipc/LayerTransactionChild.cpp
+++ b/gfx/layers/ipc/LayerTransactionChild.cpp
@@ -129,6 +129,7 @@ LayerTransactionChild::SendFenceHandle(AsyncTransactionTracker* aTracker,
 void
 LayerTransactionChild::ActorDestroy(ActorDestroyReason why)
 {
+  mDestroyed = true;
   DestroyAsyncTransactionTrackersHolder();
 #ifdef MOZ_B2G
   // Due to poor lifetime management of gralloc (and possibly shmems) we will

From 8277eea9e9425f3d29d93f7570d699652c736b8a Mon Sep 17 00:00:00 2001
From: Masatoshi Kimura 
Date: Thu, 27 Nov 2014 07:19:11 +0900
Subject: [PATCH 26/64] Bug 1092998 - Deal with "cipher mismatch intolerant"
 servers. r=keeler

---
 security/manager/ssl/src/nsNSSIOLayer.cpp     | 15 ++++++++-----
 security/manager/ssl/src/nsNSSIOLayer.h       |  3 ++-
 .../ssl/tests/gtest/TLSIntoleranceTest.cpp    | 22 +++++++++----------
 toolkit/components/telemetry/Histograms.json  |  3 ++-
 4 files changed, 24 insertions(+), 19 deletions(-)

diff --git a/security/manager/ssl/src/nsNSSIOLayer.cpp b/security/manager/ssl/src/nsNSSIOLayer.cpp
index 7bb6b2cbf7de..74d652131e65 100644
--- a/security/manager/ssl/src/nsNSSIOLayer.cpp
+++ b/security/manager/ssl/src/nsNSSIOLayer.cpp
@@ -939,7 +939,8 @@ nsSSLIOLayerHelpers::rememberIntolerantAtVersion(const nsACString& hostName,
 // returns true if we should retry the handshake
 bool
 nsSSLIOLayerHelpers::rememberStrongCiphersFailed(const nsACString& hostName,
-                                                 int16_t port)
+                                                 int16_t port,
+                                                 PRErrorCode intoleranceReason)
 {
   nsCString key;
   getSiteKey(hostName, port, key);
@@ -956,7 +957,7 @@ nsSSLIOLayerHelpers::rememberStrongCiphersFailed(const nsACString& hostName,
   } else {
     entry.tolerant = 0;
     entry.intolerant = 0;
-    entry.intoleranceReason = SSL_ERROR_NO_CYPHER_OVERLAP;
+    entry.intoleranceReason = intoleranceReason;
   }
 
   entry.strongCipherStatus = StrongCiphersFailed;
@@ -1209,15 +1210,17 @@ retryDueToTLSIntolerance(PRErrorCode err, nsNSSSocketInfo* socketInfo)
       .forgetIntolerance(socketInfo->GetHostName(), socketInfo->GetPort());
 
     return false;
-  } else if (err == SSL_ERROR_NO_CYPHER_OVERLAP &&
+  } else if ((err == SSL_ERROR_NO_CYPHER_OVERLAP ||
+              err == PR_END_OF_FILE_ERROR) &&
              nsNSSComponent::AreAnyWeakCiphersEnabled()) {
     if (socketInfo->SharedState().IOLayerHelpers()
                   .rememberStrongCiphersFailed(socketInfo->GetHostName(),
-                                               socketInfo->GetPort())) {
-      Telemetry::Accumulate(Telemetry::SSL_WEAK_CIPHERS_FALLBACK, true);
+                                               socketInfo->GetPort(), err)) {
+      Telemetry::Accumulate(Telemetry::SSL_WEAK_CIPHERS_FALLBACK,
+                            tlsIntoleranceTelemetryBucket(err));
       return true;
     }
-    Telemetry::Accumulate(Telemetry::SSL_WEAK_CIPHERS_FALLBACK, false);
+    Telemetry::Accumulate(Telemetry::SSL_WEAK_CIPHERS_FALLBACK, 0);
   }
 
   // When not using a proxy we'll see a connection reset error.
diff --git a/security/manager/ssl/src/nsNSSIOLayer.h b/security/manager/ssl/src/nsNSSIOLayer.h
index d99a37d2eb16..7404c3b6a909 100644
--- a/security/manager/ssl/src/nsNSSIOLayer.h
+++ b/security/manager/ssl/src/nsNSSIOLayer.h
@@ -223,7 +223,8 @@ public:
   bool rememberIntolerantAtVersion(const nsACString& hostname, int16_t port,
                                    uint16_t intolerant, uint16_t minVersion,
                                    PRErrorCode intoleranceReason);
-  bool rememberStrongCiphersFailed(const nsACString& hostName, int16_t port);
+  bool rememberStrongCiphersFailed(const nsACString& hostName, int16_t port,
+                                   PRErrorCode intoleranceReason);
   void forgetIntolerance(const nsACString& hostname, int16_t port);
   void adjustForTLSIntolerance(const nsACString& hostname, int16_t port,
                                /*in/out*/ SSLVersionRange& range,
diff --git a/security/manager/ssl/tests/gtest/TLSIntoleranceTest.cpp b/security/manager/ssl/tests/gtest/TLSIntoleranceTest.cpp
index 516b6336362a..45d64a4115bf 100644
--- a/security/manager/ssl/tests/gtest/TLSIntoleranceTest.cpp
+++ b/security/manager/ssl/tests/gtest/TLSIntoleranceTest.cpp
@@ -33,7 +33,7 @@ TEST_F(TLSIntoleranceTest, Test_Full_Fallback_Process)
     ASSERT_EQ(SSL_LIBRARY_VERSION_TLS_1_2, range.max);
     ASSERT_EQ(StrongCipherStatusUnknown, strongCipherStatus);
 
-    ASSERT_TRUE(helpers.rememberStrongCiphersFailed(HOST, PORT));
+    ASSERT_TRUE(helpers.rememberStrongCiphersFailed(HOST, PORT, 0));
   }
 
   {
@@ -45,7 +45,7 @@ TEST_F(TLSIntoleranceTest, Test_Full_Fallback_Process)
     ASSERT_EQ(SSL_LIBRARY_VERSION_TLS_1_2, range.max);
     ASSERT_EQ(StrongCiphersFailed, strongCipherStatus);
 
-    ASSERT_FALSE(helpers.rememberStrongCiphersFailed(HOST, PORT));
+    ASSERT_FALSE(helpers.rememberStrongCiphersFailed(HOST, PORT, 0));
     ASSERT_TRUE(helpers.rememberIntolerantAtVersion(HOST, PORT,
                                                     range.min, range.max, 0));
   }
@@ -59,7 +59,7 @@ TEST_F(TLSIntoleranceTest, Test_Full_Fallback_Process)
     ASSERT_EQ(SSL_LIBRARY_VERSION_TLS_1_1, range.max);
     ASSERT_EQ(StrongCiphersFailed, strongCipherStatus);
 
-    ASSERT_FALSE(helpers.rememberStrongCiphersFailed(HOST, PORT));
+    ASSERT_FALSE(helpers.rememberStrongCiphersFailed(HOST, PORT, 0));
     ASSERT_TRUE(helpers.rememberIntolerantAtVersion(HOST, PORT,
                                                     range.min, range.max, 0));
   }
@@ -73,7 +73,7 @@ TEST_F(TLSIntoleranceTest, Test_Full_Fallback_Process)
     ASSERT_EQ(SSL_LIBRARY_VERSION_TLS_1_0, range.max);
     ASSERT_EQ(StrongCiphersFailed, strongCipherStatus);
 
-    ASSERT_FALSE(helpers.rememberStrongCiphersFailed(HOST, PORT));
+    ASSERT_FALSE(helpers.rememberStrongCiphersFailed(HOST, PORT, 0));
     ASSERT_TRUE(helpers.rememberIntolerantAtVersion(HOST, PORT,
                                                     range.min, range.max, 0));
   }
@@ -88,7 +88,7 @@ TEST_F(TLSIntoleranceTest, Test_Full_Fallback_Process)
     ASSERT_EQ(SSL_LIBRARY_VERSION_3_0, range.max);
     ASSERT_EQ(StrongCiphersFailed, strongCipherStatus);
 
-    ASSERT_FALSE(helpers.rememberStrongCiphersFailed(HOST, PORT));
+    ASSERT_FALSE(helpers.rememberStrongCiphersFailed(HOST, PORT, 0));
     // false because we reached the floor set by range.min
     ASSERT_FALSE(helpers.rememberIntolerantAtVersion(HOST, PORT,
                                                      range.min, range.max, 0));
@@ -282,7 +282,7 @@ TEST_F(TLSIntoleranceTest, Test_Strong_Ciphers_Failed)
 {
   helpers.mVersionFallbackLimit = SSL_LIBRARY_VERSION_TLS_1_1;
 
-  ASSERT_TRUE(helpers.rememberStrongCiphersFailed(HOST, PORT));
+  ASSERT_TRUE(helpers.rememberStrongCiphersFailed(HOST, PORT, 0));
 
   {
     SSLVersionRange range = { SSL_LIBRARY_VERSION_3_0,
@@ -342,7 +342,7 @@ TEST_F(TLSIntoleranceTest, Test_Strong_Ciphers_Failed_At_1_1)
                               SSL_LIBRARY_VERSION_TLS_1_2 };
     StrongCipherStatus strongCipherStatus = StrongCipherStatusUnknown;
     helpers.adjustForTLSIntolerance(HOST, PORT, range, strongCipherStatus);
-    ASSERT_TRUE(helpers.rememberStrongCiphersFailed(HOST, PORT));
+    ASSERT_TRUE(helpers.rememberStrongCiphersFailed(HOST, PORT, 0));
   }
 
   {
@@ -375,7 +375,7 @@ TEST_F(TLSIntoleranceTest, Test_Strong_Ciphers_Failed_With_High_Limit)
   // to mark an origin as version intolerant fail
   helpers.mVersionFallbackLimit = SSL_LIBRARY_VERSION_TLS_1_2;
   // ...but weak ciphers fallback will not be disabled
-  ASSERT_TRUE(helpers.rememberStrongCiphersFailed(HOST, PORT));
+  ASSERT_TRUE(helpers.rememberStrongCiphersFailed(HOST, PORT, 0));
   ASSERT_FALSE(helpers.rememberIntolerantAtVersion(HOST, PORT,
                                                    SSL_LIBRARY_VERSION_3_0,
                                                    SSL_LIBRARY_VERSION_TLS_1_2,
@@ -392,7 +392,7 @@ TEST_F(TLSIntoleranceTest, Test_Strong_Ciphers_Failed_With_High_Limit)
 
 TEST_F(TLSIntoleranceTest, Test_Tolerant_Does_Not_Override_Weak_Ciphers_Fallback)
 {
-  ASSERT_TRUE(helpers.rememberStrongCiphersFailed(HOST, PORT));
+  ASSERT_TRUE(helpers.rememberStrongCiphersFailed(HOST, PORT, 0));
   // No adjustment made when intolerant is zero.
   helpers.rememberTolerantAtVersion(HOST, PORT, SSL_LIBRARY_VERSION_TLS_1_1);
   SSLVersionRange range = { SSL_LIBRARY_VERSION_3_0,
@@ -409,7 +409,7 @@ TEST_F(TLSIntoleranceTest, Test_Weak_Ciphers_Fallback_Does_Not_Override_Tolerant
   // No adjustment made when there is no entry for the site.
   helpers.rememberTolerantAtVersion(HOST, PORT, SSL_LIBRARY_VERSION_TLS_1_1);
   // false because strongCipherWorked is set by rememberTolerantAtVersion.
-  ASSERT_FALSE(helpers.rememberStrongCiphersFailed(HOST, PORT));
+  ASSERT_FALSE(helpers.rememberStrongCiphersFailed(HOST, PORT, 0));
   SSLVersionRange range = { SSL_LIBRARY_VERSION_3_0,
                             SSL_LIBRARY_VERSION_TLS_1_2 };
   StrongCipherStatus strongCipherStatus = StrongCipherStatusUnknown;
@@ -452,7 +452,7 @@ TEST_F(TLSIntoleranceTest, TLS_Forget_Intolerance)
 TEST_F(TLSIntoleranceTest, TLS_Forget_Strong_Cipher_Failed)
 {
   {
-    ASSERT_TRUE(helpers.rememberStrongCiphersFailed(HOST, PORT));
+    ASSERT_TRUE(helpers.rememberStrongCiphersFailed(HOST, PORT, 0));
 
     SSLVersionRange range = { SSL_LIBRARY_VERSION_3_0,
                               SSL_LIBRARY_VERSION_TLS_1_2 };
diff --git a/toolkit/components/telemetry/Histograms.json b/toolkit/components/telemetry/Histograms.json
index 7339f0b6adaf..257a9a754ada 100644
--- a/toolkit/components/telemetry/Histograms.json
+++ b/toolkit/components/telemetry/Histograms.json
@@ -6455,7 +6455,8 @@
   },
   "SSL_WEAK_CIPHERS_FALLBACK": {
     "expires_in_version": "never",
-    "kind": "boolean",
+    "kind": "enumerated",
+    "n_values": 64,
     "description": "Fallback attempted when server did not support any strong cipher suites"
   },
   "SSL_CIPHER_SUITE_FULL": {

From 889c1db9d11b640d1b87ac01f029b61186aaebdc Mon Sep 17 00:00:00 2001
From: Masatoshi Kimura 
Date: Thu, 27 Nov 2014 07:19:12 +0900
Subject: [PATCH 27/64] Bug 1093741 - Refuse install Firefox on pre-Win7 x64.
 r=rstrong

---
 browser/installer/windows/nsis/defines.nsi.in     | 2 +-
 browser/installer/windows/nsis/stub.nsi           | 4 ++--
 toolkit/mozapps/installer/windows/nsis/common.nsh | 2 +-
 3 files changed, 4 insertions(+), 4 deletions(-)

diff --git a/browser/installer/windows/nsis/defines.nsi.in b/browser/installer/windows/nsis/defines.nsi.in
index 017a2bb81ffd..b28dd4f78ec7 100644
--- a/browser/installer/windows/nsis/defines.nsi.in
+++ b/browser/installer/windows/nsis/defines.nsi.in
@@ -64,7 +64,7 @@
 #ifdef HAVE_64BIT_BUILD
 !define HAVE_64BIT_BUILD
 !define ARCH "x64"
-!define MinSupportedVer "Microsoft Windows Vista x64"
+!define MinSupportedVer "Microsoft Windows 7 x64"
 #else
 !define ARCH "x86"
 !define MinSupportedVer "Microsoft Windows XP SP2"
diff --git a/browser/installer/windows/nsis/stub.nsi b/browser/installer/windows/nsis/stub.nsi
index de763a0e5069..9b001c029c11 100644
--- a/browser/installer/windows/nsis/stub.nsi
+++ b/browser/installer/windows/nsis/stub.nsi
@@ -311,9 +311,9 @@ Function .onInit
   ${SetBrandNameVars} "$PLUGINSDIR\ignored.ini"
 
 !ifdef HAVE_64BIT_BUILD
-  ; Restrict x64 builds from being installed on x86 and pre Vista
+  ; Restrict x64 builds from being installed on x86 and pre Win7
   ${Unless} ${RunningX64}
-  ${OrUnless} ${AtLeastWinVista}
+  ${OrUnless} ${AtLeastWin7}
     MessageBox MB_OK|MB_ICONSTOP "$(WARN_MIN_SUPPORTED_OS_MSG)"
     Quit
   ${EndUnless}
diff --git a/toolkit/mozapps/installer/windows/nsis/common.nsh b/toolkit/mozapps/installer/windows/nsis/common.nsh
index d28622f2f6ea..44d14804c232 100755
--- a/toolkit/mozapps/installer/windows/nsis/common.nsh
+++ b/toolkit/mozapps/installer/windows/nsis/common.nsh
@@ -5091,7 +5091,7 @@
 
       !ifdef HAVE_64BIT_BUILD
         ${Unless} ${RunningX64}
-        ${OrUnless} ${AtLeastWinVista}
+        ${OrUnless} ${AtLeastWin7}
           MessageBox MB_OK|MB_ICONSTOP "$R9" IDOK
           ; Nothing initialized so no need to call OnEndCommon
           Quit

From 4baca31f848ec23d1a6e0f5d55160f9f38693966 Mon Sep 17 00:00:00 2001
From: James Willcox 
Date: Wed, 26 Nov 2014 16:22:41 -0600
Subject: [PATCH 28/64] Bug 1097116 - More build bustage r=me

--HG--
extra : rebase_source : 74dce437c198a17280d1fdf459d4e87a64808b21
---
 gfx/gl/GLBlitHelper.cpp | 1 +
 1 file changed, 1 insertion(+)

diff --git a/gfx/gl/GLBlitHelper.cpp b/gfx/gl/GLBlitHelper.cpp
index 46b568f0f8ec..a05076f5200c 100644
--- a/gfx/gl/GLBlitHelper.cpp
+++ b/gfx/gl/GLBlitHelper.cpp
@@ -20,6 +20,7 @@
 #ifdef MOZ_WIDGET_ANDROID
 #include "AndroidSurfaceTexture.h"
 #include "GLImages.h"
+#include "GLLibraryEGL.h"
 #endif
 
 using mozilla::layers::PlanarYCbCrImage;

From e4c077f30343abbe103d12686ccbafa0cc4997ac Mon Sep 17 00:00:00 2001
From: Blake Kaplan 
Date: Wed, 26 Nov 2014 14:28:28 -0800
Subject: [PATCH 29/64] Bug 582297 - Make  work in e10s.
 r=billm/dkeeler

---
 dom/base/crashtests/crashtests.list           |  4 +-
 dom/html/nsIFormProcessor.h                   | 31 +++++---
 dom/html/test/forms/mochitest.ini             |  2 +-
 dom/imptests/html/mochitest.ini               |  2 +-
 dom/ipc/ContentParent.cpp                     | 37 +++++++++
 dom/ipc/ContentParent.h                       |  9 +++
 dom/ipc/PContent.ipdl                         | 16 ++++
 layout/base/crashtests/crashtests.list        |  4 +-
 .../manager/ssl/crashtests/crashtests.list    |  2 +-
 security/manager/ssl/src/moz.build            |  4 +
 security/manager/ssl/src/nsKeygenHandler.cpp  | 72 +++++++++++++-----
 security/manager/ssl/src/nsKeygenHandler.h    | 41 ++++++----
 .../ssl/src/nsKeygenHandlerContent.cpp        | 76 +++++++++++++++++++
 .../manager/ssl/src/nsKeygenHandlerContent.h  | 42 ++++++++++
 14 files changed, 287 insertions(+), 55 deletions(-)
 create mode 100644 security/manager/ssl/src/nsKeygenHandlerContent.cpp
 create mode 100644 security/manager/ssl/src/nsKeygenHandlerContent.h

diff --git a/dom/base/crashtests/crashtests.list b/dom/base/crashtests/crashtests.list
index 69b47c611974..e857ab7d6d8b 100644
--- a/dom/base/crashtests/crashtests.list
+++ b/dom/base/crashtests/crashtests.list
@@ -173,8 +173,8 @@ load 830098.html
 load 831287.html
 load 832644.html
 load 836890.html
-skip-if(browserIsRemote) load 838489-1.html #  broken in e10s (bug 582297)
-skip-if(browserIsRemote) load 838489-2.html #  broken in e10s (bug 582297)
+load 838489-1.html
+load 838489-2.html
 load 841205.html
 load 844404.html
 load 845093-1.html
diff --git a/dom/html/nsIFormProcessor.h b/dom/html/nsIFormProcessor.h
index 72dc1c182c03..54c46c6195a5 100644
--- a/dom/html/nsIFormProcessor.h
+++ b/dom/html/nsIFormProcessor.h
@@ -25,13 +25,10 @@ class nsIDOMHTMLElement;
 
 #define NS_FORMPROCESSOR_CONTRACTID "@mozilla.org/layout/form-processor;1"
 
-// 6d4ea1aa-a6b2-43bd-a19d-3f0f26750df3
+// bf8b1986-8800-424b-b1e5-7a2ca8b9e76c
 #define NS_IFORMPROCESSOR_IID      \
-{ 0x6d4ea1aa, 0xa6b2, 0x43bd, \
- { 0xa1, 0x9d, 0x3f, 0x0f, 0x26, 0x75, 0x0d, 0xf3 } }
-
-
-
+{ 0xbf8b1986, 0x8800, 0x424b, \
+  { 0xb1, 0xe5, 0x7a, 0x2c, 0xa8, 0xb9, 0xe7, 0x6c } }
 
 // XXX:In the future, we should examine combining this interface with nsIFormSubmitObserver.
 // nsIFormSubmitObserver could have a before, during, and after form submission methods.
@@ -55,9 +52,19 @@ public:
    *                   On exit it contains the value which will actually be submitted for aName.
    *                   
    */
-  NS_IMETHOD ProcessValue(nsIDOMHTMLElement *aElement, 
-                          const nsAString& aName,
-                          nsAString& aValue) = 0;
+  virtual nsresult ProcessValue(nsIDOMHTMLElement* aElement,
+                                const nsAString& aName,
+                                nsAString& aValue) = 0;
+
+  /**
+   * The same as above, but with the element unpacked so that this can be
+   * called as the result of an IPC message.
+   */
+  virtual nsresult ProcessValueIPC(const nsAString& aOldValue,
+                                   const nsAString& aKeyType,
+                                   const nsAString& aChallenge,
+                                   const nsAString& aKeyParams,
+                                   nsAString& newValue) = 0;
 
   /* Provide content for a form element. This method provides a mechanism to provide 
    * content which comes from a source other than the document (i.e. a local database)
@@ -68,9 +75,9 @@ public:
    *                      the form element contains non-standard content.
    */
 
-  NS_IMETHOD ProvideContent(const nsAString& aFormType, 
-                            nsTArray& aContent,
-                            nsAString& aAttribute) = 0;
+  virtual nsresult ProvideContent(const nsAString& aFormType,
+                                  nsTArray& aContent,
+                                  nsAString& aAttribute) = 0;
 
 };
 
diff --git a/dom/html/test/forms/mochitest.ini b/dom/html/test/forms/mochitest.ini
index 5773f5fe9b81..be5fc933f122 100644
--- a/dom/html/test/forms/mochitest.ini
+++ b/dom/html/test/forms/mochitest.ini
@@ -93,7 +93,7 @@ skip-if = e10s
 [test_stepup_stepdown.html]
 [test_textarea_attributes_reflection.html]
 [test_validation.html]
-skip-if = buildapp == 'b2g' || e10s # b2g(374 total, bug 901848, no keygen support) b2g-debug(374 total, bug 901848, no keygen support) b2g-desktop(374 total, bug 901848, no keygen support)
+skip-if = buildapp == 'b2g' # b2g(374 total, bug 901848, no keygen support) b2g-debug(374 total, bug 901848, no keygen support) b2g-desktop(374 total, bug 901848, no keygen support)
 [test_valueAsDate_pref.html]
 [test_valueasdate_attribute.html]
 [test_valueasnumber_attribute.html]
diff --git a/dom/imptests/html/mochitest.ini b/dom/imptests/html/mochitest.ini
index 6be6308299cc..2aa333abf879 100644
--- a/dom/imptests/html/mochitest.ini
+++ b/dom/imptests/html/mochitest.ini
@@ -298,7 +298,7 @@ skip-if = (toolkit == 'gonk' && debug) #b2g-debug(debug-only failure)
 [html/dom/documents/dta/doc.gEBN/test_document.getElementsByName-namespace.xhtml]
 skip-if = (toolkit == 'gonk' && debug) #b2g-debug(debug-only failure)
 [html/dom/documents/dta/doc.gEBN/test_document.getElementsByName-newelements.html]
-skip-if = (toolkit == 'gonk' && debug) || (e10s && debug) #b2g-debug(debug-only failure)
+skip-if = (toolkit == 'gonk' && debug) #b2g-debug(debug-only failure)
 [html/dom/documents/dta/doc.gEBN/test_document.getElementsByName-newelements.xhtml]
 skip-if = (toolkit == 'gonk' && debug) #b2g-debug(debug-only failure)
 [html/dom/documents/dta/doc.gEBN/test_document.getElementsByName-null-undef.html]
diff --git a/dom/ipc/ContentParent.cpp b/dom/ipc/ContentParent.cpp
index 4eff021c4a94..984425238f3d 100755
--- a/dom/ipc/ContentParent.cpp
+++ b/dom/ipc/ContentParent.cpp
@@ -100,6 +100,7 @@
 #include "mozilla/dom/WakeLock.h"
 #include "nsIDOMWindow.h"
 #include "nsIExternalProtocolService.h"
+#include "nsIFormProcessor.h"
 #include "nsIGfxInfo.h"
 #include "nsIIdleService.h"
 #include "nsIJSRuntimeService.h"
@@ -4212,6 +4213,42 @@ ContentParent::RecvOpenAnonymousTemporaryFile(FileDescriptor *aFD)
     return true;
 }
 
+static NS_DEFINE_CID(kFormProcessorCID, NS_FORMPROCESSOR_CID);
+
+bool
+ContentParent::RecvFormProcessValue(const nsString& oldValue,
+                                    const nsString& challenge,
+                                    const nsString& keytype,
+                                    const nsString& keyparams,
+                                    nsString* newValue)
+{
+    nsCOMPtr formProcessor =
+      do_GetService(kFormProcessorCID);
+    if (!formProcessor) {
+        newValue->Truncate();
+        return true;
+    }
+
+    formProcessor->ProcessValueIPC(oldValue, challenge, keytype, keyparams,
+                                   *newValue);
+    return true;
+}
+
+bool
+ContentParent::RecvFormProvideContent(nsString* aAttribute,
+                                      nsTArray* aContent)
+{
+    nsCOMPtr formProcessor =
+      do_GetService(kFormProcessorCID);
+    if (!formProcessor) {
+        return true;
+    }
+
+    formProcessor->ProvideContent(NS_LITERAL_STRING("SELECT"), *aContent,
+                                  *aAttribute);
+    return true;
+}
+
 PFileDescriptorSetParent*
 ContentParent::AllocPFileDescriptorSetParent(const FileDescriptor& aFD)
 {
diff --git a/dom/ipc/ContentParent.h b/dom/ipc/ContentParent.h
index 53090e8ab846..6e2196af1328 100644
--- a/dom/ipc/ContentParent.h
+++ b/dom/ipc/ContentParent.h
@@ -714,6 +714,15 @@ private:
     virtual bool
     RecvOpenAnonymousTemporaryFile(FileDescriptor* aFD) MOZ_OVERRIDE;
 
+    virtual bool
+    RecvFormProcessValue(const nsString& oldValue, const nsString& challenge,
+                         const nsString& keytype, const nsString& keyparams,
+                         nsString* newValue) MOZ_OVERRIDE;
+
+    virtual bool
+    RecvFormProvideContent(nsString* aAttribute,
+                           nsTArray* aContent) MOZ_OVERRIDE;
+
     virtual PFileDescriptorSetParent*
     AllocPFileDescriptorSetParent(const mozilla::ipc::FileDescriptor&) MOZ_OVERRIDE;
 
diff --git a/dom/ipc/PContent.ipdl b/dom/ipc/PContent.ipdl
index ae946537801c..b49a76b08839 100644
--- a/dom/ipc/PContent.ipdl
+++ b/dom/ipc/PContent.ipdl
@@ -782,6 +782,22 @@ parent:
 
     sync OpenAnonymousTemporaryFile() returns (FileDescriptor aFD);
 
+    /**
+     * Keygen requires us to call it after a  element is parsed and
+     * before one is submitted. This is urgent because an extension might use
+     * a CPOW to synchronously submit a keygen element.
+     */
+    prio(urgent) sync FormProcessValue(nsString oldValue,
+                                       nsString challenge,
+                                       nsString keytype,
+                                       nsString keyparams)
+        returns (nsString newValue);
+
+    /**
+     * Called to provide the options for  elements.
+     */
+    sync FormProvideContent() returns (nsString aAttribute, nsString[] aContent);
+
     // Use only for testing!
     sync GetFileReferences(PersistenceType persistenceType,
                            nsCString origin,
diff --git a/layout/base/crashtests/crashtests.list b/layout/base/crashtests/crashtests.list
index b6815a115d07..cc9dfc5600fb 100644
--- a/layout/base/crashtests/crashtests.list
+++ b/layout/base/crashtests/crashtests.list
@@ -95,7 +95,7 @@ load 339651-1.html
 load 340093-1.xul
 load 341382-1.html
 load 341382-2.html
-asserts-if(browserIsRemote,1) load 341858-1.html # bug 622188
+load 341858-1.html
 load 342145-1.xhtml
 load 343293-1.xhtml
 load 343293-2.xhtml
@@ -105,7 +105,7 @@ load 344064-1.html
 load 344300-1.html
 load 344300-2.html
 load 344340-1.xul
-asserts-if(browserIsRemote,1) load 347898-1.html # bug 622188
+load 347898-1.html
 load 348126-1.html
 load 348688-1.html
 load 348708-1.xhtml
diff --git a/security/manager/ssl/crashtests/crashtests.list b/security/manager/ssl/crashtests/crashtests.list
index f869c9f65739..fbc5b85043b1 100644
--- a/security/manager/ssl/crashtests/crashtests.list
+++ b/security/manager/ssl/crashtests/crashtests.list
@@ -1 +1 @@
-asserts-if(browserIsRemote,1) load 398665-1.html # bug 582297
+load 398665-1.html
diff --git a/security/manager/ssl/src/moz.build b/security/manager/ssl/src/moz.build
index ee3cfa139579..dd6bbb2b63ed 100644
--- a/security/manager/ssl/src/moz.build
+++ b/security/manager/ssl/src/moz.build
@@ -32,6 +32,7 @@ UNIFIED_SOURCES += [
     'nsCrypto.cpp',
     'nsDataSignatureVerifier.cpp',
     'nsKeygenHandler.cpp',
+    'nsKeygenHandlerContent.cpp',
     'nsKeygenThread.cpp',
     'nsKeyModule.cpp',
     'nsNSSASN1Object.cpp',
@@ -102,6 +103,7 @@ FINAL_LIBRARY = 'xul'
 LOCAL_INCLUDES += [
     '../../../certverifier',
     '../../../pkix/include',
+    '/dom/base',
 ]
 
 if CONFIG['NSS_DISABLE_DBM']:
@@ -115,3 +117,5 @@ for var in ('DLL_PREFIX', 'DLL_SUFFIX'):
 USE_LIBS += [
     'crmf',
 ]
+
+include('/ipc/chromium/chromium-config.mozbuild')
diff --git a/security/manager/ssl/src/nsKeygenHandler.cpp b/security/manager/ssl/src/nsKeygenHandler.cpp
index f21c65c5a3f4..68cfbc5125f6 100644
--- a/security/manager/ssl/src/nsKeygenHandler.cpp
+++ b/security/manager/ssl/src/nsKeygenHandler.cpp
@@ -1,4 +1,4 @@
-/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
  *
  * This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
@@ -14,6 +14,7 @@
 #include "secasn1.h"
 #include "pk11pqg.h"
 #include "nsKeygenHandler.h"
+#include "nsKeygenHandlerContent.h"
 #include "nsIServiceManager.h"
 #include "nsIDOMHTMLSelectElement.h"
 #include "nsIContent.h"
@@ -24,6 +25,7 @@
 #include "nsITokenDialogs.h"
 #include "nsIGenKeypairInfoDlg.h"
 #include "nsNSSShutDown.h"
+#include "nsXULAppAPI.h"
 
 //These defines are taken from the PKCS#11 spec
 #define CKM_RSA_PKCS_KEY_PAIR_GEN     0x00000000
@@ -268,6 +270,11 @@ nsKeygenFormProcessor::~nsKeygenFormProcessor()
 nsresult
 nsKeygenFormProcessor::Create(nsISupports* aOuter, const nsIID& aIID, void* *aResult)
 {
+  if (GeckoProcessType_Content == XRE_GetProcessType()) {
+    nsCOMPtr contentProcessor = new nsKeygenFormProcessorContent();
+    return contentProcessor->QueryInterface(aIID, aResult);
+  }
+
   nsresult rv;
   NS_ENSURE_NO_AGGREGATION(aOuter);
   nsKeygenFormProcessor* formProc = new nsKeygenFormProcessor();
@@ -458,9 +465,11 @@ loser:
 }
 
 nsresult
-nsKeygenFormProcessor::GetPublicKey(nsAString& aValue, nsAString& aChallenge, 
-				    nsAFlatString& aKeyType,
-				    nsAString& aOutPublicKey, nsAString& aKeyParams)
+nsKeygenFormProcessor::GetPublicKey(const nsAString& aValue,
+                                    const nsAString& aChallenge,
+                                    const nsAFlatString& aKeyType,
+                                    nsAString& aOutPublicKey,
+                                    const nsAString& aKeyParams)
 {
     nsNSSShutDownPreventionLock locker;
     nsresult rv = NS_ERROR_FAILURE;
@@ -760,22 +769,20 @@ loser:
     return rv;
 }
 
-NS_METHOD 
-nsKeygenFormProcessor::ProcessValue(nsIDOMHTMLElement *aElement, 
-				    const nsAString& aName, 
-				    nsAString& aValue) 
-{ 
-    nsAutoString challengeValue;
-    nsAutoString keyTypeValue;
-    nsAutoString keyParamsValue;
-    
+// static
+void
+nsKeygenFormProcessor::ExtractParams(nsIDOMHTMLElement* aElement,
+                                     nsAString& challengeValue,
+                                     nsAString& keyTypeValue,
+                                     nsAString& keyParamsValue)
+{
     aElement->GetAttribute(NS_LITERAL_STRING("keytype"), keyTypeValue);
     if (keyTypeValue.IsEmpty()) {
         // If this field is not present, we default to rsa.
         keyTypeValue.AssignLiteral("rsa");
     }
-    
-    aElement->GetAttribute(NS_LITERAL_STRING("pqg"), 
+
+    aElement->GetAttribute(NS_LITERAL_STRING("pqg"),
                            keyParamsValue);
     /* XXX We can still support the pqg attribute in the keygen 
      * tag for backward compatibility while introducing a more 
@@ -787,17 +794,40 @@ nsKeygenFormProcessor::ProcessValue(nsIDOMHTMLElement *aElement,
     }
 
     aElement->GetAttribute(NS_LITERAL_STRING("challenge"), challengeValue);
+}
+
+nsresult
+nsKeygenFormProcessor::ProcessValue(nsIDOMHTMLElement* aElement,
+                                    const nsAString& aName,
+                                    nsAString& aValue)
+{
+    nsAutoString challengeValue;
+    nsAutoString keyTypeValue;
+    nsAutoString keyParamsValue;
+    ExtractParams(aElement, challengeValue, keyTypeValue, keyParamsValue);
 
     return GetPublicKey(aValue, challengeValue, keyTypeValue, 
                         aValue, keyParamsValue);
-} 
+}
 
-NS_METHOD nsKeygenFormProcessor::ProvideContent(const nsAString& aFormType, 
-						nsTArray& aContent, 
-						nsAString& aAttribute) 
+nsresult
+nsKeygenFormProcessor::ProcessValueIPC(const nsAString& aOldValue,
+                                       const nsAString& aChallenge,
+                                       const nsAString& aKeyType,
+                                       const nsAString& aKeyParams,
+                                       nsAString& newValue)
+{
+    return GetPublicKey(aOldValue, aChallenge, PromiseFlatString(aKeyType),
+                        newValue, aKeyParams);
+}
+
+nsresult
+nsKeygenFormProcessor::ProvideContent(const nsAString& aFormType,
+                                      nsTArray& aContent,
+                                      nsAString& aAttribute)
 { 
-  if (Compare(aFormType, NS_LITERAL_STRING("SELECT"), 
-    nsCaseInsensitiveStringComparator()) == 0) {
+  if (Compare(aFormType, NS_LITERAL_STRING("SELECT"),
+              nsCaseInsensitiveStringComparator()) == 0) {
 
     for (size_t i = 0; i < number_of_key_size_choices; ++i) {
       aContent.AppendElement(mSECKeySizeChoiceList[i].name);
diff --git a/security/manager/ssl/src/nsKeygenHandler.h b/security/manager/ssl/src/nsKeygenHandler.h
index 28757afc6ac9..c5fa7d2199f9 100644
--- a/security/manager/ssl/src/nsKeygenHandler.h
+++ b/security/manager/ssl/src/nsKeygenHandler.h
@@ -6,9 +6,9 @@
 
 #ifndef _NSKEYGENHANDLER_H_
 #define _NSKEYGENHANDLER_H_
-// Form Processor 
-#include "nsIFormProcessor.h" 
-#include "nsTArray.h" 
+// Form Processor
+#include "nsIFormProcessor.h"
+#include "nsTArray.h"
 
 nsresult GetSlotWithMechanism(uint32_t mechanism,
                               nsIInterfaceRequestor *ctx,
@@ -19,28 +19,39 @@ nsresult GetSlotWithMechanism(uint32_t mechanism,
 
 SECKEYECParams *decode_ec_params(const char *curve);
 
-class nsKeygenFormProcessor : public nsIFormProcessor { 
-public: 
-  nsKeygenFormProcessor(); 
+class nsKeygenFormProcessor : public nsIFormProcessor {
+public:
+  nsKeygenFormProcessor();
   nsresult Init();
 
-  NS_IMETHOD ProcessValue(nsIDOMHTMLElement *aElement, 
-                          const nsAString& aName, 
-                          nsAString& aValue); 
+  virtual nsresult ProcessValue(nsIDOMHTMLElement* aElement,
+                                const nsAString& aName,
+                                nsAString& aValue) MOZ_OVERRIDE;
 
-  NS_IMETHOD ProvideContent(const nsAString& aFormType, 
-                            nsTArray& aContent, 
-                            nsAString& aAttribute); 
+  virtual nsresult ProcessValueIPC(const nsAString& aOldValue,
+                                   const nsAString& aChallenge,
+                                   const nsAString& aKeyType,
+                                   const nsAString& aKeyParams,
+                                   nsAString& aNewValue) MOZ_OVERRIDE;
+
+  virtual nsresult ProvideContent(const nsAString& aFormType,
+                                  nsTArray& aContent,
+                                  nsAString& aAttribute) MOZ_OVERRIDE;
   NS_DECL_THREADSAFE_ISUPPORTS
 
   static nsresult Create(nsISupports* aOuter, const nsIID& aIID, void* *aResult);
 
+  static void ExtractParams(nsIDOMHTMLElement* aElement,
+                            nsAString& challengeValue,
+                            nsAString& keyTypeValue,
+                            nsAString& keyParamsValue);
+
 protected:
   virtual ~nsKeygenFormProcessor();
 
-  nsresult GetPublicKey(nsAString& aValue, nsAString& aChallenge, 
-			nsAFlatString& akeyType, nsAString& aOutPublicKey,
-			nsAString& aPqg);
+  nsresult GetPublicKey(const nsAString& aValue, const nsAString& aChallenge,
+                        const nsAFlatString& akeyType, nsAString& aOutPublicKey,
+                        const nsAString& aPqg);
   nsresult GetSlot(uint32_t aMechanism, PK11SlotInfo** aSlot);
 private:
   nsCOMPtr m_ctx;
diff --git a/security/manager/ssl/src/nsKeygenHandlerContent.cpp b/security/manager/ssl/src/nsKeygenHandlerContent.cpp
new file mode 100644
index 000000000000..38329e84e623
--- /dev/null
+++ b/security/manager/ssl/src/nsKeygenHandlerContent.cpp
@@ -0,0 +1,76 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
+ * vim: set ts=2 sw=2 sts=2 et tw=80:
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#include "nsKeygenHandlerContent.h"
+
+#include "nsIFormProcessor.h"
+#include "nsString.h"
+
+#include "mozilla/dom/ContentChild.h"
+#include "mozilla/unused.h"
+
+#include "keythi.h"
+#include "nss.h"
+#include "secmodt.h"
+#include "nsKeygenHandler.h"
+
+using mozilla::dom::ContentChild;
+using mozilla::unused;
+
+NS_IMPL_ISUPPORTS(nsKeygenFormProcessorContent, nsIFormProcessor)
+
+nsKeygenFormProcessorContent::nsKeygenFormProcessorContent()
+{
+}
+
+nsKeygenFormProcessorContent::~nsKeygenFormProcessorContent()
+{
+}
+
+nsresult
+nsKeygenFormProcessorContent::ProcessValue(nsIDOMHTMLElement* aElement,
+                                           const nsAString& aName,
+                                           nsAString& aValue)
+{
+  nsAutoString challengeValue;
+  nsAutoString keyTypeValue;
+  nsAutoString keyParamsValue;
+  nsKeygenFormProcessor::ExtractParams(aElement, challengeValue, keyTypeValue, keyParamsValue);
+
+  ContentChild* child = ContentChild::GetSingleton();
+
+  nsString oldValue(aValue);
+  nsString newValue;
+  unused << child->SendFormProcessValue(oldValue, challengeValue,
+                                        keyTypeValue, keyParamsValue,
+                                        &newValue);
+
+  aValue.Assign(newValue);
+  return NS_OK;
+}
+
+nsresult
+nsKeygenFormProcessorContent::ProcessValueIPC(const nsAString& aOldValue,
+                                              const nsAString& aChallenge,
+                                              const nsAString& aKeyType,
+                                              const nsAString& aKeyParams,
+                                              nsAString& aNewValue)
+{
+  MOZ_ASSERT(false, "should never be called in the child process");
+  return NS_ERROR_UNEXPECTED;
+}
+
+nsresult
+nsKeygenFormProcessorContent::ProvideContent(const nsAString& aFormType,
+                                             nsTArray& aContent,
+                                             nsAString& aAttribute)
+{
+  nsString attribute;
+  unused << ContentChild::GetSingleton()->SendFormProvideContent(&attribute, &aContent);
+  aAttribute.Assign(attribute);
+  return NS_OK;
+}
diff --git a/security/manager/ssl/src/nsKeygenHandlerContent.h b/security/manager/ssl/src/nsKeygenHandlerContent.h
new file mode 100644
index 000000000000..f49d56dd4bd4
--- /dev/null
+++ b/security/manager/ssl/src/nsKeygenHandlerContent.h
@@ -0,0 +1,42 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
+ * vim: set ts=2 sw=2 sts=2 et tw=80:
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#ifndef nsKeygenHandlerContent_h
+#define nsKeygenHandlerContent_h
+
+#include "mozilla/Attributes.h"
+#include "nsIFormProcessor.h"
+#include "nsStringFwd.h"
+#include "nsTArray.h"
+
+class nsIDOMHTMLElement;
+
+class nsKeygenFormProcessorContent MOZ_FINAL : public nsIFormProcessor {
+public:
+  nsKeygenFormProcessorContent();
+
+  virtual nsresult ProcessValue(nsIDOMHTMLElement* aElement,
+                                const nsAString& aName,
+                                nsAString& aValue) MOZ_OVERRIDE;
+
+  virtual nsresult ProcessValueIPC(const nsAString& aOldValue,
+                                   const nsAString& aChallenge,
+                                   const nsAString& aKeyType,
+                                   const nsAString& aKeyParams,
+                                   nsAString& aNewValue) MOZ_OVERRIDE;
+
+  virtual nsresult ProvideContent(const nsAString& aFormType,
+                                  nsTArray& aContent,
+                                  nsAString& aAttribute) MOZ_OVERRIDE;
+
+  NS_DECL_ISUPPORTS
+
+protected:
+  ~nsKeygenFormProcessorContent();
+};
+
+#endif // nsKeygenHandlerContent_h

From b181902fe01c4cf12f9f862baa0fc1519c2846c2 Mon Sep 17 00:00:00 2001
From: Blake Kaplan 
Date: Wed, 26 Nov 2014 14:29:52 -0800
Subject: [PATCH 30/64] Bug 948194 - Fix races related to CPOWs and tab
 switching. Original patch by Alexandru Tifrea. r=seth

---
 image/test/browser/browser.ini          |   1 -
 image/test/browser/browser_bug666317.js | 139 +++++++++++++++---------
 2 files changed, 87 insertions(+), 53 deletions(-)

diff --git a/image/test/browser/browser.ini b/image/test/browser/browser.ini
index 46f56acdb242..10bb14ea7ff4 100644
--- a/image/test/browser/browser.ini
+++ b/image/test/browser/browser.ini
@@ -8,6 +8,5 @@ support-files =
   imageX2.html
 
 [browser_bug666317.js]
-skip-if = e10s # Bug 948194 - Decoded Images seem to not be discarded on memory-pressure notification with e10s enabled
 [browser_image.js]
 skip-if = e10s || !debug # Test is only to run on debug builds
diff --git a/image/test/browser/browser_bug666317.js b/image/test/browser/browser_bug666317.js
index 15064760890e..7f592c387d8e 100644
--- a/image/test/browser/browser_bug666317.js
+++ b/image/test/browser/browser_bug666317.js
@@ -1,7 +1,9 @@
+"use strict";
+
 waitForExplicitFinish();
 
 let pageSource =
-  '' +
+  '' +
     '' +
   '';
 
@@ -10,47 +12,67 @@ let prefBranch = Cc["@mozilla.org/preferences-service;1"]
                    .getService(Ci.nsIPrefService)
                    .getBranch('image.mem.');
 
-function ImageDiscardObserver(result) {
-  this.discard = function onDiscard(request)
-  {
-    result.wasDiscarded = true;
-    this.synchronous = false;
+function imgDiscardingFrameScript() {
+  const Cc = Components.classes;
+  const Ci = Components.interfaces;
+
+  function ImageDiscardObserver(result) {
+    this.discard = function onDiscard(request) {
+      result.wasDiscarded = true;
+    }
   }
 
-  this.synchronous = true;
-}
+  function currentRequest() {
+    let img = content.document.getElementById('testImg');
+    img.QueryInterface(Ci.nsIImageLoadingContent);
+    return img.getRequest(Ci.nsIImageLoadingContent.CURRENT_REQUEST);
+  }
 
-function currentRequest() {
-  let img = gBrowser.getBrowserForTab(newTab).contentWindow
-            .document.getElementById('testImg');
-  img.QueryInterface(Ci.nsIImageLoadingContent);
-  return img.getRequest(Ci.nsIImageLoadingContent.CURRENT_REQUEST);
-}
+  function attachDiscardObserver(result) {
+    // Create the discard observer.
+    let observer = new ImageDiscardObserver(result);
+    let scriptedObserver = Cc["@mozilla.org/image/tools;1"]
+                             .getService(Ci.imgITools)
+                             .createScriptedObserver(observer);
 
-function attachDiscardObserver(result) {
-  // Create the discard observer.
-  let observer = new ImageDiscardObserver(result);
-  let scriptedObserver = Cc["@mozilla.org/image/tools;1"]
-                           .getService(Ci.imgITools)
-                           .createScriptedObserver(observer);
+    // Clone the current imgIRequest with our new observer.
+    let request = currentRequest();
+    return [ request.clone(scriptedObserver), scriptedObserver ];
+  }
 
-  // Clone the current imgIRequest with our new observer.
-  let request = currentRequest();
-  return request.clone(scriptedObserver);
-}
+  // Attach a discard listener and create a place to hold the result.
+  var result = { wasDiscarded: false };
+  var scriptedObserver;
+  var clonedRequest;
 
-function isImgDecoded() {
-  let request = currentRequest();
-  return request.imageStatus & Ci.imgIRequest.STATUS_FRAME_COMPLETE ? true : false;
-}
+  addMessageListener("test666317:testPart1", function(message) {
+    // Ensure that the image is decoded by drawing it to a canvas.
+    let doc = content.document;
+    let img = doc.getElementById('testImg');
+    let canvas = doc.createElement('canvas');
+    let ctx = canvas.getContext('2d');
+    ctx.drawImage(img, 0, 0);
 
-// Ensure that the image is decoded by drawing it to a canvas.
-function forceDecodeImg() {
-  let doc = gBrowser.getBrowserForTab(newTab).contentWindow.document;
-  let img = doc.getElementById('testImg');
-  let canvas = doc.createElement('canvas');
-  let ctx = canvas.getContext('2d');
-  ctx.drawImage(img, 0, 0);
+    // Verify that we decoded the image.
+    // Note: We grab a reference to the scripted observer because the image
+    // holds a weak ref to it. If we don't hold a strong reference, we might
+    // end up using a deleted pointer.
+    [ clonedRequest, scriptedObserver ] = attachDiscardObserver(result)
+    let decoded = clonedRequest.imageStatus & Ci.imgIRequest.STATUS_FRAME_COMPLETE ? true : false;
+
+    message.target.sendAsyncMessage("test666317:testPart1:Answer",
+                                    { decoded });
+  });
+
+  addMessageListener("test666317:wasImgDiscarded", function(message) {
+    let discarded = result.wasDiscarded;
+
+    // NOTE: We know that this is the last test.
+    clonedRequest.cancelAndForgetObserver(0);
+    scriptedObserver = null;
+    message.target.sendAsyncMessage("test666317:wasImgDiscarded:Answer",
+                                    { discarded });
+  });
 }
 
 function test() {
@@ -69,25 +91,38 @@ function test() {
 }
 
 function step2() {
-  // Attach a discard listener and create a place to hold the result.
-  var result = { wasDiscarded: false };
-  var clonedRequest = attachDiscardObserver(result);
+  let mm = gBrowser.getBrowserForTab(newTab).QueryInterface(Ci.nsIFrameLoaderOwner)
+           .frameLoader.messageManager;
+  mm.loadFrameScript("data:,(" + escape(imgDiscardingFrameScript.toString()) + ")();", false);
 
   // Check that the image is decoded.
-  forceDecodeImg();
-  ok(isImgDecoded(), 'Image should initially be decoded.');
+  mm.addMessageListener("test666317:testPart1:Answer", function(message) {
+    let decoded = message.data.decoded;
+    ok(decoded, 'Image should initially be decoded.');
 
-  // Focus the old tab, then fire a memory-pressure notification.  This should
-  // cause the decoded image in the new tab to be discarded.
-  gBrowser.selectedTab = oldTab;
-  var os = Cc["@mozilla.org/observer-service;1"]
-             .getService(Ci.nsIObserverService);
-  os.notifyObservers(null, 'memory-pressure', 'heap-minimize');
-  ok(result.wasDiscarded, 'Image should be discarded.');
+    // Focus the old tab, then fire a memory-pressure notification.  This should
+    // cause the decoded image in the new tab to be discarded.
+    gBrowser.selectedTab = oldTab;
+    waitForFocus(() => {
+      var os = Cc["@mozilla.org/observer-service;1"]
+                 .getService(Ci.nsIObserverService);
 
-  // And we're done.
-  gBrowser.removeTab(newTab);
-  prefBranch.setBoolPref('discardable', oldDiscardingPref);
-  clonedRequest.cancelAndForgetObserver(0);
-  finish();
+      os.notifyObservers(null, 'memory-pressure', 'heap-minimize');
+
+      // Now ask if it was.
+      mm.sendAsyncMessage("test666317:wasImgDiscarded");
+    }, oldTab.contentWindow);
+  });
+
+  mm.addMessageListener("test666317:wasImgDiscarded:Answer", function(message) {
+    let discarded = message.data.discarded;
+    ok(discarded, 'Image should be discarded.');
+
+    // And we're done.
+    gBrowser.removeTab(newTab);
+    prefBranch.setBoolPref('discardable', oldDiscardingPref);
+    finish();
+  });
+
+  mm.sendAsyncMessage("test666317:testPart1");
 }

From 334bec207ca8cb5a78bf1010234c85aa1cea0101 Mon Sep 17 00:00:00 2001
From: Matt Woodrow 
Date: Wed, 26 Nov 2014 18:00:31 +1300
Subject: [PATCH 31/64] Bug 1102666 - Parse the edts block in MoofParser and
 offset composition time accordingly. r=ajones

---
 media/libstagefright/binding/DecoderData.cpp  |  5 +-
 media/libstagefright/binding/MoofParser.cpp   | 49 ++++++++++++---
 .../binding/include/mp4_demuxer/ByteReader.h  | 10 +++
 .../binding/include/mp4_demuxer/DecoderData.h |  5 +-
 .../binding/include/mp4_demuxer/MoofParser.h  | 16 ++++-
 media/libstagefright/binding/mp4_demuxer.cpp  |  4 +-
 .../av/include/media/stagefright/MetaData.h   |  1 +
 .../media/libstagefright/MPEG4Extractor.cpp   | 61 ++++++++++++-------
 .../libstagefright/include/MPEG4Extractor.h   |  7 +++
 9 files changed, 120 insertions(+), 38 deletions(-)

diff --git a/media/libstagefright/binding/DecoderData.cpp b/media/libstagefright/binding/DecoderData.cpp
index ae6ac214c96a..2333d54beff3 100644
--- a/media/libstagefright/binding/DecoderData.cpp
+++ b/media/libstagefright/binding/DecoderData.cpp
@@ -131,6 +131,7 @@ TrackConfig::Update(sp& aMetaData, const char* aMimeType)
   // aMimeType points to a string from MediaDefs.cpp so we don't need to copy it
   mime_type = aMimeType;
   duration = FindInt64(aMetaData, kKeyDuration);
+  media_time = FindInt64(aMetaData, kKeyMediaTime);
   mTrackId = FindInt32(aMetaData, kKeyTrackID);
   crypto.Update(aMetaData);
 }
@@ -215,11 +216,11 @@ MP4Sample::~MP4Sample()
 }
 
 void
-MP4Sample::Update()
+MP4Sample::Update(int64_t& aMediaTime)
 {
   sp m = mMediaBuffer->meta_data();
   decode_timestamp = FindInt64(m, kKeyDecodingTime);
-  composition_timestamp = FindInt64(m, kKeyTime);
+  composition_timestamp = FindInt64(m, kKeyTime) - aMediaTime;
   duration = FindInt64(m, kKeyDuration);
   byte_offset = FindInt64(m, kKey64BitFileOffset);
   is_sync_point = FindInt32(m, kKeyIsSyncFrame);
diff --git a/media/libstagefright/binding/MoofParser.cpp b/media/libstagefright/binding/MoofParser.cpp
index f8243abd73f7..70ec122bcd0b 100644
--- a/media/libstagefright/binding/MoofParser.cpp
+++ b/media/libstagefright/binding/MoofParser.cpp
@@ -22,7 +22,7 @@ MoofParser::RebuildFragmentedIndex(const nsTArray& aByteRanges)
       mInitRange = MediaByteRange(0, box.Range().mEnd);
       ParseMoov(box);
     } else if (box.IsType("moof")) {
-      Moof moof(box, mTrex, mMdhd);
+      Moof moof(box, mTrex, mMdhd, mEdts);
 
       if (!mMoofs.IsEmpty()) {
         // Stitch time ranges together in the case of a (hopefully small) time
@@ -81,6 +81,8 @@ MoofParser::ParseTrak(Box& aBox)
       if (!mTrex.mTrackId || tkhd.mTrackId == mTrex.mTrackId) {
         ParseMdia(box, tkhd);
       }
+    } else if (box.IsType("edts")) {
+      mEdts = Edts(box);
     }
   }
 }
@@ -108,18 +110,18 @@ MoofParser::ParseMvex(Box& aBox)
   }
 }
 
-Moof::Moof(Box& aBox, Trex& aTrex, Mdhd& aMdhd) :
+Moof::Moof(Box& aBox, Trex& aTrex, Mdhd& aMdhd, Edts& aEdts) :
     mRange(aBox.Range()), mMaxRoundingError(0)
 {
   for (Box box = aBox.FirstChild(); box.IsAvailable(); box = box.Next()) {
     if (box.IsType("traf")) {
-      ParseTraf(box, aTrex, aMdhd);
+      ParseTraf(box, aTrex, aMdhd, aEdts);
     }
   }
 }
 
 void
-Moof::ParseTraf(Box& aBox, Trex& aTrex, Mdhd& aMdhd)
+Moof::ParseTraf(Box& aBox, Trex& aTrex, Mdhd& aMdhd, Edts& aEdts)
 {
   Tfhd tfhd(aTrex);
   Tfdt tfdt;
@@ -132,7 +134,7 @@ Moof::ParseTraf(Box& aBox, Trex& aTrex, Mdhd& aMdhd)
       }
     } else if (box.IsType("trun")) {
       if (!aTrex.mTrackId || tfhd.mTrackId == aTrex.mTrackId) {
-        ParseTrun(box, tfhd, tfdt, aMdhd);
+        ParseTrun(box, tfhd, tfdt, aMdhd, aEdts);
       }
     }
   }
@@ -161,7 +163,7 @@ public:
 };
 
 void
-Moof::ParseTrun(Box& aBox, Tfhd& aTfhd, Tfdt& aTfdt, Mdhd& aMdhd)
+Moof::ParseTrun(Box& aBox, Tfhd& aTfhd, Tfdt& aTfdt, Mdhd& aMdhd, Edts& aEdts)
 {
   if (!aMdhd.mTimescale) {
     return;
@@ -209,8 +211,8 @@ Moof::ParseTrun(Box& aBox, Tfhd& aTfhd, Tfdt& aTfdt, Mdhd& aMdhd)
     offset += sampleSize;
 
     sample.mCompositionRange = Interval(
-      aMdhd.ToMicroseconds(decodeTime + ctsOffset),
-      aMdhd.ToMicroseconds(decodeTime + ctsOffset + sampleDuration));
+      aMdhd.ToMicroseconds(decodeTime + ctsOffset - aEdts.mMediaStart),
+      aMdhd.ToMicroseconds(decodeTime + ctsOffset + sampleDuration - aEdts.mMediaStart));
     decodeTime += sampleDuration;
 
     sample.mSync = !(sampleFlags & 0x1010000);
@@ -328,4 +330,35 @@ Tfdt::Tfdt(Box& aBox)
   }
   reader->DiscardRemaining();
 }
+
+Edts::Edts(Box& aBox)
+  : mMediaStart(0)
+{
+  Box child = aBox.FirstChild();
+  if (!child.IsType("elst")) {
+    return;
+  }
+
+  BoxReader reader(child);
+  uint32_t flags = reader->ReadU32();
+  uint8_t version = flags >> 24;
+
+  uint32_t entryCount = reader->ReadU32();
+  NS_ASSERTION(entryCount == 1, "Can't handle videos with multiple edits");
+  if (entryCount != 1) {
+    reader->DiscardRemaining();
+    return;
+  }
+
+  uint64_t segment_duration;
+  if (version == 1) {
+    segment_duration = reader->ReadU64();
+    mMediaStart = reader->Read64();
+  } else {
+    segment_duration = reader->ReadU32();
+    mMediaStart = reader->Read32();
+  }
+  NS_ASSERTION(segment_duration == 0, "Can't handle edits with fixed durations");
+  reader->DiscardRemaining();
+}
 }
diff --git a/media/libstagefright/binding/include/mp4_demuxer/ByteReader.h b/media/libstagefright/binding/include/mp4_demuxer/ByteReader.h
index 297b379c607f..51abd517dc1d 100644
--- a/media/libstagefright/binding/include/mp4_demuxer/ByteReader.h
+++ b/media/libstagefright/binding/include/mp4_demuxer/ByteReader.h
@@ -96,6 +96,16 @@ public:
     return mozilla::BigEndian::readUint64(ptr);
   }
 
+  int64_t Read64()
+  {
+    auto ptr = Read(8);
+    if (!ptr) {
+      MOZ_ASSERT(false);
+      return 0;
+    }
+    return mozilla::BigEndian::readInt64(ptr);
+  }
+
   const uint8_t* Read(size_t aCount)
   {
     if (aCount > mRemaining) {
diff --git a/media/libstagefright/binding/include/mp4_demuxer/DecoderData.h b/media/libstagefright/binding/include/mp4_demuxer/DecoderData.h
index 1c0823b473f0..7ed3cf6d2a96 100644
--- a/media/libstagefright/binding/include/mp4_demuxer/DecoderData.h
+++ b/media/libstagefright/binding/include/mp4_demuxer/DecoderData.h
@@ -78,10 +78,11 @@ public:
 class TrackConfig
 {
 public:
-  TrackConfig() : mime_type(nullptr), mTrackId(0), duration(0) {}
+  TrackConfig() : mime_type(nullptr), mTrackId(0), duration(0), media_time(0) {}
   const char* mime_type;
   uint32_t mTrackId;
   int64_t duration;
+  int64_t media_time;
   CryptoTrack crypto;
 
   void Update(stagefright::sp& aMetaData,
@@ -144,7 +145,7 @@ class MP4Sample
 public:
   MP4Sample();
   ~MP4Sample();
-  void Update();
+  void Update(int64_t& aMediaTime);
   void Pad(size_t aPaddingBytes);
 
   stagefright::MediaBuffer* mMediaBuffer;
diff --git a/media/libstagefright/binding/include/mp4_demuxer/MoofParser.h b/media/libstagefright/binding/include/mp4_demuxer/MoofParser.h
index 629c0750ef6f..f4f175762fc8 100644
--- a/media/libstagefright/binding/include/mp4_demuxer/MoofParser.h
+++ b/media/libstagefright/binding/include/mp4_demuxer/MoofParser.h
@@ -96,6 +96,15 @@ public:
   uint64_t mBaseMediaDecodeTime;
 };
 
+class Edts
+{
+public:
+  Edts() : mMediaStart(0) {}
+  explicit Edts(Box& aBox);
+
+  int64_t mMediaStart;
+};
+
 struct Sample
 {
   mozilla::MediaByteRange mByteRange;
@@ -106,7 +115,7 @@ struct Sample
 class Moof
 {
 public:
-  Moof(Box& aBox, Trex& aTrex, Mdhd& aMdhd);
+  Moof(Box& aBox, Trex& aTrex, Mdhd& aMdhd, Edts& aEdts);
   void FixRounding(const Moof& aMoof);
 
   mozilla::MediaByteRange mRange;
@@ -115,8 +124,8 @@ public:
   nsTArray mIndex;
 
 private:
-  void ParseTraf(Box& aBox, Trex& aTrex, Mdhd& aMdhd);
-  void ParseTrun(Box& aBox, Tfhd& aTfhd, Tfdt& aTfdt, Mdhd& aMdhd);
+  void ParseTraf(Box& aBox, Trex& aTrex, Mdhd& aMdhd, Edts& aEdts);
+  void ParseTrun(Box& aBox, Tfhd& aTfhd, Tfdt& aTfdt, Mdhd& aMdhd, Edts& aEdts);
   uint64_t mMaxRoundingError;
 };
 
@@ -146,6 +155,7 @@ public:
   Mdhd mMdhd;
   Trex mTrex;
   Tfdt mTfdt;
+  Edts mEdts;
   nsTArray mMoofs;
 };
 }
diff --git a/media/libstagefright/binding/mp4_demuxer.cpp b/media/libstagefright/binding/mp4_demuxer.cpp
index 787509aed6dc..3a4e135673b8 100644
--- a/media/libstagefright/binding/mp4_demuxer.cpp
+++ b/media/libstagefright/binding/mp4_demuxer.cpp
@@ -173,7 +173,7 @@ MP4Demuxer::DemuxAudioSample()
     return nullptr;
   }
 
-  sample->Update();
+  sample->Update(mAudioConfig.media_time);
 
   return sample.forget();
 }
@@ -190,7 +190,7 @@ MP4Demuxer::DemuxVideoSample()
     return nullptr;
   }
 
-  sample->Update();
+  sample->Update(mVideoConfig.media_time);
   sample->prefix_data = mVideoConfig.annex_b;
 
   return sample.forget();
diff --git a/media/libstagefright/frameworks/av/include/media/stagefright/MetaData.h b/media/libstagefright/frameworks/av/include/media/stagefright/MetaData.h
index 30b40c8dfcd4..9c78a6948b3a 100644
--- a/media/libstagefright/frameworks/av/include/media/stagefright/MetaData.h
+++ b/media/libstagefright/frameworks/av/include/media/stagefright/MetaData.h
@@ -77,6 +77,7 @@ enum {
     kKeyIsDRM             = 'idrm',  // int32_t (bool)
     kKeyEncoderDelay      = 'encd',  // int32_t (frames)
     kKeyEncoderPadding    = 'encp',  // int32_t (frames)
+    kKeyMediaTime         = 'mtme',  // int64_t (usecs)
 
     kKeyAlbum             = 'albu',  // cstring
     kKeyArtist            = 'arti',  // cstring
diff --git a/media/libstagefright/frameworks/av/media/libstagefright/MPEG4Extractor.cpp b/media/libstagefright/frameworks/av/media/libstagefright/MPEG4Extractor.cpp
index a8417e8d5543..59613391300a 100644
--- a/media/libstagefright/frameworks/av/media/libstagefright/MPEG4Extractor.cpp
+++ b/media/libstagefright/frameworks/av/media/libstagefright/MPEG4Extractor.cpp
@@ -838,6 +838,8 @@ status_t MPEG4Extractor::parseChunk(off64_t *offset, int depth) {
                 track->includes_expensive_metadata = false;
                 track->skipTrack = false;
                 track->timescale = 0;
+                track->segment_duration = 0;
+                track->media_time = 0;
                 track->meta->setCString(kKeyMIMEType, "application/octet-stream");
             }
 
@@ -910,12 +912,10 @@ status_t MPEG4Extractor::parseChunk(off64_t *offset, int depth) {
                 ALOGW("ignoring edit list because timescale is 0");
             } else {
                 off64_t entriesoffset = data_offset + 8;
-                uint64_t segment_duration;
-                int64_t media_time;
 
                 if (version == 1) {
-                    if (!mDataSource->getUInt64(entriesoffset, &segment_duration) ||
-                            !mDataSource->getUInt64(entriesoffset + 8, (uint64_t*)&media_time)) {
+                    if (!mDataSource->getUInt64(entriesoffset, &mLastTrack->segment_duration) ||
+                            !mDataSource->getUInt64(entriesoffset + 8, (uint64_t*)&mLastTrack->media_time)) {
                         return ERROR_IO;
                     }
                 } else if (version == 0) {
@@ -925,28 +925,14 @@ status_t MPEG4Extractor::parseChunk(off64_t *offset, int depth) {
                             !mDataSource->getUInt32(entriesoffset + 4, (uint32_t*)&mt)) {
                         return ERROR_IO;
                     }
-                    segment_duration = sd;
-                    media_time = mt;
+                    mLastTrack->segment_duration = sd;
+                    mLastTrack->media_time = mt;
                 } else {
                     return ERROR_IO;
                 }
 
-                uint64_t halfscale = mHeaderTimescale / 2;
-                segment_duration = (segment_duration * 1000000 + halfscale)/ mHeaderTimescale;
-                media_time = (media_time * 1000000 + halfscale) / mHeaderTimescale;
+                storeEditList();
 
-                int64_t duration;
-                int32_t samplerate;
-                if (mLastTrack->meta->findInt64(kKeyDuration, &duration) &&
-                        mLastTrack->meta->findInt32(kKeySampleRate, &samplerate)) {
-
-                    int64_t delay = (media_time  * samplerate + 500000) / 1000000;
-                    mLastTrack->meta->setInt32(kKeyEncoderDelay, delay);
-
-                    int64_t paddingus = duration - (segment_duration + media_time);
-                    int64_t paddingsamples = (paddingus * samplerate + 500000) / 1000000;
-                    mLastTrack->meta->setInt32(kKeyEncoderPadding, paddingsamples);
-                }
             }
             *offset += chunk_size;
             break;
@@ -1115,6 +1101,10 @@ status_t MPEG4Extractor::parseChunk(off64_t *offset, int depth) {
 
             mLastTrack->timescale = ntohl(timescale);
 
+            // Now that we've parsed the media timescale, we can interpret
+            // the edit list data.
+            storeEditList();
+
             int64_t duration = 0;
             if (version == 1) {
                 if (mDataSource->readAt(
@@ -1812,6 +1802,35 @@ status_t MPEG4Extractor::parseChunk(off64_t *offset, int depth) {
     return OK;
 }
 
+void MPEG4Extractor::storeEditList()
+{
+  if (mHeaderTimescale == 0 ||
+      mLastTrack->timescale == 0) {
+    return;
+  }
+
+  uint64_t segment_duration = (mLastTrack->segment_duration * 1000000)/ mHeaderTimescale;
+  // media_time is measured in media time scale units.
+  int64_t media_time = (mLastTrack->media_time * 1000000) / mLastTrack->timescale;
+
+  if (segment_duration == 0) {
+    mLastTrack->meta->setInt64(kKeyMediaTime, media_time);
+  }
+
+  int64_t duration;
+  int32_t samplerate;
+  if (mLastTrack->meta->findInt64(kKeyDuration, &duration) &&
+      mLastTrack->meta->findInt32(kKeySampleRate, &samplerate)) {
+
+    int64_t delay = (media_time  * samplerate + 500000) / 1000000;
+    mLastTrack->meta->setInt32(kKeyEncoderDelay, delay);
+
+    int64_t paddingus = duration - (segment_duration + media_time);
+    int64_t paddingsamples = (paddingus * samplerate + 500000) / 1000000;
+    mLastTrack->meta->setInt32(kKeyEncoderPadding, paddingsamples);
+  }
+}
+
 status_t MPEG4Extractor::parseSegmentIndex(off64_t offset, size_t size) {
   ALOGV("MPEG4Extractor::parseSegmentIndex");
 
diff --git a/media/libstagefright/frameworks/av/media/libstagefright/include/MPEG4Extractor.h b/media/libstagefright/frameworks/av/media/libstagefright/include/MPEG4Extractor.h
index 113152b1d8d9..9fcb99f20063 100644
--- a/media/libstagefright/frameworks/av/media/libstagefright/include/MPEG4Extractor.h
+++ b/media/libstagefright/frameworks/av/media/libstagefright/include/MPEG4Extractor.h
@@ -86,6 +86,11 @@ private:
         Track *next;
         sp meta;
         uint32_t timescale;
+        // Temporary storage for elst until we've
+        // parsed mdhd and can interpret them.
+        uint64_t segment_duration;
+        int64_t media_time;
+
         sp sampleTable;
         bool includes_expensive_metadata;
         bool skipTrack;
@@ -141,6 +146,8 @@ private:
 
     status_t parseSegmentIndex(off64_t data_offset, size_t data_size);
 
+    void storeEditList();
+
     Track *findTrackByMimePrefix(const char *mimePrefix);
 
     MPEG4Extractor(const MPEG4Extractor &);

From e20a2085ced1f5aa9222cd236b21a6d1f3bf965e Mon Sep 17 00:00:00 2001
From: Ryan VanderMeulen 
Date: Wed, 26 Nov 2014 17:40:42 -0500
Subject: [PATCH 32/64] Backed out changeset e82170d665d8 (bug 1087944)

---
 .../test/test_OfflineAudioContext.html        | 36 ++++---------------
 1 file changed, 6 insertions(+), 30 deletions(-)

diff --git a/dom/media/webaudio/test/test_OfflineAudioContext.html b/dom/media/webaudio/test/test_OfflineAudioContext.html
index ff4e18766239..4fb5d7da141f 100644
--- a/dom/media/webaudio/test/test_OfflineAudioContext.html
+++ b/dom/media/webaudio/test/test_OfflineAudioContext.html
@@ -10,17 +10,6 @@
 
 

From 63636768a1a5466d73cc084388ebadc20601dd90 Mon Sep 17 00:00:00 2001
From: Ryan VanderMeulen 
Date: Wed, 26 Nov 2014 17:40:52 -0500
Subject: [PATCH 33/64] Backed out changeset 6dad5fe1d22b (bug 1087944) for
 Linux64 mochitest-e10s orange.

---
 dom/media/webaudio/AudioContext.cpp         | 10 ++---
 dom/media/webaudio/AudioContext.h           |  2 +-
 dom/media/webaudio/AudioDestinationNode.cpp | 46 +++------------------
 dom/media/webaudio/AudioDestinationNode.h   |  4 +-
 dom/webidl/OfflineAudioContext.webidl       |  2 +-
 5 files changed, 12 insertions(+), 52 deletions(-)

diff --git a/dom/media/webaudio/AudioContext.cpp b/dom/media/webaudio/AudioContext.cpp
index 8dd4f5cf6c3b..8f348b242bb7 100644
--- a/dom/media/webaudio/AudioContext.cpp
+++ b/dom/media/webaudio/AudioContext.cpp
@@ -632,21 +632,17 @@ AudioContext::GetGlobalJSObject() const
   return parentObject->GetGlobalJSObject();
 }
 
-already_AddRefed
+void
 AudioContext::StartRendering(ErrorResult& aRv)
 {
-  nsCOMPtr parentObject = do_QueryInterface(GetParentObject());
-
   MOZ_ASSERT(mIsOffline, "This should only be called on OfflineAudioContext");
   if (mIsStarted) {
     aRv.Throw(NS_ERROR_DOM_INVALID_STATE_ERR);
-    return nullptr;
+    return;
   }
 
   mIsStarted = true;
-  nsRefPtr promise = Promise::Create(parentObject, aRv);
-  mDestination->StartRendering(promise);
-  return promise.forget();
+  mDestination->StartRendering();
 }
 
 void
diff --git a/dom/media/webaudio/AudioContext.h b/dom/media/webaudio/AudioContext.h
index 2b1ba5e7174e..c34f2dac0324 100644
--- a/dom/media/webaudio/AudioContext.h
+++ b/dom/media/webaudio/AudioContext.h
@@ -191,7 +191,7 @@ public:
                   const Optional >& aFailureCallback);
 
   // OfflineAudioContext methods
-  already_AddRefed StartRendering(ErrorResult& aRv);
+  void StartRendering(ErrorResult& aRv);
   IMPL_EVENT_HANDLER(complete)
 
   bool IsOffline() const { return mIsOffline; }
diff --git a/dom/media/webaudio/AudioDestinationNode.cpp b/dom/media/webaudio/AudioDestinationNode.cpp
index c0dd1d31f74c..7c6f3bbbf8d6 100644
--- a/dom/media/webaudio/AudioDestinationNode.cpp
+++ b/dom/media/webaudio/AudioDestinationNode.cpp
@@ -22,7 +22,6 @@
 #include "nsServiceManagerUtils.h"
 #include "nsIAppShell.h"
 #include "nsWidgetsCID.h"
-#include "mozilla/dom/Promise.h"
 
 namespace mozilla {
 namespace dom {
@@ -127,28 +126,6 @@ public:
     }
   }
 
-  class OnCompleteTask MOZ_FINAL : public nsRunnable
-  {
-  public:
-    OnCompleteTask(AudioContext* aAudioContext, AudioBuffer* aRenderedBuffer)
-      : mAudioContext(aAudioContext)
-      , mRenderedBuffer(aRenderedBuffer)
-    {}
-
-    NS_IMETHOD Run()
-    {
-      nsRefPtr event =
-          new OfflineAudioCompletionEvent(mAudioContext, nullptr, nullptr);
-      event->InitEvent(mRenderedBuffer);
-      mAudioContext->DispatchTrustedEvent(event);
-
-      return NS_OK;
-    }
-  private:
-    nsRefPtr mAudioContext;
-    nsRefPtr mRenderedBuffer;
-  };
-
   void FireOfflineCompletionEvent(AudioDestinationNode* aNode)
   {
     AudioContext* context = aNode->Context();
@@ -175,11 +152,10 @@ public:
       renderedBuffer->SetRawChannelContents(i, mInputChannels[i]);
     }
 
-    aNode->ResolvePromise(renderedBuffer);
-
-    nsRefPtr task =
-      new OnCompleteTask(context, renderedBuffer);
-    NS_DispatchToMainThread(task);
+    nsRefPtr event =
+        new OfflineAudioCompletionEvent(context, nullptr, nullptr);
+    event->InitEvent(renderedBuffer);
+    context->DispatchTrustedEvent(event);
   }
 
   virtual size_t SizeOfExcludingThis(MallocSizeOf aMallocSizeOf) const MOZ_OVERRIDE
@@ -325,8 +301,7 @@ private:
 NS_IMPL_ISUPPORTS(EventProxyHandler, nsIDOMEventListener)
 
 NS_IMPL_CYCLE_COLLECTION_INHERITED(AudioDestinationNode, AudioNode,
-                                   mAudioChannelAgent, mEventProxyHelper,
-                                   mOfflineRenderingPromise)
+                                   mAudioChannelAgent, mEventProxyHelper)
 
 NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION_INHERITED(AudioDestinationNode)
   NS_INTERFACE_MAP_ENTRY(nsIDOMEventListener)
@@ -440,14 +415,6 @@ AudioDestinationNode::FireOfflineCompletionEvent()
   engine->FireOfflineCompletionEvent(this);
 }
 
-void
-AudioDestinationNode::ResolvePromise(AudioBuffer* aRenderedBuffer)
-{
-  MOZ_ASSERT(NS_IsMainThread());
-  MOZ_ASSERT(mIsOffline);
-  mOfflineRenderingPromise->MaybeResolve(aRenderedBuffer);
-}
-
 uint32_t
 AudioDestinationNode::MaxChannelCount() const
 {
@@ -496,9 +463,8 @@ AudioDestinationNode::WrapObject(JSContext* aCx)
 }
 
 void
-AudioDestinationNode::StartRendering(Promise* aPromise)
+AudioDestinationNode::StartRendering()
 {
-  mOfflineRenderingPromise = aPromise;
   mOfflineRenderingRef.Take(this);
   mStream->Graph()->StartNonRealtimeProcessing(mFramesToProduce);
 }
diff --git a/dom/media/webaudio/AudioDestinationNode.h b/dom/media/webaudio/AudioDestinationNode.h
index c893b0f8339c..478abc8f2c2b 100644
--- a/dom/media/webaudio/AudioDestinationNode.h
+++ b/dom/media/webaudio/AudioDestinationNode.h
@@ -54,7 +54,7 @@ public:
   void Mute();
   void Unmute();
 
-  void StartRendering(Promise* aPromise);
+  void StartRendering();
 
   void OfflineShutdown();
 
@@ -85,7 +85,6 @@ public:
   virtual size_t SizeOfIncludingThis(MallocSizeOf aMallocSizeOf) const MOZ_OVERRIDE;
 
   void InputMuted(bool aInputMuted);
-  void ResolvePromise(AudioBuffer* aRenderedBuffer);
 
 protected:
   virtual ~AudioDestinationNode();
@@ -104,7 +103,6 @@ private:
   nsCOMPtr mAudioChannelAgent;
 
   nsRefPtr mEventProxyHelper;
-  nsRefPtr mOfflineRenderingPromise;
 
   // Audio Channel Type.
   AudioChannel mAudioChannel;
diff --git a/dom/webidl/OfflineAudioContext.webidl b/dom/webidl/OfflineAudioContext.webidl
index 7e6ebeb00d6e..d987370cfbe8 100644
--- a/dom/webidl/OfflineAudioContext.webidl
+++ b/dom/webidl/OfflineAudioContext.webidl
@@ -16,7 +16,7 @@ callback OfflineRenderSuccessCallback = void (AudioBuffer renderedData);
 interface OfflineAudioContext : AudioContext {
 
     [Throws]
-    Promise startRendering();
+    void startRendering();
 
     attribute EventHandler oncomplete;
 

From ca7c8c9e8269b6c236a88b0e40b1c43e8d99ea93 Mon Sep 17 00:00:00 2001
From: Eric Faust 
Date: Wed, 26 Nov 2014 14:42:51 -0800
Subject: [PATCH 34/64] Bug 1101905 - Part -1: Clean up emitting JSOP_DELNAME.
 (r=Waldo)

---
 js/src/frontend/BytecodeEmitter.cpp | 10 ++--------
 1 file changed, 2 insertions(+), 8 deletions(-)

diff --git a/js/src/frontend/BytecodeEmitter.cpp b/js/src/frontend/BytecodeEmitter.cpp
index bbdf7554ed10..9b7a244130b2 100644
--- a/js/src/frontend/BytecodeEmitter.cpp
+++ b/js/src/frontend/BytecodeEmitter.cpp
@@ -5891,14 +5891,8 @@ EmitDelete(ExclusiveContext *cx, BytecodeEmitter *bce, ParseNode *pn)
       {
         if (!BindNameToSlot(cx, bce, pn2))
             return false;
-        JSOp op = pn2->getOp();
-        if (op == JSOP_FALSE) {
-            if (Emit1(cx, bce, op) < 0)
-                return false;
-        } else {
-            if (!EmitAtomOp(cx, pn2, op, bce))
-                return false;
-        }
+        if (!EmitAtomOp(cx, pn2, pn2->getOp(), bce))
+            return false;
         break;
       }
       case PNK_DOT:

From 21594e671ade7ef0c349d5b636b1f31399f35cc6 Mon Sep 17 00:00:00 2001
From: Eric Faust 
Date: Wed, 26 Nov 2014 14:42:51 -0800
Subject: [PATCH 35/64] Bug 1101905 - Part 0: Add general machinery for testing
 strict opcodes. (r=Waldo)

---
 js/src/frontend/BytecodeEmitter.cpp | 19 +++++++++++++++++++
 js/src/jsopcode.h                   | 18 ++++++++++++++++--
 2 files changed, 35 insertions(+), 2 deletions(-)

diff --git a/js/src/frontend/BytecodeEmitter.cpp b/js/src/frontend/BytecodeEmitter.cpp
index 9b7a244130b2..51856a05bcaa 100644
--- a/js/src/frontend/BytecodeEmitter.cpp
+++ b/js/src/frontend/BytecodeEmitter.cpp
@@ -238,9 +238,22 @@ UpdateDepth(ExclusiveContext *cx, BytecodeEmitter *bce, ptrdiff_t target)
         bce->maxStackDepth = bce->stackDepth;
 }
 
+#ifdef DEBUG
+static bool
+CheckStrictOrSloppy(BytecodeEmitter *bce, JSOp op)
+{
+    if (IsCheckStrictOp(op) && !bce->sc->strict)
+        return false;
+    if (IsCheckSloppyOp(op) && bce->sc->strict)
+        return false;
+    return true;
+}
+#endif
+
 ptrdiff_t
 frontend::Emit1(ExclusiveContext *cx, BytecodeEmitter *bce, JSOp op)
 {
+    MOZ_ASSERT(CheckStrictOrSloppy(bce, op));
     ptrdiff_t offset = EmitCheck(cx, bce, 1);
     if (offset < 0)
         return -1;
@@ -254,6 +267,7 @@ frontend::Emit1(ExclusiveContext *cx, BytecodeEmitter *bce, JSOp op)
 ptrdiff_t
 frontend::Emit2(ExclusiveContext *cx, BytecodeEmitter *bce, JSOp op, jsbytecode op1)
 {
+    MOZ_ASSERT(CheckStrictOrSloppy(bce, op));
     ptrdiff_t offset = EmitCheck(cx, bce, 2);
     if (offset < 0)
         return -1;
@@ -269,6 +283,8 @@ ptrdiff_t
 frontend::Emit3(ExclusiveContext *cx, BytecodeEmitter *bce, JSOp op, jsbytecode op1,
                 jsbytecode op2)
 {
+    MOZ_ASSERT(CheckStrictOrSloppy(bce, op));
+
     /* These should filter through EmitVarOp. */
     MOZ_ASSERT(!IsArgOp(op));
     MOZ_ASSERT(!IsLocalOp(op));
@@ -288,6 +304,7 @@ frontend::Emit3(ExclusiveContext *cx, BytecodeEmitter *bce, JSOp op, jsbytecode
 ptrdiff_t
 frontend::EmitN(ExclusiveContext *cx, BytecodeEmitter *bce, JSOp op, size_t extra)
 {
+    MOZ_ASSERT(CheckStrictOrSloppy(bce, op));
     ptrdiff_t length = 1 + (ptrdiff_t)extra;
     ptrdiff_t offset = EmitCheck(cx, bce, length);
     if (offset < 0)
@@ -1019,6 +1036,7 @@ LeaveNestedScope(ExclusiveContext *cx, BytecodeEmitter *bce, StmtInfoBCE *stmt)
 static bool
 EmitIndex32(ExclusiveContext *cx, JSOp op, uint32_t index, BytecodeEmitter *bce)
 {
+    MOZ_ASSERT(CheckStrictOrSloppy(bce, op));
     const size_t len = 1 + UINT32_INDEX_LEN;
     MOZ_ASSERT(len == size_t(js_CodeSpec[op].length));
     ptrdiff_t offset = EmitCheck(cx, bce, len);
@@ -1036,6 +1054,7 @@ EmitIndex32(ExclusiveContext *cx, JSOp op, uint32_t index, BytecodeEmitter *bce)
 static bool
 EmitIndexOp(ExclusiveContext *cx, JSOp op, uint32_t index, BytecodeEmitter *bce)
 {
+    MOZ_ASSERT(CheckStrictOrSloppy(bce, op));
     const size_t len = js_CodeSpec[op].length;
     MOZ_ASSERT(len >= 1 + UINT32_INDEX_LEN);
     ptrdiff_t offset = EmitCheck(cx, bce, len);
diff --git a/js/src/jsopcode.h b/js/src/jsopcode.h
index 31527dd49beb..06af1c13f0c8 100644
--- a/js/src/jsopcode.h
+++ b/js/src/jsopcode.h
@@ -69,8 +69,8 @@ FOR_EACH_OPCODE(ENUMERATE_OPCODE)
 #define JOF_LEFTASSOC    (1U<<16) /* left-associative operator */
 /* (1U<<17) is unused */
 /* (1U<<18) is unused */
-/* (1U<<19) is unused*/
-/* (1U<<20) is unused*/
+#define JOF_CHECKSLOPPY  (1U<<19) /* Op can only be generated in sloppy mode */
+#define JOF_CHECKSTRICT  (1U<<20) /* Op can only be generated in strict mode */
 #define JOF_INVOKE       (1U<<21) /* JSOP_CALL, JSOP_FUNCALL, JSOP_FUNAPPLY,
                                      JSOP_NEW, JSOP_EVAL */
 #define JOF_TMPSLOT      (1U<<22) /* interpreter uses extra temporary slot
@@ -633,6 +633,20 @@ IsEqualityOp(JSOp op)
     return op == JSOP_EQ || op == JSOP_NE || op == JSOP_STRICTEQ || op == JSOP_STRICTNE;
 }
 
+#ifdef DEBUG
+inline bool
+IsCheckStrictOp(JSOp op)
+{
+    return js_CodeSpec[op].format & JOF_CHECKSTRICT;
+}
+
+inline bool
+IsCheckSloppyOp(JSOp op)
+{
+    return js_CodeSpec[op].format & JOF_CHECKSLOPPY;
+}
+#endif
+
 inline bool
 IsGetPropPC(jsbytecode *pc)
 {

From 5820b647df6ee413e74a248f0c53e8bcdff1b006 Mon Sep 17 00:00:00 2001
From: Eric Faust 
Date: Wed, 26 Nov 2014 14:42:51 -0800
Subject: [PATCH 36/64] Bug 1101905 - Part 1: Add strict variants of
 JSOP_DELPROP and JSOP_DELELEM. (r=Waldo)

---
 js/src/frontend/BytecodeEmitter.cpp | 12 ++++++----
 js/src/jit/BaselineCompiler.cpp     | 18 ++++++++++++--
 js/src/jit/BaselineCompiler.h       |  2 ++
 js/src/jit/CodeGenerator.cpp        |  4 ++--
 js/src/jit/IonBuilder.cpp           |  8 +++++--
 js/src/jit/MIR.h                    | 31 +++++++++++++++++-------
 js/src/vm/Interpreter.cpp           | 15 ++++++------
 js/src/vm/Opcodes.h                 | 37 ++++++++++++++++++++++-------
 js/src/vm/Xdr.h                     |  2 +-
 9 files changed, 94 insertions(+), 35 deletions(-)

diff --git a/js/src/frontend/BytecodeEmitter.cpp b/js/src/frontend/BytecodeEmitter.cpp
index 51856a05bcaa..0141c6f38c43 100644
--- a/js/src/frontend/BytecodeEmitter.cpp
+++ b/js/src/frontend/BytecodeEmitter.cpp
@@ -5907,21 +5907,25 @@ EmitDelete(ExclusiveContext *cx, BytecodeEmitter *bce, ParseNode *pn)
     ParseNode *pn2 = pn->pn_kid;
     switch (pn2->getKind()) {
       case PNK_NAME:
-      {
         if (!BindNameToSlot(cx, bce, pn2))
             return false;
         if (!EmitAtomOp(cx, pn2, pn2->getOp(), bce))
             return false;
         break;
-      }
       case PNK_DOT:
-        if (!EmitPropOp(cx, pn2, JSOP_DELPROP, bce))
+      {
+        JSOp delOp = bce->sc->strict ? JSOP_STRICTDELPROP : JSOP_DELPROP;
+        if (!EmitPropOp(cx, pn2, delOp, bce))
             return false;
         break;
+      }
       case PNK_ELEM:
-        if (!EmitElemOp(cx, pn2, JSOP_DELELEM, bce))
+      {
+        JSOp delOp = bce->sc->strict ? JSOP_STRICTDELELEM : JSOP_DELELEM;
+        if (!EmitElemOp(cx, pn2, delOp, bce))
             return false;
         break;
+      }
       default:
       {
         /*
diff --git a/js/src/jit/BaselineCompiler.cpp b/js/src/jit/BaselineCompiler.cpp
index 335341e445b7..89a653460da9 100644
--- a/js/src/jit/BaselineCompiler.cpp
+++ b/js/src/jit/BaselineCompiler.cpp
@@ -1974,7 +1974,8 @@ BaselineCompiler::emit_JSOP_DELELEM()
     pushArg(R1);
     pushArg(R0);
 
-    if (!callVM(script->strict() ? DeleteElementStrictInfo : DeleteElementNonStrictInfo))
+    bool strict = JSOp(*pc) == JSOP_STRICTDELELEM;
+    if (!callVM(strict ? DeleteElementStrictInfo : DeleteElementNonStrictInfo))
         return false;
 
     masm.boxNonDouble(JSVAL_TYPE_BOOLEAN, ReturnReg, R1);
@@ -1983,6 +1984,12 @@ BaselineCompiler::emit_JSOP_DELELEM()
     return true;
 }
 
+bool
+BaselineCompiler::emit_JSOP_STRICTDELELEM()
+{
+    return emit_JSOP_DELELEM();
+}
+
 bool
 BaselineCompiler::emit_JSOP_IN()
 {
@@ -2113,7 +2120,8 @@ BaselineCompiler::emit_JSOP_DELPROP()
     pushArg(ImmGCPtr(script->getName(pc)));
     pushArg(R0);
 
-    if (!callVM(script->strict() ? DeletePropertyStrictInfo : DeletePropertyNonStrictInfo))
+    bool strict = JSOp(*pc) == JSOP_STRICTDELPROP;
+    if (!callVM(strict ? DeletePropertyStrictInfo : DeletePropertyNonStrictInfo))
         return false;
 
     masm.boxNonDouble(JSVAL_TYPE_BOOLEAN, ReturnReg, R1);
@@ -2122,6 +2130,12 @@ BaselineCompiler::emit_JSOP_DELPROP()
     return true;
 }
 
+bool
+BaselineCompiler::emit_JSOP_STRICTDELPROP()
+{
+    return emit_JSOP_DELPROP();
+}
+
 void
 BaselineCompiler::getScopeCoordinateObject(Register reg)
 {
diff --git a/js/src/jit/BaselineCompiler.h b/js/src/jit/BaselineCompiler.h
index d1c85bdecb85..66815672062e 100644
--- a/js/src/jit/BaselineCompiler.h
+++ b/js/src/jit/BaselineCompiler.h
@@ -110,6 +110,7 @@ namespace jit {
     _(JSOP_SETELEM)            \
     _(JSOP_CALLELEM)           \
     _(JSOP_DELELEM)            \
+    _(JSOP_STRICTDELELEM)      \
     _(JSOP_IN)                 \
     _(JSOP_GETGNAME)           \
     _(JSOP_BINDGNAME)          \
@@ -119,6 +120,7 @@ namespace jit {
     _(JSOP_SETPROP)            \
     _(JSOP_CALLPROP)           \
     _(JSOP_DELPROP)            \
+    _(JSOP_STRICTDELPROP)      \
     _(JSOP_LENGTH)             \
     _(JSOP_GETXPROP)           \
     _(JSOP_GETALIASEDVAR)      \
diff --git a/js/src/jit/CodeGenerator.cpp b/js/src/jit/CodeGenerator.cpp
index 615460ad41fa..cce52be23b43 100644
--- a/js/src/jit/CodeGenerator.cpp
+++ b/js/src/jit/CodeGenerator.cpp
@@ -8642,7 +8642,7 @@ CodeGenerator::visitCallDeleteProperty(LCallDeleteProperty *lir)
     pushArg(ImmGCPtr(lir->mir()->name()));
     pushArg(ToValue(lir, LCallDeleteProperty::Value));
 
-    if (lir->mir()->block()->info().script()->strict())
+    if (lir->mir()->strict())
         return callVM(DeletePropertyStrictInfo, lir);
 
     return callVM(DeletePropertyNonStrictInfo, lir);
@@ -8660,7 +8660,7 @@ CodeGenerator::visitCallDeleteElement(LCallDeleteElement *lir)
     pushArg(ToValue(lir, LCallDeleteElement::Index));
     pushArg(ToValue(lir, LCallDeleteElement::Value));
 
-    if (lir->mir()->block()->info().script()->strict())
+    if (lir->mir()->strict())
         return callVM(DeleteElementStrictInfo, lir);
 
     return callVM(DeleteElementNonStrictInfo, lir);
diff --git a/js/src/jit/IonBuilder.cpp b/js/src/jit/IonBuilder.cpp
index 8ab9e6778db5..d9e0a7a3e649 100644
--- a/js/src/jit/IonBuilder.cpp
+++ b/js/src/jit/IonBuilder.cpp
@@ -1769,12 +1769,14 @@ IonBuilder::inspectOpcode(JSOp op)
       }
 
       case JSOP_DELPROP:
+      case JSOP_STRICTDELPROP:
       {
         PropertyName *name = info().getAtom(pc)->asPropertyName();
         return jsop_delprop(name);
       }
 
       case JSOP_DELELEM:
+      case JSOP_STRICTDELELEM:
         return jsop_delelem();
 
       case JSOP_REGEXP:
@@ -10464,7 +10466,8 @@ IonBuilder::jsop_delprop(PropertyName *name)
 {
     MDefinition *obj = current->pop();
 
-    MInstruction *ins = MDeleteProperty::New(alloc(), obj, name);
+    bool strict = JSOp(*pc) == JSOP_STRICTDELPROP;
+    MInstruction *ins = MDeleteProperty::New(alloc(), obj, name, strict);
 
     current->add(ins);
     current->push(ins);
@@ -10478,7 +10481,8 @@ IonBuilder::jsop_delelem()
     MDefinition *index = current->pop();
     MDefinition *obj = current->pop();
 
-    MDeleteElement *ins = MDeleteElement::New(alloc(), obj, index);
+    bool strict = JSOp(*pc) == JSOP_STRICTDELELEM;
+    MDeleteElement *ins = MDeleteElement::New(alloc(), obj, index, strict);
     current->add(ins);
     current->push(ins);
 
diff --git a/js/src/jit/MIR.h b/js/src/jit/MIR.h
index eb7571e02e21..0a8c06187948 100644
--- a/js/src/jit/MIR.h
+++ b/js/src/jit/MIR.h
@@ -10139,11 +10139,13 @@ class MDeleteProperty
     public BoxInputsPolicy::Data
 {
     AlwaysTenuredPropertyName name_;
+    bool strict_;
 
   protected:
-    MDeleteProperty(MDefinition *val, PropertyName *name)
+    MDeleteProperty(MDefinition *val, PropertyName *name, bool strict)
       : MUnaryInstruction(val),
-        name_(name)
+        name_(name),
+        strict_(strict)
     {
         setResultType(MIRType_Boolean);
     }
@@ -10151,8 +10153,10 @@ class MDeleteProperty
   public:
     INSTRUCTION_HEADER(DeleteProperty)
 
-    static MDeleteProperty *New(TempAllocator &alloc, MDefinition *obj, PropertyName *name) {
-        return new(alloc) MDeleteProperty(obj, name);
+    static MDeleteProperty *New(TempAllocator &alloc, MDefinition *obj, PropertyName *name,
+                                bool strict)
+    {
+        return new(alloc) MDeleteProperty(obj, name, strict);
     }
     MDefinition *value() const {
         return getOperand(0);
@@ -10160,14 +10164,20 @@ class MDeleteProperty
     PropertyName *name() const {
         return name_;
     }
+    bool strict() const {
+        return strict_;
+    }
 };
 
 class MDeleteElement
   : public MBinaryInstruction,
     public BoxInputsPolicy::Data
 {
-    MDeleteElement(MDefinition *value, MDefinition *index)
-      : MBinaryInstruction(value, index)
+    bool strict_;
+
+    MDeleteElement(MDefinition *value, MDefinition *index, bool strict)
+      : MBinaryInstruction(value, index),
+        strict_(strict)
     {
         setResultType(MIRType_Boolean);
     }
@@ -10175,8 +10185,10 @@ class MDeleteElement
   public:
     INSTRUCTION_HEADER(DeleteElement)
 
-    static MDeleteElement *New(TempAllocator &alloc, MDefinition *value, MDefinition *index) {
-        return new(alloc) MDeleteElement(value, index);
+    static MDeleteElement *New(TempAllocator &alloc, MDefinition *value, MDefinition *index,
+                               bool strict)
+    {
+        return new(alloc) MDeleteElement(value, index, strict);
     }
     MDefinition *value() const {
         return getOperand(0);
@@ -10184,6 +10196,9 @@ class MDeleteElement
     MDefinition *index() const {
         return getOperand(1);
     }
+    bool strict() const {
+        return strict_;
+    }
 };
 
 // Note: This uses CallSetElementPolicy to always box its second input,
diff --git a/js/src/vm/Interpreter.cpp b/js/src/vm/Interpreter.cpp
index d14e21d39537..db25f0eb4698 100644
--- a/js/src/vm/Interpreter.cpp
+++ b/js/src/vm/Interpreter.cpp
@@ -1588,8 +1588,6 @@ CASE(EnableInterruptsPseudoOpcode)
 /* Various 1-byte no-ops. */
 CASE(JSOP_NOP)
 CASE(JSOP_UNUSED2)
-CASE(JSOP_UNUSED46)
-CASE(JSOP_UNUSED47)
 CASE(JSOP_UNUSED48)
 CASE(JSOP_UNUSED49)
 CASE(JSOP_UNUSED50)
@@ -2256,9 +2254,6 @@ END_CASE(JSOP_POS)
 
 CASE(JSOP_DELNAME)
 {
-    /* Strict mode code should never contain JSOP_DELNAME opcodes. */
-    MOZ_ASSERT(!script->strict());
-
     RootedPropertyName &name = rootName0;
     name = script->getName(REGS.pc);
 
@@ -2273,7 +2268,10 @@ CASE(JSOP_DELNAME)
 END_CASE(JSOP_DELNAME)
 
 CASE(JSOP_DELPROP)
+CASE(JSOP_STRICTDELPROP)
 {
+    static_assert(JSOP_DELPROP_LENGTH == JSOP_STRICTDELPROP_LENGTH,
+                  "delprop and strictdelprop must be the same size");
     RootedId &id = rootId0;
     id = NameToId(script->getName(REGS.pc));
 
@@ -2283,7 +2281,7 @@ CASE(JSOP_DELPROP)
     bool succeeded;
     if (!JSObject::deleteGeneric(cx, obj, id, &succeeded))
         goto error;
-    if (!succeeded && script->strict()) {
+    if (!succeeded && JSOp(*REGS.pc) == JSOP_STRICTDELPROP) {
         obj->reportNotConfigurable(cx, id);
         goto error;
     }
@@ -2293,7 +2291,10 @@ CASE(JSOP_DELPROP)
 END_CASE(JSOP_DELPROP)
 
 CASE(JSOP_DELELEM)
+CASE(JSOP_STRICTDELELEM)
 {
+    static_assert(JSOP_DELELEM_LENGTH == JSOP_STRICTDELELEM_LENGTH,
+                  "delelem and strictdelelem must be the same size");
     /* Fetch the left part and resolve it to a non-null object. */
     RootedObject &obj = rootObject0;
     FETCH_OBJECT(cx, -2, obj);
@@ -2307,7 +2308,7 @@ CASE(JSOP_DELELEM)
         goto error;
     if (!JSObject::deleteGeneric(cx, obj, id, &succeeded))
         goto error;
-    if (!succeeded && script->strict()) {
+    if (!succeeded && JSOp(*REGS.pc) == JSOP_STRICTDELELEM) {
         obj->reportNotConfigurable(cx, id);
         goto error;
     }
diff --git a/js/src/vm/Opcodes.h b/js/src/vm/Opcodes.h
index c24828482510..9d0ca7619623 100644
--- a/js/src/vm/Opcodes.h
+++ b/js/src/vm/Opcodes.h
@@ -332,26 +332,26 @@
      *   Operands: uint32_t nameIndex
      *   Stack: => succeeded
      */ \
-    macro(JSOP_DELNAME,   36, "delname",    NULL,         5,  0,  1, JOF_ATOM|JOF_NAME) \
+    macro(JSOP_DELNAME,   36, "delname",    NULL,         5,  0,  1, JOF_ATOM|JOF_NAME|JOF_CHECKSLOPPY) \
     /*
      * Pops the top of stack value, deletes property from it, pushes 'true' onto
      * the stack if succeeded, 'false' if not.
-     *   Category: Literals
-     *   Type: Object
+     *   Category: Operators
+     *   Type: Special Operators
      *   Operands: uint32_t nameIndex
      *   Stack: obj => succeeded
      */ \
-    macro(JSOP_DELPROP,   37, "delprop",    NULL,         5,  1,  1, JOF_ATOM|JOF_PROP) \
+    macro(JSOP_DELPROP,   37, "delprop",    NULL,         5,  1,  1, JOF_ATOM|JOF_PROP|JOF_CHECKSLOPPY) \
     /*
      * Pops the top two values on the stack as 'propval' and 'obj',
      * deletes 'propval' property from 'obj', pushes 'true'  onto the stack if
      * succeeded, 'false' if not.
-     *   Category: Literals
-     *   Type: Object
+     *   Category: Operators
+     *   Type: Special Operators
      *   Operands:
      *   Stack: obj, propval => succeeded
      */ \
-    macro(JSOP_DELELEM,   38, "delelem",    NULL,         1,  2,  1, JOF_BYTE |JOF_ELEM) \
+    macro(JSOP_DELELEM,   38, "delelem",    NULL,         1,  2,  1, JOF_BYTE |JOF_ELEM|JOF_CHECKSLOPPY) \
     /*
      * Pops the value 'val' from the stack, then pushes 'typeof val'.
      *   Category: Operator
@@ -426,8 +426,27 @@
      */ \
     macro(JSOP_SYMBOL,    45, "symbol",     NULL,         2,  0,  1,  JOF_UINT8) \
     \
-    macro(JSOP_UNUSED46,  46, "unused46",   NULL,         1,  0,  0,  JOF_BYTE) \
-    macro(JSOP_UNUSED47,  47, "unused47",   NULL,         1,  0,  0,  JOF_BYTE) \
+    /*
+     * Pops the top of stack value and attempts to delete the given property
+     * from it. Pushes 'true' onto success, else throws a TypeError per strict
+     * mode property-deletion requirements.
+     *   Category: Operators
+     *   Type: Special Operators
+     *   Operands: uint32_t nameIndex
+     *   Stack: obj => succeeded
+     */ \
+    macro(JSOP_STRICTDELPROP,   46, "strict-delprop",    NULL,         5,  1,  1, JOF_ATOM|JOF_PROP|JOF_CHECKSTRICT) \
+    /*
+     * Pops the top two values on the stack as 'propval' and 'obj',
+     * and attempts to delete 'propval' property from 'obj'. Pushes 'true' onto
+     * the stack on success, else throws a TypeError per strict mode property
+     * deletion requirements.
+     *   Category: Literals
+     *   Type: Object
+     *   Operands:
+     *   Stack: obj, propval => succeeded
+     */ \
+    macro(JSOP_STRICTDELELEM,   47, "strict-delelem",    NULL,         1,  2,  1, JOF_BYTE|JOF_ELEM|JOF_CHECKSTRICT) \
     macro(JSOP_UNUSED48,  48, "unused48",   NULL,         1,  0,  0,  JOF_BYTE) \
     macro(JSOP_UNUSED49,  49, "unused49",   NULL,         1,  0,  0,  JOF_BYTE) \
     macro(JSOP_UNUSED50,  50, "unused50",   NULL,         1,  0,  0,  JOF_BYTE) \
diff --git a/js/src/vm/Xdr.h b/js/src/vm/Xdr.h
index 3e60384d93cc..ec5a7dd39d8f 100644
--- a/js/src/vm/Xdr.h
+++ b/js/src/vm/Xdr.h
@@ -34,7 +34,7 @@ namespace js {
  * Nightly) and without (all others).  FIXME: Bug 1066322 - Enable ES6 symbols
  * in all builds.
  */
-static const uint32_t XDR_BYTECODE_VERSION_SUBTRAHEND = 206;
+static const uint32_t XDR_BYTECODE_VERSION_SUBTRAHEND = 208;
 static_assert(XDR_BYTECODE_VERSION_SUBTRAHEND % 2 == 0, "see the comment above");
 static const uint32_t XDR_BYTECODE_VERSION =
     uint32_t(0xb973c0de - (XDR_BYTECODE_VERSION_SUBTRAHEND

From ab8bc78244668961b6e8bd410d9b96a4cee4a6a6 Mon Sep 17 00:00:00 2001
From: Eric Faust 
Date: Wed, 26 Nov 2014 14:42:52 -0800
Subject: [PATCH 37/64] Bug 1101905 - Part 2: Add strict variant of
 JSOP_SETPROP. (r=Waldo)

---
 js/src/frontend/BytecodeEmitter.cpp | 13 ++++++++++---
 js/src/jit/BaselineCompiler.cpp     |  6 ++++++
 js/src/jit/BaselineCompiler.h       |  1 +
 js/src/jit/BaselineIC.cpp           |  5 +++--
 js/src/jit/IonBuilder.cpp           |  9 +++++++--
 js/src/jsopcode.h                   | 10 +++++++++-
 js/src/vm/Interpreter.cpp           | 12 ++++++++----
 js/src/vm/Opcodes.h                 | 17 +++++++++++++----
 js/src/vm/Xdr.h                     |  2 +-
 9 files changed, 58 insertions(+), 17 deletions(-)

diff --git a/js/src/frontend/BytecodeEmitter.cpp b/js/src/frontend/BytecodeEmitter.cpp
index 0141c6f38c43..68fb81bb63b6 100644
--- a/js/src/frontend/BytecodeEmitter.cpp
+++ b/js/src/frontend/BytecodeEmitter.cpp
@@ -2424,7 +2424,8 @@ EmitPropIncDec(ExclusiveContext *cx, ParseNode *pn, BytecodeEmitter *bce)
             return false;
     }
 
-    if (!EmitAtomOp(cx, pn->pn_kid, JSOP_SETPROP, bce))     // N? N+1
+    JSOp setOp = bce->sc->strict ? JSOP_STRICTSETPROP : JSOP_SETPROP;
+    if (!EmitAtomOp(cx, pn->pn_kid, setOp, bce))     // N? N+1
         return false;
     if (post && Emit1(cx, bce, JSOP_POP) < 0)       // RESULT
         return false;
@@ -3368,6 +3369,7 @@ EmitDestructuringLHS(ExclusiveContext *cx, BytecodeEmitter *bce, ParseNode *pn,
             break;
 
           case PNK_DOT:
+          {
             // See the (PNK_NAME, JSOP_SETNAME) case above.
             //
             // In `a.x = b`, `a` is evaluated first, then `b`, then a
@@ -3380,9 +3382,11 @@ EmitDestructuringLHS(ExclusiveContext *cx, BytecodeEmitter *bce, ParseNode *pn,
                 return false;
             if (Emit1(cx, bce, JSOP_SWAP) < 0)
                 return false;
-            if (!EmitAtomOp(cx, pn, JSOP_SETPROP, bce))
+            JSOp setOp = bce->sc->strict ? JSOP_STRICTSETPROP : JSOP_SETPROP;
+            if (!EmitAtomOp(cx, pn, setOp, bce))
                 return false;
             break;
+          }
 
           case PNK_ELEM:
             // See the comment at `case PNK_DOT:` above. This case,
@@ -4098,9 +4102,12 @@ EmitAssignment(ExclusiveContext *cx, BytecodeEmitter *bce, ParseNode *lhs, JSOp
         }
         break;
       case PNK_DOT:
-        if (!EmitIndexOp(cx, JSOP_SETPROP, atomIndex, bce))
+      {
+        JSOp setOp = bce->sc->strict ? JSOP_STRICTSETPROP : JSOP_SETPROP;
+        if (!EmitIndexOp(cx, setOp, atomIndex, bce))
             return false;
         break;
+      }
       case PNK_CALL:
         /* Do nothing. The JSOP_SETCALL we emitted will always throw. */
         MOZ_ASSERT(lhs->pn_xflags & PNX_SETCALL);
diff --git a/js/src/jit/BaselineCompiler.cpp b/js/src/jit/BaselineCompiler.cpp
index 89a653460da9..846091a774cf 100644
--- a/js/src/jit/BaselineCompiler.cpp
+++ b/js/src/jit/BaselineCompiler.cpp
@@ -2058,6 +2058,12 @@ BaselineCompiler::emit_JSOP_SETPROP()
     return true;
 }
 
+bool
+BaselineCompiler::emit_JSOP_STRICTSETPROP()
+{
+    return emit_JSOP_SETPROP();
+}
+
 bool
 BaselineCompiler::emit_JSOP_SETNAME()
 {
diff --git a/js/src/jit/BaselineCompiler.h b/js/src/jit/BaselineCompiler.h
index 66815672062e..1e4d5a37c323 100644
--- a/js/src/jit/BaselineCompiler.h
+++ b/js/src/jit/BaselineCompiler.h
@@ -118,6 +118,7 @@ namespace jit {
     _(JSOP_SETNAME)            \
     _(JSOP_GETPROP)            \
     _(JSOP_SETPROP)            \
+    _(JSOP_STRICTSETPROP)      \
     _(JSOP_CALLPROP)           \
     _(JSOP_DELPROP)            \
     _(JSOP_STRICTDELPROP)      \
diff --git a/js/src/jit/BaselineIC.cpp b/js/src/jit/BaselineIC.cpp
index 25f0db63cae2..e923a0c63dfd 100644
--- a/js/src/jit/BaselineIC.cpp
+++ b/js/src/jit/BaselineIC.cpp
@@ -7896,6 +7896,7 @@ DoSetPropFallback(JSContext *cx, BaselineFrame *frame, ICSetProp_Fallback *stub_
     FallbackICSpew(cx, stub, "SetProp(%s)", js_CodeName[op]);
 
     MOZ_ASSERT(op == JSOP_SETPROP ||
+               op == JSOP_STRICTSETPROP ||
                op == JSOP_SETNAME ||
                op == JSOP_SETGNAME ||
                op == JSOP_INITPROP ||
@@ -7945,8 +7946,8 @@ DoSetPropFallback(JSContext *cx, BaselineFrame *frame, ICSetProp_Fallback *stub_
     } else if (op == JSOP_SETALIASEDVAR || op == JSOP_INITALIASEDLEXICAL) {
         obj->as().setAliasedVar(cx, ScopeCoordinate(pc), name, rhs);
     } else {
-        MOZ_ASSERT(op == JSOP_SETPROP);
-        if (script->strict()) {
+        MOZ_ASSERT(op == JSOP_SETPROP || op == JSOP_STRICTSETPROP);
+        if (op == JSOP_STRICTSETPROP) {
             if (!js::SetProperty(cx, obj, id, rhs))
                 return false;
         } else {
diff --git a/js/src/jit/IonBuilder.cpp b/js/src/jit/IonBuilder.cpp
index d9e0a7a3e649..10e818ca41ca 100644
--- a/js/src/jit/IonBuilder.cpp
+++ b/js/src/jit/IonBuilder.cpp
@@ -1762,6 +1762,7 @@ IonBuilder::inspectOpcode(JSOp op)
       }
 
       case JSOP_SETPROP:
+      case JSOP_STRICTSETPROP:
       case JSOP_SETNAME:
       {
         PropertyName *name = info().getAtom(pc)->asPropertyName();
@@ -10064,7 +10065,9 @@ IonBuilder::jsop_setprop(PropertyName *name)
     // Always use a call if we are doing the definite properties analysis and
     // not actually emitting code, to simplify later analysis.
     if (info().executionModeIsAnalysis()) {
-        MInstruction *ins = MCallSetProperty::New(alloc(), obj, value, name, script()->strict());
+        // XXX: Dropped later in stack, but for now other ops rely on the old mechanic.
+        bool strict = IsStrictSetPC(pc) || script()->strict();
+        MInstruction *ins = MCallSetProperty::New(alloc(), obj, value, name, strict);
         current->add(ins);
         current->push(value);
         return resumeAfter(ins);
@@ -10445,8 +10448,10 @@ IonBuilder::setPropTryCache(bool *emitted, MDefinition *obj,
 {
     MOZ_ASSERT(*emitted == false);
 
+    // XXX Dropped later in stack, but while others rely on it, we must retain the check.
+    bool strict = IsStrictSetPC(pc) || script()->strict();
     // Emit SetPropertyCache.
-    MSetPropertyCache *ins = MSetPropertyCache::New(alloc(), obj, value, name, script()->strict(), barrier);
+    MSetPropertyCache *ins = MSetPropertyCache::New(alloc(), obj, value, name, strict, barrier);
 
     if (!objTypes || objTypes->propertyNeedsBarrier(constraints(), NameToId(name)))
         ins->setNeedsBarrier();
diff --git a/js/src/jsopcode.h b/js/src/jsopcode.h
index 06af1c13f0c8..e7fc97c39dbc 100644
--- a/js/src/jsopcode.h
+++ b/js/src/jsopcode.h
@@ -654,11 +654,19 @@ IsGetPropPC(jsbytecode *pc)
     return op == JSOP_LENGTH  || op == JSOP_GETPROP || op == JSOP_CALLPROP;
 }
 
+inline bool
+IsStrictSetPC(jsbytecode *pc)
+{
+    JSOp op = JSOp(*pc);
+    return op == JSOP_STRICTSETPROP;
+}
+
 inline bool
 IsSetPropPC(jsbytecode *pc)
 {
     JSOp op = JSOp(*pc);
-    return op == JSOP_SETPROP || op == JSOP_SETNAME || op == JSOP_SETGNAME;
+    return op == JSOP_SETPROP || op == JSOP_STRICTSETPROP ||
+           op == JSOP_SETNAME || op == JSOP_SETGNAME;
 }
 
 inline bool
diff --git a/js/src/vm/Interpreter.cpp b/js/src/vm/Interpreter.cpp
index db25f0eb4698..bfde62e76593 100644
--- a/js/src/vm/Interpreter.cpp
+++ b/js/src/vm/Interpreter.cpp
@@ -309,7 +309,9 @@ static inline bool
 SetPropertyOperation(JSContext *cx, HandleScript script, jsbytecode *pc, HandleValue lval,
                      HandleValue rval)
 {
-    MOZ_ASSERT(*pc == JSOP_SETPROP);
+    MOZ_ASSERT(*pc == JSOP_SETPROP || *pc == JSOP_STRICTSETPROP);
+
+    bool strict = *pc == JSOP_STRICTSETPROP;
 
     RootedObject obj(cx, ToObjectFromStack(cx, lval));
     if (!obj)
@@ -324,12 +326,12 @@ SetPropertyOperation(JSContext *cx, HandleScript script, jsbytecode *pc, HandleV
                                                              obj.as(),
                                                              id,
                                                              baseops::Qualified,
-                                                             &rref, script->strict()))
+                                                             &rref, strict))
         {
             return false;
         }
     } else {
-        if (!JSObject::setGeneric(cx, obj, obj, id, &rref, script->strict()))
+        if (!JSObject::setGeneric(cx, obj, obj, id, &rref, strict))
             return false;
     }
 
@@ -1588,7 +1590,6 @@ CASE(EnableInterruptsPseudoOpcode)
 /* Various 1-byte no-ops. */
 CASE(JSOP_NOP)
 CASE(JSOP_UNUSED2)
-CASE(JSOP_UNUSED48)
 CASE(JSOP_UNUSED49)
 CASE(JSOP_UNUSED50)
 CASE(JSOP_UNUSED51)
@@ -2396,7 +2397,10 @@ CASE(JSOP_SETNAME)
 END_CASE(JSOP_SETNAME)
 
 CASE(JSOP_SETPROP)
+CASE(JSOP_STRICTSETPROP)
 {
+    static_assert(JSOP_SETPROP_LENGTH == JSOP_STRICTSETPROP_LENGTH,
+                  "setprop and strictsetprop must be the same size");
     HandleValue lval = REGS.stackHandleAt(-2);
     HandleValue rval = REGS.stackHandleAt(-1);
 
diff --git a/js/src/vm/Opcodes.h b/js/src/vm/Opcodes.h
index 9d0ca7619623..1ba848bc02df 100644
--- a/js/src/vm/Opcodes.h
+++ b/js/src/vm/Opcodes.h
@@ -447,7 +447,16 @@
      *   Stack: obj, propval => succeeded
      */ \
     macro(JSOP_STRICTDELELEM,   47, "strict-delelem",    NULL,         1,  2,  1, JOF_BYTE|JOF_ELEM|JOF_CHECKSTRICT) \
-    macro(JSOP_UNUSED48,  48, "unused48",   NULL,         1,  0,  0,  JOF_BYTE) \
+    /*
+     * Pops the top two values on the stack as 'val' and 'obj', and performs
+     * 'obj.prop = val', pushing 'val' back onto the stack. Throws a TypeError
+     * if the set-operation failed (per strict mode semantics).
+     *   Category: Literals
+     *   Type: Object
+     *   Operands: uint32_t nameIndex
+     *   Stack: obj, val => val
+     */ \
+    macro(JSOP_STRICTSETPROP,   48, "strict-setprop",    NULL,         5,  2,  1, JOF_ATOM|JOF_PROP|JOF_SET|JOF_DETECTING|JOF_CHECKSTRICT) \
     macro(JSOP_UNUSED49,  49, "unused49",   NULL,         1,  0,  0,  JOF_BYTE) \
     macro(JSOP_UNUSED50,  50, "unused50",   NULL,         1,  0,  0,  JOF_BYTE) \
     macro(JSOP_UNUSED51,  51, "unused51",   NULL,         1,  0,  0,  JOF_BYTE) \
@@ -462,14 +471,14 @@
      */ \
     macro(JSOP_GETPROP,   53, "getprop",    NULL,         5,  1,  1, JOF_ATOM|JOF_PROP|JOF_TYPESET|JOF_TMPSLOT3) \
     /*
-     * Pops the top two values on the stack as 'val' and 'obj', sets property of
-     * 'obj' as 'val', pushes 'obj' onto the stack.
+     * Pops the top two values on the stack as 'val' and 'obj' and performs
+     * 'obj.prop = val', pushing 'val' back onto the stack.
      *   Category: Literals
      *   Type: Object
      *   Operands: uint32_t nameIndex
      *   Stack: obj, val => val
      */ \
-    macro(JSOP_SETPROP,   54, "setprop",    NULL,         5,  2,  1, JOF_ATOM|JOF_PROP|JOF_SET|JOF_DETECTING) \
+    macro(JSOP_SETPROP,   54, "setprop",    NULL,         5,  2,  1, JOF_ATOM|JOF_PROP|JOF_SET|JOF_DETECTING|JOF_CHECKSLOPPY) \
     /*
      * Pops the top two values on the stack as 'propval' and 'obj', pushes
      * 'propval' property of 'obj' onto the stack.
diff --git a/js/src/vm/Xdr.h b/js/src/vm/Xdr.h
index ec5a7dd39d8f..89572879a8f5 100644
--- a/js/src/vm/Xdr.h
+++ b/js/src/vm/Xdr.h
@@ -34,7 +34,7 @@ namespace js {
  * Nightly) and without (all others).  FIXME: Bug 1066322 - Enable ES6 symbols
  * in all builds.
  */
-static const uint32_t XDR_BYTECODE_VERSION_SUBTRAHEND = 208;
+static const uint32_t XDR_BYTECODE_VERSION_SUBTRAHEND = 210;
 static_assert(XDR_BYTECODE_VERSION_SUBTRAHEND % 2 == 0, "see the comment above");
 static const uint32_t XDR_BYTECODE_VERSION =
     uint32_t(0xb973c0de - (XDR_BYTECODE_VERSION_SUBTRAHEND

From 5d8b874d2c9fc966e5b65912155de1074c1f5b65 Mon Sep 17 00:00:00 2001
From: Eric Faust 
Date: Wed, 26 Nov 2014 14:42:52 -0800
Subject: [PATCH 38/64] Bug 1101905 - Part 3: Add strict variant of
 JSOP_SETNAME. (r=Waldo)

---
 js/src/frontend/BytecodeEmitter.cpp | 36 ++++++++++++++++++++++++-----
 js/src/jit/BaselineCompiler.cpp     |  6 +++++
 js/src/jit/BaselineCompiler.h       |  1 +
 js/src/jit/BaselineIC.cpp           |  6 ++++-
 js/src/jit/IonBuilder.cpp           |  1 +
 js/src/jit/VMFunctions.cpp          |  3 ++-
 js/src/jsopcode.h                   |  6 +++--
 js/src/vm/Interpreter-inl.h         |  7 ++++--
 js/src/vm/Interpreter.cpp           |  4 +++-
 js/src/vm/Opcodes.h                 | 13 +++++++++--
 js/src/vm/Xdr.h                     |  2 +-
 11 files changed, 69 insertions(+), 16 deletions(-)

diff --git a/js/src/frontend/BytecodeEmitter.cpp b/js/src/frontend/BytecodeEmitter.cpp
index 68fb81bb63b6..145be36657c7 100644
--- a/js/src/frontend/BytecodeEmitter.cpp
+++ b/js/src/frontend/BytecodeEmitter.cpp
@@ -1514,6 +1514,25 @@ BytecodeEmitter::isAliasedName(ParseNode *pn)
     return false;
 }
 
+static JSOp
+StrictifySetNameOp(JSOp op, BytecodeEmitter *bce)
+{
+    switch (op) {
+      case JSOP_SETNAME:
+        if (bce->sc->strict)
+            op = JSOP_STRICTSETNAME;
+        break;
+        default:;
+    }
+    return op;
+}
+
+static void
+StrictifySetNameNode(ParseNode *pn, BytecodeEmitter *bce)
+{
+    pn->setOp(StrictifySetNameOp(pn->getOp(), bce));
+}
+
 /*
  * Try to convert a *NAME op with a free name to a more specialized GNAME,
  * INTRINSIC or ALIASEDVAR op, which optimize accesses on that name.
@@ -1895,6 +1914,8 @@ BindNameToSlot(ExclusiveContext *cx, BytecodeEmitter *bce, ParseNode *pn)
     if (!BindNameToSlotHelper(cx, bce, pn))
         return false;
 
+    StrictifySetNameNode(pn, bce);
+
     if (bce->emitterMode == BytecodeEmitter::SelfHosting && !pn->isBound()) {
         bce->reportError(pn, JSMSG_SELFHOSTED_UNBOUND_NAME);
         return false;
@@ -2462,7 +2483,8 @@ EmitNameIncDec(ExclusiveContext *cx, ParseNode *pn, BytecodeEmitter *bce)
             return false;
     }
 
-    if (!EmitAtomOp(cx, pn->pn_kid, global ? JSOP_SETGNAME : JSOP_SETNAME, bce)) // N? N+1
+    JSOp setOp = StrictifySetNameOp(global ? JSOP_SETGNAME : JSOP_SETNAME, bce);
+    if (!EmitAtomOp(cx, pn->pn_kid, setOp, bce)) // N? N+1
         return false;
     if (post && Emit1(cx, bce, JSOP_POP) < 0)       // RESULT
         return false;
@@ -3327,6 +3349,7 @@ EmitDestructuringLHS(ExclusiveContext *cx, BytecodeEmitter *bce, ParseNode *pn,
 
             switch (pn->getOp()) {
               case JSOP_SETNAME:
+              case JSOP_STRICTSETNAME:
               case JSOP_SETGNAME:
               case JSOP_SETCONST: {
                 // This is like ordinary assignment, but with one difference.
@@ -3344,7 +3367,7 @@ EmitDestructuringLHS(ExclusiveContext *cx, BytecodeEmitter *bce, ParseNode *pn,
                     return false;
 
                 if (!pn->isOp(JSOP_SETCONST)) {
-                    JSOp bindOp = pn->isOp(JSOP_SETNAME) ? JSOP_BINDNAME : JSOP_BINDGNAME;
+                    JSOp bindOp = pn->isOp(JSOP_SETGNAME) ? JSOP_BINDGNAME : JSOP_BINDNAME;
                     if (!EmitIndex32(cx, bindOp, atomIndex, bce))
                         return false;
                     if (Emit1(cx, bce, JSOP_SWAP) < 0)
@@ -3870,10 +3893,10 @@ EmitVariables(ExclusiveContext *cx, BytecodeEmitter *bce, ParseNode *pn, VarEmit
 
         if (pn3) {
             MOZ_ASSERT(emitOption != DefineVars);
-            if (op == JSOP_SETNAME || op == JSOP_SETGNAME || op == JSOP_SETINTRINSIC) {
+            if (op == JSOP_SETNAME || op == JSOP_STRICTSETNAME || op == JSOP_SETGNAME || op == JSOP_SETINTRINSIC) {
                 MOZ_ASSERT(emitOption != PushInitialValues);
                 JSOp bindOp;
-                if (op == JSOP_SETNAME)
+                if (op == JSOP_SETNAME || op == JSOP_STRICTSETNAME)
                     bindOp = JSOP_BINDNAME;
                 else if (op == JSOP_SETGNAME)
                     bindOp = JSOP_BINDGNAME;
@@ -3949,7 +3972,7 @@ EmitAssignment(ExclusiveContext *cx, BytecodeEmitter *bce, ParseNode *lhs, JSOp
                 return false;
             if (!lhs->isConst()) {
                 JSOp bindOp;
-                if (lhs->isOp(JSOP_SETNAME))
+                if (lhs->isOp(JSOP_SETNAME) || lhs->isOp(JSOP_STRICTSETNAME))
                     bindOp = JSOP_BINDNAME;
                 else if (lhs->isOp(JSOP_SETGNAME))
                     bindOp = JSOP_BINDGNAME;
@@ -4006,7 +4029,7 @@ EmitAssignment(ExclusiveContext *cx, BytecodeEmitter *bce, ParseNode *lhs, JSOp
                     if (!EmitVarOp(cx, lhs, lhs->getOp(), bce))
                         return false;
                 }
-            } else if (lhs->isOp(JSOP_SETNAME)) {
+            } else if (lhs->isOp(JSOP_SETNAME) || lhs->isOp(JSOP_STRICTSETNAME)) {
                 if (Emit1(cx, bce, JSOP_DUP) < 0)
                     return false;
                 if (!EmitIndex32(cx, JSOP_GETXPROP, atomIndex, bce))
@@ -6286,6 +6309,7 @@ EmitIncOrDec(ExclusiveContext *cx, BytecodeEmitter *bce, ParseNode *pn)
           case JSOP_SETARG:
           case JSOP_SETALIASEDVAR:
           case JSOP_SETNAME:
+          case JSOP_STRICTSETNAME:
           case JSOP_SETGNAME:
             maySet = true;
             break;
diff --git a/js/src/jit/BaselineCompiler.cpp b/js/src/jit/BaselineCompiler.cpp
index 846091a774cf..d8a6f9c9e770 100644
--- a/js/src/jit/BaselineCompiler.cpp
+++ b/js/src/jit/BaselineCompiler.cpp
@@ -2070,6 +2070,12 @@ BaselineCompiler::emit_JSOP_SETNAME()
     return emit_JSOP_SETPROP();
 }
 
+bool
+BaselineCompiler::emit_JSOP_STRICTSETNAME()
+{
+    return emit_JSOP_SETPROP();
+}
+
 bool
 BaselineCompiler::emit_JSOP_SETGNAME()
 {
diff --git a/js/src/jit/BaselineCompiler.h b/js/src/jit/BaselineCompiler.h
index 1e4d5a37c323..09b1dc90ca9c 100644
--- a/js/src/jit/BaselineCompiler.h
+++ b/js/src/jit/BaselineCompiler.h
@@ -116,6 +116,7 @@ namespace jit {
     _(JSOP_BINDGNAME)          \
     _(JSOP_SETGNAME)           \
     _(JSOP_SETNAME)            \
+    _(JSOP_STRICTSETNAME)      \
     _(JSOP_GETPROP)            \
     _(JSOP_SETPROP)            \
     _(JSOP_STRICTSETPROP)      \
diff --git a/js/src/jit/BaselineIC.cpp b/js/src/jit/BaselineIC.cpp
index e923a0c63dfd..13eb448e7f7b 100644
--- a/js/src/jit/BaselineIC.cpp
+++ b/js/src/jit/BaselineIC.cpp
@@ -7898,6 +7898,7 @@ DoSetPropFallback(JSContext *cx, BaselineFrame *frame, ICSetProp_Fallback *stub_
     MOZ_ASSERT(op == JSOP_SETPROP ||
                op == JSOP_STRICTSETPROP ||
                op == JSOP_SETNAME ||
+               op == JSOP_STRICTSETNAME ||
                op == JSOP_SETGNAME ||
                op == JSOP_INITPROP ||
                op == JSOP_SETALIASEDVAR ||
@@ -7940,7 +7941,10 @@ DoSetPropFallback(JSContext *cx, BaselineFrame *frame, ICSetProp_Fallback *stub_
         {
             return false;
         }
-    } else if (op == JSOP_SETNAME || op == JSOP_SETGNAME) {
+    } else if (op == JSOP_SETNAME ||
+               op == JSOP_STRICTSETNAME ||
+               op == JSOP_SETGNAME)
+    {
         if (!SetNameOperation(cx, script, pc, obj, rhs))
             return false;
     } else if (op == JSOP_SETALIASEDVAR || op == JSOP_INITALIASEDLEXICAL) {
diff --git a/js/src/jit/IonBuilder.cpp b/js/src/jit/IonBuilder.cpp
index 10e818ca41ca..232d1a9c032e 100644
--- a/js/src/jit/IonBuilder.cpp
+++ b/js/src/jit/IonBuilder.cpp
@@ -1764,6 +1764,7 @@ IonBuilder::inspectOpcode(JSOp op)
       case JSOP_SETPROP:
       case JSOP_STRICTSETPROP:
       case JSOP_SETNAME:
+      case JSOP_STRICTSETNAME:
       {
         PropertyName *name = info().getAtom(pc)->asPropertyName();
         return jsop_setprop(name);
diff --git a/js/src/jit/VMFunctions.cpp b/js/src/jit/VMFunctions.cpp
index b31766903c04..d3f87915d014 100644
--- a/js/src/jit/VMFunctions.cpp
+++ b/js/src/jit/VMFunctions.cpp
@@ -507,7 +507,8 @@ SetProperty(JSContext *cx, HandleObject obj, HandlePropertyName name, HandleValu
     if (MOZ_LIKELY(!obj->getOps()->setProperty)) {
         return baseops::SetPropertyHelper(
             cx, obj.as(), obj.as(), id,
-            (op == JSOP_SETNAME || op == JSOP_SETGNAME)
+            (op == JSOP_SETNAME || op == JSOP_STRICTSETNAME ||
+             op == JSOP_SETGNAME)
             ? baseops::Unqualified
             : baseops::Qualified,
             &v,
diff --git a/js/src/jsopcode.h b/js/src/jsopcode.h
index e7fc97c39dbc..dafcebbb44c8 100644
--- a/js/src/jsopcode.h
+++ b/js/src/jsopcode.h
@@ -658,7 +658,8 @@ inline bool
 IsStrictSetPC(jsbytecode *pc)
 {
     JSOp op = JSOp(*pc);
-    return op == JSOP_STRICTSETPROP;
+    return op == JSOP_STRICTSETPROP ||
+           op == JSOP_STRICTSETNAME;
 }
 
 inline bool
@@ -666,7 +667,8 @@ IsSetPropPC(jsbytecode *pc)
 {
     JSOp op = JSOp(*pc);
     return op == JSOP_SETPROP || op == JSOP_STRICTSETPROP ||
-           op == JSOP_SETNAME || op == JSOP_SETGNAME;
+           op == JSOP_SETNAME || op == JSOP_STRICTSETNAME ||
+           op == JSOP_SETGNAME;
 }
 
 inline bool
diff --git a/js/src/vm/Interpreter-inl.h b/js/src/vm/Interpreter-inl.h
index 0e9fcf7e6f89..5c887f90d297 100644
--- a/js/src/vm/Interpreter-inl.h
+++ b/js/src/vm/Interpreter-inl.h
@@ -305,10 +305,13 @@ inline bool
 SetNameOperation(JSContext *cx, JSScript *script, jsbytecode *pc, HandleObject scope,
                  HandleValue val)
 {
-    MOZ_ASSERT(*pc == JSOP_SETNAME || *pc == JSOP_SETGNAME);
+    MOZ_ASSERT(*pc == JSOP_SETNAME ||
+               *pc == JSOP_STRICTSETNAME ||
+               *pc == JSOP_SETGNAME);
     MOZ_ASSERT_IF(*pc == JSOP_SETGNAME, scope == cx->global());
 
-    bool strict = script->strict();
+    // XXX: Removed later in stack. SETGNAME still relies on script.
+    bool strict = *pc == JSOP_STRICTSETNAME || script->strict();
     RootedPropertyName name(cx, script->getName(pc));
     RootedValue valCopy(cx, val);
 
diff --git a/js/src/vm/Interpreter.cpp b/js/src/vm/Interpreter.cpp
index bfde62e76593..4fafd8e06cad 100644
--- a/js/src/vm/Interpreter.cpp
+++ b/js/src/vm/Interpreter.cpp
@@ -1590,7 +1590,6 @@ CASE(EnableInterruptsPseudoOpcode)
 /* Various 1-byte no-ops. */
 CASE(JSOP_NOP)
 CASE(JSOP_UNUSED2)
-CASE(JSOP_UNUSED49)
 CASE(JSOP_UNUSED50)
 CASE(JSOP_UNUSED51)
 CASE(JSOP_UNUSED52)
@@ -2383,7 +2382,10 @@ END_CASE(JSOP_SETINTRINSIC)
 
 CASE(JSOP_SETGNAME)
 CASE(JSOP_SETNAME)
+CASE(JSOP_STRICTSETNAME)
 {
+    static_assert(JSOP_SETNAME_LENGTH == JSOP_STRICTSETNAME_LENGTH,
+                  "setname and strictsetname must be the same size");
     RootedObject &scope = rootObject0;
     scope = ®S.sp[-2].toObject();
     HandleValue value = REGS.stackHandleAt(-1);
diff --git a/js/src/vm/Opcodes.h b/js/src/vm/Opcodes.h
index 1ba848bc02df..39a4043eee77 100644
--- a/js/src/vm/Opcodes.h
+++ b/js/src/vm/Opcodes.h
@@ -457,7 +457,16 @@
      *   Stack: obj, val => val
      */ \
     macro(JSOP_STRICTSETPROP,   48, "strict-setprop",    NULL,         5,  2,  1, JOF_ATOM|JOF_PROP|JOF_SET|JOF_DETECTING|JOF_CHECKSTRICT) \
-    macro(JSOP_UNUSED49,  49, "unused49",   NULL,         1,  0,  0,  JOF_BYTE) \
+    /*
+     * Pops a scope and value from the stack, assigns value to the given name,
+     * and pushes the value back on the stack. If the set failed, then throw
+     * a TypeError, per usual strict mode semantics.
+     *   Category: Variables and Scopes
+     *   Type: Variables
+     *   Operands: uint32_t nameIndex
+     *   Stack: scope, val => val
+     */ \
+    macro(JSOP_STRICTSETNAME,   49, "strict-setname",    NULL,         5,  2,  1,  JOF_ATOM|JOF_NAME|JOF_SET|JOF_DETECTING|JOF_CHECKSTRICT) \
     macro(JSOP_UNUSED50,  50, "unused50",   NULL,         1,  0,  0,  JOF_BYTE) \
     macro(JSOP_UNUSED51,  51, "unused51",   NULL,         1,  0,  0,  JOF_BYTE) \
     macro(JSOP_UNUSED52,  52, "unused52",   NULL,         1,  0,  0,  JOF_BYTE) \
@@ -994,7 +1003,7 @@
      *   Operands: uint32_t nameIndex
      *   Stack: scope, val => val
      */ \
-    macro(JSOP_SETNAME,   111,"setname",    NULL,         5,  2,  1,  JOF_ATOM|JOF_NAME|JOF_SET|JOF_DETECTING) \
+    macro(JSOP_SETNAME,   111,"setname",    NULL,         5,  2,  1,  JOF_ATOM|JOF_NAME|JOF_SET|JOF_DETECTING|JOF_CHECKSLOPPY) \
     \
     /* Exception handling ops. */ \
     /*
diff --git a/js/src/vm/Xdr.h b/js/src/vm/Xdr.h
index 89572879a8f5..c3eeba0b91e3 100644
--- a/js/src/vm/Xdr.h
+++ b/js/src/vm/Xdr.h
@@ -34,7 +34,7 @@ namespace js {
  * Nightly) and without (all others).  FIXME: Bug 1066322 - Enable ES6 symbols
  * in all builds.
  */
-static const uint32_t XDR_BYTECODE_VERSION_SUBTRAHEND = 210;
+static const uint32_t XDR_BYTECODE_VERSION_SUBTRAHEND = 212;
 static_assert(XDR_BYTECODE_VERSION_SUBTRAHEND % 2 == 0, "see the comment above");
 static const uint32_t XDR_BYTECODE_VERSION =
     uint32_t(0xb973c0de - (XDR_BYTECODE_VERSION_SUBTRAHEND

From 641450c9ba5cdaa5a496065870073407ed866cf1 Mon Sep 17 00:00:00 2001
From: Eric Faust 
Date: Wed, 26 Nov 2014 14:42:52 -0800
Subject: [PATCH 39/64] Bug 1101905 - Part 4: Add strict variant of
 JSOP_SETGNAME. (r=Waldo)

---
 js/src/frontend/BytecodeEmitter.cpp | 24 ++++++++++++++++++------
 js/src/jit/BaselineCompiler.cpp     |  6 ++++++
 js/src/jit/BaselineCompiler.h       |  1 +
 js/src/jit/BaselineIC.cpp           |  4 +++-
 js/src/jit/IonBuilder.cpp           |  1 +
 js/src/jit/VMFunctions.cpp          |  2 +-
 js/src/jsopcode.h                   |  5 +++--
 js/src/vm/Interpreter-inl.h         |  7 ++++---
 js/src/vm/Interpreter.cpp           |  4 +++-
 js/src/vm/Opcodes.h                 | 15 +++++++++++++--
 js/src/vm/Xdr.h                     |  2 +-
 11 files changed, 54 insertions(+), 17 deletions(-)

diff --git a/js/src/frontend/BytecodeEmitter.cpp b/js/src/frontend/BytecodeEmitter.cpp
index 145be36657c7..2bf6beffd449 100644
--- a/js/src/frontend/BytecodeEmitter.cpp
+++ b/js/src/frontend/BytecodeEmitter.cpp
@@ -1522,6 +1522,10 @@ StrictifySetNameOp(JSOp op, BytecodeEmitter *bce)
         if (bce->sc->strict)
             op = JSOP_STRICTSETNAME;
         break;
+      case JSOP_SETGNAME:
+        if (bce->sc->strict)
+            op = JSOP_STRICTSETGNAME;
+        break;
         default:;
     }
     return op;
@@ -1658,7 +1662,7 @@ TryConvertFreeName(BytecodeEmitter *bce, ParseNode *pn)
     JSOp op;
     switch (pn->getOp()) {
       case JSOP_NAME:     op = JSOP_GETGNAME; break;
-      case JSOP_SETNAME:  op = JSOP_SETGNAME; break;
+      case JSOP_SETNAME:  op = StrictifySetNameOp(JSOP_SETGNAME, bce); break;
       case JSOP_SETCONST:
         // Not supported.
         return false;
@@ -3351,6 +3355,7 @@ EmitDestructuringLHS(ExclusiveContext *cx, BytecodeEmitter *bce, ParseNode *pn,
               case JSOP_SETNAME:
               case JSOP_STRICTSETNAME:
               case JSOP_SETGNAME:
+              case JSOP_STRICTSETGNAME:
               case JSOP_SETCONST: {
                 // This is like ordinary assignment, but with one difference.
                 //
@@ -3367,7 +3372,8 @@ EmitDestructuringLHS(ExclusiveContext *cx, BytecodeEmitter *bce, ParseNode *pn,
                     return false;
 
                 if (!pn->isOp(JSOP_SETCONST)) {
-                    JSOp bindOp = pn->isOp(JSOP_SETGNAME) ? JSOP_BINDGNAME : JSOP_BINDNAME;
+                    bool global = pn->isOp(JSOP_SETGNAME) || pn->isOp(JSOP_STRICTSETGNAME);
+                    JSOp bindOp = global ? JSOP_BINDGNAME : JSOP_BINDNAME;
                     if (!EmitIndex32(cx, bindOp, atomIndex, bce))
                         return false;
                     if (Emit1(cx, bce, JSOP_SWAP) < 0)
@@ -3893,12 +3899,17 @@ EmitVariables(ExclusiveContext *cx, BytecodeEmitter *bce, ParseNode *pn, VarEmit
 
         if (pn3) {
             MOZ_ASSERT(emitOption != DefineVars);
-            if (op == JSOP_SETNAME || op == JSOP_STRICTSETNAME || op == JSOP_SETGNAME || op == JSOP_SETINTRINSIC) {
+            if (op == JSOP_SETNAME ||
+                op == JSOP_STRICTSETNAME ||
+                op == JSOP_SETGNAME ||
+                op == JSOP_STRICTSETGNAME ||
+                op == JSOP_SETINTRINSIC)
+            {
                 MOZ_ASSERT(emitOption != PushInitialValues);
                 JSOp bindOp;
                 if (op == JSOP_SETNAME || op == JSOP_STRICTSETNAME)
                     bindOp = JSOP_BINDNAME;
-                else if (op == JSOP_SETGNAME)
+                else if (op == JSOP_SETGNAME || op == JSOP_STRICTSETGNAME)
                     bindOp = JSOP_BINDGNAME;
                 else
                     bindOp = JSOP_BINDINTRINSIC;
@@ -3974,7 +3985,7 @@ EmitAssignment(ExclusiveContext *cx, BytecodeEmitter *bce, ParseNode *lhs, JSOp
                 JSOp bindOp;
                 if (lhs->isOp(JSOP_SETNAME) || lhs->isOp(JSOP_STRICTSETNAME))
                     bindOp = JSOP_BINDNAME;
-                else if (lhs->isOp(JSOP_SETGNAME))
+                else if (lhs->isOp(JSOP_SETGNAME) || lhs->isOp(JSOP_STRICTSETGNAME))
                     bindOp = JSOP_BINDGNAME;
                 else
                     bindOp = JSOP_BINDINTRINSIC;
@@ -4034,7 +4045,7 @@ EmitAssignment(ExclusiveContext *cx, BytecodeEmitter *bce, ParseNode *lhs, JSOp
                     return false;
                 if (!EmitIndex32(cx, JSOP_GETXPROP, atomIndex, bce))
                     return false;
-            } else if (lhs->isOp(JSOP_SETGNAME)) {
+            } else if (lhs->isOp(JSOP_SETGNAME) || lhs->isOp(JSOP_STRICTSETGNAME)) {
                 MOZ_ASSERT(lhs->pn_cookie.isFree());
                 if (!EmitAtomOp(cx, lhs, JSOP_GETGNAME, bce))
                     return false;
@@ -6311,6 +6322,7 @@ EmitIncOrDec(ExclusiveContext *cx, BytecodeEmitter *bce, ParseNode *pn)
           case JSOP_SETNAME:
           case JSOP_STRICTSETNAME:
           case JSOP_SETGNAME:
+          case JSOP_STRICTSETGNAME:
             maySet = true;
             break;
           default:
diff --git a/js/src/jit/BaselineCompiler.cpp b/js/src/jit/BaselineCompiler.cpp
index d8a6f9c9e770..3a2e946cf650 100644
--- a/js/src/jit/BaselineCompiler.cpp
+++ b/js/src/jit/BaselineCompiler.cpp
@@ -2082,6 +2082,12 @@ BaselineCompiler::emit_JSOP_SETGNAME()
     return emit_JSOP_SETPROP();
 }
 
+bool
+BaselineCompiler::emit_JSOP_STRICTSETGNAME()
+{
+    return emit_JSOP_SETPROP();
+}
+
 bool
 BaselineCompiler::emit_JSOP_GETPROP()
 {
diff --git a/js/src/jit/BaselineCompiler.h b/js/src/jit/BaselineCompiler.h
index 09b1dc90ca9c..e4aa1d218092 100644
--- a/js/src/jit/BaselineCompiler.h
+++ b/js/src/jit/BaselineCompiler.h
@@ -115,6 +115,7 @@ namespace jit {
     _(JSOP_GETGNAME)           \
     _(JSOP_BINDGNAME)          \
     _(JSOP_SETGNAME)           \
+    _(JSOP_STRICTSETGNAME)     \
     _(JSOP_SETNAME)            \
     _(JSOP_STRICTSETNAME)      \
     _(JSOP_GETPROP)            \
diff --git a/js/src/jit/BaselineIC.cpp b/js/src/jit/BaselineIC.cpp
index 13eb448e7f7b..735c57b3ab06 100644
--- a/js/src/jit/BaselineIC.cpp
+++ b/js/src/jit/BaselineIC.cpp
@@ -7900,6 +7900,7 @@ DoSetPropFallback(JSContext *cx, BaselineFrame *frame, ICSetProp_Fallback *stub_
                op == JSOP_SETNAME ||
                op == JSOP_STRICTSETNAME ||
                op == JSOP_SETGNAME ||
+               op == JSOP_STRICTSETGNAME ||
                op == JSOP_INITPROP ||
                op == JSOP_SETALIASEDVAR ||
                op == JSOP_INITALIASEDLEXICAL);
@@ -7943,7 +7944,8 @@ DoSetPropFallback(JSContext *cx, BaselineFrame *frame, ICSetProp_Fallback *stub_
         }
     } else if (op == JSOP_SETNAME ||
                op == JSOP_STRICTSETNAME ||
-               op == JSOP_SETGNAME)
+               op == JSOP_SETGNAME ||
+               op == JSOP_STRICTSETGNAME)
     {
         if (!SetNameOperation(cx, script, pc, obj, rhs))
             return false;
diff --git a/js/src/jit/IonBuilder.cpp b/js/src/jit/IonBuilder.cpp
index 232d1a9c032e..697448bd502b 100644
--- a/js/src/jit/IonBuilder.cpp
+++ b/js/src/jit/IonBuilder.cpp
@@ -1680,6 +1680,7 @@ IonBuilder::inspectOpcode(JSOp op)
         return pushConstant(ObjectValue(script()->global()));
 
       case JSOP_SETGNAME:
+      case JSOP_STRICTSETGNAME:
       {
         PropertyName *name = info().getAtom(pc)->asPropertyName();
         JSObject *obj = &script()->global();
diff --git a/js/src/jit/VMFunctions.cpp b/js/src/jit/VMFunctions.cpp
index d3f87915d014..8c3dafb63762 100644
--- a/js/src/jit/VMFunctions.cpp
+++ b/js/src/jit/VMFunctions.cpp
@@ -508,7 +508,7 @@ SetProperty(JSContext *cx, HandleObject obj, HandlePropertyName name, HandleValu
         return baseops::SetPropertyHelper(
             cx, obj.as(), obj.as(), id,
             (op == JSOP_SETNAME || op == JSOP_STRICTSETNAME ||
-             op == JSOP_SETGNAME)
+             op == JSOP_SETGNAME || op == JSOP_STRICTSETGNAME)
             ? baseops::Unqualified
             : baseops::Qualified,
             &v,
diff --git a/js/src/jsopcode.h b/js/src/jsopcode.h
index dafcebbb44c8..426dfa19968d 100644
--- a/js/src/jsopcode.h
+++ b/js/src/jsopcode.h
@@ -659,7 +659,8 @@ IsStrictSetPC(jsbytecode *pc)
 {
     JSOp op = JSOp(*pc);
     return op == JSOP_STRICTSETPROP ||
-           op == JSOP_STRICTSETNAME;
+           op == JSOP_STRICTSETNAME ||
+           op == JSOP_STRICTSETGNAME;
 }
 
 inline bool
@@ -668,7 +669,7 @@ IsSetPropPC(jsbytecode *pc)
     JSOp op = JSOp(*pc);
     return op == JSOP_SETPROP || op == JSOP_STRICTSETPROP ||
            op == JSOP_SETNAME || op == JSOP_STRICTSETNAME ||
-           op == JSOP_SETGNAME;
+           op == JSOP_SETGNAME || op == JSOP_STRICTSETGNAME;
 }
 
 inline bool
diff --git a/js/src/vm/Interpreter-inl.h b/js/src/vm/Interpreter-inl.h
index 5c887f90d297..79d00b62a318 100644
--- a/js/src/vm/Interpreter-inl.h
+++ b/js/src/vm/Interpreter-inl.h
@@ -307,11 +307,12 @@ SetNameOperation(JSContext *cx, JSScript *script, jsbytecode *pc, HandleObject s
 {
     MOZ_ASSERT(*pc == JSOP_SETNAME ||
                *pc == JSOP_STRICTSETNAME ||
-               *pc == JSOP_SETGNAME);
+               *pc == JSOP_SETGNAME ||
+               *pc == JSOP_STRICTSETGNAME);
     MOZ_ASSERT_IF(*pc == JSOP_SETGNAME, scope == cx->global());
+    MOZ_ASSERT_IF(*pc == JSOP_STRICTSETGNAME, scope == cx->global());
 
-    // XXX: Removed later in stack. SETGNAME still relies on script.
-    bool strict = *pc == JSOP_STRICTSETNAME || script->strict();
+    bool strict = *pc == JSOP_STRICTSETNAME || *pc == JSOP_STRICTSETGNAME;
     RootedPropertyName name(cx, script->getName(pc));
     RootedValue valCopy(cx, val);
 
diff --git a/js/src/vm/Interpreter.cpp b/js/src/vm/Interpreter.cpp
index 4fafd8e06cad..c4e0f02fa944 100644
--- a/js/src/vm/Interpreter.cpp
+++ b/js/src/vm/Interpreter.cpp
@@ -1608,7 +1608,6 @@ CASE(JSOP_UNUSED147)
 CASE(JSOP_UNUSED148)
 CASE(JSOP_BACKPATCH)
 CASE(JSOP_UNUSED150)
-CASE(JSOP_UNUSED156)
 CASE(JSOP_UNUSED157)
 CASE(JSOP_UNUSED158)
 CASE(JSOP_UNUSED159)
@@ -2381,11 +2380,14 @@ CASE(JSOP_SETINTRINSIC)
 END_CASE(JSOP_SETINTRINSIC)
 
 CASE(JSOP_SETGNAME)
+CASE(JSOP_STRICTSETGNAME)
 CASE(JSOP_SETNAME)
 CASE(JSOP_STRICTSETNAME)
 {
     static_assert(JSOP_SETNAME_LENGTH == JSOP_STRICTSETNAME_LENGTH,
                   "setname and strictsetname must be the same size");
+    static_assert(JSOP_SETGNAME_LENGTH == JSOP_STRICTSETGNAME_LENGTH,
+                  "setganem adn strictsetgname must be the same size");
     RootedObject &scope = rootObject0;
     scope = ®S.sp[-2].toObject();
     HandleValue value = REGS.stackHandleAt(-1);
diff --git a/js/src/vm/Opcodes.h b/js/src/vm/Opcodes.h
index 39a4043eee77..a11796dba292 100644
--- a/js/src/vm/Opcodes.h
+++ b/js/src/vm/Opcodes.h
@@ -1444,9 +1444,20 @@
      *   Operands: uint32_t nameIndex
      *   Stack: scope, val => val
      */ \
-    macro(JSOP_SETGNAME,      155,"setgname",  NULL,       5,  2,  1, JOF_ATOM|JOF_NAME|JOF_SET|JOF_DETECTING|JOF_GNAME) \
+    macro(JSOP_SETGNAME,      155,"setgname",  NULL,       5,  2,  1, JOF_ATOM|JOF_NAME|JOF_SET|JOF_DETECTING|JOF_GNAME|JOF_CHECKSLOPPY) \
     \
-    macro(JSOP_UNUSED156,  156, "unused156",   NULL,         1,  0,  0,  JOF_BYTE) \
+    /*
+     * Pops the top two values on the stack as 'val' and 'scope', sets property
+     * of 'scope' as 'val' and pushes 'val' back on the stack. Throws a
+     * TypeError if the set fails, per strict mode semantics.
+     *
+     * 'scope' should be the global scope.
+     *   Category: Variables and Scopes
+     *   Type: Free Variables
+     *   Operands: uint32_t nameIndex
+     *   Stack: scope, val => val
+     */ \
+    macro(JSOP_STRICTSETGNAME, 156, "strict-setgname",  NULL,       5,  2,  1, JOF_ATOM|JOF_NAME|JOF_SET|JOF_DETECTING|JOF_GNAME|JOF_CHECKSTRICT) \
     macro(JSOP_UNUSED157,  157, "unused157",   NULL,         1,  0,  0,  JOF_BYTE) \
     macro(JSOP_UNUSED158,  158, "unused158",   NULL,         1,  0,  0,  JOF_BYTE) \
     macro(JSOP_UNUSED159,  159, "unused159",   NULL,         1,  0,  0,  JOF_BYTE) \
diff --git a/js/src/vm/Xdr.h b/js/src/vm/Xdr.h
index c3eeba0b91e3..453e872f2ba4 100644
--- a/js/src/vm/Xdr.h
+++ b/js/src/vm/Xdr.h
@@ -34,7 +34,7 @@ namespace js {
  * Nightly) and without (all others).  FIXME: Bug 1066322 - Enable ES6 symbols
  * in all builds.
  */
-static const uint32_t XDR_BYTECODE_VERSION_SUBTRAHEND = 212;
+static const uint32_t XDR_BYTECODE_VERSION_SUBTRAHEND = 214;
 static_assert(XDR_BYTECODE_VERSION_SUBTRAHEND % 2 == 0, "see the comment above");
 static const uint32_t XDR_BYTECODE_VERSION =
     uint32_t(0xb973c0de - (XDR_BYTECODE_VERSION_SUBTRAHEND

From beb5247aaad567c362b601944e147a3c9003a7a8 Mon Sep 17 00:00:00 2001
From: Eric Faust 
Date: Wed, 26 Nov 2014 14:42:52 -0800
Subject: [PATCH 40/64] Bug 1101905 - Part 5: Add strict variant of
 JSOP_SETELEM. (r=Waldo)

---
 js/src/frontend/BytecodeEmitter.cpp | 16 ++++++++++++----
 js/src/jit/BaselineCompiler.cpp     |  6 ++++++
 js/src/jit/BaselineCompiler.h       |  1 +
 js/src/jit/BaselineIC.cpp           |  3 ++-
 js/src/jit/IonBuilder.cpp           |  4 +++-
 js/src/jsopcode.h                   |  6 ++++--
 js/src/vm/Interpreter.cpp           |  6 ++++--
 js/src/vm/Opcodes.h                 | 14 ++++++++++++--
 js/src/vm/Xdr.h                     |  2 +-
 9 files changed, 45 insertions(+), 13 deletions(-)

diff --git a/js/src/frontend/BytecodeEmitter.cpp b/js/src/frontend/BytecodeEmitter.cpp
index 2bf6beffd449..3fceb58a37ad 100644
--- a/js/src/frontend/BytecodeEmitter.cpp
+++ b/js/src/frontend/BytecodeEmitter.cpp
@@ -2511,7 +2511,8 @@ EmitElemOperands(ExclusiveContext *cx, ParseNode *pn, JSOp op, BytecodeEmitter *
         return false;
     if (!EmitTree(cx, bce, pn->pn_right))
         return false;
-    if (op == JSOP_SETELEM && Emit2(cx, bce, JSOP_PICK, (jsbytecode)2) < 0)
+    bool isSetElem = op == JSOP_SETELEM || op == JSOP_STRICTSETELEM;
+    if (isSetElem && Emit2(cx, bce, JSOP_PICK, (jsbytecode)2) < 0)
         return false;
     return true;
 }
@@ -2571,7 +2572,8 @@ EmitElemIncDec(ExclusiveContext *cx, ParseNode *pn, BytecodeEmitter *bce)
             return false;
     }
 
-    if (!EmitElemOpBase(cx, bce, JSOP_SETELEM))     // N? N+1
+    JSOp setOp = bce->sc->strict ? JSOP_STRICTSETELEM : JSOP_SETELEM;
+    if (!EmitElemOpBase(cx, bce, setOp))     // N? N+1
         return false;
     if (post && Emit1(cx, bce, JSOP_POP) < 0)       // RESULT
         return false;
@@ -3418,12 +3420,15 @@ EmitDestructuringLHS(ExclusiveContext *cx, BytecodeEmitter *bce, ParseNode *pn,
           }
 
           case PNK_ELEM:
+          {
             // See the comment at `case PNK_DOT:` above. This case,
             // `[a[x]] = [b]`, is handled much the same way. The JSOP_SWAP
             // is emitted by EmitElemOperands.
-            if (!EmitElemOp(cx, pn, JSOP_SETELEM, bce))
+            JSOp setOp = bce->sc->strict ? JSOP_STRICTSETELEM : JSOP_SETELEM;
+            if (!EmitElemOp(cx, pn, setOp, bce))
                 return false;
             break;
+          }
 
           case PNK_CALL:
             MOZ_ASSERT(pn->pn_xflags & PNX_SETCALL);
@@ -4147,9 +4152,12 @@ EmitAssignment(ExclusiveContext *cx, BytecodeEmitter *bce, ParseNode *lhs, JSOp
         MOZ_ASSERT(lhs->pn_xflags & PNX_SETCALL);
         break;
       case PNK_ELEM:
-        if (Emit1(cx, bce, JSOP_SETELEM) < 0)
+      {
+        JSOp setOp = bce->sc->strict ? JSOP_STRICTSETELEM : JSOP_SETELEM;
+        if (Emit1(cx, bce, setOp) < 0)
             return false;
         break;
+      }
       case PNK_ARRAY:
       case PNK_OBJECT:
         if (!EmitDestructuringOps(cx, bce, lhs))
diff --git a/js/src/jit/BaselineCompiler.cpp b/js/src/jit/BaselineCompiler.cpp
index 3a2e946cf650..af45e723cf37 100644
--- a/js/src/jit/BaselineCompiler.cpp
+++ b/js/src/jit/BaselineCompiler.cpp
@@ -1957,6 +1957,12 @@ BaselineCompiler::emit_JSOP_SETELEM()
     return true;
 }
 
+bool
+BaselineCompiler::emit_JSOP_STRICTSETELEM()
+{
+    return emit_JSOP_SETELEM();
+}
+
 typedef bool (*DeleteElementFn)(JSContext *, HandleValue, HandleValue, bool *);
 static const VMFunction DeleteElementStrictInfo = FunctionInfo(DeleteElement);
 static const VMFunction DeleteElementNonStrictInfo = FunctionInfo(DeleteElement);
diff --git a/js/src/jit/BaselineCompiler.h b/js/src/jit/BaselineCompiler.h
index e4aa1d218092..233b96bdc4df 100644
--- a/js/src/jit/BaselineCompiler.h
+++ b/js/src/jit/BaselineCompiler.h
@@ -108,6 +108,7 @@ namespace jit {
     _(JSOP_ARRAYPUSH)          \
     _(JSOP_GETELEM)            \
     _(JSOP_SETELEM)            \
+    _(JSOP_STRICTSETELEM)      \
     _(JSOP_CALLELEM)           \
     _(JSOP_DELELEM)            \
     _(JSOP_STRICTDELELEM)      \
diff --git a/js/src/jit/BaselineIC.cpp b/js/src/jit/BaselineIC.cpp
index 735c57b3ab06..cff6220ab086 100644
--- a/js/src/jit/BaselineIC.cpp
+++ b/js/src/jit/BaselineIC.cpp
@@ -5014,6 +5014,7 @@ DoSetElemFallback(JSContext *cx, BaselineFrame *frame, ICSetElem_Fallback *stub_
     FallbackICSpew(cx, stub, "SetElem(%s)", js_CodeName[JSOp(*pc)]);
 
     MOZ_ASSERT(op == JSOP_SETELEM ||
+               op == JSOP_STRICTSETELEM ||
                op == JSOP_INITELEM ||
                op == JSOP_INITELEM_ARRAY ||
                op == JSOP_INITELEM_INC);
@@ -5043,7 +5044,7 @@ DoSetElemFallback(JSContext *cx, BaselineFrame *frame, ICSetElem_Fallback *stub_
         if (!InitArrayElemOperation(cx, pc, obj, index.toInt32(), rhs))
             return false;
     } else {
-        if (!SetObjectElement(cx, obj, index, rhs, script->strict(), script, pc))
+        if (!SetObjectElement(cx, obj, index, rhs, JSOp(*pc) == JSOP_STRICTSETELEM, script, pc))
             return false;
     }
 
diff --git a/js/src/jit/IonBuilder.cpp b/js/src/jit/IonBuilder.cpp
index 697448bd502b..40c6f6f93b60 100644
--- a/js/src/jit/IonBuilder.cpp
+++ b/js/src/jit/IonBuilder.cpp
@@ -1738,6 +1738,7 @@ IonBuilder::inspectOpcode(JSOp op)
         return jsop_getelem();
 
       case JSOP_SETELEM:
+      case JSOP_STRICTSETELEM:
         return jsop_setelem();
 
       case JSOP_LENGTH:
@@ -8538,7 +8539,8 @@ IonBuilder::setElemTryCache(bool *emitted, MDefinition *object,
         current->add(MPostWriteBarrier::New(alloc(), object, value));
 
     // Emit SetElementCache.
-    MInstruction *ins = MSetElementCache::New(alloc(), object, index, value, script()->strict(), guardHoles);
+    bool strict = JSOp(*pc) == JSOP_STRICTSETELEM;
+    MInstruction *ins = MSetElementCache::New(alloc(), object, index, value, strict, guardHoles);
     current->add(ins);
     current->push(value);
 
diff --git a/js/src/jsopcode.h b/js/src/jsopcode.h
index 426dfa19968d..642da433656e 100644
--- a/js/src/jsopcode.h
+++ b/js/src/jsopcode.h
@@ -660,7 +660,8 @@ IsStrictSetPC(jsbytecode *pc)
     JSOp op = JSOp(*pc);
     return op == JSOP_STRICTSETPROP ||
            op == JSOP_STRICTSETNAME ||
-           op == JSOP_STRICTSETGNAME;
+           op == JSOP_STRICTSETGNAME ||
+           op == JSOP_STRICTSETELEM;
 }
 
 inline bool
@@ -683,7 +684,8 @@ inline bool
 IsSetElemPC(jsbytecode *pc)
 {
     JSOp op = JSOp(*pc);
-    return op == JSOP_SETELEM;
+    return op == JSOP_SETELEM ||
+           op == JSOP_STRICTSETELEM;
 }
 
 inline bool
diff --git a/js/src/vm/Interpreter.cpp b/js/src/vm/Interpreter.cpp
index c4e0f02fa944..7f9f5f760b09 100644
--- a/js/src/vm/Interpreter.cpp
+++ b/js/src/vm/Interpreter.cpp
@@ -1593,7 +1593,6 @@ CASE(JSOP_UNUSED2)
 CASE(JSOP_UNUSED50)
 CASE(JSOP_UNUSED51)
 CASE(JSOP_UNUSED52)
-CASE(JSOP_UNUSED57)
 CASE(JSOP_UNUSED83)
 CASE(JSOP_UNUSED92)
 CASE(JSOP_UNUSED103)
@@ -2438,13 +2437,16 @@ CASE(JSOP_CALLELEM)
 END_CASE(JSOP_GETELEM)
 
 CASE(JSOP_SETELEM)
+CASE(JSOP_STRICTSETELEM)
 {
+    static_assert(JSOP_SETELEM_LENGTH == JSOP_STRICTSETELEM_LENGTH,
+                  "setelem and strictsetelem must be the same size");
     RootedObject &obj = rootObject0;
     FETCH_OBJECT(cx, -3, obj);
     RootedId &id = rootId0;
     FETCH_ELEMENT_ID(-2, id);
     Value &value = REGS.sp[-1];
-    if (!SetObjectElementOperation(cx, obj, id, value, script->strict()))
+    if (!SetObjectElementOperation(cx, obj, id, value, *REGS.pc == JSOP_STRICTSETELEM))
         goto error;
     REGS.sp[-3] = value;
     REGS.sp -= 2;
diff --git a/js/src/vm/Opcodes.h b/js/src/vm/Opcodes.h
index a11796dba292..a4d6e80ba02c 100644
--- a/js/src/vm/Opcodes.h
+++ b/js/src/vm/Opcodes.h
@@ -506,8 +506,18 @@
      *   Operands:
      *   Stack: obj, propval, val => val
      */ \
-    macro(JSOP_SETELEM,   56, "setelem",    NULL,         1,  3,  1, JOF_BYTE |JOF_ELEM|JOF_SET|JOF_DETECTING) \
-    macro(JSOP_UNUSED57,  57, "unused57",   NULL,         1,  0,  0, JOF_BYTE) \
+    macro(JSOP_SETELEM,   56, "setelem",    NULL,         1,  3,  1, JOF_BYTE |JOF_ELEM|JOF_SET|JOF_DETECTING|JOF_CHECKSLOPPY) \
+    /*
+     * Pops the top three values on the stack as 'val', 'propval' and 'obj',
+     * sets 'propval' property of 'obj' as 'val', pushes 'obj' onto the
+     * stack. Throws a TypeError if the set fails, per strict mode
+     * semantics.
+     *   Category: Literals
+     *   Type: Object
+     *   Operands:
+     *   Stack: obj, propval, val => val
+     */ \
+    macro(JSOP_STRICTSETELEM,   57, "strict-setelem",    NULL,         1,  3,  1, JOF_BYTE |JOF_ELEM|JOF_SET|JOF_DETECTING|JOF_CHECKSTRICT) \
     /*
      * Invokes 'callee' with 'this' and 'args', pushes return value onto the
      * stack.
diff --git a/js/src/vm/Xdr.h b/js/src/vm/Xdr.h
index 453e872f2ba4..b1ec7f42af97 100644
--- a/js/src/vm/Xdr.h
+++ b/js/src/vm/Xdr.h
@@ -34,7 +34,7 @@ namespace js {
  * Nightly) and without (all others).  FIXME: Bug 1066322 - Enable ES6 symbols
  * in all builds.
  */
-static const uint32_t XDR_BYTECODE_VERSION_SUBTRAHEND = 214;
+static const uint32_t XDR_BYTECODE_VERSION_SUBTRAHEND = 216;
 static_assert(XDR_BYTECODE_VERSION_SUBTRAHEND % 2 == 0, "see the comment above");
 static const uint32_t XDR_BYTECODE_VERSION =
     uint32_t(0xb973c0de - (XDR_BYTECODE_VERSION_SUBTRAHEND

From 39e2ec2d3c9c024f4c10cfb92a2dfeabf5d5ffa3 Mon Sep 17 00:00:00 2001
From: Eric Faust 
Date: Wed, 26 Nov 2014 14:42:53 -0800
Subject: [PATCH 41/64] Bug 1101905 - Part 6: Cleanup remaining uses of
 JSScript::strict() in property set paths. (r=Waldo)

---
 js/src/jit/IonBuilder.cpp  | 6 ++----
 js/src/jsfriendapi.cpp     | 2 +-
 js/src/vm/NativeObject.cpp | 5 +++--
 3 files changed, 6 insertions(+), 7 deletions(-)

diff --git a/js/src/jit/IonBuilder.cpp b/js/src/jit/IonBuilder.cpp
index 40c6f6f93b60..f90c5d8e4366 100644
--- a/js/src/jit/IonBuilder.cpp
+++ b/js/src/jit/IonBuilder.cpp
@@ -10069,8 +10069,7 @@ IonBuilder::jsop_setprop(PropertyName *name)
     // Always use a call if we are doing the definite properties analysis and
     // not actually emitting code, to simplify later analysis.
     if (info().executionModeIsAnalysis()) {
-        // XXX: Dropped later in stack, but for now other ops rely on the old mechanic.
-        bool strict = IsStrictSetPC(pc) || script()->strict();
+        bool strict = IsStrictSetPC(pc);
         MInstruction *ins = MCallSetProperty::New(alloc(), obj, value, name, strict);
         current->add(ins);
         current->push(value);
@@ -10452,8 +10451,7 @@ IonBuilder::setPropTryCache(bool *emitted, MDefinition *obj,
 {
     MOZ_ASSERT(*emitted == false);
 
-    // XXX Dropped later in stack, but while others rely on it, we must retain the check.
-    bool strict = IsStrictSetPC(pc) || script()->strict();
+    bool strict = IsStrictSetPC(pc);
     // Emit SetPropertyCache.
     MSetPropertyCache *ins = MSetPropertyCache::New(alloc(), obj, value, name, strict, barrier);
 
diff --git a/js/src/jsfriendapi.cpp b/js/src/jsfriendapi.cpp
index c86b03447863..230676e8718f 100644
--- a/js/src/jsfriendapi.cpp
+++ b/js/src/jsfriendapi.cpp
@@ -365,7 +365,7 @@ js::IsInNonStrictPropertySet(JSContext *cx)
 {
     jsbytecode *pc;
     JSScript *script = cx->currentScript(&pc, JSContext::ALLOW_CROSS_COMPARTMENT);
-    return script && !script->strict() && (js_CodeSpec[*pc].format & JOF_SET);
+    return script && !IsStrictSetPC(pc) && (js_CodeSpec[*pc].format & JOF_SET);
 }
 
 JS_FRIEND_API(bool)
diff --git a/js/src/vm/NativeObject.cpp b/js/src/vm/NativeObject.cpp
index a92d653038e8..8caaf6fd1ac6 100644
--- a/js/src/vm/NativeObject.cpp
+++ b/js/src/vm/NativeObject.cpp
@@ -1917,13 +1917,14 @@ static bool
 MaybeReportUndeclaredVarAssignment(JSContext *cx, JSString *propname)
 {
     {
-        JSScript *script = cx->currentScript(nullptr, JSContext::ALLOW_CROSS_COMPARTMENT);
+        jsbytecode *pc;
+        JSScript *script = cx->currentScript(&pc, JSContext::ALLOW_CROSS_COMPARTMENT);
         if (!script)
             return true;
 
         // If the code is not strict and extra warnings aren't enabled, then no
         // check is needed.
-        if (!script->strict() && !cx->compartment()->options().extraWarnings(cx))
+        if (!IsStrictSetPC(pc) && !cx->compartment()->options().extraWarnings(cx))
             return true;
     }
 

From 215779c22f6e021d23556efc08e9b9bed43c158a Mon Sep 17 00:00:00 2001
From: Eric Faust 
Date: Wed, 26 Nov 2014 14:42:53 -0800
Subject: [PATCH 42/64] Bug 1101905 - Part 7: Use CompileOptions to pass
 strictness in eval, rather than the invoking script. (r=Waldo)

---
 js/src/builtin/Eval.cpp              | 6 ++++--
 js/src/frontend/BytecodeCompiler.cpp | 8 +++-----
 js/src/jsapi.h                       | 4 ++++
 js/src/vm/Debugger.cpp               | 3 ++-
 4 files changed, 13 insertions(+), 8 deletions(-)

diff --git a/js/src/builtin/Eval.cpp b/js/src/builtin/Eval.cpp
index dc34a8fbf69a..9e87d0907710 100644
--- a/js/src/builtin/Eval.cpp
+++ b/js/src/builtin/Eval.cpp
@@ -320,7 +320,8 @@ EvalKernel(JSContext *cx, const CallArgs &args, EvalType evalType, AbstractFrame
                .setForEval(true)
                .setNoScriptRval(false)
                .setMutedErrors(mutedErrors)
-               .setIntroductionInfo(introducerFilename, "eval", lineno, maybeScript, pcOffset);
+               .setIntroductionInfo(introducerFilename, "eval", lineno, maybeScript, pcOffset)
+               .maybeMakeStrictMode(evalType == DIRECT_EVAL && callerScript && callerScript->strict());
 
         AutoStableStringChars flatChars(cx);
         if (!flatChars.initTwoByte(cx, flatStr))
@@ -393,7 +394,8 @@ js::DirectEvalStringFromIon(JSContext *cx,
                .setForEval(true)
                .setNoScriptRval(false)
                .setMutedErrors(mutedErrors)
-               .setIntroductionInfo(introducerFilename, "eval", lineno, maybeScript, pcOffset);
+               .setIntroductionInfo(introducerFilename, "eval", lineno, maybeScript, pcOffset)
+               .maybeMakeStrictMode(callerScript->strict());
 
         AutoStableStringChars flatChars(cx);
         if (!flatChars.initTwoByte(cx, flatStr))
diff --git a/js/src/frontend/BytecodeCompiler.cpp b/js/src/frontend/BytecodeCompiler.cpp
index 5f87964d959d..88d8be9d35f0 100644
--- a/js/src/frontend/BytecodeCompiler.cpp
+++ b/js/src/frontend/BytecodeCompiler.cpp
@@ -235,6 +235,7 @@ frontend::CompileScript(ExclusiveContext *cx, LifoAlloc *alloc, HandleObject sco
      */
     MOZ_ASSERT_IF(evalCaller, options.compileAndGo);
     MOZ_ASSERT_IF(evalCaller, options.forEval);
+    MOZ_ASSERT_IF(evalCaller && evalCaller->strict(), options.strictOption);
     MOZ_ASSERT_IF(staticLevel != 0, evalCaller);
 
     if (!CheckLength(cx, srcBuf))
@@ -314,10 +315,6 @@ frontend::CompileScript(ExclusiveContext *cx, LifoAlloc *alloc, HandleObject sco
     if (!pc->init(parser.tokenStream))
         return nullptr;
 
-    /* If this is a direct call to eval, inherit the caller's strictness.  */
-    if (evalCaller && evalCaller->strict())
-        globalsc.strict = true;
-
     if (savedCallerFun) {
         /*
          * An eval script in a caller frame needs to have its enclosing
@@ -325,7 +322,8 @@ frontend::CompileScript(ExclusiveContext *cx, LifoAlloc *alloc, HandleObject sco
          * wishes to decompile it while it's running.
          */
         JSFunction *fun = evalCaller->functionOrCallerFunction();
-        Directives directives(/* strict = */ fun->strict());
+        MOZ_ASSERT_IF(fun->strict(), options.strictOption);
+        Directives directives(/* strict = */ options.strictOption);
         ObjectBox *funbox = parser.newFunctionBox(/* fn = */ nullptr, fun, pc.ptr(),
                                                   directives, fun->generatorKind());
         if (!funbox)
diff --git a/js/src/jsapi.h b/js/src/jsapi.h
index d7e6baea8379..547c7217b29c 100644
--- a/js/src/jsapi.h
+++ b/js/src/jsapi.h
@@ -3902,6 +3902,10 @@ class MOZ_STACK_CLASS JS_FRIEND_API(CompileOptions) : public ReadOnlyCompileOpti
         hasIntroductionInfo = true;
         return *this;
     }
+    CompileOptions &maybeMakeStrictMode(bool strict) {
+        strictOption = strictOption || strict;
+        return *this;
+    }
 
   private:
     void operator=(const CompileOptions &rhs) MOZ_DELETE;
diff --git a/js/src/vm/Debugger.cpp b/js/src/vm/Debugger.cpp
index ac50abc4da33..9a62ec31faba 100644
--- a/js/src/vm/Debugger.cpp
+++ b/js/src/vm/Debugger.cpp
@@ -5629,7 +5629,8 @@ js::EvaluateInEnv(JSContext *cx, Handle env, HandleValue thisv, AbstractFr
            .setNoScriptRval(false)
            .setFileAndLine(filename, lineno)
            .setCanLazilyParse(false)
-           .setIntroductionType("debugger eval");
+           .setIntroductionType("debugger eval")
+           .maybeMakeStrictMode(frame ? frame.script()->strict() : false);
     RootedScript callerScript(cx, frame ? frame.script() : nullptr);
     SourceBufferHolder srcBuf(chars.start().get(), chars.length(), SourceBufferHolder::NoOwnership);
     RootedScript script(cx, frontend::CompileScript(cx, &cx->tempLifoAlloc(), env, callerScript,

From 9dc4eb86d66bc374384d50b795b89337f5417f64 Mon Sep 17 00:00:00 2001
From: Eric Faust 
Date: Wed, 26 Nov 2014 14:42:53 -0800
Subject: [PATCH 43/64] Bug 1101905 - Part 8: Add strict variants of JSOP_EVAL
 and JSOP_SPREADEVAL. (r=Waldo)

---
 js/src/builtin/Eval.cpp             | 21 ++++++++-----------
 js/src/frontend/BytecodeEmitter.cpp |  6 +++++-
 js/src/frontend/Parser.cpp          | 18 +++++++++++-----
 js/src/jit/BaselineCompiler.cpp     | 12 +++++++++++
 js/src/jit/BaselineCompiler.h       |  2 ++
 js/src/jit/BaselineIC.cpp           | 14 +++++++++----
 js/src/jit/IonBuilder.cpp           |  1 +
 js/src/jsopcode.cpp                 |  2 +-
 js/src/jsopcode.h                   |  7 +++++++
 js/src/jsscript.cpp                 | 12 ++++++++---
 js/src/vm/Interpreter.cpp           |  9 ++++++--
 js/src/vm/Opcodes.h                 | 32 +++++++++++++++++++++++++----
 js/src/vm/Xdr.h                     |  2 +-
 13 files changed, 104 insertions(+), 34 deletions(-)

diff --git a/js/src/builtin/Eval.cpp b/js/src/builtin/Eval.cpp
index 9e87d0907710..b21d3bff5849 100644
--- a/js/src/builtin/Eval.cpp
+++ b/js/src/builtin/Eval.cpp
@@ -191,15 +191,8 @@ ParseEvalStringAsJSON(JSContext *cx, const mozilla::Range chars, Mu
 }
 
 static EvalJSONResult
-TryEvalJSON(JSContext *cx, JSScript *callerScript, JSFlatString *str, MutableHandleValue rval)
+TryEvalJSON(JSContext *cx, JSFlatString *str, MutableHandleValue rval)
 {
-    // Don't use the JSON parser if the caller is strict mode code, because in
-    // strict mode object literals must not have repeated properties, and the
-    // JSON parser cheerfully (and correctly) accepts them.  If you're parsing
-    // JSON with eval and using strict mode, you deserve to be slow.
-    if (callerScript && callerScript->strict())
-        return EvalJSON_NotJSON;
-
     if (str->hasLatin1Chars()) {
         AutoCheckCannotGC nogc;
         if (!EvalStringMightBeJSON(str->latin1Range(nogc)))
@@ -289,7 +282,7 @@ EvalKernel(JSContext *cx, const CallArgs &args, EvalType evalType, AbstractFrame
         return false;
 
     RootedScript callerScript(cx, caller ? caller.script() : nullptr);
-    EvalJSONResult ejr = TryEvalJSON(cx, callerScript, flatStr, args.rval());
+    EvalJSONResult ejr = TryEvalJSON(cx, flatStr, args.rval());
     if (ejr != EvalJSON_NotJSON)
         return ejr == EvalJSON_Success;
 
@@ -321,7 +314,7 @@ EvalKernel(JSContext *cx, const CallArgs &args, EvalType evalType, AbstractFrame
                .setNoScriptRval(false)
                .setMutedErrors(mutedErrors)
                .setIntroductionInfo(introducerFilename, "eval", lineno, maybeScript, pcOffset)
-               .maybeMakeStrictMode(evalType == DIRECT_EVAL && callerScript && callerScript->strict());
+               .maybeMakeStrictMode(evalType == DIRECT_EVAL && IsStrictEvalPC(pc));
 
         AutoStableStringChars flatChars(cx);
         if (!flatChars.initTwoByte(cx, flatStr))
@@ -367,7 +360,7 @@ js::DirectEvalStringFromIon(JSContext *cx,
     if (!flatStr)
         return false;
 
-    EvalJSONResult ejr = TryEvalJSON(cx, callerScript, flatStr, vp);
+    EvalJSONResult ejr = TryEvalJSON(cx, flatStr, vp);
     if (ejr != EvalJSON_NotJSON)
         return ejr == EvalJSON_Success;
 
@@ -395,7 +388,7 @@ js::DirectEvalStringFromIon(JSContext *cx,
                .setNoScriptRval(false)
                .setMutedErrors(mutedErrors)
                .setIntroductionInfo(introducerFilename, "eval", lineno, maybeScript, pcOffset)
-               .maybeMakeStrictMode(callerScript->strict());
+               .maybeMakeStrictMode(IsStrictEvalPC(pc));
 
         AutoStableStringChars flatChars(cx);
         if (!flatChars.initTwoByte(cx, flatStr))
@@ -456,7 +449,9 @@ js::DirectEval(JSContext *cx, const CallArgs &args)
 
     MOZ_ASSERT(caller.scopeChain()->global().valueIsEval(args.calleev()));
     MOZ_ASSERT(JSOp(*iter.pc()) == JSOP_EVAL ||
-               JSOp(*iter.pc()) == JSOP_SPREADEVAL);
+               JSOp(*iter.pc()) == JSOP_STRICTEVAL ||
+               JSOp(*iter.pc()) == JSOP_SPREADEVAL ||
+               JSOp(*iter.pc()) == JSOP_STRICTSPREADEVAL);
     MOZ_ASSERT_IF(caller.isFunctionFrame(),
                   caller.compartment() == caller.callee()->compartment());
 
diff --git a/js/src/frontend/BytecodeEmitter.cpp b/js/src/frontend/BytecodeEmitter.cpp
index 3fceb58a37ad..775b5d5e100c 100644
--- a/js/src/frontend/BytecodeEmitter.cpp
+++ b/js/src/frontend/BytecodeEmitter.cpp
@@ -6210,7 +6210,11 @@ EmitCallOrNew(ExclusiveContext *cx, BytecodeEmitter *bce, ParseNode *pn)
             return false;
     }
     CheckTypeSet(cx, bce, pn->getOp());
-    if (pn->isOp(JSOP_EVAL) || pn->isOp(JSOP_SPREADEVAL)) {
+    if (pn->isOp(JSOP_EVAL) ||
+        pn->isOp(JSOP_STRICTEVAL) ||
+        pn->isOp(JSOP_SPREADEVAL) ||
+        pn->isOp(JSOP_STRICTSPREADEVAL))
+    {
         uint32_t lineNum = bce->parser->tokenStream.srcCoords.lineNum(pn->pn_pos.begin);
         EMIT_UINT16_IMM_OP(JSOP_LINENO, lineNum);
     }
diff --git a/js/src/frontend/Parser.cpp b/js/src/frontend/Parser.cpp
index 9a44ec1d64cf..e6c92aa9f852 100644
--- a/js/src/frontend/Parser.cpp
+++ b/js/src/frontend/Parser.cpp
@@ -3251,7 +3251,8 @@ Parser::makeSetCall(ParseNode *pn, unsigned msg)
     MOZ_ASSERT(pn->isKind(PNK_CALL));
     MOZ_ASSERT(pn->isArity(PN_LIST));
     MOZ_ASSERT(pn->isOp(JSOP_CALL) || pn->isOp(JSOP_SPREADCALL) ||
-               pn->isOp(JSOP_EVAL) || pn->isOp(JSOP_SPREADEVAL) ||
+               pn->isOp(JSOP_EVAL) || pn->isOp(JSOP_STRICTEVAL) ||
+               pn->isOp(JSOP_SPREADEVAL) || pn->isOp(JSOP_STRICTSPREADEVAL) ||
                pn->isOp(JSOP_FUNCALL) || pn->isOp(JSOP_FUNAPPLY));
 
     if (!report(ParseStrictError, pc->sc->strict, pn, msg))
@@ -6251,7 +6252,8 @@ Parser::checkAndMarkAsIncOperand(ParseNode *kid, TokenKind tt,
         !kid->isKind(PNK_ELEM) &&
         !(kid->isKind(PNK_CALL) &&
           (kid->isOp(JSOP_CALL) || kid->isOp(JSOP_SPREADCALL) ||
-           kid->isOp(JSOP_EVAL) || kid->isOp(JSOP_SPREADEVAL) ||
+           kid->isOp(JSOP_EVAL) || kid->isOp(JSOP_STRICTEVAL) ||
+           kid->isOp(JSOP_SPREADEVAL) || kid->isOp(JSOP_STRICTSPREADEVAL) ||
            kid->isOp(JSOP_FUNCALL) ||
            kid->isOp(JSOP_FUNAPPLY))))
     {
@@ -7534,7 +7536,7 @@ Parser::memberExpr(TokenKind tt, bool allowCallSyntax)
             if (JSAtom *atom = handler.isName(lhs)) {
                 if (tt == TOK_LP && atom == context->names().eval) {
                     /* Select JSOP_EVAL and flag pc as heavyweight. */
-                    op = JSOP_EVAL;
+                    op = pc->sc->strict ? JSOP_STRICTEVAL : JSOP_EVAL;
                     pc->sc->setBindingsAccessedDynamically();
 
                     /*
@@ -7562,8 +7564,14 @@ Parser::memberExpr(TokenKind tt, bool allowCallSyntax)
                 bool isSpread = false;
                 if (!argumentList(nextMember, &isSpread))
                     return null();
-                if (isSpread)
-                    op = (op == JSOP_EVAL ? JSOP_SPREADEVAL : JSOP_SPREADCALL);
+                if (isSpread) {
+                    if (op == JSOP_EVAL)
+                        op = JSOP_SPREADEVAL;
+                    else if (op == JSOP_STRICTEVAL)
+                        op = JSOP_STRICTSPREADEVAL;
+                    else
+                        op = JSOP_SPREADCALL;
+                }
             } else {
                 if (!taggedTemplate(nextMember, tt))
                     return null();
diff --git a/js/src/jit/BaselineCompiler.cpp b/js/src/jit/BaselineCompiler.cpp
index af45e723cf37..14c4f7b13e1b 100644
--- a/js/src/jit/BaselineCompiler.cpp
+++ b/js/src/jit/BaselineCompiler.cpp
@@ -2757,6 +2757,12 @@ BaselineCompiler::emit_JSOP_EVAL()
     return emitCall();
 }
 
+bool
+BaselineCompiler::emit_JSOP_STRICTEVAL()
+{
+    return emitCall();
+}
+
 bool
 BaselineCompiler::emit_JSOP_SPREADCALL()
 {
@@ -2775,6 +2781,12 @@ BaselineCompiler::emit_JSOP_SPREADEVAL()
     return emitSpreadCall();
 }
 
+bool
+BaselineCompiler::emit_JSOP_STRICTSPREADEVAL()
+{
+    return emitSpreadCall();
+}
+
 typedef bool (*ImplicitThisFn)(JSContext *, HandleObject, HandlePropertyName,
                                MutableHandleValue);
 static const VMFunction ImplicitThisInfo = FunctionInfo(ImplicitThisOperation);
diff --git a/js/src/jit/BaselineCompiler.h b/js/src/jit/BaselineCompiler.h
index 233b96bdc4df..9f8f4b05f9ba 100644
--- a/js/src/jit/BaselineCompiler.h
+++ b/js/src/jit/BaselineCompiler.h
@@ -151,9 +151,11 @@ namespace jit {
     _(JSOP_FUNAPPLY)           \
     _(JSOP_NEW)                \
     _(JSOP_EVAL)               \
+    _(JSOP_STRICTEVAL)         \
     _(JSOP_SPREADCALL)         \
     _(JSOP_SPREADNEW)          \
     _(JSOP_SPREADEVAL)         \
+    _(JSOP_STRICTSPREADEVAL)   \
     _(JSOP_IMPLICITTHIS)       \
     _(JSOP_INSTANCEOF)         \
     _(JSOP_TYPEOF)             \
diff --git a/js/src/jit/BaselineIC.cpp b/js/src/jit/BaselineIC.cpp
index cff6220ab086..402660f9e04a 100644
--- a/js/src/jit/BaselineIC.cpp
+++ b/js/src/jit/BaselineIC.cpp
@@ -8657,7 +8657,7 @@ TryAttachCallStub(JSContext *cx, ICCall_Fallback *stub, HandleScript script, jsb
                   JSOp op, uint32_t argc, Value *vp, bool constructing, bool isSpread,
                   bool useNewType)
 {
-    if (useNewType || op == JSOP_EVAL)
+    if (useNewType || op == JSOP_EVAL || op == JSOP_STRICTEVAL)
         return true;
 
     if (stub->numOptimizedStubs() >= ICCall_Fallback::MAX_OPTIMIZED_STUBS) {
@@ -8987,12 +8987,18 @@ DoCallFallback(JSContext *cx, BaselineFrame *frame, ICCall_Fallback *stub_, uint
     if (op == JSOP_NEW) {
         if (!InvokeConstructor(cx, callee, argc, args, res))
             return false;
-    } else if (op == JSOP_EVAL && frame->scopeChain()->global().valueIsEval(callee)) {
+    } else if ((op == JSOP_EVAL || op == JSOP_STRICTEVAL) &&
+               frame->scopeChain()->global().valueIsEval(callee))
+    {
         if (!DirectEval(cx, CallArgsFromVp(argc, vp)))
             return false;
         res.set(vp[0]);
     } else {
-        MOZ_ASSERT(op == JSOP_CALL || op == JSOP_FUNCALL || op == JSOP_FUNAPPLY || op == JSOP_EVAL);
+        MOZ_ASSERT(op == JSOP_CALL ||
+                   op == JSOP_FUNCALL ||
+                   op == JSOP_FUNAPPLY ||
+                   op == JSOP_EVAL ||
+                   op == JSOP_STRICTEVAL);
         if (!Invoke(cx, thisv, callee, argc, args, res))
             return false;
     }
@@ -9041,7 +9047,7 @@ DoSpreadCallFallback(JSContext *cx, BaselineFrame *frame, ICCall_Fallback *stub_
     bool constructing = (op == JSOP_SPREADNEW);
 
     // Try attaching a call stub.
-    if (op != JSOP_SPREADEVAL &&
+    if (op != JSOP_SPREADEVAL && op != JSOP_STRICTSPREADEVAL &&
         !TryAttachCallStub(cx, stub, script, pc, op, 1, vp, constructing, true, false))
     {
         return false;
diff --git a/js/src/jit/IonBuilder.cpp b/js/src/jit/IonBuilder.cpp
index f90c5d8e4366..beae6c2ca4fa 100644
--- a/js/src/jit/IonBuilder.cpp
+++ b/js/src/jit/IonBuilder.cpp
@@ -1662,6 +1662,7 @@ IonBuilder::inspectOpcode(JSOp op)
         return jsop_call(GET_ARGC(pc), (JSOp)*pc == JSOP_NEW);
 
       case JSOP_EVAL:
+      case JSOP_STRICTEVAL:
         return jsop_eval(GET_ARGC(pc));
 
       case JSOP_INT8:
diff --git a/js/src/jsopcode.cpp b/js/src/jsopcode.cpp
index 9b44292d1ff1..3187daa81d4d 100644
--- a/js/src/jsopcode.cpp
+++ b/js/src/jsopcode.cpp
@@ -122,7 +122,7 @@ js::StackUses(JSScript *script, jsbytecode *pc)
       default:
         /* stack: fun, this, [argc arguments] */
         MOZ_ASSERT(op == JSOP_NEW || op == JSOP_CALL || op == JSOP_EVAL ||
-                   op == JSOP_FUNCALL || op == JSOP_FUNAPPLY);
+                   op == JSOP_STRICTEVAL || op == JSOP_FUNCALL || op == JSOP_FUNAPPLY);
         return 2 + GET_ARGC(pc);
     }
 }
diff --git a/js/src/jsopcode.h b/js/src/jsopcode.h
index 642da433656e..a265146ab99c 100644
--- a/js/src/jsopcode.h
+++ b/js/src/jsopcode.h
@@ -694,6 +694,13 @@ IsCallPC(jsbytecode *pc)
     return js_CodeSpec[*pc].format & JOF_INVOKE;
 }
 
+inline bool
+IsStrictEvalPC(jsbytecode *pc)
+{
+    JSOp op = JSOp(*pc);
+    return op == JSOP_STRICTEVAL || op == JSOP_STRICTSPREADEVAL;
+}
+
 static inline int32_t
 GetBytecodeInteger(jsbytecode *pc)
 {
diff --git a/js/src/jsscript.cpp b/js/src/jsscript.cpp
index 73b55519be19..063ce80dc42d 100644
--- a/js/src/jsscript.cpp
+++ b/js/src/jsscript.cpp
@@ -2911,9 +2911,15 @@ js::DescribeScriptedCallerForCompilation(JSContext *cx, MutableHandleScript mayb
     if (opt == CALLED_FROM_JSOP_EVAL) {
         jsbytecode *pc = nullptr;
         maybeScript.set(cx->currentScript(&pc));
-        MOZ_ASSERT(JSOp(*pc) == JSOP_EVAL || JSOp(*pc) == JSOP_SPREADEVAL);
-        MOZ_ASSERT(*(pc + (JSOp(*pc) == JSOP_EVAL ? JSOP_EVAL_LENGTH
-                                                  : JSOP_SPREADEVAL_LENGTH)) == JSOP_LINENO);
+        static_assert(JSOP_SPREADEVAL_LENGTH == JSOP_STRICTSPREADEVAL_LENGTH,
+                    "next op after a spread must be at consistent offset");
+        static_assert(JSOP_EVAL_LENGTH == JSOP_STRICTEVAL_LENGTH,
+                    "next op after a direct eval must be at consistent offset");
+        MOZ_ASSERT(JSOp(*pc) == JSOP_EVAL || JSOp(*pc) == JSOP_STRICTEVAL ||
+                   JSOp(*pc) == JSOP_SPREADEVAL || JSOp(*pc) == JSOP_STRICTSPREADEVAL);
+        mozilla::DebugOnly isSpread = JSOp(*pc) == JSOP_SPREADEVAL ||
+                                            JSOp(*pc) == JSOP_STRICTSPREADEVAL;
+        MOZ_ASSERT(*(pc + (isSpread ? JSOP_SPREADEVAL_LENGTH : JSOP_EVAL_LENGTH)) == JSOP_LINENO);
         *file = maybeScript->filename();
         *linenop = GET_UINT16(pc + (JSOp(*pc) == JSOP_EVAL ? JSOP_EVAL_LENGTH
                                                            : JSOP_SPREADEVAL_LENGTH));
diff --git a/js/src/vm/Interpreter.cpp b/js/src/vm/Interpreter.cpp
index 7f9f5f760b09..fc5cf2fd57b0 100644
--- a/js/src/vm/Interpreter.cpp
+++ b/js/src/vm/Interpreter.cpp
@@ -1590,7 +1590,6 @@ CASE(EnableInterruptsPseudoOpcode)
 /* Various 1-byte no-ops. */
 CASE(JSOP_NOP)
 CASE(JSOP_UNUSED2)
-CASE(JSOP_UNUSED50)
 CASE(JSOP_UNUSED51)
 CASE(JSOP_UNUSED52)
 CASE(JSOP_UNUSED83)
@@ -1599,7 +1598,6 @@ CASE(JSOP_UNUSED103)
 CASE(JSOP_UNUSED104)
 CASE(JSOP_UNUSED105)
 CASE(JSOP_UNUSED107)
-CASE(JSOP_UNUSED124)
 CASE(JSOP_UNUSED125)
 CASE(JSOP_UNUSED126)
 CASE(JSOP_UNUSED146)
@@ -2454,7 +2452,10 @@ CASE(JSOP_STRICTSETELEM)
 END_CASE(JSOP_SETELEM)
 
 CASE(JSOP_EVAL)
+CASE(JSOP_STRICTEVAL)
 {
+    static_assert(JSOP_EVAL_LENGTH == JSOP_STRICTEVAL_LENGTH,
+                  "eval and stricteval must be the same size");
     CallArgs args = CallArgsFromSp(GET_ARGC(REGS.pc), REGS.sp);
     if (REGS.fp()->scopeChain()->global().valueIsEval(args.calleev())) {
         if (!DirectEval(cx, args))
@@ -2475,7 +2476,10 @@ CASE(JSOP_SPREADCALL)
     /* FALL THROUGH */
 
 CASE(JSOP_SPREADEVAL)
+CASE(JSOP_STRICTSPREADEVAL)
 {
+    static_assert(JSOP_SPREADEVAL_LENGTH == JSOP_STRICTSPREADEVAL_LENGTH,
+                  "spreadeval and strictspreadeval must be the same size");
     MOZ_ASSERT(REGS.stackDepth() >= 3);
 
     HandleValue callee = REGS.stackHandleAt(-3);
@@ -4034,6 +4038,7 @@ js::SpreadCallOperation(JSContext *cx, HandleScript script, jsbytecode *pc, Hand
             return false;
         break;
       case JSOP_SPREADEVAL:
+      case JSOP_STRICTSPREADEVAL:
         if (cx->global()->valueIsEval(args.calleev())) {
             if (!DirectEval(cx, args))
                 return false;
diff --git a/js/src/vm/Opcodes.h b/js/src/vm/Opcodes.h
index a4d6e80ba02c..4ec6fe4bb2ed 100644
--- a/js/src/vm/Opcodes.h
+++ b/js/src/vm/Opcodes.h
@@ -405,7 +405,7 @@
      *   Operands:
      *   Stack: callee, this, args => rval
      */ \
-    macro(JSOP_SPREADEVAL,43, "spreadeval", NULL,         1,  3,  1, JOF_BYTE|JOF_INVOKE|JOF_TYPESET) \
+    macro(JSOP_SPREADEVAL,43, "spreadeval", NULL,         1,  3,  1, JOF_BYTE|JOF_INVOKE|JOF_TYPESET|JOF_CHECKSLOPPY) \
     \
     /*
      * Duplicates the Nth value from the top onto the stack.
@@ -467,7 +467,19 @@
      *   Stack: scope, val => val
      */ \
     macro(JSOP_STRICTSETNAME,   49, "strict-setname",    NULL,         5,  2,  1,  JOF_ATOM|JOF_NAME|JOF_SET|JOF_DETECTING|JOF_CHECKSTRICT) \
-    macro(JSOP_UNUSED50,  50, "unused50",   NULL,         1,  0,  0,  JOF_BYTE) \
+    /*
+     * spreadcall variant of JSOP_EVAL
+     *
+     * Invokes 'eval' with 'args' and pushes the return value onto the stack.
+     *
+     * If 'eval' in global scope is not original one, invokes the function
+     * with 'this' and 'args', and pushes return value onto the stack.
+     *   Category: Statements
+     *   Type: Function
+     *   Operands:
+     *   Stack: callee, this, args => rval
+     */ \
+    macro(JSOP_STRICTSPREADEVAL,      50, "strict-spreadeval", NULL,         1,  3,  1, JOF_BYTE|JOF_INVOKE|JOF_TYPESET|JOF_CHECKSTRICT) \
     macro(JSOP_UNUSED51,  51, "unused51",   NULL,         1,  0,  0,  JOF_BYTE) \
     macro(JSOP_UNUSED52,  52, "unused52",   NULL,         1,  0,  0,  JOF_BYTE) \
     \
@@ -1169,9 +1181,21 @@
      *   Stack: callee, this, args[0], ..., args[argc-1] => rval
      *   nuses: (argc+2)
      */ \
-    macro(JSOP_EVAL,      123,"eval",       NULL,         3, -1,  1, JOF_UINT16|JOF_INVOKE|JOF_TYPESET) \
+    macro(JSOP_EVAL,      123,"eval",       NULL,         3, -1,  1, JOF_UINT16|JOF_INVOKE|JOF_TYPESET|JOF_CHECKSLOPPY) \
     \
-    macro(JSOP_UNUSED124,  124, "unused124", NULL,      1,  0,  0,  JOF_BYTE) \
+    /* ECMA-compliant call to eval op. */ \
+    /*
+     * Invokes 'eval' with 'args' and pushes return value onto the stack.
+     *
+     * If 'eval' in global scope is not original one, invokes the function
+     * with 'this' and 'args', and pushes return value onto the stack.
+     *   Category: Statements
+     *   Type: Function
+     *   Operands: uint16_t argc
+     *   Stack: callee, this, args[0], ..., args[argc-1] => rval
+     *   nuses: (argc+2)
+     */ \
+    macro(JSOP_STRICTEVAL,       124, "strict-eval",       NULL,         3, -1,  1, JOF_UINT16|JOF_INVOKE|JOF_TYPESET|JOF_CHECKSTRICT) \
     macro(JSOP_UNUSED125,  125, "unused125", NULL,      1,  0,  0,  JOF_BYTE) \
     macro(JSOP_UNUSED126,  126, "unused126", NULL,      1,  0,  0,  JOF_BYTE) \
     \
diff --git a/js/src/vm/Xdr.h b/js/src/vm/Xdr.h
index b1ec7f42af97..b6520ab6668a 100644
--- a/js/src/vm/Xdr.h
+++ b/js/src/vm/Xdr.h
@@ -34,7 +34,7 @@ namespace js {
  * Nightly) and without (all others).  FIXME: Bug 1066322 - Enable ES6 symbols
  * in all builds.
  */
-static const uint32_t XDR_BYTECODE_VERSION_SUBTRAHEND = 216;
+static const uint32_t XDR_BYTECODE_VERSION_SUBTRAHEND = 218;
 static_assert(XDR_BYTECODE_VERSION_SUBTRAHEND % 2 == 0, "see the comment above");
 static const uint32_t XDR_BYTECODE_VERSION =
     uint32_t(0xb973c0de - (XDR_BYTECODE_VERSION_SUBTRAHEND

From 7ebde708bb998fea25b739e5b18255bfe195efed Mon Sep 17 00:00:00 2001
From: Eric Faust 
Date: Wed, 26 Nov 2014 14:42:53 -0800
Subject: [PATCH 44/64] Bug 1101905 - Part 9: Use opcode strictness in
 ErrorReporter instead of the script. (r=Waldo)

---
 js/src/jscntxt.cpp | 5 +++--
 js/src/jsopcode.h  | 2 +-
 2 files changed, 4 insertions(+), 3 deletions(-)

diff --git a/js/src/jscntxt.cpp b/js/src/jscntxt.cpp
index 210585257f5e..e9bc1bc9c44d 100644
--- a/js/src/jscntxt.cpp
+++ b/js/src/jscntxt.cpp
@@ -465,8 +465,9 @@ checkReportFlags(JSContext *cx, unsigned *flags)
          * otherwise.  We assume that if the top frame is a native, then it is
          * strict if the nearest scripted frame is strict, see bug 536306.
          */
-        JSScript *script = cx->currentScript();
-        if (script && script->strict())
+        jsbytecode *pc;
+        JSScript *script = cx->currentScript(&pc);
+        if (script && IsCheckStrictOp(JSOp(*pc)))
             *flags &= ~JSREPORT_WARNING;
         else if (cx->compartment()->options().extraWarnings(cx))
             *flags |= JSREPORT_WARNING;
diff --git a/js/src/jsopcode.h b/js/src/jsopcode.h
index a265146ab99c..cd8c4d650adf 100644
--- a/js/src/jsopcode.h
+++ b/js/src/jsopcode.h
@@ -633,13 +633,13 @@ IsEqualityOp(JSOp op)
     return op == JSOP_EQ || op == JSOP_NE || op == JSOP_STRICTEQ || op == JSOP_STRICTNE;
 }
 
-#ifdef DEBUG
 inline bool
 IsCheckStrictOp(JSOp op)
 {
     return js_CodeSpec[op].format & JOF_CHECKSTRICT;
 }
 
+#ifdef DEBUG
 inline bool
 IsCheckSloppyOp(JSOp op)
 {

From fdaf162ad8e9b63163554e59c2ce66d7b6562cd0 Mon Sep 17 00:00:00 2001
From: Cameron McCormack 
Date: Thu, 27 Nov 2014 09:47:52 +1100
Subject: [PATCH 45/64] Bug 1098270 - Null check curData in AddPendingRestyle
 to avoid crashing on style sheet updates in ShadowRoots outside of the
 composed document. r=dbaron

---
 layout/base/RestyleTracker.h | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/layout/base/RestyleTracker.h b/layout/base/RestyleTracker.h
index c1d59a1cf7e2..42c7d390b4ff 100644
--- a/layout/base/RestyleTracker.h
+++ b/layout/base/RestyleTracker.h
@@ -482,7 +482,7 @@ RestyleTracker::AddPendingRestyle(Element* aElement,
       // If cur has an eRestyle_ForceDescendants restyle hint, then we
       // know that we will get to all descendants.  Don't bother
       // recording the descendant to restyle in that case.
-      if (!(curData->mRestyleHint & eRestyle_ForceDescendants)) {
+      if (curData && !(curData->mRestyleHint & eRestyle_ForceDescendants)) {
         curData->mDescendants.AppendElement(aElement);
       }
     }

From b961552ce51e080e56c97e389a6b7cf55c170909 Mon Sep 17 00:00:00 2001
From: Boris Zbarsky 
Date: Wed, 26 Nov 2014 17:50:40 -0500
Subject: [PATCH 46/64] Bug 1101823 part 1.  Refactor testCommonGetterSetter to
 just return a boolean indicating whether it's OK to proceed with the common
 getter/setter, and put the shape guards, into outparams.  r=efaust

---
 js/src/jit/IonBuilder.cpp | 38 +++++++++++++++++++++++++-------------
 js/src/jit/IonBuilder.h   | 10 +++++++---
 2 files changed, 32 insertions(+), 16 deletions(-)

diff --git a/js/src/jit/IonBuilder.cpp b/js/src/jit/IonBuilder.cpp
index beae6c2ca4fa..9511b71ad5ce 100644
--- a/js/src/jit/IonBuilder.cpp
+++ b/js/src/jit/IonBuilder.cpp
@@ -9080,18 +9080,21 @@ IonBuilder::freezePropertiesForCommonPrototype(types::TemporaryTypeSet *types, P
     }
 }
 
-inline MDefinition *
+inline bool
 IonBuilder::testCommonGetterSetter(types::TemporaryTypeSet *types, PropertyName *name,
                                    bool isGetter, JSObject *foundProto, Shape *lastProperty,
-                                   Shape *globalShape/* = nullptr*/)
+                                   MDefinition **guard,
+                                   Shape *globalShape/* = nullptr*/,
+                                   MDefinition **globalGuard/* = nullptr */)
 {
+    MOZ_ASSERT_IF(globalShape, globalGuard);
     bool guardGlobal;
 
     // Check if all objects being accessed will lookup the name through foundProto.
     if (!objectsHaveCommonPrototype(types, name, isGetter, foundProto, &guardGlobal) ||
         (guardGlobal && !globalShape))
     {
-        return nullptr;
+        return false;
     }
 
     // We can optimize the getter/setter, so freeze all involved properties to
@@ -9102,16 +9105,19 @@ IonBuilder::testCommonGetterSetter(types::TemporaryTypeSet *types, PropertyName
     // Add a shape guard on the prototype we found the property on. The rest of
     // the prototype chain is guarded by TI freezes, except when name is a global
     // name. In this case, we also have to guard on the globals shape to be able
-    // to optimize. Note that a shape guard is good enough here, even in the proxy
-    // case, because we have ensured there are no lookup hooks for this property.
+    // to optimize, because the way global property sets are handled means
+    // freezing doesn't work for what we want here. Note that a shape guard is
+    // good enough here, even in the proxy case, because we have ensured there
+    // are no lookup hooks for this property.
     if (guardGlobal) {
         JSObject *obj = &script()->global();
         MDefinition *globalObj = constant(ObjectValue(*obj));
-        addShapeGuard(globalObj, globalShape, Bailout_ShapeGuard);
+        *globalGuard = addShapeGuard(globalObj, globalShape, Bailout_ShapeGuard);
     }
 
     MInstruction *wrapper = constant(ObjectValue(*foundProto));
-    return addShapeGuard(wrapper, lastProperty, Bailout_ShapeGuard);
+    *guard = addShapeGuard(wrapper, lastProperty, Bailout_ShapeGuard);
+    return true;
 }
 
 void
@@ -9669,9 +9675,13 @@ IonBuilder::getPropTryCommonGetter(bool *emitted, MDefinition *obj, PropertyName
         return true;
 
     types::TemporaryTypeSet *objTypes = obj->resultTypeSet();
-    MDefinition *guard = testCommonGetterSetter(objTypes, name, /* isGetter = */ true,
-                                                foundProto, lastProperty, globalShape);
-    if (!guard)
+    MDefinition *guard = nullptr;
+    MDefinition *globalGuard = nullptr;
+    bool canUseCommonGetter =
+        testCommonGetterSetter(objTypes, name, /* isGetter = */ true,
+                               foundProto, lastProperty, &guard, globalShape,
+                               &globalGuard);
+    if (!canUseCommonGetter)
         return true;
 
     bool isDOM = objTypes->isDOMClass();
@@ -10120,9 +10130,11 @@ IonBuilder::setPropTryCommonSetter(bool *emitted, MDefinition *obj,
         return true;
 
     types::TemporaryTypeSet *objTypes = obj->resultTypeSet();
-    MDefinition *guard = testCommonGetterSetter(objTypes, name, /* isGetter = */ false,
-                                                foundProto, lastProperty);
-    if (!guard)
+    MDefinition *guard = nullptr;
+    bool canUseCommonSetter =
+        testCommonGetterSetter(objTypes, name, /* isGetter = */ false,
+                               foundProto, lastProperty, &guard);
+    if (!canUseCommonSetter)
         return true;
 
     bool isDOM = objTypes->isDOMClass();
diff --git a/js/src/jit/IonBuilder.h b/js/src/jit/IonBuilder.h
index 7ead49c651ed..5893a5e69179 100644
--- a/js/src/jit/IonBuilder.h
+++ b/js/src/jit/IonBuilder.h
@@ -841,9 +841,13 @@ class IonBuilder
                                     bool isGetter, JSObject *foundProto, bool *guardGlobal);
     void freezePropertiesForCommonPrototype(types::TemporaryTypeSet *types, PropertyName *name,
                                             JSObject *foundProto, bool allowEmptyTypesForGlobal = false);
-    MDefinition *testCommonGetterSetter(types::TemporaryTypeSet *types, PropertyName *name,
-                                        bool isGetter, JSObject *foundProto, Shape *lastProperty,
-                                        Shape *globalShape = nullptr);
+    /*
+     * Callers must pass a non-null globalGuard if they pass a non-null globalShape.
+     */
+    bool testCommonGetterSetter(types::TemporaryTypeSet *types, PropertyName *name,
+                                bool isGetter, JSObject *foundProto, Shape *lastProperty,
+                                MDefinition **guard, Shape *globalShape = nullptr,
+                                MDefinition **globalGuard = nullptr);
     bool testShouldDOMCall(types::TypeSet *inTypes,
                            JSFunction *func, JSJitInfo::OpType opType);
 

From 21cb1745c4d10ef49a6d43f7c3bd848fa08c7337 Mon Sep 17 00:00:00 2001
From: Boris Zbarsky 
Date: Wed, 26 Nov 2014 17:50:40 -0500
Subject: [PATCH 47/64] Bug 1101823 part 2.  Make sure to add the guard on the
 global shape to the operands of our DOM getter, if we have such a guard at
 all.  r=efaust

---
 js/src/jit/IonBuilder.cpp |  7 ++++--
 js/src/jit/MIR.h          | 52 +++++++++++++++++++++++++++++----------
 2 files changed, 44 insertions(+), 15 deletions(-)

diff --git a/js/src/jit/IonBuilder.cpp b/js/src/jit/IonBuilder.cpp
index 9511b71ad5ce..dc0c4f570eda 100644
--- a/js/src/jit/IonBuilder.cpp
+++ b/js/src/jit/IonBuilder.cpp
@@ -9692,9 +9692,12 @@ IonBuilder::getPropTryCommonGetter(bool *emitted, MDefinition *obj, PropertyName
         if (jitinfo->isAlwaysInSlot) {
             // We can't use MLoadFixedSlot here because it might not have the
             // right aliasing behavior; we want to alias DOM setters as needed.
-            get = MGetDOMMember::New(alloc(), jitinfo, obj, guard);
+            get = MGetDOMMember::New(alloc(), jitinfo, obj, guard, globalGuard);
         } else {
-            get = MGetDOMProperty::New(alloc(), jitinfo, obj, guard);
+            get = MGetDOMProperty::New(alloc(), jitinfo, obj, guard, globalGuard);
+        }
+        if (!get) {
+            return false;
         }
         current->add(get);
         current->push(get);
diff --git a/js/src/jit/MIR.h b/js/src/jit/MIR.h
index 0a8c06187948..00a454138b9d 100644
--- a/js/src/jit/MIR.h
+++ b/js/src/jit/MIR.h
@@ -10463,23 +10463,18 @@ class MSetDOMProperty
 };
 
 class MGetDOMProperty
-  : public MAryInstruction<2>,
+  : public MVariadicInstruction,
     public ObjectPolicy<0>::Data
 {
     const JSJitInfo *info_;
 
   protected:
-    MGetDOMProperty(const JSJitInfo *jitinfo, MDefinition *obj, MDefinition *guard)
+    MGetDOMProperty(const JSJitInfo *jitinfo)
       : info_(jitinfo)
     {
         MOZ_ASSERT(jitinfo);
         MOZ_ASSERT(jitinfo->type() == JSJitInfo::Getter);
 
-        initOperand(0, obj);
-
-        // Pin the guard as an operand if we want to hoist later
-        initOperand(1, guard);
-
         // We are movable iff the jitinfo says we can be.
         if (isDomMovable()) {
             MOZ_ASSERT(jitinfo->aliasSet() != JSJitInfo::AliasEverything);
@@ -10498,13 +10493,41 @@ class MGetDOMProperty
         return info_;
     }
 
+    bool init(TempAllocator &alloc, MDefinition *obj, MDefinition *guard,
+              MDefinition *globalGuard) {
+        MOZ_ASSERT(obj);
+        MOZ_ASSERT(guard);
+        // globalGuard can be null.
+        size_t operandCount;
+        if (globalGuard)
+            operandCount = 3;
+        else
+            operandCount = 2;
+
+        if (!MVariadicInstruction::init(alloc, operandCount))
+            return false;
+        initOperand(0, obj);
+
+        // Pin the guard as an operand if we want to hoist later.
+        initOperand(1, guard);
+
+        // And the same for the global guard, if we have one.
+        if (globalGuard)
+            initOperand(2, globalGuard);
+
+        return true;
+    }
+
   public:
     INSTRUCTION_HEADER(GetDOMProperty)
 
     static MGetDOMProperty *New(TempAllocator &alloc, const JSJitInfo *info, MDefinition *obj,
-                                MDefinition *guard)
+                                MDefinition *guard, MDefinition *globalGuard)
     {
-        return new(alloc) MGetDOMProperty(info, obj, guard);
+        MGetDOMProperty *res = new(alloc) MGetDOMProperty(info);
+        if (!res || !res->init(alloc, obj, guard, globalGuard))
+            return nullptr;
+        return res;
     }
 
     JSJitGetterOp fun() const {
@@ -10562,8 +10585,8 @@ class MGetDOMProperty
 class MGetDOMMember : public MGetDOMProperty
 {
     // We inherit everything from MGetDOMProperty except our possiblyCalls value
-    MGetDOMMember(const JSJitInfo *jitinfo, MDefinition *obj, MDefinition *guard)
-        : MGetDOMProperty(jitinfo, obj, guard)
+    MGetDOMMember(const JSJitInfo *jitinfo)
+        : MGetDOMProperty(jitinfo)
     {
     }
 
@@ -10571,9 +10594,12 @@ class MGetDOMMember : public MGetDOMProperty
     INSTRUCTION_HEADER(GetDOMMember)
 
     static MGetDOMMember *New(TempAllocator &alloc, const JSJitInfo *info, MDefinition *obj,
-                              MDefinition *guard)
+                              MDefinition *guard, MDefinition *globalGuard)
     {
-        return new(alloc) MGetDOMMember(info, obj, guard);
+        MGetDOMMember *res = new(alloc) MGetDOMMember(info);
+        if (!res || !res->init(alloc, obj, guard, globalGuard))
+            return nullptr;
+        return res;
     }
 
     bool possiblyCalls() const {

From 4299cfd502240619ec308e760db50206192919e1 Mon Sep 17 00:00:00 2001
From: Geoff Brown 
Date: Wed, 26 Nov 2014 16:51:13 -0700
Subject: [PATCH 48/64] Bug 1026290: Do not filter logFile parameter from
 testConfig.js; r=chmanchester

---
 testing/mochitest/runtests.py | 4 +++-
 1 file changed, 3 insertions(+), 1 deletion(-)

diff --git a/testing/mochitest/runtests.py b/testing/mochitest/runtests.py
index 8fb2085adeb9..7a4beaeaec5e 100644
--- a/testing/mochitest/runtests.py
+++ b/testing/mochitest/runtests.py
@@ -2102,7 +2102,9 @@ class Mochitest(MochitestUtilsMixin):
     if "MOZ_HIDE_RESULTS_TABLE" in os.environ and os.environ["MOZ_HIDE_RESULTS_TABLE"] == "1":
       options.hideResultsTable = True
 
-    d = dict((k, v) for k, v in options.__dict__.iteritems() if not k.startswith('log'))
+    d = dict((k, v) for k, v in options.__dict__.items() if
+        (not k.startswith('log_') or
+         not any([k.endswith(fmt) for fmt in commandline.log_formatters.keys()])))
     d['testRoot'] = self.testRoot
     content = json.dumps(d)
 

From 74313d0f7e3fd8e365ce5581090fc150cf662f21 Mon Sep 17 00:00:00 2001
From: Geoff Brown 
Date: Wed, 26 Nov 2014 16:51:14 -0700
Subject: [PATCH 49/64] Bug 1026290 - Push chrome test files to device;
 r=jmaher

---
 testing/mochitest/runtests.py       | 10 +++++++---
 testing/mochitest/runtestsremote.py | 25 ++++++++++++-------------
 2 files changed, 19 insertions(+), 16 deletions(-)

diff --git a/testing/mochitest/runtests.py b/testing/mochitest/runtests.py
index 7a4beaeaec5e..8541eb773698 100644
--- a/testing/mochitest/runtests.py
+++ b/testing/mochitest/runtests.py
@@ -765,6 +765,12 @@ class MochitestUtilsMixin(object):
     with open(os.path.join(options.profilePath, "extensions", "staged", "mochikit@mozilla.org", "chrome.manifest"), "a") as mfile:
       mfile.write(chrome)
 
+  def getChromeTestDir(self, options):
+    dir = os.path.join(os.path.abspath("."), SCRIPT_DIR) + "/"
+    if mozinfo.isWin:
+      dir = "file:///" + dir.replace("\\", "/")
+    return dir
+
   def addChromeToProfile(self, options):
     "Adds MochiKit chrome tests to the profile."
 
@@ -789,9 +795,7 @@ toolbar#nav-bar {
     manifest = os.path.join(options.profilePath, "tests.manifest")
     with open(manifest, "w") as manifestFile:
       # Register chrome directory.
-      chrometestDir = os.path.join(os.path.abspath("."), SCRIPT_DIR) + "/"
-      if mozinfo.isWin:
-        chrometestDir = "file:///" + chrometestDir.replace("\\", "/")
+      chrometestDir = self.getChromeTestDir(options)
       manifestFile.write("content mochitests %s contentaccessible=yes\n" % chrometestDir)
 
       if options.testingModulesDir is not None:
diff --git a/testing/mochitest/runtestsremote.py b/testing/mochitest/runtestsremote.py
index b2e09331d02c..83367d604bf3 100644
--- a/testing/mochitest/runtestsremote.py
+++ b/testing/mochitest/runtestsremote.py
@@ -249,6 +249,9 @@ class MochiRemote(Mochitest):
         self.remoteNSPR = os.path.join(options.remoteTestRoot, "nspr")
         self._dm.removeDir(self.remoteNSPR);
         self._dm.mkDir(self.remoteNSPR);
+        self.remoteChromeTestDir = os.path.join(options.remoteTestRoot, "chrome")
+        self._dm.removeDir(self.remoteChromeTestDir);
+        self._dm.mkDir(self.remoteChromeTestDir);
 
     def cleanup(self, options):
         if self._dm.fileExists(self.remoteLog):
@@ -257,6 +260,7 @@ class MochiRemote(Mochitest):
         else:
             self.log.warning("Unable to retrieve log file (%s) from remote device" % self.remoteLog)
         self._dm.removeDir(self.remoteProfile)
+        self._dm.removeDir(self.remoteChromeTestDir);
         # Don't leave an old robotium.config hanging around; the
         # profile it references was just deleted!
         deviceRoot = self._dm.getDeviceRoot()
@@ -413,19 +417,14 @@ class MochiRemote(Mochitest):
         else:
             return super(MochiRemote, self).buildTestPath(options, testsToFilter)
 
-    def installChromeFile(self, filename, options):
-        parts = options.app.split('/')
-        if (parts[0] == options.app):
-          return "NO_CHROME_ON_DROID"
-        path = '/'.join(parts[:-1])
-        manifest = path + "/chrome/" + os.path.basename(filename)
-        try:
-            self._dm.pushFile(filename, manifest)
-        except devicemanager.DMError:
-            self.log.error("Automation Error: Unable to install Chrome files on device.")
-            raise
-
-        return manifest
+    def getChromeTestDir(self, options):
+        local = super(MochiRemote, self).getChromeTestDir(options)
+        local = os.path.join(local, "chrome")
+        remote = self.remoteChromeTestDir
+        if options.chrome:
+            self.log.info("pushing %s to %s on device..." % (local, remote))
+            self._dm.pushDir(local, remote)
+        return remote
 
     def getLogFilePath(self, logFile):
         return logFile

From 56ad1aaa3b8d117d859b08e108964f611d1ad865 Mon Sep 17 00:00:00 2001
From: James Willcox 
Date: Wed, 26 Nov 2014 17:52:08 -0600
Subject: [PATCH 50/64] Bug 1099345 - Do not run the Android SDK code generator
 tool in parallel r=nalexander

---
 widget/android/bindings/Makefile.in | 6 +++++-
 1 file changed, 5 insertions(+), 1 deletion(-)

diff --git a/widget/android/bindings/Makefile.in b/widget/android/bindings/Makefile.in
index 348f847299a0..09b0eef9367e 100644
--- a/widget/android/bindings/Makefile.in
+++ b/widget/android/bindings/Makefile.in
@@ -2,6 +2,10 @@
 # License, v. 2.0. If a copy of the MPL was not distributed with this
 # file, You can obtain one at http://mozilla.org/MPL/2.0/.
 
+# Bug 1099345 - The SDK's lint code (used by the code generator) does not enjoy
+# concurrent access to a cache that it generates.
+.NOTPARALLEL:
+
 annotation_processor_jar_files := $(DEPTH)/build/annotationProcessors/annotationProcessors.jar:$(ANDROID_TOOLS)/lib/lint.jar:$(ANDROID_TOOLS)/lib/lint-checks.jar
 
 sdk_processor := \
@@ -15,7 +19,7 @@ sdk_processor := \
 # MediaCodec-classes.txt.  This formulation invokes the SDK processor
 # at most once.
 
-%.cpp %.h: $(ANDROID_SDK)/android.jar %-classes.txt FORCE
+%.cpp %.h: $(ANDROID_SDK)/android.jar %-classes.txt
 	$(sdk_processor) $(ANDROID_SDK)/android.jar $(srcdir)/$*-classes.txt $(CURDIR) $* 16
 
 # We'd like these to be defined in a future GENERATED_EXPORTS list.

From 1a013270b54d83b298882473bfe32cf466f9f0dc Mon Sep 17 00:00:00 2001
From: Trevor Saunders 
Date: Tue, 25 Nov 2014 13:56:07 -0500
Subject: [PATCH 51/64] bug 1105074 - make more stuff final r=froydnj

---
 docshell/base/nsDSURIContentListener.h        |  2 +-
 dom/base/EventSource.h                        | 12 +++++-----
 dom/base/nsDOMMutationObserver.h              |  8 +++----
 dom/events/MessageEvent.h                     |  4 ++--
 dom/gamepad/Gamepad.h                         |  4 ++--
 dom/html/HTMLFormControlsCollection.h         |  4 ++--
 dom/html/HTMLPropertiesCollection.h           |  4 ++--
 dom/html/UndoManager.h                        |  4 ++--
 dom/media/MediaRecorder.h                     |  4 ++--
 dom/media/fmp4/MP4Reader.h                    |  2 +-
 dom/media/mediasource/SourceBufferDecoder.h   |  2 +-
 dom/media/webaudio/AudioDestinationNode.h     |  8 +++----
 dom/offline/nsDOMOfflineResourceList.h        | 10 ++++-----
 dom/plugins/base/nsPluginTags.h               |  2 +-
 dom/xul/nsXULContentSink.h                    |  4 ++--
 dom/xul/nsXULPrototypeDocument.h              |  2 +-
 editor/txtsvc/nsTextServicesDocument.h        |  4 ++--
 embedding/components/find/nsFind.cpp          |  2 +-
 .../spellcheck/hunspell/src/mozHunspell.h     |  8 +++----
 .../spellcheck/src/mozPersonalDictionary.h    |  6 ++---
 ipc/glue/SharedMemoryBasic_chromium.h         |  2 +-
 js/src/jit/MIR.h                              |  2 +-
 js/xpconnect/src/xpcprivate.h                 | 14 ++++++------
 layout/inspector/inDeepTreeWalker.h           |  2 +-
 media/mtransport/transportflow.h              |  4 ++--
 media/mtransport/transportlayerdtls.h         |  2 +-
 modules/libjar/nsJARProtocolHandler.h         |  4 ++--
 netwerk/base/src/nsSocketTransport2.h         |  8 +++----
 netwerk/cache/nsCacheEntryDescriptor.h        |  2 +-
 netwerk/cache/nsCacheService.h                |  4 ++--
 netwerk/cache/nsDiskCacheDevice.h             |  2 +-
 netwerk/cookie/nsCookieService.h              | 10 ++++-----
 netwerk/protocol/ftp/FTPChannelParent.h       | 12 +++++-----
 netwerk/protocol/ftp/nsFtpConnectionThread.h  | 14 ++++++------
 netwerk/protocol/ftp/nsFtpProtocolHandler.h   |  6 ++---
 netwerk/protocol/res/nsResProtocolHandler.h   |  2 +-
 .../components/downloads/nsDownloadManager.h  |  8 +++----
 toolkit/components/places/History.h           | 10 ++++-----
 .../components/places/nsNavHistoryResult.h    | 22 +++++++++----------
 tools/profiler/LulDwarfExt.h                  |  2 +-
 xpcom/base/nsSystemInfo.h                     |  2 +-
 xpfe/components/windowds/nsWindowDataSource.h |  8 +++----
 42 files changed, 119 insertions(+), 119 deletions(-)

diff --git a/docshell/base/nsDSURIContentListener.h b/docshell/base/nsDSURIContentListener.h
index f8c6a6994781..2e82f215aa7c 100644
--- a/docshell/base/nsDSURIContentListener.h
+++ b/docshell/base/nsDSURIContentListener.h
@@ -16,7 +16,7 @@ class nsIWebNavigationInfo;
 class nsIHttpChannel;
 class nsAString;
 
-class nsDSURIContentListener :
+class nsDSURIContentListener MOZ_FINAL :
     public nsIURIContentListener,
     public nsSupportsWeakReference
 
diff --git a/dom/base/EventSource.h b/dom/base/EventSource.h
index 34e5025f113b..5cf486cf4044 100644
--- a/dom/base/EventSource.h
+++ b/dom/base/EventSource.h
@@ -36,12 +36,12 @@ namespace dom {
 class AsyncVerifyRedirectCallbackFwr;
 struct EventSourceInit;
 
-class EventSource : public DOMEventTargetHelper
-                  , public nsIObserver
-                  , public nsIStreamListener
-                  , public nsIChannelEventSink
-                  , public nsIInterfaceRequestor
-                  , public nsSupportsWeakReference
+class EventSource MOZ_FINAL : public DOMEventTargetHelper
+                            , public nsIObserver
+                            , public nsIStreamListener
+                            , public nsIChannelEventSink
+                            , public nsIInterfaceRequestor
+                            , public nsSupportsWeakReference
 {
 friend class AsyncVerifyRedirectCallbackFwr;
 
diff --git a/dom/base/nsDOMMutationObserver.h b/dom/base/nsDOMMutationObserver.h
index 2fa0934231cf..c49b0afca6a7 100644
--- a/dom/base/nsDOMMutationObserver.h
+++ b/dom/base/nsDOMMutationObserver.h
@@ -28,8 +28,8 @@
 class nsDOMMutationObserver;
 using mozilla::dom::MutationObservingInfo;
 
-class nsDOMMutationRecord : public nsISupports,
-                            public nsWrapperCache
+class nsDOMMutationRecord MOZ_FINAL : public nsISupports,
+                                      public nsWrapperCache
 {
   virtual ~nsDOMMutationRecord() {}
 
@@ -337,8 +337,8 @@ public:
 { 0x0c3b91f8, 0xcc3b, 0x4b08, \
   { 0x9e, 0xab, 0x07, 0x47, 0xa9, 0xe4, 0x65, 0xb4 } }
 
-class nsDOMMutationObserver : public nsISupports,
-                              public nsWrapperCache
+class nsDOMMutationObserver MOZ_FINAL : public nsISupports,
+                                        public nsWrapperCache
 {
 public:
   nsDOMMutationObserver(already_AddRefed&& aOwner,
diff --git a/dom/events/MessageEvent.h b/dom/events/MessageEvent.h
index c509ba986014..cce26006bc97 100644
--- a/dom/events/MessageEvent.h
+++ b/dom/events/MessageEvent.h
@@ -27,8 +27,8 @@ class OwningWindowProxyOrMessagePort;
  * See http://www.whatwg.org/specs/web-apps/current-work/#messageevent for
  * further details.
  */
-class MessageEvent : public Event,
-                     public nsIDOMMessageEvent
+class MessageEvent MOZ_FINAL : public Event,
+                               public nsIDOMMessageEvent
 {
 public:
   MessageEvent(EventTarget* aOwner,
diff --git a/dom/gamepad/Gamepad.h b/dom/gamepad/Gamepad.h
index d09e4fa43163..aa9a11e4b879 100644
--- a/dom/gamepad/Gamepad.h
+++ b/dom/gamepad/Gamepad.h
@@ -30,8 +30,8 @@ const int kLeftStickYAxis = 1;
 const int kRightStickXAxis = 2;
 const int kRightStickYAxis = 3;
 
-class Gamepad : public nsISupports,
-                public nsWrapperCache
+class Gamepad MOZ_FINAL : public nsISupports,
+                          public nsWrapperCache
 {
 public:
   Gamepad(nsISupports* aParent,
diff --git a/dom/html/HTMLFormControlsCollection.h b/dom/html/HTMLFormControlsCollection.h
index 9c475f43b519..37760c13eeed 100644
--- a/dom/html/HTMLFormControlsCollection.h
+++ b/dom/html/HTMLFormControlsCollection.h
@@ -23,8 +23,8 @@ class HTMLImageElement;
 class OwningRadioNodeListOrElement;
 template struct Nullable;
 
-class HTMLFormControlsCollection : public nsIHTMLCollection
-                                 , public nsWrapperCache
+class HTMLFormControlsCollection MOZ_FINAL : public nsIHTMLCollection
+                                           , public nsWrapperCache
 {
 public:
   explicit HTMLFormControlsCollection(HTMLFormElement* aForm);
diff --git a/dom/html/HTMLPropertiesCollection.h b/dom/html/HTMLPropertiesCollection.h
index 592a81e464ee..b08c41708de1 100644
--- a/dom/html/HTMLPropertiesCollection.h
+++ b/dom/html/HTMLPropertiesCollection.h
@@ -148,8 +148,8 @@ protected:
   bool mIsDirty;
 };
 
-class PropertyNodeList : public nsINodeList,
-                         public nsStubMutationObserver
+class PropertyNodeList MOZ_FINAL : public nsINodeList,
+                                   public nsStubMutationObserver
 {
 public:
   PropertyNodeList(HTMLPropertiesCollection* aCollection,
diff --git a/dom/html/UndoManager.h b/dom/html/UndoManager.h
index a29c8a50d951..25477d4b5061 100644
--- a/dom/html/UndoManager.h
+++ b/dom/html/UndoManager.h
@@ -25,8 +25,8 @@ namespace dom {
 class DOMTransaction;
 class DOMTransactionCallback;
 
-class UndoManager : public nsISupports,
-                    public nsWrapperCache
+class UndoManager MOZ_FINAL : public nsISupports,
+                              public nsWrapperCache
 {
   friend class TxnScopeGuard;
 public:
diff --git a/dom/media/MediaRecorder.h b/dom/media/MediaRecorder.h
index b12e01fef843..fbfb3595a5f5 100644
--- a/dom/media/MediaRecorder.h
+++ b/dom/media/MediaRecorder.h
@@ -38,8 +38,8 @@ class AudioNode;
  * Also extract the encoded data and create blobs on every timeslice passed from start function or RequestData function called by UA.
  */
 
-class MediaRecorder : public DOMEventTargetHelper,
-                      public nsIDocumentActivity
+class MediaRecorder MOZ_FINAL : public DOMEventTargetHelper,
+                                public nsIDocumentActivity
 {
   class Session;
 
diff --git a/dom/media/fmp4/MP4Reader.h b/dom/media/fmp4/MP4Reader.h
index 183eb3165a0f..f1c4b6fac9b3 100644
--- a/dom/media/fmp4/MP4Reader.h
+++ b/dom/media/fmp4/MP4Reader.h
@@ -26,7 +26,7 @@ typedef std::deque MP4SampleQueue;
 
 class MP4Stream;
 
-class MP4Reader : public MediaDecoderReader
+class MP4Reader MOZ_FINAL : public MediaDecoderReader
 {
   typedef mp4_demuxer::TrackType TrackType;
 
diff --git a/dom/media/mediasource/SourceBufferDecoder.h b/dom/media/mediasource/SourceBufferDecoder.h
index a2f0c1b56e0b..cae6b9a47dca 100644
--- a/dom/media/mediasource/SourceBufferDecoder.h
+++ b/dom/media/mediasource/SourceBufferDecoder.h
@@ -27,7 +27,7 @@ class TimeRanges;
 
 } // namespace dom
 
-class SourceBufferDecoder : public AbstractMediaDecoder
+class SourceBufferDecoder MOZ_FINAL : public AbstractMediaDecoder
 {
 public:
   // This class holds a weak pointer to MediaResource.  It's the responsibility
diff --git a/dom/media/webaudio/AudioDestinationNode.h b/dom/media/webaudio/AudioDestinationNode.h
index 478abc8f2c2b..0ed728cb4449 100644
--- a/dom/media/webaudio/AudioDestinationNode.h
+++ b/dom/media/webaudio/AudioDestinationNode.h
@@ -19,10 +19,10 @@ namespace dom {
 class AudioContext;
 class EventProxyHandler;
 
-class AudioDestinationNode : public AudioNode
-                           , public nsIDOMEventListener
-                           , public nsIAudioChannelAgentCallback
-                           , public MainThreadMediaStreamListener
+class AudioDestinationNode MOZ_FINAL : public AudioNode
+                                     , public nsIDOMEventListener
+                                     , public nsIAudioChannelAgentCallback
+                                     , public MainThreadMediaStreamListener
 {
 public:
   // This node type knows what MediaStreamGraph to use based on
diff --git a/dom/offline/nsDOMOfflineResourceList.h b/dom/offline/nsDOMOfflineResourceList.h
index 76e14fee180f..e5498b747ddc 100644
--- a/dom/offline/nsDOMOfflineResourceList.h
+++ b/dom/offline/nsDOMOfflineResourceList.h
@@ -34,11 +34,11 @@ class DOMStringList;
 } // namespace dom
 } // namespace mozilla
 
-class nsDOMOfflineResourceList : public mozilla::DOMEventTargetHelper,
-                                 public nsIDOMOfflineResourceList,
-                                 public nsIObserver,
-                                 public nsIOfflineCacheUpdateObserver,
-                                 public nsSupportsWeakReference
+class nsDOMOfflineResourceList MOZ_FINAL : public mozilla::DOMEventTargetHelper,
+                                           public nsIDOMOfflineResourceList,
+                                           public nsIObserver,
+                                           public nsIOfflineCacheUpdateObserver,
+                                           public nsSupportsWeakReference
 {
   typedef mozilla::ErrorResult ErrorResult;
 
diff --git a/dom/plugins/base/nsPluginTags.h b/dom/plugins/base/nsPluginTags.h
index 392b126d5660..6bc76434c679 100644
--- a/dom/plugins/base/nsPluginTags.h
+++ b/dom/plugins/base/nsPluginTags.h
@@ -22,7 +22,7 @@ class nsNPAPIPlugin;
 
 // A linked-list of plugin information that is used for instantiating plugins
 // and reflecting plugin information into JavaScript.
-class nsPluginTag : public nsIPluginTag
+class nsPluginTag MOZ_FINAL : public nsIPluginTag
 {
 public:
   NS_DECL_ISUPPORTS
diff --git a/dom/xul/nsXULContentSink.h b/dom/xul/nsXULContentSink.h
index 8c1c406d03d6..55f91af9627b 100644
--- a/dom/xul/nsXULContentSink.h
+++ b/dom/xul/nsXULContentSink.h
@@ -22,8 +22,8 @@ class nsXULPrototypeDocument;
 class nsXULPrototypeElement;
 class nsXULPrototypeNode;
 
-class XULContentSinkImpl : public nsIXMLContentSink,
-                           public nsIExpatSink
+class XULContentSinkImpl MOZ_FINAL : public nsIXMLContentSink,
+                                     public nsIExpatSink
 {
 public:
     XULContentSinkImpl();
diff --git a/dom/xul/nsXULPrototypeDocument.h b/dom/xul/nsXULPrototypeDocument.h
index 983f1aaec1a5..aa29bb7e173f 100644
--- a/dom/xul/nsXULPrototypeDocument.h
+++ b/dom/xul/nsXULPrototypeDocument.h
@@ -35,7 +35,7 @@ class XULDocument;
  * objects, from which the real DOM tree is built later in
  * XULDocument::ResumeWalk.
  */
-class nsXULPrototypeDocument : public nsISerializable
+class nsXULPrototypeDocument MOZ_FINAL : public nsISerializable
 {
 public:
     static nsresult
diff --git a/editor/txtsvc/nsTextServicesDocument.h b/editor/txtsvc/nsTextServicesDocument.h
index 6a95815c0227..0e10f0c9c34d 100644
--- a/editor/txtsvc/nsTextServicesDocument.h
+++ b/editor/txtsvc/nsTextServicesDocument.h
@@ -32,8 +32,8 @@ class nsString;
 /** implementation of a text services object.
  *
  */
-class nsTextServicesDocument : public nsITextServicesDocument,
-                               public nsIEditActionListener
+class nsTextServicesDocument MOZ_FINAL : public nsITextServicesDocument,
+                                         public nsIEditActionListener
 {
 private:
   static nsIAtom *sAAtom;
diff --git a/embedding/components/find/nsFind.cpp b/embedding/components/find/nsFind.cpp
index 445058bfd19d..2f1a88f5f6e8 100644
--- a/embedding/components/find/nsFind.cpp
+++ b/embedding/components/find/nsFind.cpp
@@ -79,7 +79,7 @@ PR_STATIC_ASSERT(CH_SHY <= 255);
 // 5) The implementation assumes that First() and Next() are only called
 // in find-forward mode, while Last() and Prev() are used in find-backward.
 
-class nsFindContentIterator : public nsIContentIterator
+class nsFindContentIterator MOZ_FINAL : public nsIContentIterator
 {
 public:
   explicit nsFindContentIterator(bool aFindBackward)
diff --git a/extensions/spellcheck/hunspell/src/mozHunspell.h b/extensions/spellcheck/hunspell/src/mozHunspell.h
index fa16587b4379..845537a0c931 100644
--- a/extensions/spellcheck/hunspell/src/mozHunspell.h
+++ b/extensions/spellcheck/hunspell/src/mozHunspell.h
@@ -81,10 +81,10 @@
 { 0x56c778e4, 0x1bee, 0x45f3, \
   { 0xa6, 0x89, 0x88, 0x66, 0x92, 0xa9, 0x7f, 0xe7 } }
 
-class mozHunspell : public mozISpellCheckingEngine,
-                    public nsIObserver,
-                    public nsSupportsWeakReference,
-                    public nsIMemoryReporter
+class mozHunspell MOZ_FINAL : public mozISpellCheckingEngine,
+                              public nsIObserver,
+                              public nsSupportsWeakReference,
+                              public nsIMemoryReporter
 {
 public:
   NS_DECL_CYCLE_COLLECTING_ISUPPORTS
diff --git a/extensions/spellcheck/src/mozPersonalDictionary.h b/extensions/spellcheck/src/mozPersonalDictionary.h
index 2764ade522c9..5f7f13b9eba8 100644
--- a/extensions/spellcheck/src/mozPersonalDictionary.h
+++ b/extensions/spellcheck/src/mozPersonalDictionary.h
@@ -26,9 +26,9 @@
 
 class mozPersonalDictionaryLoader;
 
-class mozPersonalDictionary : public mozIPersonalDictionary,
-                              public nsIObserver,
-                              public nsSupportsWeakReference
+class mozPersonalDictionary MOZ_FINAL : public mozIPersonalDictionary,
+                                        public nsIObserver,
+                                        public nsSupportsWeakReference
 {
 public:
   NS_DECL_CYCLE_COLLECTING_ISUPPORTS
diff --git a/ipc/glue/SharedMemoryBasic_chromium.h b/ipc/glue/SharedMemoryBasic_chromium.h
index fc684ba41383..42afcf02fd0d 100644
--- a/ipc/glue/SharedMemoryBasic_chromium.h
+++ b/ipc/glue/SharedMemoryBasic_chromium.h
@@ -21,7 +21,7 @@
 namespace mozilla {
 namespace ipc {
 
-class SharedMemoryBasic : public SharedMemory
+class SharedMemoryBasic MOZ_FINAL : public SharedMemory
 {
 public:
   typedef base::SharedMemoryHandle Handle;
diff --git a/js/src/jit/MIR.h b/js/src/jit/MIR.h
index 00a454138b9d..e1e3d8982adf 100644
--- a/js/src/jit/MIR.h
+++ b/js/src/jit/MIR.h
@@ -3870,7 +3870,7 @@ JSOpToCondition(MCompare::CompareType compareType, JSOp op)
 // Takes a typed value and checks if it is a certain type. If so, the payload
 // is unpacked and returned as that type. Otherwise, it is considered a
 // deoptimization.
-class MUnbox : public MUnaryInstruction, public BoxInputsPolicy::Data
+class MUnbox MOZ_FINAL : public MUnaryInstruction, public BoxInputsPolicy::Data
 {
   public:
     enum Mode {
diff --git a/js/xpconnect/src/xpcprivate.h b/js/xpconnect/src/xpcprivate.h
index a5f8b17d96e5..4f46e18b777b 100644
--- a/js/xpconnect/src/xpcprivate.h
+++ b/js/xpconnect/src/xpcprivate.h
@@ -2393,11 +2393,11 @@ private:
 // nsXPCWrappedJS objects are chained together to represent the various
 // interface on the single underlying (possibly aggregate) JSObject.
 
-class nsXPCWrappedJS : protected nsAutoXPTCStub,
-                       public nsIXPConnectWrappedJS,
-                       public nsSupportsWeakReference,
-                       public nsIPropertyBag,
-                       public XPCRootSetElem
+class nsXPCWrappedJS MOZ_FINAL : protected nsAutoXPTCStub,
+                                 public nsIXPConnectWrappedJS,
+                                 public nsSupportsWeakReference,
+                                 public nsIPropertyBag,
+                                 public XPCRootSetElem
 {
 public:
     NS_DECL_CYCLE_COLLECTING_ISUPPORTS
@@ -2720,7 +2720,7 @@ public:
 // safe.
 extern void xpc_DestroyJSxIDClassObjects();
 
-class nsJSID : public nsIJSID
+class nsJSID MOZ_FINAL : public nsIJSID
 {
 public:
     NS_DEFINE_STATIC_CID_ACCESSOR(NS_JS_ID_CID)
@@ -2967,7 +2967,7 @@ xpc_PrintJSStack(JSContext* cx, bool showArgs, bool showLocals,
 
 // Definition of nsScriptError, defined here because we lack a place to put
 // XPCOM objects associated with the JavaScript engine.
-class nsScriptError : public nsIScriptError {
+class nsScriptError MOZ_FINAL : public nsIScriptError {
 public:
     nsScriptError();
 
diff --git a/layout/inspector/inDeepTreeWalker.h b/layout/inspector/inDeepTreeWalker.h
index 187703545403..0ba473d6b5e0 100644
--- a/layout/inspector/inDeepTreeWalker.h
+++ b/layout/inspector/inDeepTreeWalker.h
@@ -14,7 +14,7 @@
 class nsINodeList;
 class inIDOMUtils;
 
-class inDeepTreeWalker : public inIDeepTreeWalker
+class inDeepTreeWalker MOZ_FINAL : public inIDeepTreeWalker
 {
 public:
   NS_DECL_ISUPPORTS
diff --git a/media/mtransport/transportflow.h b/media/mtransport/transportflow.h
index eddff571659d..ce6b8b45c227 100644
--- a/media/mtransport/transportflow.h
+++ b/media/mtransport/transportflow.h
@@ -49,8 +49,8 @@
 
 namespace mozilla {
 
-class TransportFlow : public nsISupports,
-                      public sigslot::has_slots<> {
+class TransportFlow MOZ_FINAL : public nsISupports,
+                                public sigslot::has_slots<> {
  public:
   TransportFlow()
     : id_("(anonymous)"),
diff --git a/media/mtransport/transportlayerdtls.h b/media/mtransport/transportlayerdtls.h
index 999b420d7b32..709e1967bc1a 100644
--- a/media/mtransport/transportlayerdtls.h
+++ b/media/mtransport/transportlayerdtls.h
@@ -45,7 +45,7 @@ class TransportLayerNSPRAdapter {
   std::queue input_;
 };
 
-class TransportLayerDtls : public TransportLayer {
+class TransportLayerDtls MOZ_FINAL : public TransportLayer {
  public:
   TransportLayerDtls() :
       role_(CLIENT),
diff --git a/modules/libjar/nsJARProtocolHandler.h b/modules/libjar/nsJARProtocolHandler.h
index 4687be7edd73..c1c5ffba7844 100644
--- a/modules/libjar/nsJARProtocolHandler.h
+++ b/modules/libjar/nsJARProtocolHandler.h
@@ -20,8 +20,8 @@
 class nsIHashable;
 class nsIRemoteOpenFileListener;
 
-class nsJARProtocolHandler : public nsIJARProtocolHandler
-                           , public nsSupportsWeakReference
+class nsJARProtocolHandler MOZ_FINAL : public nsIJARProtocolHandler
+                                     , public nsSupportsWeakReference
 {
     typedef nsAutoTArray, 5>
             RemoteFileListenerArray;
diff --git a/netwerk/base/src/nsSocketTransport2.h b/netwerk/base/src/nsSocketTransport2.h
index 52caccf595ab..93b362c9c42c 100644
--- a/netwerk/base/src/nsSocketTransport2.h
+++ b/netwerk/base/src/nsSocketTransport2.h
@@ -104,10 +104,10 @@ private:
 
 //-----------------------------------------------------------------------------
 
-class nsSocketTransport : public nsASocketHandler
-                        , public nsISocketTransport
-                        , public nsIDNSListener
-                        , public nsIClassInfo
+class nsSocketTransport MOZ_FINAL : public nsASocketHandler
+                                  , public nsISocketTransport
+                                  , public nsIDNSListener
+                                  , public nsIClassInfo
 {
     typedef mozilla::Mutex Mutex;
 
diff --git a/netwerk/cache/nsCacheEntryDescriptor.h b/netwerk/cache/nsCacheEntryDescriptor.h
index d224671293a5..c5af6e2f4c7c 100644
--- a/netwerk/cache/nsCacheEntryDescriptor.h
+++ b/netwerk/cache/nsCacheEntryDescriptor.h
@@ -20,7 +20,7 @@
 /******************************************************************************
 * nsCacheEntryDescriptor
 *******************************************************************************/
-class nsCacheEntryDescriptor :
+class nsCacheEntryDescriptor MOZ_FINAL :
     public PRCList,
     public nsICacheEntryDescriptor
 {
diff --git a/netwerk/cache/nsCacheService.h b/netwerk/cache/nsCacheService.h
index a54b584f85be..10148b29d781 100644
--- a/netwerk/cache/nsCacheService.h
+++ b/netwerk/cache/nsCacheService.h
@@ -62,8 +62,8 @@ private:
  *  nsCacheService
  ******************************************************************************/
 
-class nsCacheService : public nsICacheServiceInternal,
-                       public nsIMemoryReporter
+class nsCacheService MOZ_FINAL : public nsICacheServiceInternal,
+                                 public nsIMemoryReporter
 {
     virtual ~nsCacheService();
 
diff --git a/netwerk/cache/nsDiskCacheDevice.h b/netwerk/cache/nsDiskCacheDevice.h
index 6a7e3bd6b326..9d00566314eb 100644
--- a/netwerk/cache/nsDiskCacheDevice.h
+++ b/netwerk/cache/nsDiskCacheDevice.h
@@ -20,7 +20,7 @@
 class nsDiskCacheMap;
 
 
-class nsDiskCacheDevice : public nsCacheDevice {
+class nsDiskCacheDevice MOZ_FINAL : public nsCacheDevice {
 public:
     nsDiskCacheDevice();
     virtual ~nsDiskCacheDevice();
diff --git a/netwerk/cookie/nsCookieService.h b/netwerk/cookie/nsCookieService.h
index 4809be87333d..23502906d747 100644
--- a/netwerk/cookie/nsCookieService.h
+++ b/netwerk/cookie/nsCookieService.h
@@ -238,11 +238,11 @@ enum OpenDBResult
  * class declaration
  ******************************************************************************/
 
-class nsCookieService : public nsICookieService
-                      , public nsICookieManager2
-                      , public nsIObserver
-                      , public nsSupportsWeakReference
-                      , public nsIMemoryReporter
+class nsCookieService MOZ_FINAL : public nsICookieService
+                                , public nsICookieManager2
+                                , public nsIObserver
+                                , public nsSupportsWeakReference
+                                , public nsIMemoryReporter
 {
   private:
     size_t SizeOfIncludingThis(mozilla::MallocSizeOf aMallocSizeOf) const;
diff --git a/netwerk/protocol/ftp/FTPChannelParent.h b/netwerk/protocol/ftp/FTPChannelParent.h
index da537f111fdc..8101bf47734d 100644
--- a/netwerk/protocol/ftp/FTPChannelParent.h
+++ b/netwerk/protocol/ftp/FTPChannelParent.h
@@ -21,12 +21,12 @@ class nsILoadContext;
 namespace mozilla {
 namespace net {
 
-class FTPChannelParent : public PFTPChannelParent
-                       , public nsIParentChannel
-                       , public nsIInterfaceRequestor
-                       , public ADivertableParentChannel
-                       , public nsIChannelEventSink
-                       , public DisconnectableParent
+class FTPChannelParent MOZ_FINAL : public PFTPChannelParent
+                                 , public nsIParentChannel
+                                 , public nsIInterfaceRequestor
+                                 , public ADivertableParentChannel
+                                 , public nsIChannelEventSink
+                                 , public DisconnectableParent
 {
 public:
   NS_DECL_ISUPPORTS
diff --git a/netwerk/protocol/ftp/nsFtpConnectionThread.h b/netwerk/protocol/ftp/nsFtpConnectionThread.h
index c2ed325ab47d..17daa73932c8 100644
--- a/netwerk/protocol/ftp/nsFtpConnectionThread.h
+++ b/netwerk/protocol/ftp/nsFtpConnectionThread.h
@@ -76,13 +76,13 @@ class nsIStreamListener;
 // implements nsITransportEventSink so it can mix status events from both the
 // control connection and the data connection.
 
-class nsFtpState : public nsBaseContentStream,
-                   public nsIInputStreamCallback,
-                   public nsITransportEventSink,
-                   public nsICacheListener,
-                   public nsIRequestObserver,
-                   public nsFtpControlConnectionListener,
-                   public nsIProtocolProxyCallback
+class nsFtpState MOZ_FINAL : public nsBaseContentStream,
+                             public nsIInputStreamCallback,
+                             public nsITransportEventSink,
+                             public nsICacheListener,
+                             public nsIRequestObserver,
+                             public nsFtpControlConnectionListener,
+                             public nsIProtocolProxyCallback
 {
 public:
     NS_DECL_ISUPPORTS_INHERITED
diff --git a/netwerk/protocol/ftp/nsFtpProtocolHandler.h b/netwerk/protocol/ftp/nsFtpProtocolHandler.h
index f9a3d0b7e39a..51e7510c6935 100644
--- a/netwerk/protocol/ftp/nsFtpProtocolHandler.h
+++ b/netwerk/protocol/ftp/nsFtpProtocolHandler.h
@@ -17,9 +17,9 @@ class nsICacheSession;
 
 //-----------------------------------------------------------------------------
 
-class nsFtpProtocolHandler : public nsIProxiedProtocolHandler
-                           , public nsIObserver
-                           , public nsSupportsWeakReference
+class nsFtpProtocolHandler MOZ_FINAL : public nsIProxiedProtocolHandler
+                                     , public nsIObserver
+                                     , public nsSupportsWeakReference
 {
 public:
     NS_DECL_THREADSAFE_ISUPPORTS
diff --git a/netwerk/protocol/res/nsResProtocolHandler.h b/netwerk/protocol/res/nsResProtocolHandler.h
index ebd3113ac91f..6ef5fff020ae 100644
--- a/netwerk/protocol/res/nsResProtocolHandler.h
+++ b/netwerk/protocol/res/nsResProtocolHandler.h
@@ -24,7 +24,7 @@ public:
     NS_IMETHOD GetClassIDNoAlloc(nsCID *aCID);
 };
 
-class nsResProtocolHandler : public nsIResProtocolHandler, public nsSupportsWeakReference
+class nsResProtocolHandler MOZ_FINAL : public nsIResProtocolHandler, public nsSupportsWeakReference
 {
 public:
     NS_DECL_THREADSAFE_ISUPPORTS
diff --git a/toolkit/components/downloads/nsDownloadManager.h b/toolkit/components/downloads/nsDownloadManager.h
index dfe7c7d207ab..dd0d286f9c09 100644
--- a/toolkit/components/downloads/nsDownloadManager.h
+++ b/toolkit/components/downloads/nsDownloadManager.h
@@ -38,10 +38,10 @@ class nsDownload;
 #include "nsDownloadScanner.h"
 #endif
 
-class nsDownloadManager : public nsIDownloadManager,
-                          public nsINavHistoryObserver,
-                          public nsIObserver,
-                          public nsSupportsWeakReference
+class nsDownloadManager MOZ_FINAL : public nsIDownloadManager,
+                                    public nsINavHistoryObserver,
+                                    public nsIObserver,
+                                    public nsSupportsWeakReference
 {
 public:
   NS_DECL_ISUPPORTS
diff --git a/toolkit/components/places/History.h b/toolkit/components/places/History.h
index 476ca2f5c34a..5739383978b4 100644
--- a/toolkit/components/places/History.h
+++ b/toolkit/components/places/History.h
@@ -36,11 +36,11 @@ class ConcurrentStatementsHolder;
 // Max size of History::mRecentlyVisitedURIs
 #define RECENTLY_VISITED_URI_SIZE 8
 
-class History : public IHistory
-              , public nsIDownloadHistory
-              , public mozIAsyncHistory
-              , public nsIObserver
-              , public nsIMemoryReporter
+class History MOZ_FINAL : public IHistory
+                        , public nsIDownloadHistory
+                        , public mozIAsyncHistory
+                        , public nsIObserver
+                        , public nsIMemoryReporter
 {
 public:
   NS_DECL_THREADSAFE_ISUPPORTS
diff --git a/toolkit/components/places/nsNavHistoryResult.h b/toolkit/components/places/nsNavHistoryResult.h
index e28a6fad7318..9490bf6b02f9 100644
--- a/toolkit/components/places/nsNavHistoryResult.h
+++ b/toolkit/components/places/nsNavHistoryResult.h
@@ -105,10 +105,10 @@ private:
 #define NS_NAVHISTORYRESULT_IID \
   { 0x455d1d40, 0x1b9b, 0x40e6, { 0xa6, 0x41, 0x8b, 0xb7, 0xe8, 0x82, 0x23, 0x87 } }
 
-class nsNavHistoryResult : public nsSupportsWeakReference,
-                           public nsINavHistoryResult,
-                           public nsINavBookmarkObserver,
-                           public nsINavHistoryObserver
+class nsNavHistoryResult MOZ_FINAL : public nsSupportsWeakReference,
+                                     public nsINavHistoryResult,
+                                     public nsINavBookmarkObserver,
+                                     public nsINavHistoryObserver
 {
 public:
   static nsresult NewHistoryResult(nsINavHistoryQuery** aQueries,
@@ -619,9 +619,9 @@ NS_DEFINE_STATIC_IID_ACCESSOR(nsNavHistoryContainerResultNode,
 //    bookmarks. This keeps itself in sync by listening to history and
 //    bookmark notifications.
 
-class nsNavHistoryQueryResultNode : public nsNavHistoryContainerResultNode,
-                                    public nsINavHistoryQueryResultNode,
-                                    public nsINavBookmarkObserver
+class nsNavHistoryQueryResultNode MOZ_FINAL : public nsNavHistoryContainerResultNode,
+                                              public nsINavHistoryQueryResultNode,
+                                              public nsINavBookmarkObserver
 {
 public:
   nsNavHistoryQueryResultNode(const nsACString& aTitle,
@@ -700,10 +700,10 @@ protected:
 //    Overridden container type for bookmark folders. It will keep the contents
 //    of the folder in sync with the bookmark service.
 
-class nsNavHistoryFolderResultNode : public nsNavHistoryContainerResultNode,
-                                     public nsINavHistoryQueryResultNode,
-                                     public nsINavBookmarkObserver,
-                                     public mozilla::places::AsyncStatementCallback
+class nsNavHistoryFolderResultNode MOZ_FINAL : public nsNavHistoryContainerResultNode,
+                                               public nsINavHistoryQueryResultNode,
+                                               public nsINavBookmarkObserver,
+                                               public mozilla::places::AsyncStatementCallback
 {
 public:
   nsNavHistoryFolderResultNode(const nsACString& aTitle,
diff --git a/tools/profiler/LulDwarfExt.h b/tools/profiler/LulDwarfExt.h
index bb71b1ef4379..5cb3984fdd87 100644
--- a/tools/profiler/LulDwarfExt.h
+++ b/tools/profiler/LulDwarfExt.h
@@ -1062,7 +1062,7 @@ class CallFrameInfo::Handler {
 // report errors or warn about problems in the data it is parsing.
 // These messages are sent to the message sink |aLog| provided to the
 // constructor.
-class CallFrameInfo::Reporter {
+class CallFrameInfo::Reporter MOZ_FINAL {
  public:
   // Create an error reporter which attributes troubles to the section
   // named SECTION in FILENAME.
diff --git a/xpcom/base/nsSystemInfo.h b/xpcom/base/nsSystemInfo.h
index 1c459ff5aa59..7efbd8825065 100644
--- a/xpcom/base/nsSystemInfo.h
+++ b/xpcom/base/nsSystemInfo.h
@@ -12,7 +12,7 @@
 #include "nsIObserver.h"
 #endif // defined(XP_WIN)
 
-class nsSystemInfo
+class nsSystemInfo MOZ_FINAL
   : public nsHashPropertyBag
 #if defined(XP_WIN)
   , public nsIObserver
diff --git a/xpfe/components/windowds/nsWindowDataSource.h b/xpfe/components/windowds/nsWindowDataSource.h
index d26b851efed5..92939a6521d9 100644
--- a/xpfe/components/windowds/nsWindowDataSource.h
+++ b/xpfe/components/windowds/nsWindowDataSource.h
@@ -20,10 +20,10 @@
  { 0x8d, 0x70, 0x7c, 0xe6, 0x3c, 0x51, 0xc9, 0x58 } }
 
 
-class nsWindowDataSource : public nsIRDFDataSource,
-                           public nsIObserver,
-                           public nsIWindowMediatorListener,
-                           public nsIWindowDataSource
+class nsWindowDataSource MOZ_FINAL : public nsIRDFDataSource,
+                                     public nsIObserver,
+                                     public nsIWindowMediatorListener,
+                                     public nsIWindowDataSource
 {
  public:
     nsWindowDataSource() { }

From 412d4602800c637805b90a2fcbb0339c89d21883 Mon Sep 17 00:00:00 2001
From: Matthew Gregan 
Date: Tue, 25 Nov 2014 14:09:19 +1300
Subject: [PATCH 52/64] Bug 1104357 - Ensure MediaDecoderReader is shutdown on
 all exit paths from MediaDecodeTask::Decode.  r=cpearce

Also adds an assertion to MediaDecoderReader::Shutdown to ensure it is called from the appropriate thread.
---
 dom/media/MediaDecoderReader.cpp          | 1 +
 dom/media/MediaDecoderReader.h            | 3 ++-
 dom/media/webaudio/MediaBufferDecoder.cpp | 5 ++++-
 3 files changed, 7 insertions(+), 2 deletions(-)

diff --git a/dom/media/MediaDecoderReader.cpp b/dom/media/MediaDecoderReader.cpp
index 8e05c17e515f..dd056aa26967 100644
--- a/dom/media/MediaDecoderReader.cpp
+++ b/dom/media/MediaDecoderReader.cpp
@@ -264,6 +264,7 @@ MediaDecoderReader::BreakCycles()
 void
 MediaDecoderReader::Shutdown()
 {
+  MOZ_ASSERT(mDecoder->OnDecodeThread());
   ReleaseMediaResources();
 }
 
diff --git a/dom/media/MediaDecoderReader.h b/dom/media/MediaDecoderReader.h
index 0d2388adcd04..a30cc7abfe87 100644
--- a/dom/media/MediaDecoderReader.h
+++ b/dom/media/MediaDecoderReader.h
@@ -56,7 +56,8 @@ public:
 
   // Destroys the decoding state. The reader cannot be made usable again.
   // This is different from ReleaseMediaResources() as it is irreversable,
-  // whereas ReleaseMediaResources() is.
+  // whereas ReleaseMediaResources() is.  Must be called on the decode
+  // thread.
   virtual void Shutdown();
 
   virtual void SetCallback(RequestSampleCallback* aDecodedSampleCallback);
diff --git a/dom/media/webaudio/MediaBufferDecoder.cpp b/dom/media/webaudio/MediaBufferDecoder.cpp
index 8d5af170a302..9d899811e403 100644
--- a/dom/media/webaudio/MediaBufferDecoder.cpp
+++ b/dom/media/webaudio/MediaBufferDecoder.cpp
@@ -142,6 +142,7 @@ private:
     MOZ_ASSERT(NS_IsMainThread());
     // MediaDecoderReader expects that BufferDecoder is alive.
     // Destruct MediaDecoderReader first.
+    mDecoderReader->BreakCycles();
     mDecoderReader = nullptr;
     mBufferDecoder = nullptr;
     JS_free(nullptr, mBuffer);
@@ -248,11 +249,13 @@ MediaDecodeTask::Decode()
   nsAutoPtr tags;
   nsresult rv = mDecoderReader->ReadMetadata(&mediaInfo, getter_Transfers(tags));
   if (NS_FAILED(rv)) {
+    mDecoderReader->Shutdown();
     ReportFailureOnMainThread(WebAudioDecodeJob::InvalidContent);
     return;
   }
 
   if (!mDecoderReader->HasAudio()) {
+    mDecoderReader->Shutdown();
     ReportFailureOnMainThread(WebAudioDecodeJob::NoAudio);
     return;
   }
@@ -264,6 +267,7 @@ MediaDecodeTask::Decode()
     mDecoderReader->RequestAudioData();
     nsRefPtr audio;
     if (NS_FAILED(barrier->Await(audio))) {
+      mDecoderReader->Shutdown();
       ReportFailureOnMainThread(WebAudioDecodeJob::InvalidContent);
       return;
     }
@@ -274,7 +278,6 @@ MediaDecodeTask::Decode()
     audioQueue.Push(audio);
   }
   mDecoderReader->Shutdown();
-  mDecoderReader->BreakCycles();
 
   uint32_t frameCount = audioQueue.FrameCount();
   uint32_t channelCount = mediaInfo.mAudio.mChannels;

From 44fbf3bf13bc0498b8152b73f68b01d54095ed34 Mon Sep 17 00:00:00 2001
From: Jeff Gilbert 
Date: Thu, 13 Nov 2014 20:03:50 -0800
Subject: [PATCH 53/64] Bug 1099427 - Reformat WebGL. - r=kamidphish

---
 dom/canvas/WebGL1Context.cpp                  |    6 -
 dom/canvas/WebGL2Context.cpp                  |   62 +-
 dom/canvas/WebGL2Context.h                    |    2 +-
 dom/canvas/WebGL2ContextQueries.cpp           |  134 +--
 dom/canvas/WebGL2ContextTextures.cpp          |   10 +-
 dom/canvas/WebGLActiveInfo.cpp                |   11 +-
 dom/canvas/WebGLActiveInfo.h                  |   20 +-
 dom/canvas/WebGLBuffer.cpp                    |   47 +-
 dom/canvas/WebGLBuffer.h                      |   31 +-
 dom/canvas/WebGLContext.cpp                   |  513 ++++----
 dom/canvas/WebGLContext.h                     |  859 +++++++-------
 dom/canvas/WebGLContextBuffers.cpp            |  251 ++--
 dom/canvas/WebGLContextDraw.cpp               |    7 +-
 dom/canvas/WebGLContextExtensions.cpp         |  396 +++----
 dom/canvas/WebGLContextGL.cpp                 |  135 +--
 dom/canvas/WebGLContextLossHandler.cpp        |    5 +-
 dom/canvas/WebGLContextLossHandler.h          |    2 +-
 dom/canvas/WebGLContextNotSupported.cpp       |    2 +-
 dom/canvas/WebGLContextReporter.cpp           |   35 +-
 dom/canvas/WebGLContextUtils.cpp              |  220 ++--
 dom/canvas/WebGLContextUtils.h                |   50 +-
 dom/canvas/WebGLContextValidate.cpp           | 1046 +++++++++--------
 dom/canvas/WebGLContextVertexArray.cpp        |   19 +-
 dom/canvas/WebGLContextVertices.cpp           |    2 +-
 dom/canvas/WebGLElementArrayCache.cpp         |  943 ++++++++-------
 dom/canvas/WebGLElementArrayCache.h           |  129 +-
 dom/canvas/WebGLExtensionBlendMinMax.cpp      |   17 +-
 dom/canvas/WebGLExtensionColorBufferFloat.cpp |   14 +-
 .../WebGLExtensionColorBufferHalfFloat.cpp    |   14 +-
 .../WebGLExtensionCompressedTextureATC.cpp    |   17 +-
 .../WebGLExtensionCompressedTextureETC1.cpp   |   10 +-
 .../WebGLExtensionCompressedTexturePVRTC.cpp  |   19 +-
 .../WebGLExtensionCompressedTextureS3TC.cpp   |   19 +-
 .../WebGLExtensionDebugRendererInfo.cpp       |   11 +-
 dom/canvas/WebGLExtensionDebugShaders.cpp     |   30 +-
 dom/canvas/WebGLExtensionDepthTexture.cpp     |   11 +-
 dom/canvas/WebGLExtensionDrawBuffers.cpp      |   65 +-
 dom/canvas/WebGLExtensionElementIndexUint.cpp |   11 +-
 dom/canvas/WebGLExtensionFragDepth.cpp        |   21 +-
 dom/canvas/WebGLExtensionInstancedArrays.cpp  |   57 +-
 dom/canvas/WebGLExtensionLoseContext.cpp      |   11 +-
 dom/canvas/WebGLExtensionSRGB.cpp             |   27 +-
 dom/canvas/WebGLExtensionShaderTextureLod.cpp |   11 +-
 .../WebGLExtensionStandardDerivatives.cpp     |   11 +-
 ...WebGLExtensionTextureFilterAnisotropic.cpp |   11 +-
 dom/canvas/WebGLExtensionTextureFloat.cpp     |   11 +-
 .../WebGLExtensionTextureFloatLinear.cpp      |   11 +-
 dom/canvas/WebGLExtensionTextureHalfFloat.cpp |   11 +-
 .../WebGLExtensionTextureHalfFloatLinear.cpp  |   11 +-
 dom/canvas/WebGLExtensionVertexArray.cpp      |   58 +-
 dom/canvas/WebGLExtensions.h                  |   43 +-
 dom/canvas/WebGLFramebuffer.cpp               |  410 ++++---
 dom/canvas/WebGLFramebuffer.h                 |   43 +-
 dom/canvas/WebGLMemoryTracker.h               |   39 +-
 dom/canvas/WebGLObjectModel.cpp               |   20 +-
 dom/canvas/WebGLObjectModel.h                 |  117 +-
 dom/canvas/WebGLProgram.cpp                   |  186 +--
 dom/canvas/WebGLProgram.h                     |   68 +-
 dom/canvas/WebGLQuery.cpp                     |   12 +-
 dom/canvas/WebGLQuery.h                       |   47 +-
 dom/canvas/WebGLRenderbuffer.cpp              |  126 +-
 dom/canvas/WebGLRenderbuffer.h                |   38 +-
 dom/canvas/WebGLSampler.cpp                   |   11 +-
 dom/canvas/WebGLSampler.h                     |   18 +-
 dom/canvas/WebGLShader.cpp                    |   39 +-
 dom/canvas/WebGLShader.h                      |   45 +-
 dom/canvas/WebGLShaderPrecisionFormat.cpp     |   11 +-
 dom/canvas/WebGLShaderPrecisionFormat.h       |   28 +-
 dom/canvas/WebGLStrongTypes.h                 |  185 ++-
 dom/canvas/WebGLSync.cpp                      |   10 +-
 dom/canvas/WebGLSync.h                        |   18 +-
 dom/canvas/WebGLTexelConversions.cpp          |   12 +-
 dom/canvas/WebGLTexture.cpp                   |  412 ++++---
 dom/canvas/WebGLTexture.h                     |  158 +--
 dom/canvas/WebGLTransformFeedback.cpp         |   11 +-
 dom/canvas/WebGLTransformFeedback.h           |   23 +-
 dom/canvas/WebGLUniformLocation.cpp           |   20 +-
 dom/canvas/WebGLUniformLocation.h             |   18 +-
 dom/canvas/WebGLValidateStrings.h             |   19 +-
 dom/canvas/WebGLVertexArray.cpp               |   32 +-
 dom/canvas/WebGLVertexArray.h                 |   73 +-
 dom/canvas/WebGLVertexArrayFake.cpp           |   18 +-
 dom/canvas/WebGLVertexArrayFake.h             |   14 +-
 dom/canvas/WebGLVertexArrayGL.cpp             |    2 +-
 dom/canvas/WebGLVertexArrayGL.h               |   10 +-
 dom/canvas/WebGLVertexAttribData.h            |   71 +-
 .../TestWebGLElementArrayCache.cpp            |   49 +-
 dom/canvas/compiledtest/moz.build             |    3 +
 dom/canvas/moz.build                          |    3 +
 89 files changed, 4181 insertions(+), 3707 deletions(-)

diff --git a/dom/canvas/WebGL1Context.cpp b/dom/canvas/WebGL1Context.cpp
index 69dac30baad6..87b3bce798ad 100644
--- a/dom/canvas/WebGL1Context.cpp
+++ b/dom/canvas/WebGL1Context.cpp
@@ -25,9 +25,6 @@ WebGL1Context::~WebGL1Context()
 {
 }
 
-////////////////////////////////////////
-// nsWrapperCache
-
 JSObject*
 WebGL1Context::WrapObject(JSContext* cx)
 {
@@ -36,9 +33,6 @@ WebGL1Context::WrapObject(JSContext* cx)
 
 } // namespace mozilla
 
-////////////////////////////////////////
-// nsIDOMWebGLRenderingContext
-
 nsresult
 NS_NewCanvasRenderingContextWebGL(nsIDOMWebGLRenderingContext** out_result)
 {
diff --git a/dom/canvas/WebGL2Context.cpp b/dom/canvas/WebGL2Context.cpp
index e5159cab8728..0bba0aec2717 100644
--- a/dom/canvas/WebGL2Context.cpp
+++ b/dom/canvas/WebGL2Context.cpp
@@ -4,16 +4,13 @@
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "WebGL2Context.h"
+
 #include "GLContext.h"
 #include "mozilla/dom/WebGL2RenderingContextBinding.h"
 #include "mozilla/Preferences.h"
 #include "mozilla/Telemetry.h"
 
-using namespace mozilla;
-using namespace mozilla::gl;
-
-// -----------------------------------------------------------------------------
-// CONSTRUCTOR & DESTRUCTOR
+namespace mozilla {
 
 WebGL2Context::WebGL2Context()
     : WebGLContext()
@@ -27,34 +24,25 @@ WebGL2Context::~WebGL2Context()
 
 }
 
-
-// -----------------------------------------------------------------------------
-// STATIC FUNCTIONS
-
-bool
+/*static*/ bool
 WebGL2Context::IsSupported()
 {
     return Preferences::GetBool("webgl.enable-prototype-webgl2", false);
 }
 
-WebGL2Context*
+/*static*/ WebGL2Context*
 WebGL2Context::Create()
 {
     return new WebGL2Context();
 }
 
-
-// -----------------------------------------------------------------------------
-// IMPLEMENT nsWrapperCache
-
 JSObject*
-WebGL2Context::WrapObject(JSContext *cx)
+WebGL2Context::WrapObject(JSContext* cx)
 {
     return dom::WebGL2RenderingContextBinding::Wrap(cx, this);
 }
 
-
-// -----------------------------------------------------------------------------
+////////////////////////////////////////////////////////////////////////////////
 // WebGL 2 initialisation
 
 bool
@@ -76,15 +64,15 @@ WebGLContext::InitWebGL2()
         WebGLExtensionID::WEBGL_depth_texture,
         WebGLExtensionID::WEBGL_draw_buffers
     };
-    const GLFeature sFeatureRequiredArr[] = {
-        GLFeature::instanced_non_arrays,
-        GLFeature::transform_feedback2,
-        GLFeature::invalidate_framebuffer
+    const gl::GLFeature sFeatureRequiredArr[] = {
+        gl::GLFeature::instanced_non_arrays,
+        gl::GLFeature::transform_feedback2,
+        gl::GLFeature::invalidate_framebuffer
     };
 
     // check WebGL extensions that are supposed to be natively supported
-    for (size_t i = 0; i < size_t(MOZ_ARRAY_LENGTH(sExtensionNativelySupportedArr)); i++)
-    {
+    size_t len = MOZ_ARRAY_LENGTH(sExtensionNativelySupportedArr);
+    for (size_t i = 0; i < len; i++) {
         WebGLExtensionID extension = sExtensionNativelySupportedArr[i];
 
         if (!IsExtensionSupported(extension)) {
@@ -94,40 +82,42 @@ WebGLContext::InitWebGL2()
     }
 
     // check required OpenGL extensions
-    if (!gl->IsExtensionSupported(GLContext::EXT_gpu_shader4)) {
+    if (!gl->IsExtensionSupported(gl::GLContext::EXT_gpu_shader4)) {
         GenerateWarning("WebGL 2 requires GL_EXT_gpu_shader4!");
         return false;
     }
 
     // check OpenGL features
-    if (!gl->IsSupported(GLFeature::occlusion_query) &&
-        !gl->IsSupported(GLFeature::occlusion_query_boolean))
+    if (!gl->IsSupported(gl::GLFeature::occlusion_query) &&
+        !gl->IsSupported(gl::GLFeature::occlusion_query_boolean))
     {
-        /*
-         * on desktop, we fake occlusion_query_boolean with occlusion_query if
-         * necessary. See WebGLContextAsyncQueries.cpp.
-         */
+        // On desktop, we fake occlusion_query_boolean with occlusion_query if
+        //necessary. (See WebGLContextAsyncQueries.cpp)
         GenerateWarning("WebGL 2 requires occlusion queries!");
         return false;
     }
 
-    for (size_t i = 0; i < size_t(MOZ_ARRAY_LENGTH(sFeatureRequiredArr)); i++)
-    {
+    for (size_t i = 0; i < size_t(MOZ_ARRAY_LENGTH(sFeatureRequiredArr)); i++) {
         if (!gl->IsSupported(sFeatureRequiredArr[i])) {
-            GenerateWarning("WebGL 2 requires GLFeature::%s!", GLContext::GetFeatureName(sFeatureRequiredArr[i]));
+            GenerateWarning("WebGL 2 requires GLFeature::%s!",
+                            gl::GLContext::GetFeatureName(sFeatureRequiredArr[i]));
             return false;
         }
     }
 
     // ok WebGL 2 is compatible, we can enable natively supported extensions.
-    for (size_t i = 0; i < size_t(MOZ_ARRAY_LENGTH(sExtensionNativelySupportedArr)); i++) {
+    len = MOZ_ARRAY_LENGTH(sExtensionNativelySupportedArr);
+    for (size_t i = 0; i < len; i++) {
         EnableExtension(sExtensionNativelySupportedArr[i]);
 
         MOZ_ASSERT(IsExtensionEnabled(sExtensionNativelySupportedArr[i]));
     }
 
     // we initialise WebGL 2 related stuff.
-    gl->GetUIntegerv(LOCAL_GL_MAX_TRANSFORM_FEEDBACK_SEPARATE_ATTRIBS, &mGLMaxTransformFeedbackSeparateAttribs);
+    gl->GetUIntegerv(LOCAL_GL_MAX_TRANSFORM_FEEDBACK_SEPARATE_ATTRIBS,
+                     &mGLMaxTransformFeedbackSeparateAttribs);
 
     return true;
 }
+
+} // namespace mozilla
diff --git a/dom/canvas/WebGL2Context.h b/dom/canvas/WebGL2Context.h
index e9259e39443e..1c34359bee5a 100644
--- a/dom/canvas/WebGL2Context.h
+++ b/dom/canvas/WebGL2Context.h
@@ -33,7 +33,7 @@ public:
     // -------------------------------------------------------------------------
     // IMPLEMENT nsWrapperCache
 
-    virtual JSObject* WrapObject(JSContext *cx) MOZ_OVERRIDE;
+    virtual JSObject* WrapObject(JSContext* cx) MOZ_OVERRIDE;
 
 
     // -------------------------------------------------------------------------
diff --git a/dom/canvas/WebGL2ContextQueries.cpp b/dom/canvas/WebGL2ContextQueries.cpp
index 5dd3ef273c94..c666c64ae0e0 100644
--- a/dom/canvas/WebGL2ContextQueries.cpp
+++ b/dom/canvas/WebGL2ContextQueries.cpp
@@ -14,11 +14,11 @@ using namespace mozilla::dom;
  * We fake ANY_SAMPLES_PASSED and ANY_SAMPLES_PASSED_CONSERVATIVE with
  * SAMPLES_PASSED on desktop.
  *
- * OpenGL ES 3.0 spec 4.1.6
- *  If the target of the query is ANY_SAMPLES_PASSED_CONSERVATIVE, an
- *  implementation may choose to use a less precise version of the test which
- *  can additionally set the samples-boolean state to TRUE in some other
- *  implementation-dependent cases.
+ * OpenGL ES 3.0 spec 4.1.6:
+ *     If the target of the query is ANY_SAMPLES_PASSED_CONSERVATIVE, an
+ *     implementation may choose to use a less precise version of the test which
+ *     can additionally set the samples-boolean state to TRUE in some other
+ *     implementation-dependent cases.
  */
 
 static const char*
@@ -88,9 +88,9 @@ WebGL2Context::CreateQuery()
          * any target is active causes an INVALID_OPERATION error to be
          * generated.
          */
-        GenerateWarning("createQuery: the WebGL 2 prototype might generate "
-                        "INVALID_OPERATION when creating a query object while "
-                        "one other is active.");
+        GenerateWarning("createQuery: The WebGL 2 prototype might generate"
+                        " INVALID_OPERATION when creating a query object while"
+                        " one other is active.");
         /*
          * We *need* to lock webgl2 to GL>=3.0 on desktop, but we don't have a
          * good mechanism to do this yet. See bug 898404.
@@ -124,9 +124,9 @@ WebGL2Context::DeleteQuery(WebGLQuery* query)
          * any target is active causes an INVALID_OPERATION error to be
          * generated.
          */
-        GenerateWarning("deleteQuery: the WebGL 2 prototype might generate "
-                        "INVALID_OPERATION when deleting a query object while "
-                        "one other is active.");
+        GenerateWarning("deleteQuery: The WebGL 2 prototype might generate"
+                        " INVALID_OPERATION when deleting a query object while"
+                        " one other is active.");
     }
 
     query->RequestDelete();
@@ -159,59 +159,56 @@ WebGL2Context::BeginQuery(GLenum target, WebGLQuery* query)
     }
 
     if (!query) {
-        /* SPECS BeginQuery.1
-         * http://www.khronos.org/registry/gles/extensions/EXT/EXT_occlusion_query_boolean.txt
-         * BeginQueryEXT sets the active query object name for the query type given
-         * by  to . If BeginQueryEXT is called with an  of zero, if
-         * the active query object name for  is non-zero (for the targets
-         * ANY_SAMPLES_PASSED_EXT and ANY_SAMPLES_PASSED_CONSERVATIVE_EXT, if the
-         * active query for either target is non-zero), if  is the name of an
-         * existing query object whose type does not match , or if  is the
-         * active query object name for any query type, the error INVALID_OPERATION is
-         * generated.
+        /* From GLES's EXT_occlusion_query_boolean:
+         *     BeginQueryEXT sets the active query object name for the query
+         *     type given by  to . If BeginQueryEXT is called with
+         *     an  of zero, if the active query object name for  is
+         *     non-zero (for the targets ANY_SAMPLES_PASSED_EXT and
+         *     ANY_SAMPLES_PASSED_CONSERVATIVE_EXT, if the active query for
+         *     either target is non-zero), if  is the name of an existing
+         *     query object whose type does not match , or if  is
+         *     the active query object name for any query type, the error
+         *     INVALID_OPERATION is generated.
          */
-        ErrorInvalidOperation("beginQuery: query should not be null");
+        ErrorInvalidOperation("beginQuery: Query should not be null.");
         return;
     }
 
     if (query->IsDeleted()) {
-        /* http://www.khronos.org/registry/gles/extensions/EXT/EXT_occlusion_query_boolean.txt
-         * BeginQueryEXT fails and an INVALID_OPERATION error is generated if 
-         * is not a name returned from a previous call to GenQueriesEXT, or if such
-         * a name has since been deleted with DeleteQueriesEXT.
+        /* From GLES's EXT_occlusion_query_boolean:
+         *     BeginQueryEXT fails and an INVALID_OPERATION error is generated
+         *     if  is not a name returned from a previous call to
+         *     GenQueriesEXT, or if such a name has since been deleted with
+         *     DeleteQueriesEXT.
          */
-        ErrorInvalidOperation("beginQuery: query has been deleted");
+        ErrorInvalidOperation("beginQuery: Query has been deleted.");
         return;
     }
 
     if (query->HasEverBeenActive() &&
         query->mType != target)
     {
-        /*
-         * See SPECS BeginQuery.1
-         */
-        ErrorInvalidOperation("beginQuery: target doesn't match with the query type");
+        ErrorInvalidOperation("beginQuery: Target doesn't match with the query"
+                              " type.");
         return;
     }
 
     if (*targetSlot) {
-        /*
-         * See SPECS BeginQuery.1
-         */
-        ErrorInvalidOperation("beginQuery: an other query already active");
+        ErrorInvalidOperation("beginQuery: An other query already active.");
         return;
     }
 
-    if (!query->HasEverBeenActive()) {
+    if (!query->HasEverBeenActive())
         query->mType = target;
-    }
 
     MakeContextCurrent();
 
     if (target == LOCAL_GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN) {
-        gl->fBeginQuery(LOCAL_GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN, query->mGLName);
+        gl->fBeginQuery(LOCAL_GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN,
+                        query->mGLName);
     } else {
-        gl->fBeginQuery(SimulateOcclusionQueryTarget(gl, target), query->mGLName);
+        gl->fBeginQuery(SimulateOcclusionQueryTarget(gl, target),
+                        query->mGLName);
     }
 
     *targetSlot = query;
@@ -229,18 +226,21 @@ WebGL2Context::EndQuery(GLenum target)
         return;
     }
 
-    if (!*targetSlot || target != (*targetSlot)->mType) {
-        /* http://www.khronos.org/registry/gles/extensions/EXT/EXT_occlusion_query_boolean.txt
-         * marks the end of the sequence of commands to be tracked for the query type
-         * given by . The active query object for  is updated to
-         * indicate that query results are not available, and the active query object
-         * name for  is reset to zero. When the commands issued prior to
-         * EndQueryEXT have completed and a final query result is available, the
-         * query object active when EndQueryEXT is called is updated by the GL. The
-         * query object is updated to indicate that the query results are available
-         * and to contain the query result. If the active query object name for
-         *  is zero when EndQueryEXT is called, the error INVALID_OPERATION
-         * is generated.
+    if (!*targetSlot ||
+        target != (*targetSlot)->mType)
+    {
+        /* From GLES's EXT_occlusion_query_boolean:
+         *     marks the end of the sequence of commands to be tracked for the
+         *     query type given by . The active query object for
+         *      is updated to indicate that query results are not
+         *     available, and the active query object name for  is reset
+         *     to zero. When the commands issued prior to EndQueryEXT have
+         *     completed and a final query result is available, the query object
+         *     active when EndQueryEXT is called is updated by the GL. The query
+         *     object is updated to indicate that the query results are
+         *     available and to contain the query result. If the active query
+         *     object name for  is zero when EndQueryEXT is called, the
+         *     error INVALID_OPERATION is generated.
          */
         ErrorInvalidOperation("endQuery: There is no active query of type %s.",
                               GetQueryTargetEnumString(target));
@@ -271,10 +271,10 @@ WebGL2Context::GetQuery(GLenum target, GLenum pname)
     }
 
     if (pname != LOCAL_GL_CURRENT_QUERY) {
-        /* OpenGL ES 3.0 spec 6.1.7
-         *  pname must be CURRENT_QUERY.
+        /* OpenGL ES 3.0 spec 6.1.7:
+         *     pname must be CURRENT_QUERY.
          */
-        ErrorInvalidEnum("getQuery: pname must be CURRENT_QUERY");
+        ErrorInvalidEnum("getQuery: `pname` must be CURRENT_QUERY.");
         return nullptr;
     }
 
@@ -283,7 +283,8 @@ WebGL2Context::GetQuery(GLenum target, GLenum pname)
 }
 
 void
-WebGL2Context::GetQueryParameter(JSContext*, WebGLQuery* query, GLenum pname, JS::MutableHandleValue retval)
+WebGL2Context::GetQueryParameter(JSContext*, WebGLQuery* query, GLenum pname,
+                                 JS::MutableHandleValue retval)
 {
     retval.set(JS::NullValue());
 
@@ -291,33 +292,34 @@ WebGL2Context::GetQueryParameter(JSContext*, WebGLQuery* query, GLenum pname, JS
         return;
 
     if (!query) {
-        /* OpenGL ES 3.0 spec 6.1.7 (spec getQueryObject 1)
-         *  If id is not the name of a query object, or if the query object named by id is
-         *  currently active, then an INVALID_OPERATION error is generated. pname must be
-         *  QUERY_RESULT or QUERY_RESULT_AVAILABLE.
+        /* OpenGL ES 3.0 spec 6.1.7 (spec getQueryObject 1):
+         *    If id is not the name of a query object, or if the query object
+         *    named by id is currently active, then an INVALID_OPERATION error
+         *    is generated. pname must be QUERY_RESULT or
+         *    QUERY_RESULT_AVAILABLE.
          */
-        ErrorInvalidOperation("getQueryObject: query should not be null");
+        ErrorInvalidOperation("getQueryObject: `query` should not be null.");
         return;
     }
 
     if (query->IsDeleted()) {
         // See (spec getQueryObject 1)
-        ErrorInvalidOperation("getQueryObject: query has been deleted");
+        ErrorInvalidOperation("getQueryObject: `query` has been deleted.");
         return;
     }
 
     if (query->IsActive()) {
         // See (spec getQueryObject 1)
-        ErrorInvalidOperation("getQueryObject: query is active");
+        ErrorInvalidOperation("getQueryObject: `query` is active.");
         return;
     }
 
     if (!query->HasEverBeenActive()) {
         /* See (spec getQueryObject 1)
-         *  If this instance of WebGLQuery has never been active before, that mean that
-         *  query->mGLName is not a query object yet.
+         *     If this instance of WebGLQuery has never been active before, that
+         *     mean that query->mGLName is not a query object yet.
          */
-        ErrorInvalidOperation("getQueryObject: query has never been active");
+        ErrorInvalidOperation("getQueryObject: `query` has never been active.");
         return;
     }
 
@@ -349,5 +351,5 @@ WebGL2Context::GetQueryParameter(JSContext*, WebGLQuery* query, GLenum pname, JS
         break;
     }
 
-    ErrorInvalidEnum("getQueryObject: pname must be QUERY_RESULT{_AVAILABLE}");
+    ErrorInvalidEnum("getQueryObject: `pname` must be QUERY_RESULT{_AVAILABLE}.");
 }
diff --git a/dom/canvas/WebGL2ContextTextures.cpp b/dom/canvas/WebGL2ContextTextures.cpp
index 44d586d469c3..97899bb9c6f3 100644
--- a/dom/canvas/WebGL2ContextTextures.cpp
+++ b/dom/canvas/WebGL2ContextTextures.cpp
@@ -90,7 +90,7 @@ WebGL2Context::ValidateTexStorage(GLenum target, GLsizei levels, GLenum internal
                                       const char* info)
 {
     // GL_INVALID_OPERATION is generated if the default texture object is curently bound to target.
-    WebGLTexture* tex = activeBoundTextureForTarget(target);
+    WebGLTexture* tex = ActiveBoundTextureForTarget(target);
     if (!tex) {
         ErrorInvalidOperation("%s: no texture is bound to target %s", info, EnumName(target));
         return false;
@@ -145,7 +145,7 @@ WebGL2Context::TexStorage2D(GLenum target, GLsizei levels, GLenum internalformat
         return GenerateWarning("texStorage2D generated error %s", ErrorName(error));
     }
 
-    WebGLTexture* tex = activeBoundTextureForTarget(target);
+    WebGLTexture* tex = ActiveBoundTextureForTarget(target);
     tex->SetImmutable();
 
     const size_t facesCount = (target == LOCAL_GL_TEXTURE_2D) ? 1 : 6;
@@ -184,7 +184,7 @@ WebGL2Context::TexStorage3D(GLenum target, GLsizei levels, GLenum internalformat
         return GenerateWarning("texStorage3D generated error %s", ErrorName(error));
     }
 
-    WebGLTexture* tex = activeBoundTextureForTarget(target);
+    WebGLTexture* tex = ActiveBoundTextureForTarget(target);
     tex->SetImmutable();
 
     GLsizei w = width;
@@ -275,7 +275,7 @@ WebGL2Context::TexImage3D(GLenum target, GLint level, GLenum internalformat,
         return ErrorInvalidOperation("texImage3D: not enough data for operation (need %d, have %d)",
                                  bytesNeeded, dataLength);
 
-    WebGLTexture* tex = activeBoundTextureForTexImageTarget(texImageTarget);
+    WebGLTexture* tex = ActiveBoundTextureForTexImageTarget(texImageTarget);
 
     if (!tex)
         return ErrorInvalidOperation("texImage3D: no texture is bound to this target");
@@ -338,7 +338,7 @@ WebGL2Context::TexSubImage3D(GLenum rawTarget, GLint level,
 
     TexImageTarget texImageTarget(rawTarget);
 
-    WebGLTexture* tex = activeBoundTextureForTexImageTarget(texImageTarget);
+    WebGLTexture* tex = ActiveBoundTextureForTexImageTarget(texImageTarget);
     if (!tex) {
         return ErrorInvalidOperation("texSubImage3D: no texture bound on active texture unit");
     }
diff --git a/dom/canvas/WebGLActiveInfo.cpp b/dom/canvas/WebGLActiveInfo.cpp
index d84d4e10c011..cece184fbf05 100644
--- a/dom/canvas/WebGLActiveInfo.cpp
+++ b/dom/canvas/WebGLActiveInfo.cpp
@@ -3,13 +3,18 @@
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
+#include "WebGLActiveInfo.h"
+
+#include "mozilla/dom/WebGLRenderingContextBinding.h"
 #include "WebGLContext.h"
 #include "WebGLTexture.h"
-#include "mozilla/dom/WebGLRenderingContextBinding.h"
 
-using namespace mozilla;
+namespace mozilla {
 
 JSObject*
-WebGLActiveInfo::WrapObject(JSContext *cx) {
+WebGLActiveInfo::WrapObject(JSContext* cx)
+{
     return dom::WebGLActiveInfoBinding::Wrap(cx, this);
 }
+
+} // namespace mozilla
diff --git a/dom/canvas/WebGLActiveInfo.h b/dom/canvas/WebGLActiveInfo.h
index eedc5a446c21..2cb1f4609ba6 100644
--- a/dom/canvas/WebGLActiveInfo.h
+++ b/dom/canvas/WebGLActiveInfo.h
@@ -3,22 +3,22 @@
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
-#ifndef WEBGLACTIVEINFO_H_
-#define WEBGLACTIVEINFO_H_
+#ifndef WEBGL_ACTIVE_INFO_H_
+#define WEBGL_ACTIVE_INFO_H_
 
-#include "WebGLObjectModel.h"
-#include "nsString.h"
 #include "js/TypeDecls.h"
+#include "nsString.h"
+#include "WebGLObjectModel.h"
 
 namespace mozilla {
 
 class WebGLActiveInfo MOZ_FINAL
 {
 public:
-    WebGLActiveInfo(GLint size, GLenum type, const nsACString& name) :
-        mSize(size),
-        mType(type),
-        mName(NS_ConvertASCIItoUTF16(name))
+    WebGLActiveInfo(GLint size, GLenum type, const nsACString& name)
+        : mSize(size)
+        , mType(type)
+        , mName(NS_ConvertASCIItoUTF16(name))
     {}
 
     // WebIDL attributes
@@ -35,7 +35,7 @@ public:
         retval = mName;
     }
 
-    JSObject* WrapObject(JSContext *cx);
+    JSObject* WrapObject(JSContext* cx);
 
    NS_INLINE_DECL_REFCOUNTING(WebGLActiveInfo)
 
@@ -52,4 +52,4 @@ private:
 
 } // namespace mozilla
 
-#endif
+#endif // WEBGL_ACTIVE_INFO_H_
diff --git a/dom/canvas/WebGLBuffer.cpp b/dom/canvas/WebGLBuffer.cpp
index 3b0a018c6d07..990a58d0624f 100644
--- a/dom/canvas/WebGLBuffer.cpp
+++ b/dom/canvas/WebGLBuffer.cpp
@@ -10,22 +10,24 @@
 #include "WebGLContext.h"
 #include "WebGLElementArrayCache.h"
 
-using namespace mozilla;
+namespace mozilla {
 
-WebGLBuffer::WebGLBuffer(WebGLContext* context, GLuint buf)
+WebGLBuffer::WebGLBuffer(WebGLContext* webgl, GLuint buf)
     : WebGLBindableName(buf)
-    , WebGLContextBoundObject(context)
+    , WebGLContextBoundObject(webgl)
     , mByteLength(0)
 {
     mContext->mBuffers.insertBack(this);
 }
 
-WebGLBuffer::~WebGLBuffer() {
+WebGLBuffer::~WebGLBuffer()
+{
     DeleteOnce();
 }
 
 void
-WebGLBuffer::Delete() {
+WebGLBuffer::Delete()
+{
     mContext->MakeContextCurrent();
     mContext->gl->fDeleteBuffers(1, &mGLName);
     mByteLength = 0;
@@ -34,37 +36,43 @@ WebGLBuffer::Delete() {
 }
 
 void
-WebGLBuffer::OnTargetChanged() {
+WebGLBuffer::OnTargetChanged()
+{
     if (!mCache && mTarget == LOCAL_GL_ELEMENT_ARRAY_BUFFER)
         mCache = new WebGLElementArrayCache;
 }
 
 bool
-WebGLBuffer::ElementArrayCacheBufferData(const void* ptr, size_t buffer_size_in_bytes) {
+WebGLBuffer::ElementArrayCacheBufferData(const void* ptr,
+                                         size_t bufferSizeInBytes)
+{
     if (mTarget == LOCAL_GL_ELEMENT_ARRAY_BUFFER)
-        return mCache->BufferData(ptr, buffer_size_in_bytes);
+        return mCache->BufferData(ptr, bufferSizeInBytes);
+
     return true;
 }
 
 void
-WebGLBuffer::ElementArrayCacheBufferSubData(size_t pos, const void* ptr, size_t update_size_in_bytes) {
+WebGLBuffer::ElementArrayCacheBufferSubData(size_t pos, const void* ptr,
+                                            size_t updateSizeInBytes)
+{
     if (mTarget == LOCAL_GL_ELEMENT_ARRAY_BUFFER)
-        mCache->BufferSubData(pos, ptr, update_size_in_bytes);
+        mCache->BufferSubData(pos, ptr, updateSizeInBytes);
 }
 
 size_t
-WebGLBuffer::SizeOfIncludingThis(mozilla::MallocSizeOf aMallocSizeOf) const
+WebGLBuffer::SizeOfIncludingThis(mozilla::MallocSizeOf mallocSizeOf) const
 {
-    size_t sizeOfCache = mCache ? mCache->SizeOfIncludingThis(aMallocSizeOf) : 0;
-    return aMallocSizeOf(this) + sizeOfCache;
+    size_t sizeOfCache = mCache ? mCache->SizeOfIncludingThis(mallocSizeOf)
+                                : 0;
+    return mallocSizeOf(this) + sizeOfCache;
 }
 
 bool
-WebGLBuffer::Validate(GLenum type, uint32_t max_allowed,
-                      size_t first, size_t count,
-                      uint32_t* out_upperBound)
+WebGLBuffer::Validate(GLenum type, uint32_t maxAllowed, size_t first,
+                      size_t count, uint32_t* const out_upperBound)
 {
-    return mCache->Validate(type, max_allowed, first, count, out_upperBound);
+    return mCache->Validate(type, maxAllowed, first, count, out_upperBound);
 }
 
 bool
@@ -74,7 +82,8 @@ WebGLBuffer::IsElementArrayUsedWithMultipleTypes() const
 }
 
 JSObject*
-WebGLBuffer::WrapObject(JSContext *cx) {
+WebGLBuffer::WrapObject(JSContext* cx)
+{
     return dom::WebGLBufferBinding::Wrap(cx, this);
 }
 
@@ -82,3 +91,5 @@ NS_IMPL_CYCLE_COLLECTION_WRAPPERCACHE_0(WebGLBuffer)
 
 NS_IMPL_CYCLE_COLLECTION_ROOT_NATIVE(WebGLBuffer, AddRef)
 NS_IMPL_CYCLE_COLLECTION_UNROOT_NATIVE(WebGLBuffer, Release)
+
+} // namespace mozilla
diff --git a/dom/canvas/WebGLBuffer.h b/dom/canvas/WebGLBuffer.h
index 664516d1b2aa..bc8d4d33e209 100644
--- a/dom/canvas/WebGLBuffer.h
+++ b/dom/canvas/WebGLBuffer.h
@@ -3,8 +3,8 @@
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
-#ifndef WEBGLBUFFER_H_
-#define WEBGLBUFFER_H_
+#ifndef WEBGL_BUFFER_H_
+#define WEBGL_BUFFER_H_
 
 #include "GLDefs.h"
 #include "mozilla/LinkedList.h"
@@ -12,8 +12,8 @@
 #include "nsWrapperCache.h"
 #include "WebGLBindableName.h"
 #include "WebGLObjectModel.h"
-#include "WebGLTypes.h"
 #include "WebGLStrongTypes.h"
+#include "WebGLTypes.h"
 
 namespace mozilla {
 
@@ -27,30 +27,30 @@ class WebGLBuffer MOZ_FINAL
     , public WebGLContextBoundObject
 {
 public:
-    explicit WebGLBuffer(WebGLContext* context, GLuint buf);
+    explicit WebGLBuffer(WebGLContext* webgl, GLuint buf);
 
     void Delete();
 
-    size_t SizeOfIncludingThis(mozilla::MallocSizeOf aMallocSizeOf) const;
+    size_t SizeOfIncludingThis(mozilla::MallocSizeOf mallocSizeOf) const;
 
     WebGLsizeiptr ByteLength() const { return mByteLength; }
-
     void SetByteLength(WebGLsizeiptr byteLength) { mByteLength = byteLength; }
 
-    bool ElementArrayCacheBufferData(const void* ptr, size_t buffer_size_in_bytes);
+    bool ElementArrayCacheBufferData(const void* ptr, size_t bufferSizeInBytes);
 
-    void ElementArrayCacheBufferSubData(size_t pos, const void* ptr, size_t update_size_in_bytes);
+    void ElementArrayCacheBufferSubData(size_t pos, const void* ptr,
+                                        size_t updateSizeInBytes);
 
     bool Validate(GLenum type, uint32_t max_allowed, size_t first, size_t count,
-                  uint32_t* out_upperBound);
+                  uint32_t* const out_upperBound);
 
     bool IsElementArrayUsedWithMultipleTypes() const;
 
-    WebGLContext *GetParentObject() const {
+    WebGLContext* GetParentObject() const {
         return Context();
-    }
+    };
 
-    virtual JSObject* WrapObject(JSContext *cx) MOZ_OVERRIDE;
+    virtual JSObject* WrapObject(JSContext* cx) MOZ_OVERRIDE;
 
     NS_INLINE_DECL_CYCLE_COLLECTING_NATIVE_REFCOUNTING(WebGLBuffer)
     NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_NATIVE_CLASS(WebGLBuffer)
@@ -61,8 +61,9 @@ protected:
     virtual void OnTargetChanged() MOZ_OVERRIDE;
 
     WebGLsizeiptr mByteLength;
-
     nsAutoPtr mCache;
 };
-}
-#endif //WEBGLBUFFER_H_
+
+} // namespace mozilla
+
+#endif // WEBGL_BUFFER_H_
diff --git a/dom/canvas/WebGLContext.cpp b/dom/canvas/WebGLContext.cpp
index 977b2c9f6e76..9354bb5beb72 100644
--- a/dom/canvas/WebGLContext.cpp
+++ b/dom/canvas/WebGLContext.cpp
@@ -5,9 +5,48 @@
 
 #include "WebGLContext.h"
 
-#include "WebGLContextLossHandler.h"
+#include "AccessCheck.h"
+#include "CanvasUtils.h"
+#include "gfxContext.h"
+#include "gfxCrashReporterUtils.h"
+#include "gfxPattern.h"
+#include "gfxPrefs.h"
+#include "gfxUtils.h"
+#include "GLBlitHelper.h"
+#include "GLContext.h"
+#include "GLContextProvider.h"
+#include "GLReadTexImageHelper.h"
+#include "ImageContainer.h"
+#include "ImageEncoder.h"
+#include "Layers.h"
+#include "mozilla/dom/BindingUtils.h"
+#include "mozilla/dom/HTMLVideoElement.h"
+#include "mozilla/dom/ImageData.h"
+#include "mozilla/dom/WebGLRenderingContextBinding.h"
+#include "mozilla/EnumeratedArrayCycleCollection.h"
+#include "mozilla/Preferences.h"
+#include "mozilla/ProcessPriorityManager.h"
+#include "mozilla/Services.h"
+#include "mozilla/Telemetry.h"
+#include "nsContentUtils.h"
+#include "nsDisplayList.h"
+#include "nsError.h"
+#include "nsIClassInfoImpl.h"
+#include "nsIConsoleService.h"
+#include "nsIGfxInfo.h"
+#include "nsIObserverService.h"
+#include "nsIDOMEvent.h"
+#include "nsIVariant.h"
+#include "nsIWidget.h"
+#include "nsIXPConnect.h"
+#include "nsServiceManagerUtils.h"
+#include "nsSVGEffects.h"
+#include "prenv.h"
+#include 
+#include "ScopedGLHelpers.h"
 #include "WebGL1Context.h"
 #include "WebGLBuffer.h"
+#include "WebGLContextLossHandler.h"
 #include "WebGLContextUtils.h"
 #include "WebGLExtensions.h"
 #include "WebGLFramebuffer.h"
@@ -18,71 +57,18 @@
 #include "WebGLVertexArray.h"
 #include "WebGLVertexAttribData.h"
 
-#include "GLBlitHelper.h"
-#include "AccessCheck.h"
-#include "nsIConsoleService.h"
-#include "nsServiceManagerUtils.h"
-#include "nsIClassInfoImpl.h"
-#include "nsContentUtils.h"
-#include "nsIXPConnect.h"
-#include "nsError.h"
-#include "nsIGfxInfo.h"
-#include "nsIWidget.h"
-
-#include "nsIVariant.h"
-
-#include "ImageEncoder.h"
-#include "ImageContainer.h"
-
-#include "gfxContext.h"
-#include "gfxPattern.h"
-#include "gfxPrefs.h"
-#include "gfxUtils.h"
-
-#include "CanvasUtils.h"
-#include "nsDisplayList.h"
-
-#include "GLContextProvider.h"
-#include "GLContext.h"
-#include "ScopedGLHelpers.h"
-#include "GLReadTexImageHelper.h"
-
-#include "gfxCrashReporterUtils.h"
-
-#include "nsSVGEffects.h"
-
-#include "prenv.h"
-
-#include "mozilla/Preferences.h"
-#include "mozilla/Services.h"
-#include "mozilla/Telemetry.h"
-
-#include "nsIObserverService.h"
-#include "nsIDOMEvent.h"
-#include "mozilla/Services.h"
-#include "mozilla/dom/WebGLRenderingContextBinding.h"
-#include "mozilla/dom/BindingUtils.h"
-#include "mozilla/dom/HTMLVideoElement.h"
-#include "mozilla/dom/ImageData.h"
-#include "mozilla/ProcessPriorityManager.h"
-#include "mozilla/EnumeratedArrayCycleCollection.h"
-
-#include "Layers.h"
-
 #ifdef MOZ_WIDGET_GONK
 #include "mozilla/layers/ShadowLayers.h"
 #endif
 
-#include 
-
 using namespace mozilla;
 using namespace mozilla::dom;
 using namespace mozilla::gfx;
 using namespace mozilla::gl;
 using namespace mozilla::layers;
 
-WebGLObserver::WebGLObserver(WebGLContext* aContext)
-    : mContext(aContext)
+WebGLObserver::WebGLObserver(WebGLContext* webgl)
+    : mWebGL(webgl)
 {
 }
 
@@ -95,71 +81,62 @@ WebGLObserver::Destroy()
 {
     UnregisterMemoryPressureEvent();
     UnregisterVisibilityChangeEvent();
-    mContext = nullptr;
+    mWebGL = nullptr;
 }
 
 void
 WebGLObserver::RegisterVisibilityChangeEvent()
 {
-    if (!mContext) {
+    if (!mWebGL)
         return;
-    }
 
-    HTMLCanvasElement* canvasElement = mContext->GetCanvas();
+    HTMLCanvasElement* canvas = mWebGL->GetCanvas();
+    MOZ_ASSERT(canvas);
 
-    MOZ_ASSERT(canvasElement);
-
-    if (canvasElement) {
-        nsIDocument* document = canvasElement->OwnerDoc();
+    if (canvas) {
+        nsIDocument* document = canvas->OwnerDoc();
 
         document->AddSystemEventListener(NS_LITERAL_STRING("visibilitychange"),
-                                         this,
-                                         true,
-                                         false);
+                                         this, true, false);
     }
 }
 
 void
 WebGLObserver::UnregisterVisibilityChangeEvent()
 {
-    if (!mContext) {
+    if (!mWebGL)
         return;
-    }
 
-    HTMLCanvasElement* canvasElement = mContext->GetCanvas();
+    HTMLCanvasElement* canvas = mWebGL->GetCanvas();
 
-    if (canvasElement) {
-        nsIDocument* document = canvasElement->OwnerDoc();
+    if (canvas) {
+        nsIDocument* document = canvas->OwnerDoc();
 
         document->RemoveSystemEventListener(NS_LITERAL_STRING("visibilitychange"),
-                                            this,
-                                            true);
+                                            this, true);
     }
 }
 
 void
 WebGLObserver::RegisterMemoryPressureEvent()
 {
-    if (!mContext) {
+    if (!mWebGL)
         return;
-    }
 
     nsCOMPtr observerService =
         mozilla::services::GetObserverService();
 
     MOZ_ASSERT(observerService);
 
-    if (observerService) {
+    if (observerService)
         observerService->AddObserver(this, "memory-pressure", false);
-    }
 }
 
 void
 WebGLObserver::UnregisterMemoryPressureEvent()
 {
-    if (!mContext) {
+    if (!mWebGL)
         return;
-    }
 
     nsCOMPtr observerService =
         mozilla::services::GetObserverService();
@@ -167,59 +144,55 @@ WebGLObserver::UnregisterMemoryPressureEvent()
     // Do not assert on observerService here. This might be triggered by
     // the cycle collector at a late enough time, that XPCOM services are
     // no longer available. See bug 1029504.
-    if (observerService) {
+    if (observerService)
         observerService->RemoveObserver(this, "memory-pressure");
-    }
 }
 
 NS_IMETHODIMP
-WebGLObserver::Observe(nsISupports* aSubject,
-                       const char* aTopic,
-                       const char16_t* aSomeData)
+WebGLObserver::Observe(nsISupports*, const char* topic, const char16_t*)
 {
-    if (!mContext || strcmp(aTopic, "memory-pressure")) {
+    if (!mWebGL || strcmp(topic, "memory-pressure")) {
         return NS_OK;
     }
 
-    bool wantToLoseContext = mContext->mLoseContextOnMemoryPressure;
+    bool wantToLoseContext = mWebGL->mLoseContextOnMemoryPressure;
 
-    if (!mContext->mCanLoseContextInForeground &&
+    if (!mWebGL->mCanLoseContextInForeground &&
         ProcessPriorityManager::CurrentProcessIsForeground())
     {
         wantToLoseContext = false;
     }
 
-    if (wantToLoseContext) {
-        mContext->ForceLoseContext();
-    }
+    if (wantToLoseContext)
+        mWebGL->ForceLoseContext();
 
     return NS_OK;
 }
 
 NS_IMETHODIMP
-WebGLObserver::HandleEvent(nsIDOMEvent* aEvent)
+WebGLObserver::HandleEvent(nsIDOMEvent* event)
 {
     nsAutoString type;
-    aEvent->GetType(type);
-    if (!mContext || !type.EqualsLiteral("visibilitychange")) {
+    event->GetType(type);
+    if (!mWebGL || !type.EqualsLiteral("visibilitychange"))
         return NS_OK;
-    }
 
-    HTMLCanvasElement* canvasElement = mContext->GetCanvas();
+    HTMLCanvasElement* canvas = mWebGL->GetCanvas();
+    MOZ_ASSERT(canvas);
 
-    MOZ_ASSERT(canvasElement);
-
-    if (canvasElement && !canvasElement->OwnerDoc()->Hidden()) {
-        mContext->ForceRestoreContext();
-    }
+    if (canvas && !canvas->OwnerDoc()->Hidden())
+        mWebGL->ForceRestoreContext();
 
     return NS_OK;
 }
 
 WebGLContextOptions::WebGLContextOptions()
-    : alpha(true), depth(true), stencil(false),
-      premultipliedAlpha(true), antialias(true),
-      preserveDrawingBuffer(false)
+    : alpha(true)
+    , depth(true)
+    , stencil(false)
+    , premultipliedAlpha(true)
+    , antialias(true)
+    , preserveDrawingBuffer(false)
 {
     // Set default alpha state based on preference.
     if (Preferences::GetBool("webgl.default-no-alpha", false))
@@ -301,9 +274,9 @@ WebGLContext::WebGLContext()
     mAlreadyGeneratedWarnings = 0;
     mAlreadyWarnedAboutFakeVertexAttrib0 = false;
     mAlreadyWarnedAboutViewportLargerThanDest = false;
+
     mMaxWarnings = Preferences::GetInt("webgl.max-warnings-per-context", 32);
-    if (mMaxWarnings < -1)
-    {
+    if (mMaxWarnings < -1) {
         GenerateWarning("webgl.max-warnings-per-context size is too large (seems like a negative value wrapped)");
         mMaxWarnings = 0;
     }
@@ -380,9 +353,8 @@ WebGLContext::DestroyResourcesAndContext()
     mBlackTransparentTexture2D = nullptr;
     mBlackTransparentTextureCubeMap = nullptr;
 
-    if (mFakeVertexAttrib0BufferObject) {
+    if (mFakeVertexAttrib0BufferObject)
         gl->fDeleteBuffers(1, &mFakeVertexAttrib0BufferObject);
-    }
 
     // disable all extensions except "WEBGL_lose_context". see bug #927969
     // spec: http://www.khronos.org/registry/webgl/specs/latest/1.0/#5.15.2
@@ -399,9 +371,8 @@ WebGLContext::DestroyResourcesAndContext()
     // We just got rid of everything, so the context had better
     // have been going away.
 #ifdef DEBUG
-    if (gl->DebugMode()) {
+    if (gl->DebugMode())
         printf_stderr("--- WebGL context destroyed: %p\n", gl.get());
-    }
 #endif
 
     gl = nullptr;
@@ -427,14 +398,13 @@ WebGLContext::Invalidate()
 //
 
 NS_IMETHODIMP
-WebGLContext::SetContextOptions(JSContext* aCx, JS::Handle aOptions)
+WebGLContext::SetContextOptions(JSContext* cx, JS::Handle options)
 {
-    if (aOptions.isNullOrUndefined() && mOptionsFrozen) {
+    if (options.isNullOrUndefined() && mOptionsFrozen)
         return NS_OK;
-    }
 
     WebGLContextAttributes attributes;
-    NS_ENSURE_TRUE(attributes.Init(aCx, aOptions), NS_ERROR_UNEXPECTED);
+    NS_ENSURE_TRUE(attributes.Init(cx, options), NS_ERROR_UNEXPECTED);
 
     WebGLContextOptions newOpts;
 
@@ -444,14 +414,12 @@ WebGLContext::SetContextOptions(JSContext* aCx, JS::Handle aOptions)
     newOpts.antialias = attributes.mAntialias;
     newOpts.preserveDrawingBuffer = attributes.mPreserveDrawingBuffer;
 
-    if (attributes.mAlpha.WasPassed()) {
+    if (attributes.mAlpha.WasPassed())
         newOpts.alpha = attributes.mAlpha.Value();
-    }
 
     // Don't do antialiasing if we've disabled MSAA.
-    if (!gfxPrefs::MSAALevel()) {
+    if (!gfxPrefs::MSAALevel())
       newOpts.antialias = false;
-    }
 
 #if 0
     GenerateWarning("aaHint: %d stencil: %d depth: %d alpha: %d premult: %d preserve: %d\n",
@@ -515,8 +483,7 @@ IsFeatureInBlacklist(const nsCOMPtr& gfxInfo, int32_t feature)
 }
 
 static already_AddRefed
-CreateHeadlessNativeGL(bool forceEnabled,
-                       const nsCOMPtr& gfxInfo,
+CreateHeadlessNativeGL(bool forceEnabled, const nsCOMPtr& gfxInfo,
                        WebGLContext* webgl)
 {
     if (!forceEnabled &&
@@ -541,8 +508,7 @@ CreateHeadlessNativeGL(bool forceEnabled,
 // right now, we get ANGLE implicitly by using EGL on Windows.
 // Eventually, we want to be able to pick ANGLE-EGL or native EGL.
 static already_AddRefed
-CreateHeadlessANGLE(bool forceEnabled,
-                    const nsCOMPtr& gfxInfo,
+CreateHeadlessANGLE(bool forceEnabled, const nsCOMPtr& gfxInfo,
                     WebGLContext* webgl)
 {
     nsRefPtr gl;
@@ -568,8 +534,7 @@ CreateHeadlessANGLE(bool forceEnabled,
 }
 
 static already_AddRefed
-CreateHeadlessEGL(bool forceEnabled,
-                  const nsCOMPtr& gfxInfo,
+CreateHeadlessEGL(bool forceEnabled, const nsCOMPtr& gfxInfo,
                   WebGLContext* webgl)
 {
     nsRefPtr gl;
@@ -588,16 +553,14 @@ CreateHeadlessEGL(bool forceEnabled,
 
 
 static already_AddRefed
-CreateHeadlessGL(bool forceEnabled,
-                 const nsCOMPtr& gfxInfo,
+CreateHeadlessGL(bool forceEnabled, const nsCOMPtr& gfxInfo,
                  WebGLContext* webgl)
 {
     bool preferEGL = PR_GetEnv("MOZ_WEBGL_PREFER_EGL");
     bool disableANGLE = Preferences::GetBool("webgl.disable-angle", false);
 
-    if (PR_GetEnv("MOZ_WEBGL_FORCE_OPENGL")) {
+    if (PR_GetEnv("MOZ_WEBGL_FORCE_OPENGL"))
         disableANGLE = true;
-    }
 
     nsRefPtr gl;
 
@@ -623,9 +586,9 @@ CreateOffscreenWithCaps(GLContext* gl, const SurfaceCaps& caps)
 
 static void
 PopulateCapFallbackQueue(const SurfaceCaps& baseCaps,
-                         std::queue* fallbackCaps)
+                         std::queue* out_fallbackCaps)
 {
-    fallbackCaps->push(baseCaps);
+    out_fallbackCaps->push(baseCaps);
 
     // Dropping antialias drops our quality, but not our correctness.
     // The user basically doesn't have to handle if this fails, they
@@ -633,7 +596,7 @@ PopulateCapFallbackQueue(const SurfaceCaps& baseCaps,
     if (baseCaps.antialias) {
         SurfaceCaps nextCaps(baseCaps);
         nextCaps.antialias = false;
-        PopulateCapFallbackQueue(nextCaps, fallbackCaps);
+        PopulateCapFallbackQueue(nextCaps, out_fallbackCaps);
     }
 
     // If we have to drop one of depth or stencil, we'd prefer to keep
@@ -642,21 +605,19 @@ PopulateCapFallbackQueue(const SurfaceCaps& baseCaps,
     if (baseCaps.stencil) {
         SurfaceCaps nextCaps(baseCaps);
         nextCaps.stencil = false;
-        PopulateCapFallbackQueue(nextCaps, fallbackCaps);
+        PopulateCapFallbackQueue(nextCaps, out_fallbackCaps);
     }
 
     if (baseCaps.depth) {
         SurfaceCaps nextCaps(baseCaps);
         nextCaps.depth = false;
-        PopulateCapFallbackQueue(nextCaps, fallbackCaps);
+        PopulateCapFallbackQueue(nextCaps, out_fallbackCaps);
     }
 }
 
 static bool
-CreateOffscreen(GLContext* gl,
-                const WebGLContextOptions& options,
-                const nsCOMPtr& gfxInfo,
-                WebGLContext* webgl,
+CreateOffscreen(GLContext* gl, const WebGLContextOptions& options,
+                const nsCOMPtr& gfxInfo, WebGLContext* webgl,
                 layers::ISurfaceAllocator* surfAllocator)
 {
     SurfaceCaps baseCaps;
@@ -728,9 +689,8 @@ WebGLContext::CreateOffscreenGL(bool forceEnabled)
         if (layerManager) {
             // XXX we really want "AsSurfaceAllocator" here for generality
             layers::ShadowLayerForwarder* forwarder = layerManager->AsShadowForwarder();
-            if (forwarder) {
+            if (forwarder)
                 surfAllocator = static_cast(forwarder);
-            }
         }
     }
 #endif
@@ -756,7 +716,8 @@ WebGLContext::CreateOffscreenGL(bool forceEnabled)
 
 // Fallback for resizes:
 bool
-WebGLContext::ResizeBackbuffer(uint32_t requestedWidth, uint32_t requestedHeight)
+WebGLContext::ResizeBackbuffer(uint32_t requestedWidth,
+                               uint32_t requestedHeight)
 {
     uint32_t width = requestedWidth;
     uint32_t height = requestedHeight;
@@ -795,32 +756,30 @@ WebGLContext::ResizeBackbuffer(uint32_t requestedWidth, uint32_t requestedHeight
     return true;
 }
 
-
 NS_IMETHODIMP
-WebGLContext::SetDimensions(int32_t sWidth, int32_t sHeight)
+WebGLContext::SetDimensions(int32_t signedWidth, int32_t signedHeight)
 {
     // Early error return cases
     if (!GetCanvas())
         return NS_ERROR_FAILURE;
 
-    if (sWidth < 0 || sHeight < 0) {
+    if (signedWidth < 0 || signedHeight < 0) {
         GenerateWarning("Canvas size is too large (seems like a negative value wrapped)");
         return NS_ERROR_OUT_OF_MEMORY;
     }
 
-    uint32_t width = sWidth;
-    uint32_t height = sHeight;
+    uint32_t width = signedWidth;
+    uint32_t height = signedHeight;
 
     // Early success return cases
     GetCanvas()->InvalidateCanvas();
 
     // Zero-sized surfaces can cause problems.
-    if (width == 0) {
+    if (width == 0)
         width = 1;
-    }
-    if (height == 0) {
+
+    if (height == 0)
         height = 1;
-    }
 
     // If we already have a gl context, then we just need to resize it
     if (gl) {
@@ -901,9 +860,8 @@ WebGLContext::SetDimensions(int32_t sWidth, int32_t sHeight)
     }
 
 #ifdef DEBUG
-    if (gl->DebugMode()) {
+    if (gl->DebugMode())
         printf_stderr("--- WebGL context created: %p\n", gl.get());
-    }
 #endif
 
     mResetLayer = true;
@@ -914,9 +872,8 @@ WebGLContext::SetDimensions(int32_t sWidth, int32_t sHeight)
 
     // Update our internal stuff:
     if (gl->WorkAroundDriverBugs()) {
-        if (!mOptions.alpha && gl->Caps().alpha) {
+        if (!mOptions.alpha && gl->Caps().alpha)
             mNeedsFakeNoAlpha = true;
-        }
     }
 
     // Update mOptions.
@@ -978,7 +935,8 @@ WebGLContext::ClearBackbufferIfNeeded()
     mBackbufferNeedsClear = false;
 }
 
-void WebGLContext::LoseOldestWebGLContextIfLimitExceeded()
+void
+WebGLContext::LoseOldestWebGLContextIfLimitExceeded()
 {
 #ifdef MOZ_GFX_OPTIMIZE_MOBILE
     // some mobile devices can't have more than 8 GL contexts overall
@@ -995,13 +953,11 @@ void WebGLContext::LoseOldestWebGLContextIfLimitExceeded()
     // when choosing which one to lose first.
     UpdateLastUseIndex();
 
-    WebGLMemoryTracker::ContextsArrayType &contexts
-      = WebGLMemoryTracker::Contexts();
+    WebGLMemoryTracker::ContextsArrayType& contexts = WebGLMemoryTracker::Contexts();
 
     // quick exit path, should cover a majority of cases
-    if (contexts.Length() <= kMaxWebGLContextsPerPrincipal) {
+    if (contexts.Length() <= kMaxWebGLContextsPerPrincipal)
         return;
-    }
 
     // note that here by "context" we mean "non-lost context". See the check for
     // IsContextLost() below. Indeed, the point of this function is to maybe lose
@@ -1009,13 +965,12 @@ void WebGLContext::LoseOldestWebGLContextIfLimitExceeded()
 
     uint64_t oldestIndex = UINT64_MAX;
     uint64_t oldestIndexThisPrincipal = UINT64_MAX;
-    const WebGLContext *oldestContext = nullptr;
-    const WebGLContext *oldestContextThisPrincipal = nullptr;
+    const WebGLContext* oldestContext = nullptr;
+    const WebGLContext* oldestContextThisPrincipal = nullptr;
     size_t numContexts = 0;
     size_t numContextsThisPrincipal = 0;
 
     for(size_t i = 0; i < contexts.Length(); ++i) {
-
         // don't want to lose ourselves.
         if (contexts[i] == this)
             continue;
@@ -1037,8 +992,8 @@ void WebGLContext::LoseOldestWebGLContextIfLimitExceeded()
             oldestContext = contexts[i];
         }
 
-        nsIPrincipal *ourPrincipal = GetCanvas()->NodePrincipal();
-        nsIPrincipal *theirPrincipal = contexts[i]->GetCanvas()->NodePrincipal();
+        nsIPrincipal* ourPrincipal = GetCanvas()->NodePrincipal();
+        nsIPrincipal* theirPrincipal = contexts[i]->GetCanvas()->NodePrincipal();
         bool samePrincipal;
         nsresult rv = ourPrincipal->Equals(theirPrincipal, &samePrincipal);
         if (NS_SUCCEEDED(rv) && samePrincipal) {
@@ -1064,26 +1019,25 @@ void WebGLContext::LoseOldestWebGLContextIfLimitExceeded()
 }
 
 void
-WebGLContext::GetImageBuffer(uint8_t** aImageBuffer, int32_t* aFormat)
+WebGLContext::GetImageBuffer(uint8_t** out_imageBuffer, int32_t* out_format)
 {
-    *aImageBuffer = nullptr;
-    *aFormat = 0;
+    *out_imageBuffer = nullptr;
+    *out_format = 0;
 
     // Use GetSurfaceSnapshot() to make sure that appropriate y-flip gets applied
     bool premult;
     RefPtr snapshot =
       GetSurfaceSnapshot(mOptions.premultipliedAlpha ? nullptr : &premult);
-    if (!snapshot) {
+    if (!snapshot)
         return;
-    }
+
     MOZ_ASSERT(mOptions.premultipliedAlpha || !premult, "We must get unpremult when we ask for it!");
 
     RefPtr dataSurface = snapshot->GetDataSurface();
 
     DataSourceSurface::MappedSurface map;
-    if (!dataSurface->Map(DataSourceSurface::MapType::READ, &map)) {
+    if (!dataSurface->Map(DataSourceSurface::MapType::READ, &map))
         return;
-    }
 
     static const fallible_t fallible = fallible_t();
     uint8_t* imageBuffer = new (fallible) uint8_t[mWidth * mHeight * 4];
@@ -1106,38 +1060,37 @@ WebGLContext::GetImageBuffer(uint8_t** aImageBuffer, int32_t* aFormat)
         format = imgIEncoder::INPUT_FORMAT_RGBA;
     }
 
-    *aImageBuffer = imageBuffer;
-    *aFormat = format;
+    *out_imageBuffer = imageBuffer;
+    *out_format = format;
 }
 
 NS_IMETHODIMP
-WebGLContext::GetInputStream(const char* aMimeType,
-                             const char16_t* aEncoderOptions,
-                             nsIInputStream **aStream)
+WebGLContext::GetInputStream(const char* mimeType,
+                             const char16_t* encoderOptions,
+                             nsIInputStream** out_stream)
 {
     NS_ASSERTION(gl, "GetInputStream on invalid context?");
     if (!gl)
         return NS_ERROR_FAILURE;
 
     nsCString enccid("@mozilla.org/image/encoder;2?type=");
-    enccid += aMimeType;
+    enccid += mimeType;
     nsCOMPtr encoder = do_CreateInstance(enccid.get());
-    if (!encoder) {
+    if (!encoder)
         return NS_ERROR_FAILURE;
-    }
 
     nsAutoArrayPtr imageBuffer;
     int32_t format = 0;
     GetImageBuffer(getter_Transfers(imageBuffer), &format);
-    if (!imageBuffer) {
+    if (!imageBuffer)
         return NS_ERROR_FAILURE;
-    }
 
     return ImageEncoder::GetInputStream(mWidth, mHeight, imageBuffer, format,
-                                        encoder, aEncoderOptions, aStream);
+                                        encoder, encoderOptions, out_stream);
 }
 
-void WebGLContext::UpdateLastUseIndex()
+void
+WebGLContext::UpdateLastUseIndex()
 {
     static CheckedInt sIndex = 0;
 
@@ -1145,9 +1098,8 @@ void WebGLContext::UpdateLastUseIndex()
 
     // should never happen with 64-bit; trying to handle this would be riskier than
     // not handling it as the handler code would never get exercised.
-    if (!sIndex.isValid()) {
+    if (!sIndex.isValid())
         NS_RUNTIMEABORT("Can't believe it's been 2^64 transactions already!");
-    }
 
     mLastUseIndex = sIndex.value();
 }
@@ -1156,68 +1108,68 @@ static uint8_t gWebGLLayerUserData;
 
 namespace mozilla {
 
-class WebGLContextUserData : public LayerUserData {
+class WebGLContextUserData : public LayerUserData
+{
 public:
-    explicit WebGLContextUserData(HTMLCanvasElement* aContent)
-        : mContent(aContent)
+    explicit WebGLContextUserData(HTMLCanvasElement* canvas)
+        : mCanvas(canvas)
     {}
 
     /* PreTransactionCallback gets called by the Layers code every time the
      * WebGL canvas is going to be composited.
      */
-    static void PreTransactionCallback(void* data)
-    {
+    static void PreTransactionCallback(void* data) {
         WebGLContextUserData* userdata = static_cast(data);
-        HTMLCanvasElement* canvas = userdata->mContent;
-        WebGLContext* context = static_cast(canvas->GetContextAtIndex(0));
+        HTMLCanvasElement* canvas = userdata->mCanvas;
+        WebGLContext* webgl = static_cast(canvas->GetContextAtIndex(0));
 
         // Present our screenbuffer, if needed.
-        context->PresentScreenBuffer();
-        context->mDrawCallsSinceLastFlush = 0;
+        webgl->PresentScreenBuffer();
+        webgl->mDrawCallsSinceLastFlush = 0;
     }
 
     /** DidTransactionCallback gets called by the Layers code everytime the WebGL canvas gets composite,
       * so it really is the right place to put actions that have to be performed upon compositing
       */
-    static void DidTransactionCallback(void* aData)
-    {
-        WebGLContextUserData *userdata = static_cast(aData);
-        HTMLCanvasElement *canvas = userdata->mContent;
-        WebGLContext *context = static_cast(canvas->GetContextAtIndex(0));
+    static void DidTransactionCallback(void* data) {
+        WebGLContextUserData* userdata = static_cast(data);
+        HTMLCanvasElement* canvas = userdata->mCanvas;
+        WebGLContext* webgl = static_cast(canvas->GetContextAtIndex(0));
 
         // Mark ourselves as no longer invalidated.
-        context->MarkContextClean();
+        webgl->MarkContextClean();
 
-        context->UpdateLastUseIndex();
+        webgl->UpdateLastUseIndex();
     }
 
 private:
-    nsRefPtr mContent;
+    nsRefPtr mCanvas;
 };
 
 } // end namespace mozilla
 
 already_AddRefed
-WebGLContext::GetCanvasLayer(nsDisplayListBuilder* aBuilder,
-                             CanvasLayer *aOldLayer,
-                             LayerManager *aManager)
+WebGLContext::GetCanvasLayer(nsDisplayListBuilder* builder,
+                             CanvasLayer* oldLayer,
+                             LayerManager* manager)
 {
     if (IsContextLost())
         return nullptr;
 
-    if (!mResetLayer && aOldLayer &&
-        aOldLayer->HasUserData(&gWebGLLayerUserData)) {
-        nsRefPtr ret = aOldLayer;
+    if (!mResetLayer && oldLayer &&
+        oldLayer->HasUserData(&gWebGLLayerUserData)) {
+        nsRefPtr ret = oldLayer;
         return ret.forget();
     }
 
-    nsRefPtr canvasLayer = aManager->CreateCanvasLayer();
+    nsRefPtr canvasLayer = manager->CreateCanvasLayer();
     if (!canvasLayer) {
         NS_WARNING("CreateCanvasLayer returned null!");
         return nullptr;
     }
-    WebGLContextUserData *userData = nullptr;
-    if (aBuilder->IsPaintingToWindow()) {
+
+    WebGLContextUserData* userData = nullptr;
+    if (builder->IsPaintingToWindow()) {
       // Make the layer tell us whenever a transaction finishes (including
       // the current transaction), so we can clear our invalidation state and
       // start invalidating again. We need to do this for the layer that is
@@ -1255,7 +1207,7 @@ WebGLContext::GetCanvasLayer(nsDisplayListBuilder* aBuilder,
 }
 
 void
-WebGLContext::GetContextAttributes(Nullable &retval)
+WebGLContext::GetContextAttributes(Nullable& retval)
 {
     retval.SetNull();
     if (IsContextLost())
@@ -1287,11 +1239,12 @@ WebGLContext::MozGetUnderlyingParamString(uint32_t pname, nsAString& retval)
     case LOCAL_GL_RENDERER:
     case LOCAL_GL_VERSION:
     case LOCAL_GL_SHADING_LANGUAGE_VERSION:
-    case LOCAL_GL_EXTENSIONS: {
-        const char *s = (const char *) gl->fGetString(pname);
-        retval.Assign(NS_ConvertASCIItoUTF16(nsDependentCString(s)));
-    }
-        break;
+    case LOCAL_GL_EXTENSIONS:
+        {
+            const char* s = (const char*)gl->fGetString(pname);
+            retval.Assign(NS_ConvertASCIItoUTF16(nsDependentCString(s)));
+            break;
+        }
 
     default:
         return NS_ERROR_INVALID_ARG;
@@ -1320,7 +1273,8 @@ WebGLContext::ClearScreen()
 }
 
 void
-WebGLContext::ForceClearFramebufferWithDefaultValues(GLbitfield mask, const bool colorAttachmentsMask[kMaxColorAttachments])
+WebGLContext::ForceClearFramebufferWithDefaultValues(GLbitfield mask,
+                                                     const bool colorAttachmentsMask[kMaxColorAttachments])
 {
     MakeContextCurrent();
 
@@ -1462,15 +1416,17 @@ WebGLContext::PresentScreenBuffer()
 }
 
 void
-WebGLContext::DummyFramebufferOperation(const char *info)
+WebGLContext::DummyFramebufferOperation(const char* funcName)
 {
     FBStatus status = CheckFramebufferStatus(LOCAL_GL_FRAMEBUFFER);
-    if (status != LOCAL_GL_FRAMEBUFFER_COMPLETE)
-        ErrorInvalidFramebufferOperation("%s: incomplete framebuffer", info);
+    if (status != LOCAL_GL_FRAMEBUFFER_COMPLETE) {
+        ErrorInvalidFramebufferOperation("%s: incomplete framebuffer",
+                                         funcName);
+    }
 }
 
 static bool
-CheckContextLost(GLContext* gl, bool* out_isGuilty)
+CheckContextLost(GLContext* gl, bool* const out_isGuilty)
 {
     MOZ_ASSERT(gl);
     MOZ_ASSERT(out_isGuilty);
@@ -1543,16 +1499,16 @@ WebGLContext::RunContextLossTimer()
 
 class UpdateContextLossStatusTask : public nsRunnable
 {
-    nsRefPtr mContext;
+    nsRefPtr mWebGL;
 
 public:
-    explicit UpdateContextLossStatusTask(WebGLContext* aContext)
-        : mContext(aContext)
+    explicit UpdateContextLossStatusTask(WebGLContext* webgl)
+        : mWebGL(webgl)
     {
     }
 
     NS_IMETHOD Run() {
-        mContext->UpdateContextLossStatus();
+        mWebGL->UpdateContextLossStatus();
 
         return NS_OK;
     }
@@ -1713,10 +1669,13 @@ WebGLContext::ForceRestoreContext()
 }
 
 void
-WebGLContext::MakeContextCurrent() const { gl->MakeCurrent(); }
+WebGLContext::MakeContextCurrent() const
+{
+    gl->MakeCurrent();
+}
 
 mozilla::TemporaryRef
-WebGLContext::GetSurfaceSnapshot(bool* aPremultAlpha)
+WebGLContext::GetSurfaceSnapshot(bool* out_premultAlpha)
 {
     if (!gl)
         return nullptr;
@@ -1739,13 +1698,13 @@ WebGLContext::GetSurfaceSnapshot(bool* aPremultAlpha)
         ReadPixelsIntoDataSurface(gl, surf);
     }
 
-    if (aPremultAlpha) {
-        *aPremultAlpha = true;
+    if (out_premultAlpha) {
+        *out_premultAlpha = true;
     }
     bool srcPremultAlpha = mOptions.premultipliedAlpha;
     if (!srcPremultAlpha) {
-        if (aPremultAlpha) {
-            *aPremultAlpha = false;
+        if (out_premultAlpha) {
+            *out_premultAlpha = false;
         } else {
             gfxUtils::PremultiplyDataSurface(surf, surf);
         }
@@ -1779,24 +1738,25 @@ WebGLContext::DidRefresh()
     }
 }
 
-bool WebGLContext::TexImageFromVideoElement(const TexImageTarget texImageTarget, GLint level,
-                              GLenum internalformat, GLenum format, GLenum type,
-                              mozilla::dom::Element& elt)
+bool
+WebGLContext::TexImageFromVideoElement(const TexImageTarget texImageTarget,
+                                       GLint level, GLenum internalFormat,
+                                       GLenum format, GLenum type,
+                                       mozilla::dom::Element& elt)
 {
-    if (type == LOCAL_GL_HALF_FLOAT_OES) {
+    if (type == LOCAL_GL_HALF_FLOAT_OES)
         type = LOCAL_GL_HALF_FLOAT;
-    }
 
     if (!ValidateTexImageFormatAndType(format, type,
-                                       WebGLTexImageFunc::TexImage, WebGLTexDimensions::Tex2D))
+                                       WebGLTexImageFunc::TexImage,
+                                       WebGLTexDimensions::Tex2D))
     {
         return false;
     }
 
     HTMLVideoElement* video = HTMLVideoElement::FromContentOrNull(&elt);
-    if (!video) {
+    if (!video)
         return false;
-    }
 
     uint16_t readyState;
     if (NS_SUCCEEDED(video->GetReadyState(&readyState)) &&
@@ -1808,14 +1768,12 @@ bool WebGLContext::TexImageFromVideoElement(const TexImageTarget texImageTarget,
 
     // If it doesn't have a principal, just bail
     nsCOMPtr principal = video->GetCurrentPrincipal();
-    if (!principal) {
+    if (!principal)
         return false;
-    }
 
     mozilla::layers::ImageContainer* container = video->GetImageContainer();
-    if (!container) {
+    if (!container)
         return false;
-    }
 
     if (video->GetCORSMode() == CORS_NONE) {
         bool subsumes;
@@ -1829,24 +1787,35 @@ bool WebGLContext::TexImageFromVideoElement(const TexImageTarget texImageTarget,
 
     gl->MakeCurrent();
     nsRefPtr srcImage = container->LockCurrentImage();
-    WebGLTexture* tex = activeBoundTextureForTexImageTarget(texImageTarget);
+    WebGLTexture* tex = ActiveBoundTextureForTexImageTarget(texImageTarget);
 
     const WebGLTexture::ImageInfo& info = tex->ImageInfoAt(texImageTarget, 0);
     bool dimensionsMatch = info.Width() == srcImage->GetSize().width &&
                            info.Height() == srcImage->GetSize().height;
     if (!dimensionsMatch) {
         // we need to allocation
-        gl->fTexImage2D(texImageTarget.get(), level, internalformat, srcImage->GetSize().width, srcImage->GetSize().height, 0, format, type, nullptr);
+        gl->fTexImage2D(texImageTarget.get(), level, internalFormat,
+                        srcImage->GetSize().width, srcImage->GetSize().height,
+                        0, format, type, nullptr);
     }
-    bool ok = gl->BlitHelper()->BlitImageToTexture(srcImage.get(), srcImage->GetSize(), tex->GLName(), texImageTarget.get(), mPixelStoreFlipY);
+
+    bool ok = gl->BlitHelper()->BlitImageToTexture(srcImage.get(),
+                                                   srcImage->GetSize(),
+                                                   tex->GLName(),
+                                                   texImageTarget.get(),
+                                                   mPixelStoreFlipY);
     if (ok) {
-        TexInternalFormat effectiveinternalformat =
-            EffectiveInternalFormatFromInternalFormatAndType(internalformat, type);
-        MOZ_ASSERT(effectiveinternalformat != LOCAL_GL_NONE);
-        tex->SetImageInfo(texImageTarget, level, srcImage->GetSize().width, srcImage->GetSize().height, 1,
-                          effectiveinternalformat, WebGLImageDataStatus::InitializedImageData);
+        TexInternalFormat effectiveInternalFormat =
+            EffectiveInternalFormatFromInternalFormatAndType(internalFormat,
+                                                             type);
+        MOZ_ASSERT(effectiveInternalFormat != LOCAL_GL_NONE);
+        tex->SetImageInfo(texImageTarget, level, srcImage->GetSize().width,
+                          srcImage->GetSize().height, 1,
+                          effectiveInternalFormat,
+                          WebGLImageDataStatus::InitializedImageData);
         tex->Bind(TexImageTargetToTexTarget(texImageTarget));
     }
+
     srcImage = nullptr;
     container->UnlockCurrentImage();
     return ok;
@@ -1882,27 +1851,27 @@ NS_IMPL_CYCLE_COLLECTING_ADDREF(WebGLContext)
 NS_IMPL_CYCLE_COLLECTING_RELEASE(WebGLContext)
 
 NS_IMPL_CYCLE_COLLECTION_WRAPPERCACHE(WebGLContext,
-  mCanvasElement,
-  mExtensions,
-  mBound2DTextures,
-  mBoundCubeMapTextures,
-  mBound3DTextures,
-  mBoundArrayBuffer,
-  mBoundTransformFeedbackBuffer,
-  mCurrentProgram,
-  mBoundFramebuffer,
-  mBoundRenderbuffer,
-  mBoundVertexArray,
-  mDefaultVertexArray,
-  mActiveOcclusionQuery,
-  mActiveTransformFeedbackQuery)
+                                      mCanvasElement,
+                                      mExtensions,
+                                      mBound2DTextures,
+                                      mBoundCubeMapTextures,
+                                      mBound3DTextures,
+                                      mBoundArrayBuffer,
+                                      mBoundTransformFeedbackBuffer,
+                                      mCurrentProgram,
+                                      mBoundFramebuffer,
+                                      mBoundRenderbuffer,
+                                      mBoundVertexArray,
+                                      mDefaultVertexArray,
+                                      mActiveOcclusionQuery,
+                                      mActiveTransformFeedbackQuery)
 
 NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(WebGLContext)
-  NS_WRAPPERCACHE_INTERFACE_MAP_ENTRY
-  NS_INTERFACE_MAP_ENTRY(nsIDOMWebGLRenderingContext)
-  NS_INTERFACE_MAP_ENTRY(nsICanvasRenderingContextInternal)
-  NS_INTERFACE_MAP_ENTRY(nsISupportsWeakReference)
-  // If the exact way we cast to nsISupports here ever changes, fix our
-  // ToSupports() method.
-  NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIDOMWebGLRenderingContext)
+    NS_WRAPPERCACHE_INTERFACE_MAP_ENTRY
+    NS_INTERFACE_MAP_ENTRY(nsIDOMWebGLRenderingContext)
+    NS_INTERFACE_MAP_ENTRY(nsICanvasRenderingContextInternal)
+    NS_INTERFACE_MAP_ENTRY(nsISupportsWeakReference)
+    // If the exact way we cast to nsISupports here ever changes, fix our
+    // ToSupports() method.
+    NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIDOMWebGLRenderingContext)
 NS_INTERFACE_MAP_END
diff --git a/dom/canvas/WebGLContext.h b/dom/canvas/WebGLContext.h
index 52314d1f4028..6f61b671b10b 100644
--- a/dom/canvas/WebGLContext.h
+++ b/dom/canvas/WebGLContext.h
@@ -66,28 +66,27 @@ class nsIDocShell;
 
 namespace mozilla {
 
-class WebGLContextLossHandler;
-class WebGLObserver;
-class WebGLContextBoundObject;
 class WebGLActiveInfo;
-class WebGLExtensionBase;
+class WebGLContextBoundObject;
+class WebGLContextLossHandler;
 class WebGLBuffer;
-class WebGLShader;
+class WebGLExtensionBase;
+class WebGLFramebuffer;
+class WebGLObserver;
 class WebGLProgram;
 class WebGLQuery;
-class WebGLUniformLocation;
-class WebGLFramebuffer;
 class WebGLRenderbuffer;
 class WebGLSampler;
+class WebGLShader;
 class WebGLShaderPrecisionFormat;
 class WebGLTexture;
+class WebGLUniformLocation;
 class WebGLVertexArray;
 struct WebGLVertexAttribData;
 
 namespace dom {
-class ImageData;
 class Element;
-
+class ImageData;
 struct WebGLContextAttributes;
 template struct Nullable;
 }
@@ -102,7 +101,8 @@ WebGLTexelFormat GetWebGLTexelFormat(TexInternalFormat format);
 
 void AssertUintParamCorrect(gl::GLContext* gl, GLenum pname, GLuint shadow);
 
-struct WebGLContextOptions {
+struct WebGLContextOptions
+{
     // these are defaults
     WebGLContextOptions();
 
@@ -149,14 +149,14 @@ public:
     GLfloat AsFloat() const { return (mType == Float) ? mValue.f : GLfloat(mValue.i); }
 };
 
-class WebGLContext :
-    public nsIDOMWebGLRenderingContext,
-    public nsICanvasRenderingContextInternal,
-    public nsSupportsWeakReference,
-    public WebGLContextUnchecked,
-    public WebGLRectangleObject,
-    public nsWrapperCache,
-    public SupportsWeakPtr
+class WebGLContext
+    : public nsIDOMWebGLRenderingContext
+    , public nsICanvasRenderingContextInternal
+    , public nsSupportsWeakReference
+    , public WebGLContextUnchecked
+    , public WebGLRectangleObject
+    , public nsWrapperCache
+    , public SupportsWeakPtr
 {
     friend class WebGLContextUserData;
     friend class WebGLExtensionCompressedTextureATC;
@@ -167,8 +167,8 @@ class WebGLContext :
     friend class WebGLExtensionDrawBuffers;
     friend class WebGLExtensionLoseContext;
     friend class WebGLExtensionVertexArray;
-    friend class WebGLObserver;
     friend class WebGLMemoryTracker;
+    friend class WebGLObserver;
 
     enum {
         UNPACK_FLIP_Y_WEBGL = 0x9240,
@@ -190,7 +190,7 @@ public:
     NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS_AMBIGUOUS(WebGLContext,
                                                            nsIDOMWebGLRenderingContext)
 
-    virtual JSObject* WrapObject(JSContext *cx) = 0;
+    virtual JSObject* WrapObject(JSContext* cx) = 0;
 
     NS_DECL_NSIDOMWEBGLRENDERINGCONTEXT
 
@@ -200,22 +200,34 @@ public:
     virtual int32_t GetHeight() const MOZ_OVERRIDE;
 #endif
     NS_IMETHOD SetDimensions(int32_t width, int32_t height) MOZ_OVERRIDE;
-    NS_IMETHOD InitializeWithSurface(nsIDocShell *docShell, gfxASurface *surface, int32_t width, int32_t height) MOZ_OVERRIDE
-        { return NS_ERROR_NOT_IMPLEMENTED; }
-    NS_IMETHOD Reset() MOZ_OVERRIDE
-        { /* (InitializeWithSurface) */ return NS_ERROR_NOT_IMPLEMENTED; }
-    virtual void GetImageBuffer(uint8_t** aImageBuffer, int32_t* aFormat);
-    NS_IMETHOD GetInputStream(const char* aMimeType,
-                              const char16_t* aEncoderOptions,
-                              nsIInputStream **aStream) MOZ_OVERRIDE;
-    mozilla::TemporaryRef GetSurfaceSnapshot(bool* aPremultAlpha) MOZ_OVERRIDE;
+    NS_IMETHOD InitializeWithSurface(nsIDocShell*, gfxASurface*, int32_t,
+                                     int32_t) MOZ_OVERRIDE
+    {
+        return NS_ERROR_NOT_IMPLEMENTED;
+    }
 
-    NS_IMETHOD SetIsOpaque(bool b) MOZ_OVERRIDE { return NS_OK; };
+    NS_IMETHOD Reset() MOZ_OVERRIDE {
+        /* (InitializeWithSurface) */
+        return NS_ERROR_NOT_IMPLEMENTED;
+    }
+
+    virtual void GetImageBuffer(uint8_t** out_imageBuffer,
+                                int32_t* out_format) MOZ_OVERRIDE;
+    NS_IMETHOD GetInputStream(const char* mimeType,
+                              const char16_t* encoderOptions,
+                              nsIInputStream** out_stream) MOZ_OVERRIDE;
+
+    mozilla::TemporaryRef
+    GetSurfaceSnapshot(bool* out_premultAlpha) MOZ_OVERRIDE;
+
+    NS_IMETHOD SetIsOpaque(bool) MOZ_OVERRIDE { return NS_OK; };
     bool GetIsOpaque() MOZ_OVERRIDE { return false; }
-    NS_IMETHOD SetContextOptions(JSContext* aCx,
-                                 JS::Handle aOptions) MOZ_OVERRIDE;
+    NS_IMETHOD SetContextOptions(JSContext* cx,
+                                 JS::Handle options) MOZ_OVERRIDE;
 
-    NS_IMETHOD SetIsIPC(bool b) MOZ_OVERRIDE { return NS_ERROR_NOT_IMPLEMENTED; }
+    NS_IMETHOD SetIsIPC(bool) MOZ_OVERRIDE {
+        return NS_ERROR_NOT_IMPLEMENTED;
+    }
 
     /**
      * An abstract base class to be implemented by callers wanting to be notified
@@ -224,26 +236,27 @@ public:
      */
     virtual void DidRefresh() MOZ_OVERRIDE;
 
-    NS_IMETHOD Redraw(const gfxRect&) MOZ_OVERRIDE { return NS_ERROR_NOT_IMPLEMENTED; }
+    NS_IMETHOD Redraw(const gfxRect&) MOZ_OVERRIDE {
+        return NS_ERROR_NOT_IMPLEMENTED;
+    }
 
     void SynthesizeGLError(GLenum err);
-    void SynthesizeGLError(GLenum err, const char *fmt, ...);
+    void SynthesizeGLError(GLenum err, const char* fmt, ...);
 
-    void ErrorInvalidEnum(const char *fmt = 0, ...);
-    void ErrorInvalidOperation(const char *fmt = 0, ...);
-    void ErrorInvalidValue(const char *fmt = 0, ...);
-    void ErrorInvalidFramebufferOperation(const char *fmt = 0, ...);
-    void ErrorInvalidEnumInfo(const char *info, GLenum enumvalue);
-    void ErrorOutOfMemory(const char *fmt = 0, ...);
+    void ErrorInvalidEnum(const char* fmt = 0, ...);
+    void ErrorInvalidOperation(const char* fmt = 0, ...);
+    void ErrorInvalidValue(const char* fmt = 0, ...);
+    void ErrorInvalidFramebufferOperation(const char* fmt = 0, ...);
+    void ErrorInvalidEnumInfo(const char* info, GLenum enumvalue);
+    void ErrorOutOfMemory(const char* fmt = 0, ...);
 
-    const char *ErrorName(GLenum error);
+    const char* ErrorName(GLenum error);
 
     /**
      * Return displayable name for GLenum.
      * This version is like gl::GLenumToStr but with out the GL_ prefix to
      * keep consistency with how errors are reported from WebGL.
      */
-
     // Returns nullptr if glenum is unknown.
     static const char* EnumName(GLenum glenum);
     // Returns hex formatted version of glenum if glenum is unknown.
@@ -252,18 +265,18 @@ public:
     bool IsCompressedTextureFormat(GLenum format);
     bool IsTextureFormatCompressed(TexInternalFormat format);
 
-    void DummyFramebufferOperation(const char *info);
+    void DummyFramebufferOperation(const char* funcName);
 
-    WebGLTexture* activeBoundTextureForTarget(const TexTarget texTarget) const {
+    WebGLTexture* ActiveBoundTextureForTarget(const TexTarget texTarget) const {
         switch (texTarget.get()) {
-            case LOCAL_GL_TEXTURE_2D:
-                return mBound2DTextures[mActiveTexture];
-            case LOCAL_GL_TEXTURE_CUBE_MAP:
-                return mBoundCubeMapTextures[mActiveTexture];
-            case LOCAL_GL_TEXTURE_3D:
-                return mBound3DTextures[mActiveTexture];
-            default:
-                MOZ_CRASH("bad target");
+        case LOCAL_GL_TEXTURE_2D:
+            return mBound2DTextures[mActiveTexture];
+        case LOCAL_GL_TEXTURE_CUBE_MAP:
+            return mBoundCubeMapTextures[mActiveTexture];
+        case LOCAL_GL_TEXTURE_3D:
+            return mBound3DTextures[mActiveTexture];
+        default:
+            MOZ_CRASH("bad target");
         }
     }
 
@@ -271,14 +284,16 @@ public:
      * GL_TEXTURE_2D, GL_TEXTURE_CUBE_MAP_[POSITIVE|NEGATIVE]_[X|Y|Z], and
      * not the actual texture binding target: GL_TEXTURE_2D or GL_TEXTURE_CUBE_MAP.
      */
-    WebGLTexture* activeBoundTextureForTexImageTarget(const TexImageTarget texImgTarget) const {
+    WebGLTexture*
+    ActiveBoundTextureForTexImageTarget(const TexImageTarget texImgTarget) const
+    {
         const TexTarget texTarget = TexImageTargetToTexTarget(texImgTarget);
-        return activeBoundTextureForTarget(texTarget);
+        return ActiveBoundTextureForTarget(texTarget);
     }
 
-    already_AddRefed GetCanvasLayer(nsDisplayListBuilder* aBuilder,
-                                                 CanvasLayer *aOldLayer,
-                                                 LayerManager *aManager) MOZ_OVERRIDE;
+    already_AddRefed
+    GetCanvasLayer(nsDisplayListBuilder* builder, CanvasLayer* oldLayer,
+                   LayerManager* manager) MOZ_OVERRIDE;
 
     // Note that 'clean' here refers to its invalidation state, not the
     // contents of the buffer.
@@ -303,7 +318,8 @@ public:
     // amount of work it does.
     // It only clears the buffers we specify, and can reset its state without
     // first having to query anything, as WebGL knows its state at all times.
-    void ForceClearFramebufferWithDefaultValues(GLbitfield mask, const bool colorAttachmentsMask[kMaxColorAttachments]);
+    void ForceClearFramebufferWithDefaultValues(GLbitfield mask,
+                                                const bool colorAttachmentsMask[kMaxColorAttachments]);
 
     // Calls ForceClearFramebufferWithDefaultValues() for the Context's 'screen'.
     void ClearScreen();
@@ -323,22 +339,26 @@ public:
     // WebIDL WebGLRenderingContext API
     dom::HTMLCanvasElement* GetCanvas() const { return mCanvasElement; }
     GLsizei DrawingBufferWidth() const { return IsContextLost() ? 0 : mWidth; }
-    GLsizei DrawingBufferHeight() const { return IsContextLost() ? 0 : mHeight; }
+    GLsizei DrawingBufferHeight() const {
+        return IsContextLost() ? 0 : mHeight;
+    }
+
+    void
+    GetContextAttributes(dom::Nullable& retval);
 
-    void GetContextAttributes(dom::Nullable& retval);
     bool IsContextLost() const { return mContextStatus != ContextNotLost; }
-    void GetSupportedExtensions(JSContext *cx, dom::Nullable< nsTArray > &retval);
-    void GetExtension(JSContext* cx, const nsAString& aName,
-                      JS::MutableHandle aRetval,
-                      ErrorResult& rv);
+    void GetSupportedExtensions(JSContext* cx,
+                                dom::Nullable< nsTArray >& retval);
+    void GetExtension(JSContext* cx, const nsAString& name,
+                      JS::MutableHandle retval, ErrorResult& rv);
     void ActiveTexture(GLenum texture);
-    void AttachShader(WebGLProgram* program, WebGLShader* shader);
-    void BindAttribLocation(WebGLProgram* program, GLuint location,
+    void AttachShader(WebGLProgram* prog, WebGLShader* shader);
+    void BindAttribLocation(WebGLProgram* prog, GLuint location,
                             const nsAString& name);
-    void BindFramebuffer(GLenum target, WebGLFramebuffer* wfb);
-    void BindRenderbuffer(GLenum target, WebGLRenderbuffer* wrb);
-    void BindTexture(GLenum target, WebGLTexture *tex);
-    void BindVertexArray(WebGLVertexArray *vao);
+    void BindFramebuffer(GLenum target, WebGLFramebuffer* fb);
+    void BindRenderbuffer(GLenum target, WebGLRenderbuffer* fb);
+    void BindTexture(GLenum target, WebGLTexture* tex);
+    void BindVertexArray(WebGLVertexArray* vao);
     void BlendColor(GLclampf r, GLclampf g, GLclampf b, GLclampf a);
     void BlendEquation(GLenum mode);
     void BlendEquationSeparate(GLenum modeRGB, GLenum modeAlpha);
@@ -352,21 +372,20 @@ public:
     void ClearStencil(GLint v);
     void ColorMask(WebGLboolean r, WebGLboolean g, WebGLboolean b, WebGLboolean a);
     void CompileShader(WebGLShader* shader);
-    void CompressedTexImage2D(GLenum target, GLint level,
+    void CompressedTexImage2D(GLenum texImageTarget, GLint level,
                               GLenum internalformat, GLsizei width,
                               GLsizei height, GLint border,
                               const dom::ArrayBufferView& view);
-    void CompressedTexSubImage2D(GLenum target, GLint level,
-                                 GLint xoffset, GLint yoffset,
-                                 GLsizei width, GLsizei height,
-                                 GLenum format,
+    void CompressedTexSubImage2D(GLenum texImageTarget, GLint level,
+                                 GLint xoffset, GLint yoffset, GLsizei width,
+                                 GLsizei height, GLenum format,
                                  const dom::ArrayBufferView& view);
-    void CopyTexImage2D(GLenum target, GLint level,
-                        GLenum internalformat, GLint x, GLint y,
-                        GLsizei width, GLsizei height, GLint border);
-    void CopyTexSubImage2D(GLenum target, GLint level, GLint xoffset,
-                           GLint yoffset, GLint x, GLint y,
-                           GLsizei width, GLsizei height);
+    void CopyTexImage2D(GLenum texImageTarget, GLint level,
+                        GLenum internalformat, GLint x, GLint y, GLsizei width,
+                        GLsizei height, GLint border);
+    void CopyTexSubImage2D(GLenum texImageTarget, GLint level, GLint xoffset,
+                           GLint yoffset, GLint x, GLint y, GLsizei width,
+                           GLsizei height);
     already_AddRefed CreateFramebuffer();
     already_AddRefed CreateProgram();
     already_AddRefed CreateRenderbuffer();
@@ -374,23 +393,23 @@ public:
     already_AddRefed CreateShader(GLenum type);
     already_AddRefed CreateVertexArray();
     void CullFace(GLenum face);
-    void DeleteFramebuffer(WebGLFramebuffer *fbuf);
-    void DeleteProgram(WebGLProgram *prog);
-    void DeleteRenderbuffer(WebGLRenderbuffer *rbuf);
-    void DeleteShader(WebGLShader *shader);
-    void DeleteVertexArray(WebGLVertexArray *vao);
-    void DeleteTexture(WebGLTexture *tex);
+    void DeleteFramebuffer(WebGLFramebuffer* fb);
+    void DeleteProgram(WebGLProgram* prog);
+    void DeleteRenderbuffer(WebGLRenderbuffer* rb);
+    void DeleteShader(WebGLShader* shader);
+    void DeleteVertexArray(WebGLVertexArray* vao);
+    void DeleteTexture(WebGLTexture* tex);
     void DepthFunc(GLenum func);
     void DepthMask(WebGLboolean b);
     void DepthRange(GLclampf zNear, GLclampf zFar);
-    void DetachShader(WebGLProgram *program, WebGLShader *shader);
+    void DetachShader(WebGLProgram* prog, WebGLShader* shader);
     void DrawBuffers(const dom::Sequence& buffers);
     void Flush();
     void Finish();
     void FramebufferRenderbuffer(GLenum target, GLenum attachment,
-                                 GLenum rbtarget, WebGLRenderbuffer *wrb);
+                                 GLenum rbTarget, WebGLRenderbuffer* rb);
     void FramebufferTexture2D(GLenum target, GLenum attachment,
-                              GLenum textarget, WebGLTexture *tobj,
+                              GLenum texImageTarget, WebGLTexture* tex,
                               GLint level);
 
     // Framebuffer validation
@@ -398,166 +417,186 @@ public:
 
     void FrontFace(GLenum mode);
     void GenerateMipmap(GLenum target);
-    already_AddRefed GetActiveAttrib(WebGLProgram *prog,
+    already_AddRefed GetActiveAttrib(WebGLProgram* prog,
                                                       GLuint index);
-    already_AddRefed GetActiveUniform(WebGLProgram *prog,
+    already_AddRefed GetActiveUniform(WebGLProgram* prog,
                                                        GLuint index);
-    void GetAttachedShaders(WebGLProgram* prog,
-                            dom::Nullable>>& retval);
+
+    void
+    GetAttachedShaders(WebGLProgram* prog,
+                       dom::Nullable>>& retval);
+
     GLint GetAttribLocation(WebGLProgram* prog, const nsAString& name);
     JS::Value GetBufferParameter(GLenum target, GLenum pname);
-    void GetBufferParameter(JSContext* /* unused */, GLenum target,
-                            GLenum pname,
-                            JS::MutableHandle retval) {
+
+    void GetBufferParameter(JSContext*, GLenum target, GLenum pname,
+                            JS::MutableHandle retval)
+    {
         retval.set(GetBufferParameter(target, pname));
     }
+
     GLenum GetError();
-    JS::Value GetFramebufferAttachmentParameter(JSContext* cx,
-                                                GLenum target,
-                                                GLenum attachment,
-                                                GLenum pname,
+    JS::Value GetFramebufferAttachmentParameter(JSContext* cx, GLenum target,
+                                                GLenum attachment, GLenum pname,
                                                 ErrorResult& rv);
-    void GetFramebufferAttachmentParameter(JSContext* cx,
-                                           GLenum target,
-                                           GLenum attachment,
-                                           GLenum pname,
+
+    void GetFramebufferAttachmentParameter(JSContext* cx, GLenum target,
+                                           GLenum attachment, GLenum pname,
                                            JS::MutableHandle retval,
-                                           ErrorResult& rv) {
+                                           ErrorResult& rv)
+    {
         retval.set(GetFramebufferAttachmentParameter(cx, target, attachment,
                                                      pname, rv));
     }
-    JS::Value GetProgramParameter(WebGLProgram *prog, GLenum pname);
-    void  GetProgramParameter(JSContext* /* unused */, WebGLProgram *prog,
-                              GLenum pname,
-                              JS::MutableHandle retval) {
+
+    JS::Value GetProgramParameter(WebGLProgram* prog, GLenum pname);
+
+    void  GetProgramParameter(JSContext*, WebGLProgram* prog, GLenum pname,
+                              JS::MutableHandle retval)
+    {
         retval.set(GetProgramParameter(prog, pname));
     }
-    void GetProgramInfoLog(WebGLProgram *prog, nsACString& retval);
-    void GetProgramInfoLog(WebGLProgram *prog, nsAString& retval);
+
+    void GetProgramInfoLog(WebGLProgram* prog, nsACString& retval);
+    void GetProgramInfoLog(WebGLProgram* prog, nsAString& retval);
     JS::Value GetRenderbufferParameter(GLenum target, GLenum pname);
-    void GetRenderbufferParameter(JSContext* /* unused */,
-                                  GLenum target, GLenum pname,
-                                  JS::MutableHandle retval) {
+
+    void GetRenderbufferParameter(JSContext*, GLenum target, GLenum pname,
+                                  JS::MutableHandle retval)
+    {
         retval.set(GetRenderbufferParameter(target, pname));
     }
-    JS::Value GetShaderParameter(WebGLShader *shader, GLenum pname);
-    void GetShaderParameter(JSContext* /* unused */, WebGLShader *shader,
-                            GLenum pname,
-                            JS::MutableHandle retval) {
+
+    JS::Value GetShaderParameter(WebGLShader* shader, GLenum pname);
+
+    void GetShaderParameter(JSContext*, WebGLShader* shader, GLenum pname,
+                            JS::MutableHandle retval)
+    {
         retval.set(GetShaderParameter(shader, pname));
     }
+
     already_AddRefed
-      GetShaderPrecisionFormat(GLenum shadertype, GLenum precisiontype);
-    void GetShaderInfoLog(WebGLShader *shader, nsACString& retval);
-    void GetShaderInfoLog(WebGLShader *shader, nsAString& retval);
-    void GetShaderSource(WebGLShader *shader, nsAString& retval);
-    void GetShaderTranslatedSource(WebGLShader *shader, nsAString& retval);
+    GetShaderPrecisionFormat(GLenum shadertype, GLenum precisiontype);
+
+    void GetShaderInfoLog(WebGLShader* shader, nsACString& retval);
+    void GetShaderInfoLog(WebGLShader* shader, nsAString& retval);
+    void GetShaderSource(WebGLShader* shader, nsAString& retval);
+    void GetShaderTranslatedSource(WebGLShader* shader, nsAString& retval);
     JS::Value GetTexParameter(GLenum target, GLenum pname);
-    void GetTexParameter(JSContext * /* unused */, GLenum target,
-                         GLenum pname,
-                         JS::MutableHandle retval) {
+
+    void GetTexParameter(JSContext*, GLenum target, GLenum pname,
+                         JS::MutableHandle retval)
+    {
         retval.set(GetTexParameter(target, pname));
     }
-    JS::Value GetUniform(JSContext* cx, WebGLProgram *prog,
-                         WebGLUniformLocation *location);
-    void GetUniform(JSContext* cx, WebGLProgram *prog,
-                    WebGLUniformLocation *location,
-                    JS::MutableHandle retval) {
-        retval.set(GetUniform(cx, prog, location));
+
+    JS::Value GetUniform(JSContext* cx, WebGLProgram* prog,
+                         WebGLUniformLocation* loc);
+
+    void GetUniform(JSContext* cx, WebGLProgram* prog,
+                    WebGLUniformLocation* loc,
+                    JS::MutableHandle retval)
+    {
+        retval.set(GetUniform(cx, prog, loc));
     }
+
     already_AddRefed
-      GetUniformLocation(WebGLProgram *prog, const nsAString& name);
+    GetUniformLocation(WebGLProgram* prog, const nsAString& name);
+
     void Hint(GLenum target, GLenum mode);
-    bool IsFramebuffer(WebGLFramebuffer *fb);
-    bool IsProgram(WebGLProgram *prog);
-    bool IsRenderbuffer(WebGLRenderbuffer *rb);
-    bool IsShader(WebGLShader *shader);
-    bool IsTexture(WebGLTexture *tex);
-    bool IsVertexArray(WebGLVertexArray *vao);
+    bool IsFramebuffer(WebGLFramebuffer* fb);
+    bool IsProgram(WebGLProgram* prog);
+    bool IsRenderbuffer(WebGLRenderbuffer* rb);
+    bool IsShader(WebGLShader* shader);
+    bool IsTexture(WebGLTexture* tex);
+    bool IsVertexArray(WebGLVertexArray* vao);
     void LineWidth(GLfloat width);
-    void LinkProgram(WebGLProgram *program);
+    void LinkProgram(WebGLProgram* prog);
     void PixelStorei(GLenum pname, GLint param);
     void PolygonOffset(GLfloat factor, GLfloat units);
     void ReadPixels(GLint x, GLint y, GLsizei width, GLsizei height,
                     GLenum format, GLenum type,
-                    const Nullable &pixels,
+                    const Nullable& pixels,
                     ErrorResult& rv);
-    void RenderbufferStorage(GLenum target, GLenum internalformat,
+    void RenderbufferStorage(GLenum target, GLenum internalFormat,
                              GLsizei width, GLsizei height);
     void SampleCoverage(GLclampf value, WebGLboolean invert);
     void Scissor(GLint x, GLint y, GLsizei width, GLsizei height);
-    void ShaderSource(WebGLShader *shader, const nsAString& source);
+    void ShaderSource(WebGLShader* shader, const nsAString& source);
     void StencilFunc(GLenum func, GLint ref, GLuint mask);
-    void StencilFuncSeparate(GLenum face, GLenum func, GLint ref,
-                             GLuint mask);
+    void StencilFuncSeparate(GLenum face, GLenum func, GLint ref, GLuint mask);
     void StencilMask(GLuint mask);
     void StencilMaskSeparate(GLenum face, GLuint mask);
     void StencilOp(GLenum sfail, GLenum dpfail, GLenum dppass);
     void StencilOpSeparate(GLenum face, GLenum sfail, GLenum dpfail,
                            GLenum dppass);
-    void TexImage2D(GLenum target, GLint level,
-                    GLenum internalformat, GLsizei width,
-                    GLsizei height, GLint border, GLenum format,
-                    GLenum type,
-                    const Nullable &pixels,
+    void TexImage2D(GLenum texImageTarget, GLint level, GLenum internalFormat,
+                    GLsizei width, GLsizei height, GLint border, GLenum format,
+                    GLenum type, const Nullable& pixels,
+                    ErrorResult& rv);
+    void TexImage2D(GLenum texImageTarget, GLint level, GLenum internalFormat,
+                    GLenum format, GLenum type, dom::ImageData* pixels,
                     ErrorResult& rv);
-    void TexImage2D(GLenum target, GLint level,
-                    GLenum internalformat, GLenum format, GLenum type,
-                    dom::ImageData* pixels, ErrorResult& rv);
     // Allow whatever element types the bindings are willing to pass
     // us in TexImage2D
     bool TexImageFromVideoElement(TexImageTarget texImageTarget, GLint level,
-                                  GLenum internalformat, GLenum format, GLenum type,
-                                  mozilla::dom::Element& image);
+                                  GLenum internalFormat, GLenum format,
+                                  GLenum type, mozilla::dom::Element& image);
 
     template
-    void TexImage2D(GLenum rawTexImgTarget, GLint level,
-                    GLenum internalformat, GLenum format, GLenum type,
+    void TexImage2D(GLenum rawTexImageTarget, GLint level,
+                    GLenum internalFormat, GLenum format, GLenum type,
                     ElementType& elt, ErrorResult& rv)
     {
         if (IsContextLost())
             return;
 
-        if (!ValidateTexImageTarget(rawTexImgTarget,
+        if (!ValidateTexImageTarget(rawTexImageTarget,
                                     WebGLTexImageFunc::TexImage,
                                     WebGLTexDimensions::Tex2D))
         {
-            return ErrorInvalidEnumInfo("texSubImage2D: target", rawTexImgTarget);
+            ErrorInvalidEnumInfo("texSubImage2D: target", rawTexImageTarget);
+            return;
         }
 
-        const TexImageTarget texImageTarget(rawTexImgTarget);
+        const TexImageTarget texImageTarget(rawTexImageTarget);
 
         if (level < 0)
             return ErrorInvalidValue("texImage2D: level is negative");
 
         const int32_t maxLevel = MaxTextureLevelForTexImageTarget(texImageTarget);
-        if (level > maxLevel)
-            return ErrorInvalidValue("texImage2D: level %d is too large, max is %d", level, maxLevel);
+        if (level > maxLevel) {
+            ErrorInvalidValue("texImage2D: level %d is too large, max is %d",
+                              level, maxLevel);
+            return;
+        }
 
-        WebGLTexture* tex = activeBoundTextureForTexImageTarget(texImageTarget);
+        WebGLTexture* tex = ActiveBoundTextureForTexImageTarget(texImageTarget);
 
         if (!tex)
             return ErrorInvalidOperation("no texture is bound to this target");
 
         // Trying to handle the video by GPU directly first
-        if (TexImageFromVideoElement(texImageTarget, level, internalformat, format, type, elt)) {
+        if (TexImageFromVideoElement(texImageTarget, level, internalFormat,
+                                     format, type, elt))
+        {
             return;
         }
 
         RefPtr data;
         WebGLTexelFormat srcFormat;
         nsLayoutUtils::SurfaceFromElementResult res = SurfaceFromElement(elt);
-        rv = SurfaceFromElementResultToImageSurface(res, data,
-                                                    &srcFormat);
+        rv = SurfaceFromElementResultToImageSurface(res, data, &srcFormat);
         if (rv.Failed() || !data)
             return;
 
         gfx::IntSize size = data->GetSize();
         uint32_t byteLength = data->Stride() * size.height;
-        return TexImage2D_base(texImageTarget, level, internalformat,
-                               size.width, size.height, data->Stride(),
-                               0, format, type, data->GetData(), byteLength,
-                               js::Scalar::TypeMax, srcFormat, mPixelStorePremultiplyAlpha);
+        return TexImage2D_base(texImageTarget, level, internalFormat,
+                               size.width, size.height, data->Stride(), 0,
+                               format, type, data->GetData(), byteLength,
+                               js::Scalar::TypeMax, srcFormat,
+                               mPixelStorePremultiplyAlpha);
     }
 
     void TexParameterf(GLenum target, GLenum pname, GLfloat param) {
@@ -567,23 +606,19 @@ public:
         TexParameter_base(target, pname, ¶m, nullptr);
     }
 
-    void TexSubImage2D(GLenum target, GLint level,
-                       GLint xoffset, GLint yoffset,
-                       GLsizei width, GLsizei height, GLenum format,
-                       GLenum type,
-                       const Nullable &pixels,
+    void TexSubImage2D(GLenum texImageTarget, GLint level, GLint xoffset,
+                       GLint yoffset, GLsizei width, GLsizei height,
+                       GLenum format, GLenum type,
+                       const Nullable& pixels,
                        ErrorResult& rv);
-    void TexSubImage2D(GLenum target, GLint level,
-                       GLint xoffset, GLint yoffset, GLenum format,
-                       GLenum type, dom::ImageData* pixels, ErrorResult& rv);
+    void TexSubImage2D(GLenum texImageTarget, GLint level, GLint xoffset,
+                       GLint yoffset, GLenum format, GLenum type,
+                       dom::ImageData* pixels, ErrorResult& rv);
     // Allow whatever element types the bindings are willing to pass
     // us in TexSubImage2D
     template
-    void TexSubImage2D(GLenum rawTexImageTarget,
-                       GLint level,
-                       GLint xoffset, GLint yoffset,
-                       GLenum format,
-                       GLenum type,
+    void TexSubImage2D(GLenum rawTexImageTarget, GLint level, GLint xoffset,
+                       GLint yoffset, GLenum format, GLenum type,
                        ElementType& elt, ErrorResult& rv)
     {
         if (IsContextLost())
@@ -593,7 +628,8 @@ public:
                                     WebGLTexImageFunc::TexSubImage,
                                     WebGLTexDimensions::Tex2D))
         {
-            return ErrorInvalidEnumInfo("texSubImage2D: target", rawTexImageTarget);
+            ErrorInvalidEnumInfo("texSubImage2D: target", rawTexImageTarget);
+            return;
         }
 
         const TexImageTarget texImageTarget(rawTexImageTarget);
@@ -602,19 +638,22 @@ public:
             return ErrorInvalidValue("texSubImage2D: level is negative");
 
         const int32_t maxLevel = MaxTextureLevelForTexImageTarget(texImageTarget);
-        if (level > maxLevel)
-            return ErrorInvalidValue("texSubImage2D: level %d is too large, max is %d", level, maxLevel);
-
-        WebGLTexture* tex = activeBoundTextureForTexImageTarget(texImageTarget);
-        if (!tex) {
-            return ErrorInvalidOperation("texSubImage2D: no texture bound on active texture unit");
+        if (level > maxLevel) {
+            ErrorInvalidValue("texSubImage2D: level %d is too large, max is %d",
+                              level, maxLevel);
+            return;
         }
-        const WebGLTexture::ImageInfo &imageInfo = tex->ImageInfoAt(texImageTarget, level);
-        const TexInternalFormat internalformat = imageInfo.EffectiveInternalFormat();
+
+        WebGLTexture* tex = ActiveBoundTextureForTexImageTarget(texImageTarget);
+        if (!tex)
+            return ErrorInvalidOperation("texSubImage2D: no texture bound on active texture unit");
+
+        const WebGLTexture::ImageInfo& imageInfo = tex->ImageInfoAt(texImageTarget, level);
+        const TexInternalFormat internalFormat = imageInfo.EffectiveInternalFormat();
 
         // Trying to handle the video by GPU directly first
         if (TexImageFromVideoElement(texImageTarget, level,
-                                     internalformat.get(), format, type, elt))
+                                     internalFormat.get(), format, type, elt))
         {
             return;
         }
@@ -622,19 +661,17 @@ public:
         RefPtr data;
         WebGLTexelFormat srcFormat;
         nsLayoutUtils::SurfaceFromElementResult res = SurfaceFromElement(elt);
-        rv = SurfaceFromElementResultToImageSurface(res, data,
-                                                    &srcFormat);
+        rv = SurfaceFromElementResultToImageSurface(res, data, &srcFormat);
         if (rv.Failed() || !data)
             return;
 
         gfx::IntSize size = data->GetSize();
         uint32_t byteLength = data->Stride() * size.height;
         return TexSubImage2D_base(texImageTarget.get(), level, xoffset, yoffset,
-                                  size.width, size.height,
-                                  data->Stride(), format, type,
-                                  data->GetData(), byteLength,
-                                  js::Scalar::TypeMax, srcFormat, mPixelStorePremultiplyAlpha);
-
+                                  size.width, size.height, data->Stride(),
+                                  format, type, data->GetData(), byteLength,
+                                  js::Scalar::TypeMax, srcFormat,
+                                  mPixelStorePremultiplyAlpha);
     }
 
     void Uniform1i(WebGLUniformLocation* loc, GLint x);
@@ -795,8 +832,9 @@ public:
                                WebGLboolean transpose, size_t arrayLength,
                                const float* data);
 
-    void UseProgram(WebGLProgram *prog);
-    bool ValidateAttribArraySetter(const char* name, uint32_t cnt, uint32_t arrayLength);
+    void UseProgram(WebGLProgram* prog);
+    bool ValidateAttribArraySetter(const char* name, uint32_t count,
+                                   uint32_t arrayLength);
     bool ValidateUniformSetter(WebGLUniformLocation* loc, uint8_t setterSize,
                                GLenum setterType, const char* info,
                                GLuint* out_rawLoc);
@@ -811,11 +849,10 @@ public:
                                           bool setterTranspose,
                                           const char* info, GLuint* out_rawLoc,
                                           GLsizei* out_numElementsToUpload);
-    void ValidateProgram(WebGLProgram *prog);
-    bool ValidateUniformLocation(const char* info, WebGLUniformLocation *location_object);
+    void ValidateProgram(WebGLProgram* prog);
+    bool ValidateUniformLocation(const char* info, WebGLUniformLocation* loc);
     bool ValidateSamplerUniformSetter(const char* info,
-                                    WebGLUniformLocation *location,
-                                    GLint value);
+                                      WebGLUniformLocation* loc, GLint value);
     void Viewport(GLint x, GLint y, GLsizei width, GLsizei height);
 // -----------------------------------------------------------------------------
 // WEBGL_lose_context
@@ -827,22 +864,21 @@ public:
 // Buffer Objects (WebGLContextBuffers.cpp)
 public:
     void BindBuffer(GLenum target, WebGLBuffer* buf);
-    void BindBufferBase(GLenum target, GLuint index, WebGLBuffer* buffer);
-    void BindBufferRange(GLenum target, GLuint index, WebGLBuffer* buffer,
+    void BindBufferBase(GLenum target, GLuint index, WebGLBuffer* buf);
+    void BindBufferRange(GLenum target, GLuint index, WebGLBuffer* buf,
                          WebGLintptr offset, WebGLsizeiptr size);
     void BufferData(GLenum target, WebGLsizeiptr size, GLenum usage);
-    void BufferData(GLenum target, const dom::ArrayBufferView &data,
+    void BufferData(GLenum target, const dom::ArrayBufferView& data,
                     GLenum usage);
-    void BufferData(GLenum target,
-                    const Nullable &maybeData,
+    void BufferData(GLenum target, const Nullable& maybeData,
                     GLenum usage);
     void BufferSubData(GLenum target, WebGLsizeiptr byteOffset,
-                       const dom::ArrayBufferView &data);
+                       const dom::ArrayBufferView& data);
     void BufferSubData(GLenum target, WebGLsizeiptr byteOffset,
-                       const Nullable &maybeData);
+                       const Nullable& maybeData);
     already_AddRefed CreateBuffer();
-    void DeleteBuffer(WebGLBuffer *buf);
-    bool IsBuffer(WebGLBuffer *buffer);
+    void DeleteBuffer(WebGLBuffer* buf);
+    bool IsBuffer(WebGLBuffer* buf);
 
 private:
     // ARRAY_BUFFER slot
@@ -852,9 +888,12 @@ private:
     WebGLRefPtr mBoundTransformFeedbackBuffer;
 
     // these two functions emit INVALID_ENUM for invalid `target`.
-    WebGLRefPtr* GetBufferSlotByTarget(GLenum target, const char* infos);
-    WebGLRefPtr* GetBufferSlotByTargetIndexed(GLenum target, GLuint index, const char* infos);
-    bool ValidateBufferUsageEnum(GLenum target, const char* infos);
+    WebGLRefPtr* GetBufferSlotByTarget(GLenum target,
+                                                    const char* info);
+    WebGLRefPtr* GetBufferSlotByTargetIndexed(GLenum target,
+                                                           GLuint index,
+                                                           const char* info);
+    bool ValidateBufferUsageEnum(GLenum target, const char* info);
 
 // -----------------------------------------------------------------------------
 // Queries (WebGL2ContextQueries.cpp)
@@ -871,10 +910,13 @@ public:
     void Enable(GLenum cap);
     bool GetStencilBits(GLint* out_stencilBits);
     JS::Value GetParameter(JSContext* cx, GLenum pname, ErrorResult& rv);
+
     void GetParameter(JSContext* cx, GLenum pname,
-                      JS::MutableHandle retval, ErrorResult& rv) {
+                      JS::MutableHandle retval, ErrorResult& rv)
+    {
         retval.set(GetParameter(cx, pname, rv));
     }
+
     void GetParameterIndexed(JSContext* cx, GLenum pname, GLuint index,
                              JS::MutableHandle retval);
     bool IsEnabled(GLenum cap);
@@ -892,8 +934,10 @@ private:
 // Vertices Feature (WebGLContextVertices.cpp)
 public:
     void DrawArrays(GLenum mode, GLint first, GLsizei count);
-    void DrawArraysInstanced(GLenum mode, GLint first, GLsizei count, GLsizei primcount);
-    void DrawElements(GLenum mode, GLsizei count, GLenum type, WebGLintptr byteOffset);
+    void DrawArraysInstanced(GLenum mode, GLint first, GLsizei count,
+                             GLsizei primcount);
+    void DrawElements(GLenum mode, GLsizei count, GLenum type,
+                      WebGLintptr byteOffset);
     void DrawElementsInstanced(GLenum mode, GLsizei count, GLenum type,
                                WebGLintptr byteOffset, GLsizei primcount);
 
@@ -902,21 +946,22 @@ public:
 
     JS::Value GetVertexAttrib(JSContext* cx, GLuint index, GLenum pname,
                               ErrorResult& rv);
+
     void GetVertexAttrib(JSContext* cx, GLuint index, GLenum pname,
-                         JS::MutableHandle retval,
-                         ErrorResult& rv) {
+                         JS::MutableHandle retval, ErrorResult& rv)
+    {
         retval.set(GetVertexAttrib(cx, index, pname, rv));
     }
+
     WebGLsizeiptr GetVertexAttribOffset(GLuint index, GLenum pname);
 
     void VertexAttrib1f(GLuint index, GLfloat x0);
     void VertexAttrib2f(GLuint index, GLfloat x0, GLfloat x1);
-    void VertexAttrib3f(GLuint index, GLfloat x0, GLfloat x1,
-                        GLfloat x2);
-    void VertexAttrib4f(GLuint index, GLfloat x0, GLfloat x1,
-                        GLfloat x2, GLfloat x3);
+    void VertexAttrib3f(GLuint index, GLfloat x0, GLfloat x1, GLfloat x2);
+    void VertexAttrib4f(GLuint index, GLfloat x0, GLfloat x1, GLfloat x2,
+                        GLfloat x3);
 
-    void VertexAttrib1fv(GLuint idx, const dom::Float32Array &arr) {
+    void VertexAttrib1fv(GLuint idx, const dom::Float32Array& arr) {
         arr.ComputeLengthAndData();
         VertexAttrib1fv_base(idx, arr.Length(), arr.Data());
     }
@@ -924,7 +969,7 @@ public:
         VertexAttrib1fv_base(idx, arr.Length(), arr.Elements());
     }
 
-    void VertexAttrib2fv(GLuint idx, const dom::Float32Array &arr) {
+    void VertexAttrib2fv(GLuint idx, const dom::Float32Array& arr) {
         arr.ComputeLengthAndData();
         VertexAttrib2fv_base(idx, arr.Length(), arr.Data());
     }
@@ -932,7 +977,7 @@ public:
         VertexAttrib2fv_base(idx, arr.Length(), arr.Elements());
     }
 
-    void VertexAttrib3fv(GLuint idx, const dom::Float32Array &arr) {
+    void VertexAttrib3fv(GLuint idx, const dom::Float32Array& arr) {
         arr.ComputeLengthAndData();
         VertexAttrib3fv_base(idx, arr.Length(), arr.Data());
     }
@@ -940,7 +985,7 @@ public:
         VertexAttrib3fv_base(idx, arr.Length(), arr.Elements());
     }
 
-    void VertexAttrib4fv(GLuint idx, const dom::Float32Array &arr) {
+    void VertexAttrib4fv(GLuint idx, const dom::Float32Array& arr) {
         arr.ComputeLengthAndData();
         VertexAttrib4fv_base(idx, arr.Length(), arr.Data());
     }
@@ -961,28 +1006,32 @@ private:
     uint32_t mMaxFetchedVertices;
     uint32_t mMaxFetchedInstances;
 
-    inline void InvalidateBufferFetching()
-    {
+    inline void InvalidateBufferFetching() {
         mBufferFetchingIsVerified = false;
         mBufferFetchingHasPerVertex = false;
         mMaxFetchedVertices = 0;
         mMaxFetchedInstances = 0;
     }
 
-    bool DrawArrays_check(GLint first, GLsizei count, GLsizei primcount, const char* info);
+    bool DrawArrays_check(GLint first, GLsizei count, GLsizei primcount,
+                          const char* info);
     bool DrawElements_check(GLsizei count, GLenum type, WebGLintptr byteOffset,
                             GLsizei primcount, const char* info,
                             GLuint* out_upperBound);
     bool DrawInstanced_check(const char* info);
     void Draw_cleanup();
 
-    void VertexAttrib1fv_base(GLuint idx, uint32_t arrayLength, const GLfloat* ptr);
-    void VertexAttrib2fv_base(GLuint idx, uint32_t arrayLength, const GLfloat* ptr);
-    void VertexAttrib3fv_base(GLuint idx, uint32_t arrayLength, const GLfloat* ptr);
-    void VertexAttrib4fv_base(GLuint idx, uint32_t arrayLength, const GLfloat* ptr);
+    void VertexAttrib1fv_base(GLuint index, uint32_t arrayLength,
+                              const GLfloat* ptr);
+    void VertexAttrib2fv_base(GLuint index, uint32_t arrayLength,
+                              const GLfloat* ptr);
+    void VertexAttrib3fv_base(GLuint index, uint32_t arrayLength,
+                              const GLfloat* ptr);
+    void VertexAttrib4fv_base(GLuint index, uint32_t arrayLength,
+                              const GLfloat* ptr);
 
-    bool ValidateBufferFetching(const char *info);
-    bool BindArrayAttribToLocation0(WebGLProgram *program);
+    bool ValidateBufferFetching(const char* info);
+    bool BindArrayAttribToLocation0(WebGLProgram* prog);
 
 // -----------------------------------------------------------------------------
 // PROTECTED
@@ -1003,16 +1052,17 @@ protected:
     bool DoFakeVertexAttrib0(GLuint vertexCount);
     void UndoFakeVertexAttrib0();
 
-    static CheckedUint32 GetImageSize(GLsizei height,
-                                      GLsizei width,
-                                      GLsizei depth,
-                                      uint32_t pixelSize,
+    static CheckedUint32 GetImageSize(GLsizei height, GLsizei width,
+                                      GLsizei depth, uint32_t pixelSize,
                                       uint32_t alignment);
 
-    virtual JS::Value GetTexParameterInternal(const TexTarget& target, GLenum pname);
+    virtual JS::Value GetTexParameterInternal(const TexTarget& target,
+                                              GLenum pname);
 
     // Returns x rounded to the next highest multiple of y.
-    static CheckedUint32 RoundedToNextMultipleOf(CheckedUint32 x, CheckedUint32 y) {
+    static CheckedUint32 RoundedToNextMultipleOf(CheckedUint32 x,
+                                                 CheckedUint32 y)
+    {
         return ((x + y - 1) / y) * y;
     }
 
@@ -1095,8 +1145,7 @@ protected:
 
     // -------------------------------------------------------------------------
     // WebGL extensions (implemented in WebGLContextExtensions.cpp)
-    typedef EnumeratedArray> ExtensionsArrayType;
 
     ExtensionsArrayType mExtensions;
@@ -1112,7 +1161,7 @@ protected:
     bool IsExtensionEnabled(WebGLExtensionID ext) const;
 
     // returns true if the extension is supported for this JSContext (this decides what getSupportedExtensions exposes)
-    bool IsExtensionSupported(JSContext *cx, WebGLExtensionID ext) const;
+    bool IsExtensionSupported(JSContext* cx, WebGLExtensionID ext) const;
     bool IsExtensionSupported(WebGLExtensionID ext) const;
 
     static const char* GetExtensionString(WebGLExtensionID ext);
@@ -1126,33 +1175,30 @@ protected:
 
     bool InitWebGL2();
 
-
     // -------------------------------------------------------------------------
     // Validation functions (implemented in WebGLContextValidate.cpp)
     bool CreateOffscreenGL(bool forceEnabled);
     bool InitAndValidateGL();
     bool ResizeBackbuffer(uint32_t width, uint32_t height);
-    bool ValidateBlendEquationEnum(GLenum cap, const char *info);
-    bool ValidateBlendFuncDstEnum(GLenum mode, const char *info);
-    bool ValidateBlendFuncSrcEnum(GLenum mode, const char *info);
-    bool ValidateBlendFuncEnumsCompatibility(GLenum sfactor, GLenum dfactor, const char *info);
-    bool ValidateTextureTargetEnum(GLenum target, const char *info);
-    bool ValidateComparisonEnum(GLenum target, const char *info);
-    bool ValidateStencilOpEnum(GLenum action, const char *info);
-    bool ValidateFaceEnum(GLenum face, const char *info);
-    bool ValidateTexInputData(GLenum type,
-                              js::Scalar::Type jsArrayType,
-                              WebGLTexImageFunc func,
-                              WebGLTexDimensions dims);
-    bool ValidateDrawModeEnum(GLenum mode, const char *info);
+    bool ValidateBlendEquationEnum(GLenum cap, const char* info);
+    bool ValidateBlendFuncDstEnum(GLenum mode, const char* info);
+    bool ValidateBlendFuncSrcEnum(GLenum mode, const char* info);
+    bool ValidateBlendFuncEnumsCompatibility(GLenum sfactor, GLenum dfactor,
+                                             const char* info);
+    bool ValidateTextureTargetEnum(GLenum target, const char* info);
+    bool ValidateComparisonEnum(GLenum target, const char* info);
+    bool ValidateStencilOpEnum(GLenum action, const char* info);
+    bool ValidateFaceEnum(GLenum face, const char* info);
+    bool ValidateTexInputData(GLenum type, js::Scalar::Type jsArrayType,
+                              WebGLTexImageFunc func, WebGLTexDimensions dims);
+    bool ValidateDrawModeEnum(GLenum mode, const char* info);
     bool ValidateStencilParamsForDrawCall();
 
-    bool ValidateGLSLVariableName(const nsAString& name, const char *info);
+    bool ValidateGLSLVariableName(const nsAString& name, const char* info);
     bool ValidateGLSLCharacter(char16_t c);
-    bool ValidateGLSLString(const nsAString& string, const char *info);
+    bool ValidateGLSLString(const nsAString& string, const char* info);
 
-    bool ValidateCopyTexImage(GLenum internalformat,
-                              WebGLTexImageFunc func,
+    bool ValidateCopyTexImage(GLenum internalFormat, WebGLTexImageFunc func,
                               WebGLTexDimensions dims);
 
     bool ValidateSamplerParameterName(GLenum pname, const char* info);
@@ -1163,19 +1209,14 @@ protected:
                           GLint xoffset, GLint yoffset, GLint zoffset,
                           GLint width, GLint height, GLint depth,
                           GLint border, GLenum format, GLenum type,
-                          WebGLTexImageFunc func,
-                          WebGLTexDimensions dims);
-    bool ValidateTexImageTarget(GLenum target,
-                                WebGLTexImageFunc func,
+                          WebGLTexImageFunc func, WebGLTexDimensions dims);
+    bool ValidateTexImageTarget(GLenum texImageTarget, WebGLTexImageFunc func,
                                 WebGLTexDimensions dims);
-    bool ValidateTexImageFormat(GLenum internalformat,
-                                WebGLTexImageFunc func,
+    bool ValidateTexImageFormat(GLenum internalFormat, WebGLTexImageFunc func,
                                 WebGLTexDimensions dims);
-    bool ValidateTexImageType(GLenum type,
-                              WebGLTexImageFunc func,
+    bool ValidateTexImageType(GLenum type, WebGLTexImageFunc func,
                               WebGLTexDimensions dims);
-    bool ValidateTexImageFormatAndType(GLenum format,
-                                       GLenum type,
+    bool ValidateTexImageFormatAndType(GLenum format, GLenum type,
                                        WebGLTexImageFunc func,
                                        WebGLTexDimensions dims);
     bool ValidateCompTexImageInternalFormat(GLenum format,
@@ -1184,24 +1225,20 @@ protected:
     bool ValidateCopyTexImageInternalFormat(GLenum format,
                                             WebGLTexImageFunc func,
                                             WebGLTexDimensions dims);
-    bool ValidateTexImageSize(TexImageTarget target, GLint level,
+    bool ValidateTexImageSize(TexImageTarget texImageTarget, GLint level,
                               GLint width, GLint height, GLint depth,
-                              WebGLTexImageFunc func,
-                              WebGLTexDimensions dims);
-    bool ValidateTexSubImageSize(GLint x, GLint y, GLint z,
-                                 GLsizei width, GLsizei height, GLsizei depth,
-                                 GLsizei baseWidth, GLsizei baseHeight, GLsizei baseDepth,
-                                 WebGLTexImageFunc func,
+                              WebGLTexImageFunc func, WebGLTexDimensions dims);
+    bool ValidateTexSubImageSize(GLint x, GLint y, GLint z, GLsizei width,
+                                 GLsizei height, GLsizei depth,
+                                 GLsizei baseWidth, GLsizei baseHeight,
+                                 GLsizei baseDepth, WebGLTexImageFunc func,
                                  WebGLTexDimensions dims);
-    bool ValidateCompTexImageSize(GLint level,
-                                  GLenum internalformat,
-                                  GLint xoffset, GLint yoffset,
-                                  GLsizei width, GLsizei height,
-                                  GLsizei levelWidth, GLsizei levelHeight,
-                                  WebGLTexImageFunc func,
+    bool ValidateCompTexImageSize(GLint level, GLenum internalFormat,
+                                  GLint xoffset, GLint yoffset, GLsizei width,
+                                  GLsizei height, GLsizei levelWidth,
+                                  GLsizei levelHeight, WebGLTexImageFunc func,
                                   WebGLTexDimensions dims);
-    bool ValidateCompTexImageDataSize(GLint level,
-                                      GLenum internalformat,
+    bool ValidateCompTexImageDataSize(GLint level, GLenum internalFormat,
                                       GLsizei width, GLsizei height,
                                       uint32_t byteLength,
                                       WebGLTexImageFunc func,
@@ -1214,114 +1251,112 @@ protected:
 
     // helpers
 
-    void TexImage2D_base(TexImageTarget target,
-                         GLint level,
-                         GLenum internalformat,
-                         GLsizei width, GLsizei height, GLsizei srcStrideOrZero, GLint border,
-                         GLenum format,
-                         GLenum type,
-                         void *data, uint32_t byteLength,
-                         js::Scalar::Type jsArrayType, // special value TypeMax used to mean no array
+    // If `isArrayType is TypeMax, it means no array.
+    void TexImage2D_base(TexImageTarget texImageTarget, GLint level,
+                         GLenum internalFormat, GLsizei width,
+                         GLsizei height, GLsizei srcStrideOrZero, GLint border,
+                         GLenum format, GLenum type, void* data,
+                         uint32_t byteLength, js::Scalar::Type jsArrayType,
                          WebGLTexelFormat srcFormat, bool srcPremultiplied);
-    void TexSubImage2D_base(TexImageTarget target, GLint level,
-                            GLint xoffset, GLint yoffset,
-                            GLsizei width, GLsizei height, GLsizei srcStrideOrZero,
-                            GLenum format,
-                            GLenum type,
-                            void *pixels, uint32_t byteLength,
-                            js::Scalar::Type jsArrayType, // special value TypeMax used to mean no array
+    void TexSubImage2D_base(TexImageTarget texImageTarget, GLint level,
+                            GLint xoffset, GLint yoffset, GLsizei width,
+                            GLsizei height, GLsizei srcStrideOrZero,
+                            GLenum format, GLenum type, void* pixels,
+                            uint32_t byteLength, js::Scalar::Type jsArrayType,
                             WebGLTexelFormat srcFormat, bool srcPremultiplied);
-    void TexParameter_base(GLenum target, GLenum pname,
-                           GLint *intParamPtr, GLfloat *floatParamPtr);
 
-    bool ConvertImage(size_t width, size_t height, size_t srcStride, size_t dstStride,
-                      const uint8_t* src, uint8_t *dst,
+    void TexParameter_base(GLenum target, GLenum pname,
+                           GLint* const out_intParam,
+                           GLfloat* const out_floatParam);
+
+    bool ConvertImage(size_t width, size_t height, size_t srcStride,
+                      size_t dstStride, const uint8_t* src, uint8_t* dst,
                       WebGLTexelFormat srcFormat, bool srcPremultiplied,
                       WebGLTexelFormat dstFormat, bool dstPremultiplied,
                       size_t dstTexelSize);
 
     template
-    nsLayoutUtils::SurfaceFromElementResult SurfaceFromElement(ElementType* aElement) {
-        MOZ_ASSERT(aElement);
-        uint32_t flags =
-             nsLayoutUtils::SFE_WANT_IMAGE_SURFACE;
+    nsLayoutUtils::SurfaceFromElementResult
+    SurfaceFromElement(ElementType* element) {
+        MOZ_ASSERT(element);
 
+        uint32_t flags = nsLayoutUtils::SFE_WANT_IMAGE_SURFACE;
         if (mPixelStoreColorspaceConversion == LOCAL_GL_NONE)
             flags |= nsLayoutUtils::SFE_NO_COLORSPACE_CONVERSION;
         if (!mPixelStorePremultiplyAlpha)
             flags |= nsLayoutUtils::SFE_PREFER_NO_PREMULTIPLY_ALPHA;
-        return nsLayoutUtils::SurfaceFromElement(aElement, flags);
-    }
-    template
-    nsLayoutUtils::SurfaceFromElementResult SurfaceFromElement(ElementType& aElement)
-    {
-      return SurfaceFromElement(&aElement);
+
+        return nsLayoutUtils::SurfaceFromElement(element, flags);
     }
 
-    nsresult SurfaceFromElementResultToImageSurface(nsLayoutUtils::SurfaceFromElementResult& res,
-                                                    RefPtr& imageOut,
-                                                    WebGLTexelFormat *format);
+    template
+    nsLayoutUtils::SurfaceFromElementResult
+    SurfaceFromElement(ElementType& element) {
+       return SurfaceFromElement(&element);
+    }
+
+    nsresult
+    SurfaceFromElementResultToImageSurface(nsLayoutUtils::SurfaceFromElementResult& res,
+                                           RefPtr& imageOut,
+                                           WebGLTexelFormat* format);
 
     void CopyTexSubImage2D_base(TexImageTarget texImageTarget,
-                                GLint level,
-                                TexInternalFormat internalformat,
-                                GLint xoffset,
-                                GLint yoffset,
-                                GLint x,
-                                GLint y,
-                                GLsizei width,
-                                GLsizei height,
-                                bool sub);
+                                GLint level, TexInternalFormat internalFormat,
+                                GLint xoffset, GLint yoffset, GLint x, GLint y,
+                                GLsizei width, GLsizei height, bool isSub);
 
-    // Returns false if aObject is null or not valid
+    // Returns false if `object` is null or not valid.
     template
-    bool ValidateObject(const char* info, ObjectType *aObject);
-    // Returns false if aObject is not valid.  Considers null to be valid.
+    bool ValidateObject(const char* info, ObjectType* object);
+
+    // Returns false if `object` is not valid.  Considers null to be valid.
     template
-    bool ValidateObjectAllowNull(const char* info, ObjectType *aObject);
-    // Returns false if aObject is not valid, but considers deleted
-    // objects and null objects valid.
+    bool ValidateObjectAllowNull(const char* info, ObjectType* object);
+
+    // Returns false if `object` is not valid, but considers deleted objects and
+    // null objects valid.
     template
-    bool ValidateObjectAllowDeletedOrNull(const char* info, ObjectType *aObject);
-    // Returns false if aObject is null or not valid, but considers deleted
+    bool ValidateObjectAllowDeletedOrNull(const char* info, ObjectType* object);
+
+    // Returns false if `object` is null or not valid, but considers deleted
     // objects valid.
     template
-    bool ValidateObjectAllowDeleted(const char* info, ObjectType *aObject);
+    bool ValidateObjectAllowDeleted(const char* info, ObjectType* object);
+
 private:
-    // Like ValidateObject, but only for cases when aObject is known
-    // to not be null already.
+    // Like ValidateObject, but only for cases when `object` is known to not be
+    // null already.
     template
-    bool ValidateObjectAssumeNonNull(const char* info, ObjectType *aObject);
+    bool ValidateObjectAssumeNonNull(const char* info, ObjectType* object);
 
 protected:
     int32_t MaxTextureSizeForTarget(TexTarget target) const {
-        return (target == LOCAL_GL_TEXTURE_2D) ? mGLMaxTextureSize : mGLMaxCubeMapTextureSize;
+        return (target == LOCAL_GL_TEXTURE_2D) ? mGLMaxTextureSize
+                                               : mGLMaxCubeMapTextureSize;
     }
 
-    int32_t MaxTextureLevelForTexImageTarget(TexImageTarget texImageTarget) const {
+    int32_t
+    MaxTextureLevelForTexImageTarget(TexImageTarget texImageTarget) const {
         const TexTarget target = TexImageTargetToTexTarget(texImageTarget);
-        return (target == LOCAL_GL_TEXTURE_2D) ? mGLMaxTextureSizeLog2 : mGLMaxCubeMapTextureSizeLog2;
+        return (target == LOCAL_GL_TEXTURE_2D) ? mGLMaxTextureSizeLog2
+                                               : mGLMaxCubeMapTextureSizeLog2;
     }
 
-    /** like glBufferData but if the call may change the buffer size, checks any GL error generated
-     * by this glBufferData call and returns it */
-    GLenum CheckedBufferData(GLenum target,
-                             GLsizeiptr size,
-                             const GLvoid *data,
+    /** Like glBufferData, but if the call may change the buffer size, checks
+     *  any GL error generated by this glBufferData call and returns it.
+     */
+    GLenum CheckedBufferData(GLenum target, GLsizeiptr size, const GLvoid* data,
                              GLenum usage);
-    /** like glTexImage2D but if the call may change the texture size, checks any GL error generated
-     * by this glTexImage2D call and returns it */
-    GLenum CheckedTexImage2D(TexImageTarget texImageTarget,
-                             GLint level,
-                             TexInternalFormat internalFormat,
-                             GLsizei width,
-                             GLsizei height,
-                             GLint border,
-                             TexFormat format,
-                             TexType type,
-                             const GLvoid *data);
 
-    void ForceLoseContext(bool simulateLosing = false);
+    /** Like glTexImage2D, but if the call may change the texture size, checks
+     * any GL error generated by this glTexImage2D call and returns it.
+     */
+    GLenum CheckedTexImage2D(TexImageTarget texImageTarget, GLint level,
+                             TexInternalFormat internalFormat, GLsizei width,
+                             GLsizei height, GLint border, TexFormat format,
+                             TexType type, const GLvoid* data);
+
+    void ForceLoseContext(bool simulateLoss = false);
     void ForceRestoreContext();
 
     nsTArray > mBound2DTextures;
@@ -1351,14 +1386,16 @@ protected:
     WebGLRefPtr mDefaultVertexArray;
 
     // PixelStore parameters
-    uint32_t mPixelStorePackAlignment, mPixelStoreUnpackAlignment, mPixelStoreColorspaceConversion;
-    bool mPixelStoreFlipY, mPixelStorePremultiplyAlpha;
+    uint32_t mPixelStorePackAlignment;
+    uint32_t mPixelStoreUnpackAlignment;
+    uint32_t mPixelStoreColorspaceConversion;
+    bool mPixelStoreFlipY;
+    bool mPixelStorePremultiplyAlpha;
 
     WebGLContextFakeBlackStatus mFakeBlackStatus;
 
-    class FakeBlackTexture
-    {
-        gl::GLContext* mGL;
+    class FakeBlackTexture {
+        gl::GLContext* const mGL;
         GLuint mGLName;
 
     public:
@@ -1367,16 +1404,16 @@ protected:
         GLuint GLName() const { return mGLName; }
     };
 
-    UniquePtr mBlackOpaqueTexture2D,
-                                mBlackOpaqueTextureCubeMap,
-                                mBlackTransparentTexture2D,
-                                mBlackTransparentTextureCubeMap;
+    UniquePtr mBlackOpaqueTexture2D;
+    UniquePtr mBlackOpaqueTextureCubeMap;
+    UniquePtr mBlackTransparentTexture2D;
+    UniquePtr mBlackTransparentTextureCubeMap;
 
-    void BindFakeBlackTexturesHelper(
-        GLenum target,
-        const nsTArray >& boundTexturesArray,
-        UniquePtr & opaqueTextureScopedPtr,
-        UniquePtr & transparentTextureScopedPtr);
+    void
+    BindFakeBlackTexturesHelper(GLenum target,
+                                const nsTArray >& boundTexturesArray,
+                                UniquePtr& opaqueTextureScopedPtr,
+                                UniquePtr& transparentTextureScopedPtr);
 
     GLfloat mVertexAttrib0Vector[4];
     GLfloat mFakeVertexAttrib0BufferObjectVector[4];
@@ -1384,9 +1421,12 @@ protected:
     GLuint mFakeVertexAttrib0BufferObject;
     WebGLVertexAttrib0Status mFakeVertexAttrib0BufferStatus;
 
-    GLint mStencilRefFront, mStencilRefBack;
-    GLuint mStencilValueMaskFront, mStencilValueMaskBack,
-           mStencilWriteMaskFront, mStencilWriteMaskBack;
+    GLint mStencilRefFront;
+    GLint mStencilRefBack;
+    GLuint mStencilValueMaskFront;
+    GLuint mStencilValueMaskBack;
+    GLuint mStencilWriteMaskFront;
+    GLuint mStencilWriteMaskBack;
     realGLboolean mColorWriteMask[4];
     realGLboolean mDepthWriteMask;
     GLfloat mColorClearValue[4];
@@ -1428,7 +1468,7 @@ protected:
                    webgl.mColorWriteMask[3] != false;
         }
 
-        explicit ScopedMaskWorkaround(WebGLContext& aWebgl);
+        explicit ScopedMaskWorkaround(WebGLContext& webgl);
 
         ~ScopedMaskWorkaround();
     };
@@ -1437,9 +1477,11 @@ protected:
     void UpdateLastUseIndex();
 
     template 
-    JS::Value WebGLObjectAsJSValue(JSContext *cx, const WebGLObjectType *, ErrorResult& rv) const;
+    JS::Value WebGLObjectAsJSValue(JSContext* cx, const WebGLObjectType*,
+                                   ErrorResult& rv) const;
     template 
-    JSObject* WebGLObjectAsJSObject(JSContext *cx, const WebGLObjectType *, ErrorResult& rv) const;
+    JSObject* WebGLObjectAsJSObject(JSContext* cx, const WebGLObjectType*,
+                                    ErrorResult& rv) const;
 
 #ifdef XP_MACOSX
     // see bug 713305. This RAII helper guarantees that we're on the discrete GPU, during its lifetime
@@ -1454,8 +1496,8 @@ protected:
 
 public:
     // console logging helpers
-    void GenerateWarning(const char *fmt, ...);
-    void GenerateWarning(const char *fmt, va_list ap);
+    void GenerateWarning(const char* fmt, ...);
+    void GenerateWarning(const char* fmt, va_list ap);
 
     friend class WebGLTexture;
     friend class WebGLFramebuffer;
@@ -1473,9 +1515,9 @@ public:
 
 // used by DOM bindings in conjunction with GetParentObject
 inline nsISupports*
-ToSupports(WebGLContext* context)
+ToSupports(WebGLContext* webgl)
 {
-  return static_cast(context);
+    return static_cast(webgl);
 }
 
 /**
@@ -1485,9 +1527,9 @@ ToSupports(WebGLContext* context)
 template
 inline bool
 WebGLContext::ValidateObjectAllowDeletedOrNull(const char* info,
-                                               ObjectType *aObject)
+                                               ObjectType* object)
 {
-    if (aObject && !aObject->IsCompatibleWithContext(this)) {
+    if (object && !object->IsCompatibleWithContext(this)) {
         ErrorInvalidOperation("%s: object from different WebGL context "
                               "(or older generation of this one) "
                               "passed as argument", info);
@@ -1499,14 +1541,14 @@ WebGLContext::ValidateObjectAllowDeletedOrNull(const char* info,
 
 template
 inline bool
-WebGLContext::ValidateObjectAssumeNonNull(const char* info, ObjectType *aObject)
+WebGLContext::ValidateObjectAssumeNonNull(const char* info, ObjectType* object)
 {
-    MOZ_ASSERT(aObject);
+    MOZ_ASSERT(object);
 
-    if (!ValidateObjectAllowDeletedOrNull(info, aObject))
+    if (!ValidateObjectAllowDeletedOrNull(info, object))
         return false;
 
-    if (aObject->IsDeleted()) {
+    if (object->IsDeleted()) {
         ErrorInvalidValue("%s: deleted object passed as argument", info);
         return false;
     }
@@ -1516,37 +1558,36 @@ WebGLContext::ValidateObjectAssumeNonNull(const char* info, ObjectType *aObject)
 
 template
 inline bool
-WebGLContext::ValidateObjectAllowNull(const char* info, ObjectType *aObject)
+WebGLContext::ValidateObjectAllowNull(const char* info, ObjectType* object)
 {
-    if (!aObject) {
+    if (!object)
         return true;
-    }
 
-    return ValidateObjectAssumeNonNull(info, aObject);
+    return ValidateObjectAssumeNonNull(info, object);
 }
 
 template
 inline bool
-WebGLContext::ValidateObjectAllowDeleted(const char* info, ObjectType *aObject)
+WebGLContext::ValidateObjectAllowDeleted(const char* info, ObjectType* object)
 {
-    if (!aObject) {
+    if (!object) {
         ErrorInvalidValue("%s: null object passed as argument", info);
         return false;
     }
 
-    return ValidateObjectAllowDeletedOrNull(info, aObject);
+    return ValidateObjectAllowDeletedOrNull(info, object);
 }
 
 template
 inline bool
-WebGLContext::ValidateObject(const char* info, ObjectType *aObject)
+WebGLContext::ValidateObject(const char* info, ObjectType* object)
 {
-    if (!aObject) {
+    if (!object) {
         ErrorInvalidValue("%s: null object passed as argument", info);
         return false;
     }
 
-    return ValidateObjectAssumeNonNull(info, aObject);
+    return ValidateObjectAssumeNonNull(info, object);
 }
 
 // Listen visibilitychange and memory-pressure event for context lose/restore
@@ -1559,7 +1600,7 @@ public:
     NS_DECL_NSIOBSERVER
     NS_DECL_NSIDOMEVENTLISTENER
 
-    explicit WebGLObserver(WebGLContext* aContext);
+    explicit WebGLObserver(WebGLContext* webgl);
 
     void Destroy();
 
@@ -1572,7 +1613,7 @@ public:
 private:
     ~WebGLObserver();
 
-    WebGLContext* mContext;
+    WebGLContext* mWebGL;
 };
 
 } // namespace mozilla
diff --git a/dom/canvas/WebGLContextBuffers.cpp b/dom/canvas/WebGLContextBuffers.cpp
index 7a762f3c5f73..32013428555f 100644
--- a/dom/canvas/WebGLContextBuffers.cpp
+++ b/dom/canvas/WebGLContextBuffers.cpp
@@ -4,15 +4,15 @@
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "WebGLContext.h"
+
 #include "GLContext.h"
 #include "WebGLBuffer.h"
 #include "WebGLVertexArray.h"
 
-using namespace mozilla;
-using namespace mozilla::dom;
+namespace mozilla {
 
 void
-WebGLContext::BindBuffer(GLenum target, WebGLBuffer *buffer)
+WebGLContext::BindBuffer(GLenum target, WebGLBuffer* buffer)
 {
     if (IsContextLost())
         return;
@@ -24,17 +24,18 @@ WebGLContext::BindBuffer(GLenum target, WebGLBuffer *buffer)
     if (buffer && buffer->IsDeleted())
         return;
 
-    WebGLRefPtr* bufferSlot = GetBufferSlotByTarget(target, "bindBuffer");
-
-    if (!bufferSlot) {
+    WebGLRefPtr* bufferSlot = GetBufferSlotByTarget(target,
+                                                                 "bindBuffer");
+    if (!bufferSlot)
         return;
-    }
 
     if (buffer) {
         if (!buffer->HasEverBeenBound()) {
             buffer->BindTo(target);
         } else if (target != buffer->Target()) {
-            return ErrorInvalidOperation("bindBuffer: buffer already bound to a different target");
+            ErrorInvalidOperation("bindBuffer: Buffer already bound to a"
+                                  " different target.");
+            return;
         }
     }
 
@@ -59,21 +60,25 @@ WebGLContext::BindBufferBase(GLenum target, GLuint index, WebGLBuffer* buffer)
         return;
     }
 
-    WebGLRefPtr* indexedBufferSlot = GetBufferSlotByTargetIndexed(target, index, "bindBufferBase");
-
-    if (!indexedBufferSlot) {
+    WebGLRefPtr* indexedBufferSlot;
+    indexedBufferSlot = GetBufferSlotByTargetIndexed(target, index,
+                                                     "bindBufferBase");
+    if (!indexedBufferSlot)
         return;
-    }
 
     if (buffer) {
         if (!buffer->HasEverBeenBound())
             buffer->BindTo(target);
 
-        if (target != buffer->Target())
-            return ErrorInvalidOperation("bindBuffer: buffer already bound to a different target");
+        if (target != buffer->Target()) {
+            ErrorInvalidOperation("bindBuffer: Buffer already bound to a"
+                                  " different target.");
+            return;
+        }
     }
 
-    WebGLRefPtr* bufferSlot = GetBufferSlotByTarget(target, "bindBuffer");
+    WebGLRefPtr* bufferSlot = GetBufferSlotByTarget(target,
+                                                                 "bindBufferBase");
 
     MOZ_ASSERT(bufferSlot, "GetBufferSlotByTarget(Indexed) mismatch");
 
@@ -99,18 +104,21 @@ WebGLContext::BindBufferRange(GLenum target, GLuint index, WebGLBuffer* buffer,
     if (buffer && buffer->IsDeleted())
         return;
 
-    WebGLRefPtr* indexedBufferSlot = GetBufferSlotByTargetIndexed(target, index, "bindBufferBase");
-
-    if (!indexedBufferSlot) {
+    WebGLRefPtr* indexedBufferSlot;
+    indexedBufferSlot = GetBufferSlotByTargetIndexed(target, index,
+                                                     "bindBufferRange");
+    if (!indexedBufferSlot)
         return;
-    }
 
     if (buffer) {
         if (!buffer->HasEverBeenBound())
             buffer->BindTo(target);
 
-        if (target != buffer->Target())
-            return ErrorInvalidOperation("bindBuffer: buffer already bound to a different target");
+        if (target != buffer->Target()) {
+            ErrorInvalidOperation("bindBuffer: Buffer already bound to a"
+                                  " different target.");
+            return;
+        }
 
         CheckedInt checked_neededByteLength = CheckedInt(offset) + size;
         if (!checked_neededByteLength.isValid() ||
@@ -120,7 +128,8 @@ WebGLContext::BindBufferRange(GLenum target, GLuint index, WebGLBuffer* buffer,
         }
     }
 
-    WebGLRefPtr* bufferSlot = GetBufferSlotByTarget(target, "bindBuffer");
+    WebGLRefPtr* bufferSlot = GetBufferSlotByTarget(target,
+                                                                 "BindBufferRange");
 
     MOZ_ASSERT(bufferSlot, "GetBufferSlotByTarget(Indexed) mismatch");
 
@@ -129,21 +138,20 @@ WebGLContext::BindBufferRange(GLenum target, GLuint index, WebGLBuffer* buffer,
 
     MakeContextCurrent();
 
-    gl->fBindBufferRange(target, index, buffer ? buffer->GLName() : 0, offset, size);
+    gl->fBindBufferRange(target, index, buffer ? buffer->GLName() : 0, offset,
+                         size);
 }
 
 void
-WebGLContext::BufferData(GLenum target, WebGLsizeiptr size,
-                         GLenum usage)
+WebGLContext::BufferData(GLenum target, WebGLsizeiptr size, GLenum usage)
 {
     if (IsContextLost())
         return;
 
-    WebGLRefPtr* bufferSlot = GetBufferSlotByTarget(target, "bufferData");
-
-    if (!bufferSlot) {
+    WebGLRefPtr* bufferSlot = GetBufferSlotByTarget(target,
+                                                                 "bufferData");
+    if (!bufferSlot)
         return;
-    }
 
     if (size < 0)
         return ErrorInvalidValue("bufferData: negative size");
@@ -182,7 +190,7 @@ WebGLContext::BufferData(GLenum target, WebGLsizeiptr size,
 
 void
 WebGLContext::BufferData(GLenum target,
-                         const Nullable &maybeData,
+                         const dom::Nullable& maybeData,
                          GLenum usage)
 {
     if (IsContextLost())
@@ -193,13 +201,12 @@ WebGLContext::BufferData(GLenum target,
         return ErrorInvalidValue("bufferData: null object passed");
     }
 
-    WebGLRefPtr* bufferSlot = GetBufferSlotByTarget(target, "bufferData");
-
-    if (!bufferSlot) {
+    WebGLRefPtr* bufferSlot = GetBufferSlotByTarget(target,
+                                                                 "bufferData");
+    if (!bufferSlot)
         return;
-    }
 
-    const ArrayBuffer& data = maybeData.Value();
+    const dom::ArrayBuffer& data = maybeData.Value();
     data.ComputeLengthAndData();
 
     // Careful: data.Length() could conceivably be any uint32_t, but GLsizeiptr
@@ -226,23 +233,21 @@ WebGLContext::BufferData(GLenum target,
     }
 
     boundBuffer->SetByteLength(data.Length());
-    if (!boundBuffer->ElementArrayCacheBufferData(data.Data(), data.Length())) {
+    if (!boundBuffer->ElementArrayCacheBufferData(data.Data(), data.Length()))
         return ErrorOutOfMemory("bufferData: out of memory");
-    }
 }
 
 void
-WebGLContext::BufferData(GLenum target, const ArrayBufferView& data,
+WebGLContext::BufferData(GLenum target, const dom::ArrayBufferView& data,
                          GLenum usage)
 {
     if (IsContextLost())
         return;
 
-    WebGLRefPtr* bufferSlot = GetBufferSlotByTarget(target, "bufferSubData");
-
-    if (!bufferSlot) {
+    WebGLRefPtr* bufferSlot = GetBufferSlotByTarget(target,
+                                                                 "bufferSubData");
+    if (!bufferSlot)
         return;
-    }
 
     if (!ValidateBufferUsageEnum(usage, "bufferData: usage"))
         return;
@@ -269,14 +274,13 @@ WebGLContext::BufferData(GLenum target, const ArrayBufferView& data,
     }
 
     boundBuffer->SetByteLength(data.Length());
-    if (!boundBuffer->ElementArrayCacheBufferData(data.Data(), data.Length())) {
+    if (!boundBuffer->ElementArrayCacheBufferData(data.Data(), data.Length()))
         return ErrorOutOfMemory("bufferData: out of memory");
-    }
 }
 
 void
 WebGLContext::BufferSubData(GLenum target, WebGLsizeiptr byteOffset,
-                            const Nullable &maybeData)
+                            const dom::Nullable& maybeData)
 {
     if (IsContextLost())
         return;
@@ -286,11 +290,10 @@ WebGLContext::BufferSubData(GLenum target, WebGLsizeiptr byteOffset,
         return;
     }
 
-    WebGLRefPtr* bufferSlot = GetBufferSlotByTarget(target, "bufferSubData");
-
-    if (!bufferSlot) {
+    WebGLRefPtr* bufferSlot = GetBufferSlotByTarget(target,
+                                                                 "bufferSubData");
+    if (!bufferSlot)
         return;
-    }
 
     if (byteOffset < 0)
         return ErrorInvalidValue("bufferSubData: negative offset");
@@ -300,36 +303,42 @@ WebGLContext::BufferSubData(GLenum target, WebGLsizeiptr byteOffset,
     if (!boundBuffer)
         return ErrorInvalidOperation("bufferData: no buffer bound!");
 
-    const ArrayBuffer& data = maybeData.Value();
+    const dom::ArrayBuffer& data = maybeData.Value();
     data.ComputeLengthAndData();
 
     CheckedInt checked_neededByteLength = CheckedInt(byteOffset) + data.Length();
-    if (!checked_neededByteLength.isValid())
-        return ErrorInvalidValue("bufferSubData: integer overflow computing the needed byte length");
+    if (!checked_neededByteLength.isValid()) {
+        ErrorInvalidValue("bufferSubData: Integer overflow computing the needed"
+                          " byte length.");
+        return;
+    }
 
-    if (checked_neededByteLength.value() > boundBuffer->ByteLength())
-        return ErrorInvalidValue("bufferSubData: not enough data - operation requires %d bytes, but buffer only has %d bytes",
-                                 checked_neededByteLength.value(), boundBuffer->ByteLength());
+    if (checked_neededByteLength.value() > boundBuffer->ByteLength()) {
+        ErrorInvalidValue("bufferSubData: Not enough data. Operation requires"
+                          " %d bytes, but buffer only has %d bytes.",
+                          checked_neededByteLength.value(),
+                          boundBuffer->ByteLength());
+        return;
+    }
+
+    boundBuffer->ElementArrayCacheBufferSubData(byteOffset, data.Data(),
+                                                data.Length());
 
     MakeContextCurrent();
-
-    boundBuffer->ElementArrayCacheBufferSubData(byteOffset, data.Data(), data.Length());
-
     gl->fBufferSubData(target, byteOffset, data.Length(), data.Data());
 }
 
 void
 WebGLContext::BufferSubData(GLenum target, WebGLsizeiptr byteOffset,
-                            const ArrayBufferView& data)
+                            const dom::ArrayBufferView& data)
 {
     if (IsContextLost())
         return;
 
-    WebGLRefPtr* bufferSlot = GetBufferSlotByTarget(target, "bufferSubData");
-
-    if (!bufferSlot) {
+    WebGLRefPtr* bufferSlot = GetBufferSlotByTarget(target,
+                                                                 "bufferSubData");
+    if (!bufferSlot)
         return;
-    }
 
     if (byteOffset < 0)
         return ErrorInvalidValue("bufferSubData: negative offset");
@@ -342,14 +351,22 @@ WebGLContext::BufferSubData(GLenum target, WebGLsizeiptr byteOffset,
     data.ComputeLengthAndData();
 
     CheckedInt checked_neededByteLength = CheckedInt(byteOffset) + data.Length();
-    if (!checked_neededByteLength.isValid())
-        return ErrorInvalidValue("bufferSubData: integer overflow computing the needed byte length");
+    if (!checked_neededByteLength.isValid()) {
+        ErrorInvalidValue("bufferSubData: Integer overflow computing the needed"
+                          " byte length.");
+        return;
+    }
 
-    if (checked_neededByteLength.value() > boundBuffer->ByteLength())
-        return ErrorInvalidValue("bufferSubData: not enough data -- operation requires %d bytes, but buffer only has %d bytes",
-                                 checked_neededByteLength.value(), boundBuffer->ByteLength());
+    if (checked_neededByteLength.value() > boundBuffer->ByteLength()) {
+        ErrorInvalidValue("bufferSubData: Not enough data. Operation requires"
+                          " %d bytes, but buffer only has %d bytes.",
+                          checked_neededByteLength.value(),
+                          boundBuffer->ByteLength());
+        return;
+    }
 
-    boundBuffer->ElementArrayCacheBufferSubData(byteOffset, data.Data(), data.Length());
+    boundBuffer->ElementArrayCacheBufferSubData(byteOffset, data.Data(),
+                                                data.Length());
 
     MakeContextCurrent();
     gl->fBufferSubData(target, byteOffset, data.Length(), data.Data());
@@ -370,7 +387,7 @@ WebGLContext::CreateBuffer()
 }
 
 void
-WebGLContext::DeleteBuffer(WebGLBuffer *buffer)
+WebGLContext::DeleteBuffer(WebGLBuffer* buffer)
 {
     if (IsContextLost())
         return;
@@ -381,10 +398,8 @@ WebGLContext::DeleteBuffer(WebGLBuffer *buffer)
     if (!buffer || buffer->IsDeleted())
         return;
 
-    if (mBoundArrayBuffer == buffer) {
-        BindBuffer(LOCAL_GL_ARRAY_BUFFER,
-                   static_cast(nullptr));
-    }
+    if (mBoundArrayBuffer == buffer)
+        BindBuffer(LOCAL_GL_ARRAY_BUFFER, static_cast(nullptr));
 
     if (mBoundVertexArray->mElementArrayBuffer == buffer) {
         BindBuffer(LOCAL_GL_ELEMENT_ARRAY_BUFFER,
@@ -392,15 +407,18 @@ WebGLContext::DeleteBuffer(WebGLBuffer *buffer)
     }
 
     for (int32_t i = 0; i < mGLMaxVertexAttribs; i++) {
-        if (mBoundVertexArray->HasAttrib(i) && mBoundVertexArray->mAttribs[i].buf == buffer)
+        if (mBoundVertexArray->HasAttrib(i) &&
+            mBoundVertexArray->mAttribs[i].buf == buffer)
+        {
             mBoundVertexArray->mAttribs[i].buf = nullptr;
+        }
     }
 
     buffer->RequestDelete();
 }
 
 bool
-WebGLContext::IsBuffer(WebGLBuffer *buffer)
+WebGLContext::IsBuffer(WebGLBuffer* buffer)
 {
     if (IsContextLost())
         return false;
@@ -411,86 +429,89 @@ WebGLContext::IsBuffer(WebGLBuffer *buffer)
 }
 
 bool
-WebGLContext::ValidateBufferUsageEnum(GLenum target, const char *infos)
+WebGLContext::ValidateBufferUsageEnum(GLenum target, const char* info)
 {
     switch (target) {
-        case LOCAL_GL_STREAM_DRAW:
-        case LOCAL_GL_STATIC_DRAW:
-        case LOCAL_GL_DYNAMIC_DRAW:
-            return true;
-        default:
-            break;
+    case LOCAL_GL_STREAM_DRAW:
+    case LOCAL_GL_STATIC_DRAW:
+    case LOCAL_GL_DYNAMIC_DRAW:
+        return true;
+    default:
+        break;
     }
 
-    ErrorInvalidEnumInfo(infos, target);
+    ErrorInvalidEnumInfo(info, target);
     return false;
 }
 
 WebGLRefPtr*
-WebGLContext::GetBufferSlotByTarget(GLenum target, const char* infos)
+WebGLContext::GetBufferSlotByTarget(GLenum target, const char* info)
 {
     switch (target) {
-        case LOCAL_GL_ARRAY_BUFFER:
-            return &mBoundArrayBuffer;
+    case LOCAL_GL_ARRAY_BUFFER:
+        return &mBoundArrayBuffer;
 
-        case LOCAL_GL_ELEMENT_ARRAY_BUFFER:
-            return &mBoundVertexArray->mElementArrayBuffer;
+    case LOCAL_GL_ELEMENT_ARRAY_BUFFER:
+        return &mBoundVertexArray->mElementArrayBuffer;
 
-        case LOCAL_GL_TRANSFORM_FEEDBACK_BUFFER:
-            if (!IsWebGL2()) {
-                break;
-            }
-            return &mBoundTransformFeedbackBuffer;
-
-        default:
+    case LOCAL_GL_TRANSFORM_FEEDBACK_BUFFER:
+        if (!IsWebGL2()) {
             break;
+        }
+        return &mBoundTransformFeedbackBuffer;
+
+    default:
+        break;
     }
 
-    ErrorInvalidEnum("%s: target: invalid enum value 0x%x", infos, target);
+    ErrorInvalidEnum("%s: target: Invalid enum value 0x%x.", info, target);
     return nullptr;
 }
 
 WebGLRefPtr*
-WebGLContext::GetBufferSlotByTargetIndexed(GLenum target, GLuint index, const char* infos)
+WebGLContext::GetBufferSlotByTargetIndexed(GLenum target, GLuint index,
+                                           const char* info)
 {
     switch (target) {
-        case LOCAL_GL_TRANSFORM_FEEDBACK_BUFFER:
-            if (index >= mGLMaxTransformFeedbackSeparateAttribs) {
-                ErrorInvalidValue("%s: index should be less than MAX_TRANSFORM_FEEDBACK_SEPARATE_ATTRIBS", infos, index);
-                return nullptr;
-            }
-            return nullptr; // See bug 903594
+    case LOCAL_GL_TRANSFORM_FEEDBACK_BUFFER:
+        if (index >= mGLMaxTransformFeedbackSeparateAttribs) {
+            ErrorInvalidValue("%s: `index` should be less than"
+                              " MAX_TRANSFORM_FEEDBACK_SEPARATE_ATTRIBS.", info,
+                              index);
+            return nullptr;
+        }
+        return nullptr; // See bug 903594
 
-        default:
-            break;
+    default:
+        break;
     }
 
-    ErrorInvalidEnum("%s: target: invalid enum value 0x%x", infos, target);
+    ErrorInvalidEnum("%s: target: invalid enum value 0x%x", info, target);
     return nullptr;
 }
 
 GLenum
-WebGLContext::CheckedBufferData(GLenum target,
-                                GLsizeiptr size,
-                                const GLvoid *data,
-                                GLenum usage)
+WebGLContext::CheckedBufferData(GLenum target, GLsizeiptr size,
+                                const GLvoid* data, GLenum usage)
 {
 #ifdef XP_MACOSX
     // bug 790879
     if (gl->WorkAroundDriverBugs() &&
         int64_t(size) > INT32_MAX) // the cast avoids a potential always-true warning on 32bit
     {
-        GenerateWarning("Rejecting valid bufferData call with size %lu to avoid a Mac bug", size);
+        GenerateWarning("Rejecting valid bufferData call with size %lu to avoid"
+                        " a Mac bug", size);
         return LOCAL_GL_INVALID_VALUE;
     }
 #endif
-    WebGLBuffer *boundBuffer = nullptr;
+
+    WebGLBuffer* boundBuffer = nullptr;
     if (target == LOCAL_GL_ARRAY_BUFFER) {
         boundBuffer = mBoundArrayBuffer;
     } else if (target == LOCAL_GL_ELEMENT_ARRAY_BUFFER) {
         boundBuffer = mBoundVertexArray->mElementArrayBuffer;
     }
-    MOZ_ASSERT(boundBuffer != nullptr, "no buffer bound for this target");
+    MOZ_ASSERT(boundBuffer, "No buffer bound for this target.");
 
     bool sizeChanges = uint32_t(size) != boundBuffer->ByteLength();
     if (sizeChanges) {
@@ -503,3 +524,5 @@ WebGLContext::CheckedBufferData(GLenum target,
         return LOCAL_GL_NO_ERROR;
     }
 }
+
+} // namespace mozilla
diff --git a/dom/canvas/WebGLContextDraw.cpp b/dom/canvas/WebGLContextDraw.cpp
index 5c68dd751138..1cbd96c69b1a 100644
--- a/dom/canvas/WebGLContextDraw.cpp
+++ b/dom/canvas/WebGLContextDraw.cpp
@@ -408,7 +408,7 @@ void WebGLContext::Draw_cleanup()
  */
 
 bool
-WebGLContext::ValidateBufferFetching(const char *info)
+WebGLContext::ValidateBufferFetching(const char* info)
 {
 #ifdef DEBUG
     GLint currentProgram = 0;
@@ -418,9 +418,8 @@ WebGLContext::ValidateBufferFetching(const char *info)
                "WebGL: current program doesn't agree with GL state");
 #endif
 
-    if (mBufferFetchingIsVerified) {
+    if (mBufferFetchingIsVerified)
         return true;
-    }
 
     bool hasPerVertex = false;
     uint32_t maxVertices = UINT32_MAX;
@@ -735,7 +734,7 @@ WebGLContext::UnbindFakeBlackTextures()
     gl->fActiveTexture(LOCAL_GL_TEXTURE0 + mActiveTexture);
 }
 
-WebGLContext::FakeBlackTexture::FakeBlackTexture(GLContext *gl, TexTarget target, GLenum format)
+WebGLContext::FakeBlackTexture::FakeBlackTexture(GLContext* gl, TexTarget target, GLenum format)
     : mGL(gl)
     , mGLName(0)
 {
diff --git a/dom/canvas/WebGLContextExtensions.cpp b/dom/canvas/WebGLContextExtensions.cpp
index eb85ecebd098..4b6a18a6bcc0 100644
--- a/dom/canvas/WebGLContextExtensions.cpp
+++ b/dom/canvas/WebGLContextExtensions.cpp
@@ -12,16 +12,15 @@
 #include "mozilla/Preferences.h"
 #include "AccessCheck.h"
 
-using namespace mozilla;
-using namespace mozilla::gl;
+namespace mozilla {
 
-/* static */ const char*
+/*static*/ const char*
 WebGLContext::GetExtensionString(WebGLExtensionID ext)
 {
-    typedef EnumeratedArray
-            names_array_t;
-    static names_array_t sExtensionNamesEnumeratedArray;
+    typedef EnumeratedArray names_array_t;
 
+    static names_array_t sExtensionNamesEnumeratedArray;
     static bool initialized = false;
 
     if (!initialized) {
@@ -62,11 +61,13 @@ WebGLContext::GetExtensionString(WebGLExtensionID ext)
 }
 
 bool
-WebGLContext::IsExtensionEnabled(WebGLExtensionID ext) const {
+WebGLContext::IsExtensionEnabled(WebGLExtensionID ext) const
+{
     return mExtensions[ext];
 }
 
-bool WebGLContext::IsExtensionSupported(JSContext *cx, WebGLExtensionID ext) const
+bool WebGLContext::IsExtensionSupported(JSContext* cx,
+                                        WebGLExtensionID ext) const
 {
     bool allowPrivilegedExts = false;
 
@@ -81,13 +82,13 @@ bool WebGLContext::IsExtensionSupported(JSContext *cx, WebGLExtensionID ext) con
 
     if (allowPrivilegedExts) {
         switch (ext) {
-            case WebGLExtensionID::WEBGL_debug_renderer_info:
-                return true;
-            case WebGLExtensionID::WEBGL_debug_shaders:
-                return true;
-            default:
-                // For warnings-as-errors.
-                break;
+        case WebGLExtensionID::WEBGL_debug_renderer_info:
+            return true;
+        case WebGLExtensionID::WEBGL_debug_shaders:
+            return true;
+        default:
+            // For warnings-as-errors.
+            break;
         }
     }
 
@@ -96,84 +97,86 @@ bool WebGLContext::IsExtensionSupported(JSContext *cx, WebGLExtensionID ext) con
 
 bool WebGLContext::IsExtensionSupported(WebGLExtensionID ext) const
 {
-    if (mDisableExtensions) {
+    if (mDisableExtensions)
         return false;
-    }
 
     switch (ext) {
-        case WebGLExtensionID::EXT_blend_minmax:
-            return WebGLExtensionBlendMinMax::IsSupported(this);
-        case WebGLExtensionID::OES_element_index_uint:
-            return gl->IsSupported(GLFeature::element_index_uint);
-        case WebGLExtensionID::OES_standard_derivatives:
-            return gl->IsSupported(GLFeature::standard_derivatives);
-        case WebGLExtensionID::WEBGL_lose_context:
-            // We always support this extension.
+    case WebGLExtensionID::OES_vertex_array_object:
+    case WebGLExtensionID::WEBGL_lose_context:
+        // Always supported.
+        return true;
+
+    case WebGLExtensionID::EXT_blend_minmax:
+        return WebGLExtensionBlendMinMax::IsSupported(this);
+    case WebGLExtensionID::OES_element_index_uint:
+        return gl->IsSupported(gl::GLFeature::element_index_uint);
+    case WebGLExtensionID::OES_standard_derivatives:
+        return gl->IsSupported(gl::GLFeature::standard_derivatives);
+
+    case WebGLExtensionID::OES_texture_float:
+        return gl->IsSupported(gl::GLFeature::texture_float);
+    case WebGLExtensionID::OES_texture_float_linear:
+        return gl->IsSupported(gl::GLFeature::texture_float_linear);
+    case WebGLExtensionID::OES_texture_half_float:
+        // If we have Feature::texture_half_float, we must not be on ES2
+        // and need to translate HALF_FLOAT_OES -> HALF_FLOAT.  We do that
+        // right before making the relevant calls.
+        return gl->IsExtensionSupported(gl::GLContext::OES_texture_half_float) ||
+               gl->IsSupported(gl::GLFeature::texture_half_float);
+
+    case WebGLExtensionID::OES_texture_half_float_linear:
+        return gl->IsSupported(gl::GLFeature::texture_half_float_linear);
+    case WebGLExtensionID::EXT_texture_filter_anisotropic:
+        return gl->IsExtensionSupported(gl::GLContext::EXT_texture_filter_anisotropic);
+    case WebGLExtensionID::WEBGL_compressed_texture_s3tc:
+        if (gl->IsExtensionSupported(gl::GLContext::EXT_texture_compression_s3tc))
             return true;
-        case WebGLExtensionID::OES_texture_float:
-            return gl->IsSupported(GLFeature::texture_float);
-        case WebGLExtensionID::OES_texture_float_linear:
-            return gl->IsSupported(GLFeature::texture_float_linear);
-        case WebGLExtensionID::OES_texture_half_float:
-            // If we have Feature::texture_half_float, we must not be on ES2
-            // and need to translate HALF_FLOAT_OES -> HALF_FLOAT.  We do that
-            // right before making the relevant calls.
-            return gl->IsExtensionSupported(GLContext::OES_texture_half_float) ||
-                   gl->IsSupported(GLFeature::texture_half_float);
-        case WebGLExtensionID::OES_texture_half_float_linear:
-            return gl->IsSupported(GLFeature::texture_half_float_linear);
-        case WebGLExtensionID::OES_vertex_array_object:
-            return WebGLExtensionVertexArray::IsSupported(this);
-        case WebGLExtensionID::EXT_texture_filter_anisotropic:
-            return gl->IsExtensionSupported(GLContext::EXT_texture_filter_anisotropic);
-        case WebGLExtensionID::WEBGL_compressed_texture_s3tc:
-            if (gl->IsExtensionSupported(GLContext::EXT_texture_compression_s3tc)) {
-                return true;
-            }
-            else if (gl->IsExtensionSupported(GLContext::EXT_texture_compression_dxt1) &&
-                     gl->IsExtensionSupported(GLContext::ANGLE_texture_compression_dxt3) &&
-                     gl->IsExtensionSupported(GLContext::ANGLE_texture_compression_dxt5))
-            {
-                return true;
-            }
+
+        return gl->IsExtensionSupported(gl::GLContext::EXT_texture_compression_dxt1) &&
+               gl->IsExtensionSupported(gl::GLContext::ANGLE_texture_compression_dxt3) &&
+               gl->IsExtensionSupported(gl::GLContext::ANGLE_texture_compression_dxt5);
+
+    case WebGLExtensionID::WEBGL_compressed_texture_atc:
+        return gl->IsExtensionSupported(gl::GLContext::AMD_compressed_ATC_texture);
+    case WebGLExtensionID::WEBGL_compressed_texture_etc1:
+        return gl->IsExtensionSupported(gl::GLContext::OES_compressed_ETC1_RGB8_texture);
+    case WebGLExtensionID::WEBGL_compressed_texture_pvrtc:
+        return gl->IsExtensionSupported(gl::GLContext::IMG_texture_compression_pvrtc);
+    case WebGLExtensionID::WEBGL_depth_texture:
+        // WEBGL_depth_texture supports DEPTH_STENCIL textures
+        if (!gl->IsSupported(gl::GLFeature::packed_depth_stencil))
             return false;
-        case WebGLExtensionID::WEBGL_compressed_texture_atc:
-            return gl->IsExtensionSupported(GLContext::AMD_compressed_ATC_texture);
-        case WebGLExtensionID::WEBGL_compressed_texture_etc1:
-            return gl->IsExtensionSupported(GLContext::OES_compressed_ETC1_RGB8_texture);
-        case WebGLExtensionID::WEBGL_compressed_texture_pvrtc:
-            return gl->IsExtensionSupported(GLContext::IMG_texture_compression_pvrtc);
-        case WebGLExtensionID::WEBGL_depth_texture:
-            // WEBGL_depth_texture supports DEPTH_STENCIL textures
-            if (!gl->IsSupported(GLFeature::packed_depth_stencil)) {
-                return false;
-            }
-            return gl->IsSupported(GLFeature::depth_texture) ||
-                   gl->IsExtensionSupported(GLContext::ANGLE_depth_texture);
-        case WebGLExtensionID::ANGLE_instanced_arrays:
-            return WebGLExtensionInstancedArrays::IsSupported(this);
-        case WebGLExtensionID::EXT_sRGB:
-            return WebGLExtensionSRGB::IsSupported(this);
-        case WebGLExtensionID::WEBGL_draw_buffers:
-            return WebGLExtensionDrawBuffers::IsSupported(this);
-        case WebGLExtensionID::EXT_frag_depth:
-            return WebGLExtensionFragDepth::IsSupported(this);
-        case WebGLExtensionID::EXT_shader_texture_lod:
-            return gl->IsExtensionSupported(GLContext::EXT_shader_texture_lod);
+
+        return gl->IsSupported(gl::GLFeature::depth_texture) ||
+               gl->IsExtensionSupported(gl::GLContext::ANGLE_depth_texture);
+
+    case WebGLExtensionID::ANGLE_instanced_arrays:
+        return WebGLExtensionInstancedArrays::IsSupported(this);
+    case WebGLExtensionID::EXT_sRGB:
+        return WebGLExtensionSRGB::IsSupported(this);
+    case WebGLExtensionID::WEBGL_draw_buffers:
+        return WebGLExtensionDrawBuffers::IsSupported(this);
+    case WebGLExtensionID::EXT_frag_depth:
+        return WebGLExtensionFragDepth::IsSupported(this);
+    case WebGLExtensionID::EXT_shader_texture_lod:
+        return gl->IsExtensionSupported(gl::GLContext::EXT_shader_texture_lod);
+
+    default:
+        // For warnings-as-errors.
+        break;
+    }
+
+    if (Preferences::GetBool("webgl.enable-draft-extensions", false) ||
+        IsWebGL2())
+    {
+        switch (ext) {
+        case WebGLExtensionID::EXT_color_buffer_half_float:
+            return WebGLExtensionColorBufferHalfFloat::IsSupported(this);
+        case WebGLExtensionID::WEBGL_color_buffer_float:
+            return WebGLExtensionColorBufferFloat::IsSupported(this);
         default:
             // For warnings-as-errors.
             break;
-    }
-
-    if (Preferences::GetBool("webgl.enable-draft-extensions", false) || IsWebGL2()) {
-        switch (ext) {
-            case WebGLExtensionID::EXT_color_buffer_half_float:
-                return WebGLExtensionColorBufferHalfFloat::IsSupported(this);
-            case WebGLExtensionID::WEBGL_color_buffer_float:
-                return WebGLExtensionColorBufferFloat::IsSupported(this);
-            default:
-                // For warnings-as-errors.
-                break;
         }
     }
 
@@ -181,7 +184,7 @@ bool WebGLContext::IsExtensionSupported(WebGLExtensionID ext) const
 }
 
 static bool
-CompareWebGLExtensionName(const nsACString& name, const char *other)
+CompareWebGLExtensionName(const nsACString& name, const char* other)
 {
     return name.Equals(other, nsCaseInsensitiveCStringComparator());
 }
@@ -200,16 +203,15 @@ WebGLContext::EnableSupportedExtension(JSContext* js, WebGLExtensionID ext)
 }
 
 void
-WebGLContext::GetExtension(JSContext *cx, const nsAString& aName,
-                           JS::MutableHandle aRetval,
-                           ErrorResult& rv)
+WebGLContext::GetExtension(JSContext* cx, const nsAString& wideName,
+                           JS::MutableHandle retval, ErrorResult& rv)
 {
-    if (IsContextLost()) {
-        aRetval.set(nullptr);
-        return;
-    }
+    retval.set(nullptr);
 
-    NS_LossyConvertUTF16toASCII name(aName);
+    if (IsContextLost())
+        return;
+
+    NS_LossyConvertUTF16toASCII name(wideName);
 
     WebGLExtensionID ext = WebGLExtensionID::Unknown;
 
@@ -224,52 +226,47 @@ WebGLContext::GetExtension(JSContext *cx, const nsAString& aName,
     }
 
     if (ext == WebGLExtensionID::Unknown) {
-        /**
-         * We keep backward compatibility for these deprecated vendor-prefixed
-         * alias. Do not add new ones anymore. Hide it behind the
-         * webgl.enable-draft-extensions flag instead.
-         */
+        // We keep backward compatibility for these deprecated vendor-prefixed
+        // alias. Do not add new ones anymore. Hide it behind the
+        // webgl.enable-draft-extensions flag instead.
+
         if (CompareWebGLExtensionName(name, "MOZ_WEBGL_lose_context")) {
             ext = WebGLExtensionID::WEBGL_lose_context;
-        }
-        else if (CompareWebGLExtensionName(name, "MOZ_WEBGL_compressed_texture_s3tc")) {
+
+        } else if (CompareWebGLExtensionName(name, "MOZ_WEBGL_compressed_texture_s3tc")) {
             ext = WebGLExtensionID::WEBGL_compressed_texture_s3tc;
-        }
-        else if (CompareWebGLExtensionName(name, "MOZ_WEBGL_compressed_texture_atc")) {
+
+        } else if (CompareWebGLExtensionName(name, "MOZ_WEBGL_compressed_texture_atc")) {
             ext = WebGLExtensionID::WEBGL_compressed_texture_atc;
-        }
-        else if (CompareWebGLExtensionName(name, "MOZ_WEBGL_compressed_texture_pvrtc")) {
+
+        } else if (CompareWebGLExtensionName(name, "MOZ_WEBGL_compressed_texture_pvrtc")) {
             ext = WebGLExtensionID::WEBGL_compressed_texture_pvrtc;
-        }
-        else if (CompareWebGLExtensionName(name, "MOZ_WEBGL_depth_texture")) {
+
+        } else if (CompareWebGLExtensionName(name, "MOZ_WEBGL_depth_texture")) {
             ext = WebGLExtensionID::WEBGL_depth_texture;
         }
 
         if (ext != WebGLExtensionID::Unknown) {
-            GenerateWarning("getExtension('%s'): MOZ_ prefixed WebGL extension strings are deprecated. "
-                            "Support for them will be removed in the future. Use unprefixed extension strings. "
-                            "To get draft extensions, set the webgl.enable-draft-extensions preference.",
+            GenerateWarning("getExtension('%s'): MOZ_ prefixed WebGL extension"
+                            " strings are deprecated. Support for them will be"
+                            " removed in the future. Use unprefixed extension"
+                            " strings. To get draft extensions, set the"
+                            " webgl.enable-draft-extensions preference.",
                             name.get());
         }
     }
 
-    if (ext == WebGLExtensionID::Unknown) {
-        aRetval.set(nullptr);
+    if (ext == WebGLExtensionID::Unknown)
         return;
-    }
 
     // step 2: check if the extension is supported
-    if (!IsExtensionSupported(cx, ext)) {
-        aRetval.set(nullptr);
+    if (!IsExtensionSupported(cx, ext))
         return;
-    }
 
     // step 3: if the extension hadn't been previously been created, create it now, thus enabling it
     WebGLExtensionBase* extObj = EnableSupportedExtension(cx, ext);
-    if (!extObj) {
-        aRetval.set(nullptr);
+    if (!extObj)
         return;
-    }
 
     // Step 4: Enable any implied extensions.
     switch (ext) {
@@ -285,7 +282,7 @@ WebGLContext::GetExtension(JSContext *cx, const nsAString& aName,
         break;
     }
 
-    aRetval.set(WebGLObjectAsJSObject(cx, extObj, rv));
+    retval.set(WebGLObjectAsJSObject(cx, extObj, rv));
 }
 
 void
@@ -295,87 +292,89 @@ WebGLContext::EnableExtension(WebGLExtensionID ext)
 
     WebGLExtensionBase* obj = nullptr;
     switch (ext) {
-        case WebGLExtensionID::OES_element_index_uint:
-            obj = new WebGLExtensionElementIndexUint(this);
-            break;
-        case WebGLExtensionID::OES_standard_derivatives:
-            obj = new WebGLExtensionStandardDerivatives(this);
-            break;
-        case WebGLExtensionID::EXT_texture_filter_anisotropic:
-            obj = new WebGLExtensionTextureFilterAnisotropic(this);
-            break;
-        case WebGLExtensionID::WEBGL_lose_context:
-            obj = new WebGLExtensionLoseContext(this);
-            break;
-        case WebGLExtensionID::WEBGL_compressed_texture_s3tc:
-            obj = new WebGLExtensionCompressedTextureS3TC(this);
-            break;
-        case WebGLExtensionID::WEBGL_compressed_texture_atc:
-            obj = new WebGLExtensionCompressedTextureATC(this);
-            break;
-        case WebGLExtensionID::WEBGL_compressed_texture_etc1:
-            obj = new WebGLExtensionCompressedTextureETC1(this);
-            break;
-        case WebGLExtensionID::WEBGL_compressed_texture_pvrtc:
-            obj = new WebGLExtensionCompressedTexturePVRTC(this);
-            break;
-        case WebGLExtensionID::WEBGL_debug_renderer_info:
-            obj = new WebGLExtensionDebugRendererInfo(this);
-            break;
-        case WebGLExtensionID::WEBGL_debug_shaders:
-            obj = new WebGLExtensionDebugShaders(this);
-            break;
-        case WebGLExtensionID::WEBGL_depth_texture:
-            obj = new WebGLExtensionDepthTexture(this);
-            break;
-        case WebGLExtensionID::OES_texture_float:
-            obj = new WebGLExtensionTextureFloat(this);
-            break;
-        case WebGLExtensionID::OES_texture_float_linear:
-            obj = new WebGLExtensionTextureFloatLinear(this);
-            break;
-        case WebGLExtensionID::OES_texture_half_float:
-            obj = new WebGLExtensionTextureHalfFloat(this);
-            break;
-        case WebGLExtensionID::OES_texture_half_float_linear:
-            obj = new WebGLExtensionTextureHalfFloatLinear(this);
-            break;
-        case WebGLExtensionID::WEBGL_color_buffer_float:
-            obj = new WebGLExtensionColorBufferFloat(this);
-            break;
-        case WebGLExtensionID::EXT_color_buffer_half_float:
-            obj = new WebGLExtensionColorBufferHalfFloat(this);
-            break;
-        case WebGLExtensionID::WEBGL_draw_buffers:
-            obj = new WebGLExtensionDrawBuffers(this);
-            break;
-        case WebGLExtensionID::OES_vertex_array_object:
-            obj = new WebGLExtensionVertexArray(this);
-            break;
-        case WebGLExtensionID::ANGLE_instanced_arrays:
-            obj = new WebGLExtensionInstancedArrays(this);
-            break;
-        case WebGLExtensionID::EXT_sRGB:
-            obj = new WebGLExtensionSRGB(this);
-            break;
-        case WebGLExtensionID::EXT_frag_depth:
-            obj = new WebGLExtensionFragDepth(this);
-            break;
-        case WebGLExtensionID::EXT_blend_minmax:
-            obj = new WebGLExtensionBlendMinMax(this);
-            break;
-        case WebGLExtensionID::EXT_shader_texture_lod:
-            obj = new WebGLExtensionShaderTextureLod(this);
-            break;
-        default:
-            MOZ_ASSERT(false, "should not get there.");
+    case WebGLExtensionID::OES_element_index_uint:
+        obj = new WebGLExtensionElementIndexUint(this);
+        break;
+    case WebGLExtensionID::OES_standard_derivatives:
+        obj = new WebGLExtensionStandardDerivatives(this);
+        break;
+    case WebGLExtensionID::EXT_texture_filter_anisotropic:
+        obj = new WebGLExtensionTextureFilterAnisotropic(this);
+        break;
+    case WebGLExtensionID::WEBGL_lose_context:
+        obj = new WebGLExtensionLoseContext(this);
+        break;
+    case WebGLExtensionID::WEBGL_compressed_texture_s3tc:
+        obj = new WebGLExtensionCompressedTextureS3TC(this);
+        break;
+    case WebGLExtensionID::WEBGL_compressed_texture_atc:
+        obj = new WebGLExtensionCompressedTextureATC(this);
+        break;
+    case WebGLExtensionID::WEBGL_compressed_texture_etc1:
+        obj = new WebGLExtensionCompressedTextureETC1(this);
+        break;
+    case WebGLExtensionID::WEBGL_compressed_texture_pvrtc:
+        obj = new WebGLExtensionCompressedTexturePVRTC(this);
+        break;
+    case WebGLExtensionID::WEBGL_debug_renderer_info:
+        obj = new WebGLExtensionDebugRendererInfo(this);
+        break;
+    case WebGLExtensionID::WEBGL_debug_shaders:
+        obj = new WebGLExtensionDebugShaders(this);
+        break;
+    case WebGLExtensionID::WEBGL_depth_texture:
+        obj = new WebGLExtensionDepthTexture(this);
+        break;
+    case WebGLExtensionID::OES_texture_float:
+        obj = new WebGLExtensionTextureFloat(this);
+        break;
+    case WebGLExtensionID::OES_texture_float_linear:
+        obj = new WebGLExtensionTextureFloatLinear(this);
+        break;
+    case WebGLExtensionID::OES_texture_half_float:
+        obj = new WebGLExtensionTextureHalfFloat(this);
+        break;
+    case WebGLExtensionID::OES_texture_half_float_linear:
+        obj = new WebGLExtensionTextureHalfFloatLinear(this);
+        break;
+    case WebGLExtensionID::WEBGL_color_buffer_float:
+        obj = new WebGLExtensionColorBufferFloat(this);
+        break;
+    case WebGLExtensionID::EXT_color_buffer_half_float:
+        obj = new WebGLExtensionColorBufferHalfFloat(this);
+        break;
+    case WebGLExtensionID::WEBGL_draw_buffers:
+        obj = new WebGLExtensionDrawBuffers(this);
+        break;
+    case WebGLExtensionID::OES_vertex_array_object:
+        obj = new WebGLExtensionVertexArray(this);
+        break;
+    case WebGLExtensionID::ANGLE_instanced_arrays:
+        obj = new WebGLExtensionInstancedArrays(this);
+        break;
+    case WebGLExtensionID::EXT_sRGB:
+        obj = new WebGLExtensionSRGB(this);
+        break;
+    case WebGLExtensionID::EXT_frag_depth:
+        obj = new WebGLExtensionFragDepth(this);
+        break;
+    case WebGLExtensionID::EXT_blend_minmax:
+        obj = new WebGLExtensionBlendMinMax(this);
+        break;
+    case WebGLExtensionID::EXT_shader_texture_lod:
+        obj = new WebGLExtensionShaderTextureLod(this);
+        break;
+    default:
+        MOZ_ASSERT(false, "should not get there.");
+        break;
     }
 
     mExtensions[ext] = obj;
 }
 
 void
-WebGLContext::GetSupportedExtensions(JSContext *cx, Nullable< nsTArray > &retval)
+WebGLContext::GetSupportedExtensions(JSContext* cx,
+                                     Nullable< nsTArray >& retval)
 {
     retval.SetNull();
     if (IsContextLost())
@@ -383,12 +382,12 @@ WebGLContext::GetSupportedExtensions(JSContext *cx, Nullable< nsTArray
 
     nsTArray& arr = retval.SetValue();
 
-    for (size_t i = 0; i < size_t(WebGLExtensionID::Max); i++)
-    {
+    for (size_t i = 0; i < size_t(WebGLExtensionID::Max); i++) {
         WebGLExtensionID extension = WebGLExtensionID(i);
 
         if (IsExtensionSupported(cx, extension)) {
-            arr.AppendElement(NS_ConvertUTF8toUTF16(GetExtensionString(extension)));
+            const char* extStr = GetExtensionString(extension);
+            arr.AppendElement(NS_ConvertUTF8toUTF16(extStr));
         }
     }
 
@@ -409,3 +408,4 @@ WebGLContext::GetSupportedExtensions(JSContext *cx, Nullable< nsTArray
         arr.AppendElement(NS_LITERAL_STRING("MOZ_WEBGL_depth_texture"));
 }
 
+} // namespace mozilla
diff --git a/dom/canvas/WebGLContextGL.cpp b/dom/canvas/WebGLContextGL.cpp
index 4996a7e7154a..8f7f757f5303 100644
--- a/dom/canvas/WebGLContextGL.cpp
+++ b/dom/canvas/WebGLContextGL.cpp
@@ -55,7 +55,8 @@ using namespace mozilla::dom;
 using namespace mozilla::gl;
 using namespace mozilla::gfx;
 
-static bool BaseTypeAndSizeFromUniformType(GLenum uType, GLenum *baseType, GLint *unitSize);
+static bool BaseTypeAndSizeFromUniformType(GLenum uType, GLenum* baseType,
+                                           GLint* unitSize);
 
 const WebGLRectangleObject*
 WebGLContext::CurValidFBRectObject() const
@@ -101,7 +102,7 @@ WebGLContext::ActiveTexture(GLenum texture)
 }
 
 void
-WebGLContext::AttachShader(WebGLProgram *program, WebGLShader *shader)
+WebGLContext::AttachShader(WebGLProgram* program, WebGLShader* shader)
 {
     if (IsContextLost())
         return;
@@ -158,7 +159,7 @@ WebGLContext::BindAttribLocation(WebGLProgram* prog, GLuint location,
 }
 
 void
-WebGLContext::BindFramebuffer(GLenum target, WebGLFramebuffer *wfb)
+WebGLContext::BindFramebuffer(GLenum target, WebGLFramebuffer* wfb)
 {
     if (IsContextLost())
         return;
@@ -187,7 +188,7 @@ WebGLContext::BindFramebuffer(GLenum target, WebGLFramebuffer *wfb)
 }
 
 void
-WebGLContext::BindRenderbuffer(GLenum target, WebGLRenderbuffer *wrb)
+WebGLContext::BindRenderbuffer(GLenum target, WebGLRenderbuffer* wrb)
 {
     if (IsContextLost())
         return;
@@ -219,7 +220,7 @@ WebGLContext::BindRenderbuffer(GLenum target, WebGLRenderbuffer *wrb)
 }
 
 void
-WebGLContext::BindTexture(GLenum rawTarget, WebGLTexture *newTex)
+WebGLContext::BindTexture(GLenum rawTarget, WebGLTexture* newTex)
 {
     if (IsContextLost())
         return;
@@ -403,7 +404,7 @@ WebGLContext::CopyTexSubImage2D_base(TexImageTarget texImageTarget,
 
     MakeContextCurrent();
 
-    WebGLTexture *tex = activeBoundTextureForTexImageTarget(texImageTarget);
+    WebGLTexture* tex = ActiveBoundTextureForTexImageTarget(texImageTarget);
 
     if (!tex)
         return ErrorInvalidOperation("%s: no texture is bound to this target");
@@ -587,7 +588,7 @@ WebGLContext::CopyTexSubImage2D(GLenum rawTexImgTarget,
     if (xoffset < 0 || yoffset < 0)
         return ErrorInvalidValue("copyTexSubImage2D: xoffset and yoffset may not be negative");
 
-    WebGLTexture *tex = activeBoundTextureForTexImageTarget(texImageTarget);
+    WebGLTexture* tex = ActiveBoundTextureForTexImageTarget(texImageTarget);
     if (!tex)
         return ErrorInvalidOperation("copyTexSubImage2D: no texture bound to this target");
 
@@ -686,7 +687,7 @@ WebGLContext::DeleteFramebuffer(WebGLFramebuffer* fbuf)
 }
 
 void
-WebGLContext::DeleteRenderbuffer(WebGLRenderbuffer *rbuf)
+WebGLContext::DeleteRenderbuffer(WebGLRenderbuffer* rbuf)
 {
     if (IsContextLost())
         return;
@@ -711,7 +712,7 @@ WebGLContext::DeleteRenderbuffer(WebGLRenderbuffer *rbuf)
 }
 
 void
-WebGLContext::DeleteTexture(WebGLTexture *tex)
+WebGLContext::DeleteTexture(WebGLTexture* tex)
 {
     if (IsContextLost())
         return;
@@ -744,7 +745,7 @@ WebGLContext::DeleteTexture(WebGLTexture *tex)
 }
 
 void
-WebGLContext::DeleteProgram(WebGLProgram *prog)
+WebGLContext::DeleteProgram(WebGLProgram* prog)
 {
     if (IsContextLost())
         return;
@@ -759,7 +760,7 @@ WebGLContext::DeleteProgram(WebGLProgram *prog)
 }
 
 void
-WebGLContext::DeleteShader(WebGLShader *shader)
+WebGLContext::DeleteShader(WebGLShader* shader)
 {
     if (IsContextLost())
         return;
@@ -774,7 +775,7 @@ WebGLContext::DeleteShader(WebGLShader *shader)
 }
 
 void
-WebGLContext::DetachShader(WebGLProgram *program, WebGLShader *shader)
+WebGLContext::DetachShader(WebGLProgram* program, WebGLShader* shader)
 {
     if (IsContextLost())
         return;
@@ -816,7 +817,8 @@ WebGLContext::DepthRange(GLfloat zNear, GLfloat zFar)
 }
 
 void
-WebGLContext::FramebufferRenderbuffer(GLenum target, GLenum attachment, GLenum rbtarget, WebGLRenderbuffer *wrb)
+WebGLContext::FramebufferRenderbuffer(GLenum target, GLenum attachment,
+                                      GLenum rbtarget, WebGLRenderbuffer* wrb)
 {
     if (IsContextLost())
         return;
@@ -840,7 +842,7 @@ void
 WebGLContext::FramebufferTexture2D(GLenum target,
                                    GLenum attachment,
                                    GLenum textarget,
-                                   WebGLTexture *tobj,
+                                   WebGLTexture* tobj,
                                    GLint level)
 {
     if (IsContextLost())
@@ -884,7 +886,7 @@ WebGLContext::FrontFace(GLenum mode)
 }
 
 already_AddRefed
-WebGLContext::GetActiveAttrib(WebGLProgram *prog, uint32_t index)
+WebGLContext::GetActiveAttrib(WebGLProgram* prog, uint32_t index)
 {
     if (IsContextLost())
         return nullptr;
@@ -938,7 +940,7 @@ WebGLContext::GenerateMipmap(GLenum rawTarget)
 
     const TexTarget target(rawTarget);
 
-    WebGLTexture *tex = activeBoundTextureForTarget(target);
+    WebGLTexture* tex = ActiveBoundTextureForTarget(target);
 
     if (!tex)
         return ErrorInvalidOperation("generateMipmap: No texture is bound to this target.");
@@ -992,7 +994,7 @@ WebGLContext::GenerateMipmap(GLenum rawTarget)
 }
 
 already_AddRefed
-WebGLContext::GetActiveUniform(WebGLProgram *prog, uint32_t index)
+WebGLContext::GetActiveUniform(WebGLProgram* prog, uint32_t index)
 {
     if (IsContextLost())
         return nullptr;
@@ -1053,7 +1055,7 @@ WebGLContext::GetActiveUniform(WebGLProgram *prog, uint32_t index)
 }
 
 void
-WebGLContext::GetAttachedShaders(WebGLProgram *prog,
+WebGLContext::GetAttachedShaders(WebGLProgram* prog,
                                  Nullable>>& retval)
 {
     retval.SetNull();
@@ -1076,7 +1078,7 @@ WebGLContext::GetAttachedShaders(WebGLProgram *prog,
 }
 
 GLint
-WebGLContext::GetAttribLocation(WebGLProgram *prog, const nsAString& name)
+WebGLContext::GetAttribLocation(WebGLProgram* prog, const nsAString& name)
 {
     if (IsContextLost())
         return -1;
@@ -1432,7 +1434,7 @@ WebGLContext::GetError()
 }
 
 JS::Value
-WebGLContext::GetProgramParameter(WebGLProgram *prog, GLenum pname)
+WebGLContext::GetProgramParameter(WebGLProgram* prog, GLenum pname)
 {
     if (IsContextLost())
         return JS::NullValue();
@@ -1488,7 +1490,7 @@ WebGLContext::GetProgramParameter(WebGLProgram *prog, GLenum pname)
 }
 
 void
-WebGLContext::GetProgramInfoLog(WebGLProgram *prog, nsAString& retval)
+WebGLContext::GetProgramInfoLog(WebGLProgram* prog, nsAString& retval)
 {
     nsAutoCString s;
     GetProgramInfoLog(prog, s);
@@ -1499,7 +1501,7 @@ WebGLContext::GetProgramInfoLog(WebGLProgram *prog, nsAString& retval)
 }
 
 void
-WebGLContext::GetProgramInfoLog(WebGLProgram *prog, nsACString& retval)
+WebGLContext::GetProgramInfoLog(WebGLProgram* prog, nsACString& retval)
 {
     if (IsContextLost())
     {
@@ -1540,8 +1542,8 @@ WebGLContext::GetProgramInfoLog(WebGLProgram *prog, nsACString& retval)
 // See this discussion:
 //  https://www.khronos.org/webgl/public-mailing-list/archives/1008/msg00014.html
 void WebGLContext::TexParameter_base(GLenum rawTarget, GLenum pname,
-                                     GLint *intParamPtr,
-                                     GLfloat *floatParamPtr)
+                                     GLint* intParamPtr,
+                                     GLfloat* floatParamPtr)
 {
     MOZ_ASSERT(intParamPtr || floatParamPtr);
 
@@ -1556,7 +1558,7 @@ void WebGLContext::TexParameter_base(GLenum rawTarget, GLenum pname,
 
     const TexTarget texTarget = TexTarget(rawTarget);
 
-    WebGLTexture *tex = activeBoundTextureForTarget(texTarget);
+    WebGLTexture* tex = ActiveBoundTextureForTarget(texTarget);
     if (!tex)
         return ErrorInvalidOperation("texParameter: no texture is bound to this target");
 
@@ -1673,7 +1675,7 @@ WebGLContext::GetTexParameter(GLenum rawTarget, GLenum pname)
 
     const TexTarget target(rawTarget);
 
-    if (!activeBoundTextureForTarget(target)) {
+    if (!ActiveBoundTextureForTarget(target)) {
         ErrorInvalidOperation("getTexParameter: no texture bound");
         return JS::NullValue();
     }
@@ -1712,8 +1714,8 @@ WebGLContext::GetTexParameterInternal(const TexTarget& target, GLenum pname)
 }
 
 JS::Value
-WebGLContext::GetUniform(JSContext* cx, WebGLProgram *prog,
-                         WebGLUniformLocation *location)
+WebGLContext::GetUniform(JSContext* cx, WebGLProgram* prog,
+                         WebGLUniformLocation* location)
 {
     if (IsContextLost())
         return JS::NullValue();
@@ -1849,7 +1851,7 @@ WebGLContext::GetUniform(JSContext* cx, WebGLProgram *prog,
 }
 
 already_AddRefed
-WebGLContext::GetUniformLocation(WebGLProgram *prog, const nsAString& name)
+WebGLContext::GetUniformLocation(WebGLProgram* prog, const nsAString& name)
 {
     if (IsContextLost())
         return nullptr;
@@ -1905,7 +1907,7 @@ WebGLContext::Hint(GLenum target, GLenum mode)
 }
 
 bool
-WebGLContext::IsFramebuffer(WebGLFramebuffer *fb)
+WebGLContext::IsFramebuffer(WebGLFramebuffer* fb)
 {
     if (IsContextLost())
         return false;
@@ -1916,7 +1918,7 @@ WebGLContext::IsFramebuffer(WebGLFramebuffer *fb)
 }
 
 bool
-WebGLContext::IsProgram(WebGLProgram *prog)
+WebGLContext::IsProgram(WebGLProgram* prog)
 {
     if (IsContextLost())
         return false;
@@ -1925,7 +1927,7 @@ WebGLContext::IsProgram(WebGLProgram *prog)
 }
 
 bool
-WebGLContext::IsRenderbuffer(WebGLRenderbuffer *rb)
+WebGLContext::IsRenderbuffer(WebGLRenderbuffer* rb)
 {
     if (IsContextLost())
         return false;
@@ -1936,7 +1938,7 @@ WebGLContext::IsRenderbuffer(WebGLRenderbuffer *rb)
 }
 
 bool
-WebGLContext::IsShader(WebGLShader *shader)
+WebGLContext::IsShader(WebGLShader* shader)
 {
     if (IsContextLost())
         return false;
@@ -1946,7 +1948,7 @@ WebGLContext::IsShader(WebGLShader *shader)
 }
 
 bool
-WebGLContext::IsTexture(WebGLTexture *tex)
+WebGLContext::IsTexture(WebGLTexture* tex)
 {
     if (IsContextLost())
         return false;
@@ -1957,7 +1959,8 @@ WebGLContext::IsTexture(WebGLTexture *tex)
 }
 
 // Try to bind an attribute that is an array to location 0:
-bool WebGLContext::BindArrayAttribToLocation0(WebGLProgram *program)
+bool
+WebGLContext::BindArrayAttribToLocation0(WebGLProgram* program)
 {
     if (mBoundVertexArray->IsAttribArrayEnabled(0)) {
         return false;
@@ -2006,7 +2009,7 @@ LinkAndUpdateProgram(GLContext* gl, WebGLProgram* prog)
 }
 
 void
-WebGLContext::LinkProgram(WebGLProgram *program)
+WebGLContext::LinkProgram(WebGLProgram* program)
 {
     if (IsContextLost())
         return;
@@ -2077,7 +2080,7 @@ WebGLContext::LinkProgram(WebGLProgram *program)
                 if (shader->CompileStatus())
                     continue;
 
-                const char *shaderTypeName = nullptr;
+                const char* shaderTypeName = nullptr;
                 if (shader->ShaderType() == LOCAL_GL_VERTEX_SHADER) {
                     shaderTypeName = "vertex";
                 } else if (shader->ShaderType() == LOCAL_GL_FRAGMENT_SHADER) {
@@ -2656,7 +2659,8 @@ WebGLContext::StencilOpSeparate(GLenum face, GLenum sfail, GLenum dpfail, GLenum
 
 nsresult
 WebGLContext::SurfaceFromElementResultToImageSurface(nsLayoutUtils::SurfaceFromElementResult& res,
-                                                     RefPtr& imageOut, WebGLTexelFormat *format)
+                                                     RefPtr& imageOut,
+                                                     WebGLTexelFormat* format)
 {
    *format = WebGLTexelFormat::None;
 
@@ -3058,7 +3062,7 @@ WebGLContext::UniformMatrix4fv_base(WebGLUniformLocation* loc, bool transpose,
 ////////////////////////////////////////////////////////////////////////////////
 
 void
-WebGLContext::UseProgram(WebGLProgram *prog)
+WebGLContext::UseProgram(WebGLProgram* prog)
 {
     if (IsContextLost())
         return;
@@ -3081,7 +3085,7 @@ WebGLContext::UseProgram(WebGLProgram *prog)
 }
 
 void
-WebGLContext::ValidateProgram(WebGLProgram *prog)
+WebGLContext::ValidateProgram(WebGLProgram* prog)
 {
     if (IsContextLost())
         return;
@@ -3145,7 +3149,7 @@ WebGLContext::Viewport(GLint x, GLint y, GLsizei width, GLsizei height)
 }
 
 void
-WebGLContext::CompileShader(WebGLShader *shader)
+WebGLContext::CompileShader(WebGLShader* shader)
 {
     if (IsContextLost())
         return;
@@ -3231,7 +3235,7 @@ WebGLContext::CompileShader(WebGLShader *shader)
                                      maxSourceLength);
     }
 
-    const char *s = sourceCString.get();
+    const char* s = sourceCString.get();
 
 #define WEBGL2_BYPASS_ANGLE
 #ifdef WEBGL2_BYPASS_ANGLE
@@ -3251,8 +3255,8 @@ WebGLContext::CompileShader(WebGLShader *shader)
      *    - one for the angle compilor, to get informations about vertex attributes
      *      and uniforms
      */
-    static const char *bypassPrefixSearch = "#version proto-200";
-    static const char *bypassANGLEPrefix[2] = {"precision mediump float;\n"
+    static const char* bypassPrefixSearch = "#version proto-200";
+    static const char* bypassANGLEPrefix[2] = {"precision mediump float;\n"
                                                "#define gl_VertexID 0\n"
                                                "#define gl_InstanceID 0\n",
 
@@ -3262,13 +3266,13 @@ WebGLContext::CompileShader(WebGLShader *shader)
 
     const bool bypassANGLE = IsWebGL2() && (strstr(s, bypassPrefixSearch) != 0);
 
-    const char *angleShaderCode = s;
+    const char* angleShaderCode = s;
     nsTArray bypassANGLEShaderCode;
     nsTArray bypassDriverShaderCode;
 
     if (bypassANGLE) {
         const int bypassStage = (shader->ShaderType() == LOCAL_GL_FRAGMENT_SHADER) ? 1 : 0;
-        const char *originalShader = strstr(s, bypassPrefixSearch) + strlen(bypassPrefixSearch);
+        const char* originalShader = strstr(s, bypassPrefixSearch) + strlen(bypassPrefixSearch);
         int originalShaderSize = strlen(s) - (originalShader - s);
         int bypassShaderCodeSize = originalShaderSize + 4096 + 1;
 
@@ -3428,7 +3432,7 @@ WebGLContext::CompileShader(WebGLShader *shader)
 
     CopyASCIItoUTF16(translatedSrc, shader->mTranslatedSource);
 
-    const char *ts = translatedSrc.get();
+    const char* ts = translatedSrc.get();
 
 #ifdef WEBGL2_BYPASS_ANGLE
     if (bypassANGLE) {
@@ -3490,7 +3494,7 @@ WebGLContext::CompressedTexImage2D(GLenum rawTexImgTarget,
 
     const TexImageTarget texImageTarget(rawTexImgTarget);
 
-    WebGLTexture* tex = activeBoundTextureForTexImageTarget(texImageTarget);
+    WebGLTexture* tex = ActiveBoundTextureForTexImageTarget(texImageTarget);
     MOZ_ASSERT(tex);
     if (tex->IsImmutable()) {
         return ErrorInvalidOperation(
@@ -3532,7 +3536,7 @@ WebGLContext::CompressedTexSubImage2D(GLenum rawTexImgTarget, GLint level, GLint
 
     const TexImageTarget texImageTarget(rawTexImgTarget);
 
-    WebGLTexture *tex = activeBoundTextureForTexImageTarget(texImageTarget);
+    WebGLTexture* tex = ActiveBoundTextureForTexImageTarget(texImageTarget);
     MOZ_ASSERT(tex);
     WebGLTexture::ImageInfo& levelInfo = tex->ImageInfoAt(texImageTarget, level);
 
@@ -3572,7 +3576,7 @@ WebGLContext::CompressedTexSubImage2D(GLenum rawTexImgTarget, GLint level, GLint
 }
 
 JS::Value
-WebGLContext::GetShaderParameter(WebGLShader *shader, GLenum pname)
+WebGLContext::GetShaderParameter(WebGLShader* shader, GLenum pname)
 {
     if (IsContextLost())
         return JS::NullValue();
@@ -3610,7 +3614,7 @@ WebGLContext::GetShaderParameter(WebGLShader *shader, GLenum pname)
 }
 
 void
-WebGLContext::GetShaderInfoLog(WebGLShader *shader, nsAString& retval)
+WebGLContext::GetShaderInfoLog(WebGLShader* shader, nsAString& retval)
 {
     nsAutoCString s;
     GetShaderInfoLog(shader, s);
@@ -3621,7 +3625,7 @@ WebGLContext::GetShaderInfoLog(WebGLShader *shader, nsAString& retval)
 }
 
 void
-WebGLContext::GetShaderInfoLog(WebGLShader *shader, nsACString& retval)
+WebGLContext::GetShaderInfoLog(WebGLShader* shader, nsACString& retval)
 {
     if (IsContextLost())
     {
@@ -3706,7 +3710,7 @@ WebGLContext::GetShaderPrecisionFormat(GLenum shadertype, GLenum precisiontype)
 }
 
 void
-WebGLContext::GetShaderSource(WebGLShader *shader, nsAString& retval)
+WebGLContext::GetShaderSource(WebGLShader* shader, nsAString& retval)
 {
     if (IsContextLost()) {
         retval.SetIsVoid(true);
@@ -3720,7 +3724,7 @@ WebGLContext::GetShaderSource(WebGLShader *shader, nsAString& retval)
 }
 
 void
-WebGLContext::ShaderSource(WebGLShader *shader, const nsAString& source)
+WebGLContext::ShaderSource(WebGLShader* shader, const nsAString& source)
 {
     if (IsContextLost())
         return;
@@ -3742,7 +3746,7 @@ WebGLContext::ShaderSource(WebGLShader *shader, const nsAString& source)
 }
 
 void
-WebGLContext::GetShaderTranslatedSource(WebGLShader *shader, nsAString& retval)
+WebGLContext::GetShaderTranslatedSource(WebGLShader* shader, nsAString& retval)
 {
     if (IsContextLost()) {
         retval.SetIsVoid(true);
@@ -3763,10 +3767,10 @@ GLenum WebGLContext::CheckedTexImage2D(TexImageTarget texImageTarget,
                                        GLint border,
                                        TexFormat format,
                                        TexType type,
-                                       const GLvoid *data)
+                                       const GLvoid* data)
 {
-    WebGLTexture *tex = activeBoundTextureForTexImageTarget(texImageTarget);
-    MOZ_ASSERT(tex != nullptr, "no texture bound");
+    WebGLTexture* tex = ActiveBoundTextureForTexImageTarget(texImageTarget);
+    MOZ_ASSERT(tex, "no texture bound");
 
     TexInternalFormat effectiveInternalFormat =
         EffectiveInternalFormatFromInternalFormatAndType(internalformat, type);
@@ -3881,7 +3885,7 @@ WebGLContext::TexImage2D_base(TexImageTarget texImageTarget, GLint level,
         return ErrorInvalidOperation("texImage2D: not enough data for operation (need %d, have %d)",
                                  bytesNeeded, byteLength);
 
-    WebGLTexture *tex = activeBoundTextureForTexImageTarget(texImageTarget);
+    WebGLTexture* tex = ActiveBoundTextureForTexImageTarget(texImageTarget);
 
     if (!tex)
         return ErrorInvalidOperation("texImage2D: no texture is bound to this target");
@@ -4031,18 +4035,15 @@ WebGLContext::TexSubImage2D_base(TexImageTarget texImageTarget, GLint level,
     const WebGLTexImageFunc func = WebGLTexImageFunc::TexSubImage;
     const WebGLTexDimensions dims = WebGLTexDimensions::Tex2D;
 
-    if (type == LOCAL_GL_HALF_FLOAT_OES) {
+    if (type == LOCAL_GL_HALF_FLOAT_OES)
         type = LOCAL_GL_HALF_FLOAT;
-    }
 
-    WebGLTexture *tex = activeBoundTextureForTexImageTarget(texImageTarget);
-    if (!tex) {
+    WebGLTexture* tex = ActiveBoundTextureForTexImageTarget(texImageTarget);
+    if (!tex)
         return ErrorInvalidOperation("texSubImage2D: no texture bound on active texture unit");
-    }
 
-    if (!tex->HasImageInfoAt(texImageTarget, level)) {
+    if (!tex->HasImageInfoAt(texImageTarget, level))
         return ErrorInvalidOperation("texSubImage2D: no previously defined texture image");
-    }
 
     const WebGLTexture::ImageInfo& imageInfo = tex->ImageInfoAt(texImageTarget, level);
     const TexInternalFormat existingEffectiveInternalFormat = imageInfo.EffectiveInternalFormat();
@@ -4234,7 +4235,7 @@ WebGLContext::RestoreContext()
 }
 
 bool
-BaseTypeAndSizeFromUniformType(GLenum uType, GLenum *baseType, GLint *unitSize)
+BaseTypeAndSizeFromUniformType(GLenum uType, GLenum* baseType, GLint* unitSize)
 {
     switch (uType) {
         case LOCAL_GL_INT:
diff --git a/dom/canvas/WebGLContextLossHandler.cpp b/dom/canvas/WebGLContextLossHandler.cpp
index 913db7cc009f..b15b3368e4a0 100644
--- a/dom/canvas/WebGLContextLossHandler.cpp
+++ b/dom/canvas/WebGLContextLossHandler.cpp
@@ -41,9 +41,8 @@ WebGLContextLossHandler::StartTimer(unsigned long delayMS)
                                  nsITimer::TYPE_ONE_SHOT);
 }
 
-/* static */ void
-WebGLContextLossHandler::StaticTimerCallback(nsITimer*,
-                                             void* voidHandler)
+/*static*/ void
+WebGLContextLossHandler::StaticTimerCallback(nsITimer*, void* voidHandler)
 {
     typedef WebGLContextLossHandler T;
     T* handler = static_cast(voidHandler);
diff --git a/dom/canvas/WebGLContextLossHandler.h b/dom/canvas/WebGLContextLossHandler.h
index 9ffc871847a7..0769de910535 100644
--- a/dom/canvas/WebGLContextLossHandler.h
+++ b/dom/canvas/WebGLContextLossHandler.h
@@ -29,7 +29,7 @@ class WebGLContextLossHandler
 public:
     NS_INLINE_DECL_REFCOUNTING(WebGLContextLossHandler)
 
-    explicit WebGLContextLossHandler(WebGLContext* aWebgl);
+    explicit WebGLContextLossHandler(WebGLContext* webgl);
 
     void RunTimer();
     void DisableTimer();
diff --git a/dom/canvas/WebGLContextNotSupported.cpp b/dom/canvas/WebGLContextNotSupported.cpp
index 94eb14eaf2a5..f39a5bac2a2f 100644
--- a/dom/canvas/WebGLContextNotSupported.cpp
+++ b/dom/canvas/WebGLContextNotSupported.cpp
@@ -5,6 +5,6 @@
 
 #include "nsIDOMWebGLRenderingContext.h"
 
-#define DUMMY(func,rtype)  nsresult func (rtype ** aResult) { return NS_ERROR_FAILURE; }
+#define DUMMY(func,rtype) nsresult func (rtype **) { return NS_ERROR_FAILURE; }
 
 DUMMY(NS_NewCanvasRenderingContextWebGL, nsIDOMWebGLRenderingContext)
diff --git a/dom/canvas/WebGLContextReporter.cpp b/dom/canvas/WebGLContextReporter.cpp
index 0135467c1fed..1fb1916e33be 100644
--- a/dom/canvas/WebGLContextReporter.cpp
+++ b/dom/canvas/WebGLContextReporter.cpp
@@ -11,16 +11,16 @@ using namespace mozilla;
 NS_IMPL_ISUPPORTS(WebGLObserver, nsIObserver)
 
 NS_IMETHODIMP
-WebGLMemoryTracker::CollectReports(nsIHandleReportCallback* aHandleReport,
-                                   nsISupports* aData, bool aAnonymize)
+WebGLMemoryTracker::CollectReports(nsIHandleReportCallback* handleReport,
+                                   nsISupports* data, bool)
 {
-#define REPORT(_path, _kind, _units, _amount, _desc)                          \
-    do {                                                                      \
-      nsresult rv;                                                            \
-      rv = aHandleReport->Callback(EmptyCString(), NS_LITERAL_CSTRING(_path), \
-                                   _kind, _units, _amount,                    \
-                                   NS_LITERAL_CSTRING(_desc), aData);         \
-      NS_ENSURE_SUCCESS(rv, rv);                                              \
+#define REPORT(_path, _kind, _units, _amount, _desc)                         \
+    do {                                                                     \
+      nsresult rv;                                                           \
+      rv = handleReport->Callback(EmptyCString(), NS_LITERAL_CSTRING(_path), \
+                                   _kind, _units, _amount,                   \
+                                   NS_LITERAL_CSTRING(_desc), data);         \
+      NS_ENSURE_SUCCESS(rv, rv);                                             \
     } while (0)
 
     REPORT("webgl-texture-memory",
@@ -89,7 +89,8 @@ NS_IMPL_ISUPPORTS(WebGLMemoryTracker, nsIMemoryReporter)
 
 StaticRefPtr WebGLMemoryTracker::sUniqueInstance;
 
-WebGLMemoryTracker* WebGLMemoryTracker::UniqueInstance()
+WebGLMemoryTracker*
+WebGLMemoryTracker::UniqueInstance()
 {
     if (!sUniqueInstance) {
         sUniqueInstance = new WebGLMemoryTracker;
@@ -116,11 +117,12 @@ WebGLMemoryTracker::~WebGLMemoryTracker()
 MOZ_DEFINE_MALLOC_SIZE_OF(WebGLBufferMallocSizeOf)
 
 int64_t
-WebGLMemoryTracker::GetBufferCacheMemoryUsed() {
-    const ContextsArrayType & contexts = Contexts();
+WebGLMemoryTracker::GetBufferCacheMemoryUsed()
+{
+    const ContextsArrayType& contexts = Contexts();
     int64_t result = 0;
     for(size_t i = 0; i < contexts.Length(); ++i) {
-        for (const WebGLBuffer *buffer = contexts[i]->mBuffers.getFirst();
+        for (const WebGLBuffer* buffer = contexts[i]->mBuffers.getFirst();
              buffer;
              buffer = buffer->getNext())
         {
@@ -134,11 +136,12 @@ WebGLMemoryTracker::GetBufferCacheMemoryUsed() {
 MOZ_DEFINE_MALLOC_SIZE_OF(WebGLShaderMallocSizeOf)
 
 int64_t
-WebGLMemoryTracker::GetShaderSize() {
-    const ContextsArrayType & contexts = Contexts();
+WebGLMemoryTracker::GetShaderSize()
+{
+    const ContextsArrayType& contexts = Contexts();
     int64_t result = 0;
     for(size_t i = 0; i < contexts.Length(); ++i) {
-        for (const WebGLShader *shader = contexts[i]->mShaders.getFirst();
+        for (const WebGLShader* shader = contexts[i]->mShaders.getFirst();
              shader;
              shader = shader->getNext())
         {
diff --git a/dom/canvas/WebGLContextUtils.cpp b/dom/canvas/WebGLContextUtils.cpp
index 8a990a08e74f..6fe0b5520165 100644
--- a/dom/canvas/WebGLContextUtils.cpp
+++ b/dom/canvas/WebGLContextUtils.cpp
@@ -5,10 +5,9 @@
 
 #include "WebGLContext.h"
 
-#include 
-
 #include "GLContext.h"
 #include "jsapi.h"
+#include "mozilla/dom/ScriptSettings.h"
 #include "mozilla/Preferences.h"
 #include "nsIDOMDataContainerEvent.h"
 #include "nsIDOMEvent.h"
@@ -17,6 +16,7 @@
 #include "nsPrintfCString.h"
 #include "nsServiceManagerUtils.h"
 #include "prprf.h"
+#include 
 #include "WebGLBuffer.h"
 #include "WebGLExtensions.h"
 #include "WebGLFramebuffer.h"
@@ -25,8 +25,6 @@
 #include "WebGLVertexArray.h"
 #include "WebGLContextUtils.h"
 
-#include "mozilla/dom/ScriptSettings.h"
-
 namespace mozilla {
 
 using namespace gl;
@@ -83,33 +81,33 @@ GLComponents::GLComponents(TexInternalFormat internalformat)
     mComponents = 0;
 
     switch (unsizedformat.get()) {
-        case LOCAL_GL_RGBA:
-        case LOCAL_GL_RGBA4:
-        case LOCAL_GL_RGBA8:
-        case LOCAL_GL_RGB5_A1:
-        // Luminance + Alpha can be converted
-        // to and from RGBA
-        case LOCAL_GL_LUMINANCE_ALPHA:
-            mComponents |= Components::Alpha;
-        // Drops through
-        case LOCAL_GL_RGB:
-        case LOCAL_GL_RGB565:
-        // Luminance can be converted to and from RGB
-        case LOCAL_GL_LUMINANCE:
-            mComponents |= Components::Red | Components::Green | Components::Blue;
-            break;
-        case LOCAL_GL_ALPHA:
-            mComponents |= Components::Alpha;
-            break;
-        case LOCAL_GL_DEPTH_COMPONENT:
-            mComponents |= Components::Depth;
-            break;
-        case LOCAL_GL_DEPTH_STENCIL:
-            mComponents |= Components::Stencil;
-            break;
-        default:
-            MOZ_ASSERT(false, "Unhandled case - GLComponents");
-            break;
+    case LOCAL_GL_RGBA:
+    case LOCAL_GL_RGBA4:
+    case LOCAL_GL_RGBA8:
+    case LOCAL_GL_RGB5_A1:
+    // Luminance + Alpha can be converted
+    // to and from RGBA
+    case LOCAL_GL_LUMINANCE_ALPHA:
+        mComponents |= Components::Alpha;
+    // Drops through
+    case LOCAL_GL_RGB:
+    case LOCAL_GL_RGB565:
+    // Luminance can be converted to and from RGB
+    case LOCAL_GL_LUMINANCE:
+        mComponents |= Components::Red | Components::Green | Components::Blue;
+        break;
+    case LOCAL_GL_ALPHA:
+        mComponents |= Components::Alpha;
+        break;
+    case LOCAL_GL_DEPTH_COMPONENT:
+        mComponents |= Components::Depth;
+        break;
+    case LOCAL_GL_DEPTH_STENCIL:
+        mComponents |= Components::Stencil;
+        break;
+    default:
+        MOZ_ASSERT(false, "Unhandled case - GLComponents");
+        break;
     }
 }
 
@@ -173,8 +171,8 @@ EffectiveInternalFormatFromUnsizedInternalFormatAndType(TexInternalFormat intern
 
 void
 UnsizedInternalFormatAndTypeFromEffectiveInternalFormat(TexInternalFormat effectiveinternalformat,
-                                                        TexInternalFormat* out_internalformat,
-                                                        TexType* out_type)
+                                                        TexInternalFormat* const out_internalformat,
+                                                        TexType* const out_type)
 {
     MOZ_ASSERT(TypeFromInternalFormat(effectiveinternalformat) != LOCAL_GL_NONE);
 
@@ -207,13 +205,13 @@ EffectiveInternalFormatFromInternalFormatAndType(TexInternalFormat internalforma
                                                  TexType type)
 {
     TexType typeOfInternalFormat = TypeFromInternalFormat(internalformat);
-    if (typeOfInternalFormat == LOCAL_GL_NONE) {
+    if (typeOfInternalFormat == LOCAL_GL_NONE)
         return EffectiveInternalFormatFromUnsizedInternalFormatAndType(internalformat, type);
-    } else if (typeOfInternalFormat == type) {
+
+    if (typeOfInternalFormat == type)
         return internalformat;
-    } else {
-        return LOCAL_GL_NONE;
-    }
+
+    return LOCAL_GL_NONE;
 }
 
 /**
@@ -223,9 +221,9 @@ EffectiveInternalFormatFromInternalFormatAndType(TexInternalFormat internalforma
 void
 DriverFormatsFromEffectiveInternalFormat(gl::GLContext* gl,
                                          TexInternalFormat effectiveinternalformat,
-                                         GLenum* out_driverInternalFormat,
-                                         GLenum* out_driverFormat,
-                                         GLenum* out_driverType)
+                                         GLenum* const out_driverInternalFormat,
+                                         GLenum* const out_driverFormat,
+                                         GLenum* const out_driverType)
 {
     MOZ_ASSERT(out_driverInternalFormat);
     MOZ_ASSERT(out_driverFormat);
@@ -235,14 +233,14 @@ DriverFormatsFromEffectiveInternalFormat(gl::GLContext* gl,
     TexType type = LOCAL_GL_NONE;
 
     UnsizedInternalFormatAndTypeFromEffectiveInternalFormat(effectiveinternalformat,
-                                                            &unsizedinternalformat, &type);
+                                                            &unsizedinternalformat,
+                                                            &type);
 
     // driverType: almost always the generic type that we just got, except on ES
     // we must replace HALF_FLOAT by HALF_FLOAT_OES
     GLenum driverType = type.get();
-    if (gl->IsGLES() && type == LOCAL_GL_HALF_FLOAT) {
+    if (gl->IsGLES() && type == LOCAL_GL_HALF_FLOAT)
         driverType = LOCAL_GL_HALF_FLOAT_OES;
-    }
 
     // driverFormat: always just the unsized internalformat that we just got
     GLenum driverFormat = unsizedinternalformat.get();
@@ -253,11 +251,10 @@ DriverFormatsFromEffectiveInternalFormat(gl::GLContext* gl,
     GLenum driverInternalFormat = driverFormat;
     if (!gl->IsGLES()) {
         // Cases where desktop OpenGL requires a tweak to 'format'
-        if (driverFormat == LOCAL_GL_SRGB) {
+        if (driverFormat == LOCAL_GL_SRGB)
             driverFormat = LOCAL_GL_RGB;
-        } else if (driverFormat == LOCAL_GL_SRGB_ALPHA) {
+        else if (driverFormat == LOCAL_GL_SRGB_ALPHA)
             driverFormat = LOCAL_GL_RGBA;
-        }
 
         // WebGL2's new formats are not legal values for internalformat,
         // as using unsized internalformat is deprecated.
@@ -405,7 +402,7 @@ GetBitsPerTexel(TexInternalFormat effectiveinternalformat)
 }
 
 void
-WebGLContext::GenerateWarning(const char *fmt, ...)
+WebGLContext::GenerateWarning(const char* fmt, ...)
 {
     va_list ap;
     va_start(ap, fmt);
@@ -416,7 +413,7 @@ WebGLContext::GenerateWarning(const char *fmt, ...)
 }
 
 void
-WebGLContext::GenerateWarning(const char *fmt, va_list ap)
+WebGLContext::GenerateWarning(const char* fmt, va_list ap)
 {
     if (!ShouldGenerateWarnings())
         return;
@@ -432,27 +429,24 @@ WebGLContext::GenerateWarning(const char *fmt, va_list ap)
     JS_ReportWarning(cx, "WebGL: %s", buf);
     if (!ShouldGenerateWarnings()) {
         JS_ReportWarning(cx,
-            "WebGL: No further warnings will be reported for this WebGL context "
-            "(already reported %d warnings)", mAlreadyGeneratedWarnings);
+                         "WebGL: No further warnings will be reported for this"
+                         " WebGL context. (already reported %d warnings)",
+                         mAlreadyGeneratedWarnings);
     }
 }
 
 bool
 WebGLContext::ShouldGenerateWarnings() const
 {
-    if (mMaxWarnings == -1) {
+    if (mMaxWarnings == -1)
         return true;
-    }
 
     return mAlreadyGeneratedWarnings < mMaxWarnings;
 }
 
 CheckedUint32
-WebGLContext::GetImageSize(GLsizei height,
-                           GLsizei width,
-                           GLsizei depth,
-                           uint32_t pixelSize,
-                           uint32_t packOrUnpackAlignment)
+WebGLContext::GetImageSize(GLsizei height, GLsizei width, GLsizei depth,
+                           uint32_t pixelSize, uint32_t packOrUnpackAlignment)
 {
     CheckedUint32 checked_plainRowSize = CheckedUint32(width) * pixelSize;
 
@@ -460,8 +454,11 @@ WebGLContext::GetImageSize(GLsizei height,
     CheckedUint32 checked_alignedRowSize = RoundedToNextMultipleOf(checked_plainRowSize, packOrUnpackAlignment);
 
     // if height is 0, we don't need any memory to store this; without this check, we'll get an overflow
-    CheckedUint32 checked_2dImageSize
-        = height <= 0 ? 0 : (height-1) * checked_alignedRowSize + checked_plainRowSize;
+    CheckedUint32 checked_2dImageSize = 0;
+    if (height >= 1) {
+        checked_2dImageSize = (height-1) * checked_alignedRowSize +
+                              checked_plainRowSize;
+    }
 
     // FIXME - we should honor UNPACK_IMAGE_HEIGHT
     CheckedUint32 checked_imageSize = checked_2dImageSize * depth;
@@ -482,7 +479,7 @@ WebGLContext::SynthesizeGLError(GLenum err)
 }
 
 void
-WebGLContext::SynthesizeGLError(GLenum err, const char *fmt, ...)
+WebGLContext::SynthesizeGLError(GLenum err, const char* fmt, ...)
 {
     va_list va;
     va_start(va, fmt);
@@ -493,7 +490,7 @@ WebGLContext::SynthesizeGLError(GLenum err, const char *fmt, ...)
 }
 
 void
-WebGLContext::ErrorInvalidEnum(const char *fmt, ...)
+WebGLContext::ErrorInvalidEnum(const char* fmt, ...)
 {
     va_list va;
     va_start(va, fmt);
@@ -504,7 +501,7 @@ WebGLContext::ErrorInvalidEnum(const char *fmt, ...)
 }
 
 void
-WebGLContext::ErrorInvalidEnumInfo(const char *info, GLenum enumvalue)
+WebGLContext::ErrorInvalidEnumInfo(const char* info, GLenum enumvalue)
 {
     nsCString name;
     EnumName(enumvalue, &name);
@@ -513,7 +510,7 @@ WebGLContext::ErrorInvalidEnumInfo(const char *info, GLenum enumvalue)
 }
 
 void
-WebGLContext::ErrorInvalidOperation(const char *fmt, ...)
+WebGLContext::ErrorInvalidOperation(const char* fmt, ...)
 {
     va_list va;
     va_start(va, fmt);
@@ -524,7 +521,7 @@ WebGLContext::ErrorInvalidOperation(const char *fmt, ...)
 }
 
 void
-WebGLContext::ErrorInvalidValue(const char *fmt, ...)
+WebGLContext::ErrorInvalidValue(const char* fmt, ...)
 {
     va_list va;
     va_start(va, fmt);
@@ -535,7 +532,7 @@ WebGLContext::ErrorInvalidValue(const char *fmt, ...)
 }
 
 void
-WebGLContext::ErrorInvalidFramebufferOperation(const char *fmt, ...)
+WebGLContext::ErrorInvalidFramebufferOperation(const char* fmt, ...)
 {
     va_list va;
     va_start(va, fmt);
@@ -546,7 +543,7 @@ WebGLContext::ErrorInvalidFramebufferOperation(const char *fmt, ...)
 }
 
 void
-WebGLContext::ErrorOutOfMemory(const char *fmt, ...)
+WebGLContext::ErrorOutOfMemory(const char* fmt, ...)
 {
     va_list va;
     va_start(va, fmt);
@@ -556,25 +553,25 @@ WebGLContext::ErrorOutOfMemory(const char *fmt, ...)
     return SynthesizeGLError(LOCAL_GL_OUT_OF_MEMORY);
 }
 
-const char *
+const char*
 WebGLContext::ErrorName(GLenum error)
 {
     switch(error) {
-        case LOCAL_GL_INVALID_ENUM:
-            return "INVALID_ENUM";
-        case LOCAL_GL_INVALID_OPERATION:
-            return "INVALID_OPERATION";
-        case LOCAL_GL_INVALID_VALUE:
-            return "INVALID_VALUE";
-        case LOCAL_GL_OUT_OF_MEMORY:
-            return "OUT_OF_MEMORY";
-        case LOCAL_GL_INVALID_FRAMEBUFFER_OPERATION:
-            return "INVALID_FRAMEBUFFER_OPERATION";
-        case LOCAL_GL_NO_ERROR:
-            return "NO_ERROR";
-        default:
-            MOZ_ASSERT(false);
-            return "[unknown WebGL error!]";
+    case LOCAL_GL_INVALID_ENUM:
+        return "INVALID_ENUM";
+    case LOCAL_GL_INVALID_OPERATION:
+        return "INVALID_OPERATION";
+    case LOCAL_GL_INVALID_VALUE:
+        return "INVALID_VALUE";
+    case LOCAL_GL_OUT_OF_MEMORY:
+        return "OUT_OF_MEMORY";
+    case LOCAL_GL_INVALID_FRAMEBUFFER_OPERATION:
+        return "INVALID_FRAMEBUFFER_OPERATION";
+    case LOCAL_GL_NO_ERROR:
+        return "NO_ERROR";
+    default:
+        MOZ_ASSERT(false);
+        return "[unknown WebGL error]";
     }
 }
 
@@ -919,31 +916,31 @@ bool
 WebGLContext::IsCompressedTextureFormat(GLenum format)
 {
     switch (format) {
-        case LOCAL_GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
-        case LOCAL_GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
-        case LOCAL_GL_COMPRESSED_RGBA_S3TC_DXT3_EXT:
-        case LOCAL_GL_COMPRESSED_RGBA_S3TC_DXT5_EXT:
-        case LOCAL_GL_ATC_RGB:
-        case LOCAL_GL_ATC_RGBA_EXPLICIT_ALPHA:
-        case LOCAL_GL_ATC_RGBA_INTERPOLATED_ALPHA:
-        case LOCAL_GL_COMPRESSED_RGB_PVRTC_4BPPV1:
-        case LOCAL_GL_COMPRESSED_RGB_PVRTC_2BPPV1:
-        case LOCAL_GL_COMPRESSED_RGBA_PVRTC_4BPPV1:
-        case LOCAL_GL_COMPRESSED_RGBA_PVRTC_2BPPV1:
-        case LOCAL_GL_ETC1_RGB8_OES:
-        case LOCAL_GL_COMPRESSED_R11_EAC:
-        case LOCAL_GL_COMPRESSED_SIGNED_R11_EAC:
-        case LOCAL_GL_COMPRESSED_RG11_EAC:
-        case LOCAL_GL_COMPRESSED_SIGNED_RG11_EAC:
-        case LOCAL_GL_COMPRESSED_RGB8_ETC2:
-        case LOCAL_GL_COMPRESSED_SRGB8_ETC2:
-        case LOCAL_GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_ETC2:
-        case LOCAL_GL_COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_ETC2:
-        case LOCAL_GL_COMPRESSED_RGBA8_ETC2_EAC:
-        case LOCAL_GL_COMPRESSED_SRGB8_ALPHA8_ETC2_EAC:
-            return true;
-        default:
-            return false;
+    case LOCAL_GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
+    case LOCAL_GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
+    case LOCAL_GL_COMPRESSED_RGBA_S3TC_DXT3_EXT:
+    case LOCAL_GL_COMPRESSED_RGBA_S3TC_DXT5_EXT:
+    case LOCAL_GL_ATC_RGB:
+    case LOCAL_GL_ATC_RGBA_EXPLICIT_ALPHA:
+    case LOCAL_GL_ATC_RGBA_INTERPOLATED_ALPHA:
+    case LOCAL_GL_COMPRESSED_RGB_PVRTC_4BPPV1:
+    case LOCAL_GL_COMPRESSED_RGB_PVRTC_2BPPV1:
+    case LOCAL_GL_COMPRESSED_RGBA_PVRTC_4BPPV1:
+    case LOCAL_GL_COMPRESSED_RGBA_PVRTC_2BPPV1:
+    case LOCAL_GL_ETC1_RGB8_OES:
+    case LOCAL_GL_COMPRESSED_R11_EAC:
+    case LOCAL_GL_COMPRESSED_SIGNED_R11_EAC:
+    case LOCAL_GL_COMPRESSED_RG11_EAC:
+    case LOCAL_GL_COMPRESSED_SIGNED_RG11_EAC:
+    case LOCAL_GL_COMPRESSED_RGB8_ETC2:
+    case LOCAL_GL_COMPRESSED_SRGB8_ETC2:
+    case LOCAL_GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_ETC2:
+    case LOCAL_GL_COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_ETC2:
+    case LOCAL_GL_COMPRESSED_RGBA8_ETC2_EAC:
+    case LOCAL_GL_COMPRESSED_SRGB8_ALPHA8_ETC2_EAC:
+        return true;
+    default:
+        return false;
     }
 }
 
@@ -995,7 +992,8 @@ AssertUintParamCorrect(gl::GLContext* gl, GLenum pname, GLuint shadow)
 }
 
 void
-AssertMaskedUintParamCorrect(gl::GLContext* gl, GLenum pname, GLuint mask, GLuint shadow)
+AssertMaskedUintParamCorrect(gl::GLContext* gl, GLenum pname, GLuint mask,
+                             GLuint shadow)
 {
     GLuint val = 0;
     gl->GetUIntegerv(pname, &val);
@@ -1040,11 +1038,11 @@ WebGLContext::AssertCachedBindings()
     GLenum activeTexture = mActiveTexture + LOCAL_GL_TEXTURE0;
     AssertUintParamCorrect(gl, LOCAL_GL_ACTIVE_TEXTURE, activeTexture);
 
-    WebGLTexture* curTex = activeBoundTextureForTarget(LOCAL_GL_TEXTURE_2D);
+    WebGLTexture* curTex = ActiveBoundTextureForTarget(LOCAL_GL_TEXTURE_2D);
     bound = curTex ? curTex->GLName() : 0;
     AssertUintParamCorrect(gl, LOCAL_GL_TEXTURE_BINDING_2D, bound);
 
-    curTex = activeBoundTextureForTarget(LOCAL_GL_TEXTURE_CUBE_MAP);
+    curTex = ActiveBoundTextureForTarget(LOCAL_GL_TEXTURE_CUBE_MAP);
     bound = curTex ? curTex->GLName() : 0;
     AssertUintParamCorrect(gl, LOCAL_GL_TEXTURE_BINDING_CUBE_MAP, bound);
 
diff --git a/dom/canvas/WebGLContextUtils.h b/dom/canvas/WebGLContextUtils.h
index cf6c54943252..89c9c61720c7 100644
--- a/dom/canvas/WebGLContextUtils.h
+++ b/dom/canvas/WebGLContextUtils.h
@@ -3,8 +3,8 @@
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
-#ifndef WEBGLCONTEXTUTILS_H_
-#define WEBGLCONTEXTUTILS_H_
+#ifndef WEBGL_CONTEXT_UTILS_H_
+#define WEBGL_CONTEXT_UTILS_H_
 
 #include "WebGLContext.h"
 #include "WebGLStrongTypes.h"
@@ -16,12 +16,13 @@ namespace mozilla {
 bool IsGLDepthFormat(TexInternalFormat webGLFormat);
 bool IsGLDepthStencilFormat(TexInternalFormat webGLFormat);
 bool FormatHasAlpha(TexInternalFormat webGLFormat);
+
 void
 DriverFormatsFromEffectiveInternalFormat(gl::GLContext* gl,
                                          TexInternalFormat internalformat,
-                                         GLenum* out_driverInternalFormat,
-                                         GLenum* out_driverFormat,
-                                         GLenum* out_driverType);
+                                         GLenum* const out_driverInternalFormat,
+                                         GLenum* const out_driverFormat,
+                                         GLenum* const out_driverType);
 TexInternalFormat
 EffectiveInternalFormatFromInternalFormatAndType(TexInternalFormat internalformat,
                                                  TexType type);
@@ -30,14 +31,14 @@ EffectiveInternalFormatFromUnsizedInternalFormatAndType(TexInternalFormat intern
                                                         TexType type);
 void
 UnsizedInternalFormatAndTypeFromEffectiveInternalFormat(TexInternalFormat effectiveinternalformat,
-                                                        TexInternalFormat* out_internalformat,
-                                                        TexType* out_type);
-TexType
-TypeFromInternalFormat(TexInternalFormat internalformat);
+                                                        TexInternalFormat* const out_internalformat,
+                                                        TexType* const out_type);
+TexType TypeFromInternalFormat(TexInternalFormat internalformat);
+
 TexInternalFormat
 UnsizedInternalFormatFromInternalFormat(TexInternalFormat internalformat);
-size_t
-GetBitsPerTexel(TexInternalFormat effectiveinternalformat);
+
+size_t GetBitsPerTexel(TexInternalFormat effectiveinternalformat);
 
 // For use with the different texture calls, i.e.
 //   TexImage2D, CopyTex[Sub]Image2D, ...
@@ -68,9 +69,9 @@ struct GLComponents
 
     GLComponents()
         : mComponents(0)
-    { }
+    {}
 
-    explicit GLComponents(TexInternalFormat aFormat);
+    explicit GLComponents(TexInternalFormat format);
 
     // Returns true iff other has all (or more) of
     // the components present in this GLComponents
@@ -79,17 +80,17 @@ struct GLComponents
 
 template 
 JS::Value
-WebGLContext::WebGLObjectAsJSValue(JSContext *cx, const WebGLObjectType *object, ErrorResult& rv) const
+WebGLContext::WebGLObjectAsJSValue(JSContext* cx, const WebGLObjectType* object,
+                                   ErrorResult& rv) const
 {
-    if (!object) {
+    if (!object)
         return JS::NullValue();
-    }
+
     MOZ_ASSERT(this == object->Context());
     JS::Rooted v(cx);
     JS::Rooted wrapper(cx, GetWrapper());
     JSAutoCompartment ac(cx, wrapper);
-    if (!dom::GetOrCreateDOMReflector(cx, const_cast(object),
-                                      &v)) {
+    if (!dom::GetOrCreateDOMReflector(cx, const_cast(object), &v)) {
         rv.Throw(NS_ERROR_FAILURE);
         return JS::NullValue();
     }
@@ -98,12 +99,14 @@ WebGLContext::WebGLObjectAsJSValue(JSContext *cx, const WebGLObjectType *object,
 
 template 
 JSObject*
-WebGLContext::WebGLObjectAsJSObject(JSContext *cx, const WebGLObjectType *object, ErrorResult& rv) const
+WebGLContext::WebGLObjectAsJSObject(JSContext* cx,
+                                    const WebGLObjectType* object,
+                                    ErrorResult& rv) const
 {
     JS::Value v = WebGLObjectAsJSValue(cx, object, rv);
-    if (v.isNull()) {
+    if (v.isNull())
         return nullptr;
-    }
+
     return &v.toObject();
 }
 
@@ -111,9 +114,8 @@ WebGLContext::WebGLObjectAsJSObject(JSContext *cx, const WebGLObjectType *object
  * Return the displayable name for the texture function that is the
  * source for validation.
  */
-const char*
-InfoFrom(WebGLTexImageFunc func, WebGLTexDimensions dims);
+const char* InfoFrom(WebGLTexImageFunc func, WebGLTexDimensions dims);
 
 } // namespace mozilla
 
-#endif // WEBGLCONTEXTUTILS_H_
+#endif // WEBGL_CONTEXT_UTILS_H_
diff --git a/dom/canvas/WebGLContextValidate.cpp b/dom/canvas/WebGLContextValidate.cpp
index ea48ccb0d914..14cb93b3e92d 100644
--- a/dom/canvas/WebGLContextValidate.cpp
+++ b/dom/canvas/WebGLContextValidate.cpp
@@ -29,15 +29,16 @@
 #include "nsCocoaFeatures.h"
 #endif
 
-using namespace mozilla;
+namespace mozilla {
 
 /**
  * Return the block size for format.
  */
 static void
-BlockSizeFor(GLenum format, GLint* blockWidth, GLint* blockHeight)
+BlockSizeFor(GLenum format, GLint* const out_blockWidth,
+             GLint* const out_blockHeight)
 {
-    MOZ_ASSERT(blockWidth && blockHeight);
+    MOZ_ASSERT(out_blockWidth && out_blockHeight);
 
     switch (format) {
     case LOCAL_GL_ATC_RGB:
@@ -47,14 +48,14 @@ BlockSizeFor(GLenum format, GLint* blockWidth, GLint* blockHeight)
     case LOCAL_GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
     case LOCAL_GL_COMPRESSED_RGBA_S3TC_DXT3_EXT:
     case LOCAL_GL_COMPRESSED_RGBA_S3TC_DXT5_EXT:
-        if (blockWidth)
-            *blockWidth = 4;
-        if (blockHeight)
-            *blockHeight = 4;
+        *out_blockWidth = 4;
+        *out_blockHeight = 4;
         break;
 
     case LOCAL_GL_ETC1_RGB8_OES:
         // 4x4 blocks, but no 4-multiple requirement.
+        break;
+
     default:
         break;
     }
@@ -72,13 +73,16 @@ IsCompressedFunc(WebGLTexImageFunc func)
  * name for \a glenum.
  */
 static void
-ErrorInvalidEnumWithName(WebGLContext* ctx, const char* msg, GLenum glenum, WebGLTexImageFunc func, WebGLTexDimensions dims)
+ErrorInvalidEnumWithName(WebGLContext* ctx, const char* msg, GLenum glenum,
+                         WebGLTexImageFunc func, WebGLTexDimensions dims)
 {
     const char* name = WebGLContext::EnumName(glenum);
-    if (name)
+    if (name) {
         ctx->ErrorInvalidEnum("%s: %s %s", InfoFrom(func, dims), msg, name);
-    else
-        ctx->ErrorInvalidEnum("%s: %s 0x%04X", InfoFrom(func, dims), msg, glenum);
+    } else {
+        ctx->ErrorInvalidEnum("%s: %s 0x%04x", InfoFrom(func, dims), msg,
+                              glenum);
+    }
 }
 
 /**
@@ -140,178 +144,201 @@ IsTexImageCubemapTarget(GLenum texImageTarget)
             texImageTarget <= LOCAL_GL_TEXTURE_CUBE_MAP_NEGATIVE_Z);
 }
 
-bool WebGLContext::ValidateBlendEquationEnum(GLenum mode, const char *info)
+bool
+WebGLContext::ValidateBlendEquationEnum(GLenum mode, const char* info)
 {
     switch (mode) {
-        case LOCAL_GL_FUNC_ADD:
-        case LOCAL_GL_FUNC_SUBTRACT:
-        case LOCAL_GL_FUNC_REVERSE_SUBTRACT:
+    case LOCAL_GL_FUNC_ADD:
+    case LOCAL_GL_FUNC_SUBTRACT:
+    case LOCAL_GL_FUNC_REVERSE_SUBTRACT:
+        return true;
+
+    case LOCAL_GL_MIN:
+    case LOCAL_GL_MAX:
+        if (IsExtensionEnabled(WebGLExtensionID::EXT_blend_minmax))
             return true;
-        case LOCAL_GL_MIN:
-        case LOCAL_GL_MAX:
-            if (IsExtensionEnabled(WebGLExtensionID::EXT_blend_minmax)) {
-                return true;
-            }
-            break;
-        default:
-            break;
+
+        break;
+
+    default:
+        break;
     }
 
     ErrorInvalidEnumInfo(info, mode);
     return false;
 }
 
-bool WebGLContext::ValidateBlendFuncDstEnum(GLenum factor, const char *info)
+bool
+WebGLContext::ValidateBlendFuncDstEnum(GLenum factor, const char* info)
 {
     switch (factor) {
-        case LOCAL_GL_ZERO:
-        case LOCAL_GL_ONE:
-        case LOCAL_GL_SRC_COLOR:
-        case LOCAL_GL_ONE_MINUS_SRC_COLOR:
-        case LOCAL_GL_DST_COLOR:
-        case LOCAL_GL_ONE_MINUS_DST_COLOR:
-        case LOCAL_GL_SRC_ALPHA:
-        case LOCAL_GL_ONE_MINUS_SRC_ALPHA:
-        case LOCAL_GL_DST_ALPHA:
-        case LOCAL_GL_ONE_MINUS_DST_ALPHA:
-        case LOCAL_GL_CONSTANT_COLOR:
-        case LOCAL_GL_ONE_MINUS_CONSTANT_COLOR:
-        case LOCAL_GL_CONSTANT_ALPHA:
-        case LOCAL_GL_ONE_MINUS_CONSTANT_ALPHA:
-            return true;
-        default:
-            ErrorInvalidEnumInfo(info, factor);
-            return false;
+    case LOCAL_GL_ZERO:
+    case LOCAL_GL_ONE:
+    case LOCAL_GL_SRC_COLOR:
+    case LOCAL_GL_ONE_MINUS_SRC_COLOR:
+    case LOCAL_GL_DST_COLOR:
+    case LOCAL_GL_ONE_MINUS_DST_COLOR:
+    case LOCAL_GL_SRC_ALPHA:
+    case LOCAL_GL_ONE_MINUS_SRC_ALPHA:
+    case LOCAL_GL_DST_ALPHA:
+    case LOCAL_GL_ONE_MINUS_DST_ALPHA:
+    case LOCAL_GL_CONSTANT_COLOR:
+    case LOCAL_GL_ONE_MINUS_CONSTANT_COLOR:
+    case LOCAL_GL_CONSTANT_ALPHA:
+    case LOCAL_GL_ONE_MINUS_CONSTANT_ALPHA:
+        return true;
+
+    default:
+        ErrorInvalidEnumInfo(info, factor);
+        return false;
     }
 }
 
-bool WebGLContext::ValidateBlendFuncSrcEnum(GLenum factor, const char *info)
+bool
+WebGLContext::ValidateBlendFuncSrcEnum(GLenum factor, const char* info)
 {
     if (factor == LOCAL_GL_SRC_ALPHA_SATURATE)
         return true;
-    else
-        return ValidateBlendFuncDstEnum(factor, info);
+
+    return ValidateBlendFuncDstEnum(factor, info);
 }
 
-bool WebGLContext::ValidateBlendFuncEnumsCompatibility(GLenum sfactor, GLenum dfactor, const char *info)
+bool
+WebGLContext::ValidateBlendFuncEnumsCompatibility(GLenum sfactor,
+                                                  GLenum dfactor,
+                                                  const char* info)
 {
     bool sfactorIsConstantColor = sfactor == LOCAL_GL_CONSTANT_COLOR ||
-                                    sfactor == LOCAL_GL_ONE_MINUS_CONSTANT_COLOR;
+                                  sfactor == LOCAL_GL_ONE_MINUS_CONSTANT_COLOR;
     bool sfactorIsConstantAlpha = sfactor == LOCAL_GL_CONSTANT_ALPHA ||
-                                    sfactor == LOCAL_GL_ONE_MINUS_CONSTANT_ALPHA;
+                                  sfactor == LOCAL_GL_ONE_MINUS_CONSTANT_ALPHA;
     bool dfactorIsConstantColor = dfactor == LOCAL_GL_CONSTANT_COLOR ||
-                                    dfactor == LOCAL_GL_ONE_MINUS_CONSTANT_COLOR;
+                                  dfactor == LOCAL_GL_ONE_MINUS_CONSTANT_COLOR;
     bool dfactorIsConstantAlpha = dfactor == LOCAL_GL_CONSTANT_ALPHA ||
-                                    dfactor == LOCAL_GL_ONE_MINUS_CONSTANT_ALPHA;
+                                  dfactor == LOCAL_GL_ONE_MINUS_CONSTANT_ALPHA;
     if ( (sfactorIsConstantColor && dfactorIsConstantAlpha) ||
-         (dfactorIsConstantColor && sfactorIsConstantAlpha) ) {
-        ErrorInvalidOperation("%s are mutually incompatible, see section 6.8 in the WebGL 1.0 spec", info);
+         (dfactorIsConstantColor && sfactorIsConstantAlpha) )
+    {
+        ErrorInvalidOperation("%s are mutually incompatible, see section 6.8 in"
+                              " the WebGL 1.0 spec", info);
         return false;
-    } else {
+    }
+
+    return true;
+}
+
+bool
+WebGLContext::ValidateTextureTargetEnum(GLenum target, const char* info)
+{
+    switch (target) {
+    case LOCAL_GL_TEXTURE_2D:
+    case LOCAL_GL_TEXTURE_CUBE_MAP:
         return true;
+
+    case LOCAL_GL_TEXTURE_3D:
+        if (IsWebGL2())
+            return true;
+
+        break;
+
+    default:
+        break;
     }
+
+    ErrorInvalidEnumInfo(info, target);
+    return false;
 }
 
-bool WebGLContext::ValidateTextureTargetEnum(GLenum target, const char *info)
+bool
+WebGLContext::ValidateComparisonEnum(GLenum target, const char* info)
 {
     switch (target) {
-        case LOCAL_GL_TEXTURE_2D:
-        case LOCAL_GL_TEXTURE_CUBE_MAP:
-            return true;
-        case LOCAL_GL_TEXTURE_3D: {
-            const bool isValid = IsWebGL2();
-            if (!isValid) {
-                ErrorInvalidEnumInfo(info, target);
-            }
-            return isValid;
-        }
-        default:
-            ErrorInvalidEnumInfo(info, target);
-            return false;
+    case LOCAL_GL_NEVER:
+    case LOCAL_GL_LESS:
+    case LOCAL_GL_LEQUAL:
+    case LOCAL_GL_GREATER:
+    case LOCAL_GL_GEQUAL:
+    case LOCAL_GL_EQUAL:
+    case LOCAL_GL_NOTEQUAL:
+    case LOCAL_GL_ALWAYS:
+        return true;
+
+    default:
+        ErrorInvalidEnumInfo(info, target);
+        return false;
     }
 }
 
-bool WebGLContext::ValidateComparisonEnum(GLenum target, const char *info)
-{
-    switch (target) {
-        case LOCAL_GL_NEVER:
-        case LOCAL_GL_LESS:
-        case LOCAL_GL_LEQUAL:
-        case LOCAL_GL_GREATER:
-        case LOCAL_GL_GEQUAL:
-        case LOCAL_GL_EQUAL:
-        case LOCAL_GL_NOTEQUAL:
-        case LOCAL_GL_ALWAYS:
-            return true;
-        default:
-            ErrorInvalidEnumInfo(info, target);
-            return false;
-    }
-}
-
-bool WebGLContext::ValidateStencilOpEnum(GLenum action, const char *info)
+bool
+WebGLContext::ValidateStencilOpEnum(GLenum action, const char* info)
 {
     switch (action) {
-        case LOCAL_GL_KEEP:
-        case LOCAL_GL_ZERO:
-        case LOCAL_GL_REPLACE:
-        case LOCAL_GL_INCR:
-        case LOCAL_GL_INCR_WRAP:
-        case LOCAL_GL_DECR:
-        case LOCAL_GL_DECR_WRAP:
-        case LOCAL_GL_INVERT:
-            return true;
-        default:
-            ErrorInvalidEnumInfo(info, action);
-            return false;
+    case LOCAL_GL_KEEP:
+    case LOCAL_GL_ZERO:
+    case LOCAL_GL_REPLACE:
+    case LOCAL_GL_INCR:
+    case LOCAL_GL_INCR_WRAP:
+    case LOCAL_GL_DECR:
+    case LOCAL_GL_DECR_WRAP:
+    case LOCAL_GL_INVERT:
+        return true;
+
+    default:
+        ErrorInvalidEnumInfo(info, action);
+        return false;
     }
 }
 
-bool WebGLContext::ValidateFaceEnum(GLenum face, const char *info)
+bool
+WebGLContext::ValidateFaceEnum(GLenum face, const char* info)
 {
     switch (face) {
-        case LOCAL_GL_FRONT:
-        case LOCAL_GL_BACK:
-        case LOCAL_GL_FRONT_AND_BACK:
-            return true;
-        default:
-            ErrorInvalidEnumInfo(info, face);
-            return false;
+    case LOCAL_GL_FRONT:
+    case LOCAL_GL_BACK:
+    case LOCAL_GL_FRONT_AND_BACK:
+        return true;
+
+    default:
+        ErrorInvalidEnumInfo(info, face);
+        return false;
     }
 }
 
-bool WebGLContext::ValidateDrawModeEnum(GLenum mode, const char *info)
+bool
+WebGLContext::ValidateDrawModeEnum(GLenum mode, const char* info)
 {
     switch (mode) {
-        case LOCAL_GL_TRIANGLES:
-        case LOCAL_GL_TRIANGLE_STRIP:
-        case LOCAL_GL_TRIANGLE_FAN:
-        case LOCAL_GL_POINTS:
-        case LOCAL_GL_LINE_STRIP:
-        case LOCAL_GL_LINE_LOOP:
-        case LOCAL_GL_LINES:
-            return true;
-        default:
-            ErrorInvalidEnumInfo(info, mode);
-            return false;
+    case LOCAL_GL_TRIANGLES:
+    case LOCAL_GL_TRIANGLE_STRIP:
+    case LOCAL_GL_TRIANGLE_FAN:
+    case LOCAL_GL_POINTS:
+    case LOCAL_GL_LINE_STRIP:
+    case LOCAL_GL_LINE_LOOP:
+    case LOCAL_GL_LINES:
+        return true;
+
+    default:
+        ErrorInvalidEnumInfo(info, mode);
+        return false;
     }
 }
 
-bool WebGLContext::ValidateGLSLVariableName(const nsAString& name, const char *info)
+bool
+WebGLContext::ValidateGLSLVariableName(const nsAString& name, const char* info)
 {
     if (name.IsEmpty())
         return false;
 
     const uint32_t maxSize = 256;
     if (name.Length() > maxSize) {
-        ErrorInvalidValue("%s: identifier is %d characters long, exceeds the maximum allowed length of %d characters",
-                          info, name.Length(), maxSize);
+        ErrorInvalidValue("%s: Identifier is %d characters long, exceeds the"
+                          " maximum allowed length of %d characters.", info,
+                          name.Length(), maxSize);
         return false;
     }
 
-    if (!ValidateGLSLString(name, info)) {
+    if (!ValidateGLSLString(name, info))
         return false;
-    }
 
     nsString prefix1 = NS_LITERAL_STRING("webgl_");
     nsString prefix2 = NS_LITERAL_STRING("_webgl_");
@@ -319,18 +346,20 @@ bool WebGLContext::ValidateGLSLVariableName(const nsAString& name, const char *i
     if (Substring(name, 0, prefix1.Length()).Equals(prefix1) ||
         Substring(name, 0, prefix2.Length()).Equals(prefix2))
     {
-        ErrorInvalidOperation("%s: string contains a reserved GLSL prefix", info);
+        ErrorInvalidOperation("%s: String contains a reserved GLSL prefix.",
+                              info);
         return false;
     }
 
     return true;
 }
 
-bool WebGLContext::ValidateGLSLString(const nsAString& string, const char *info)
+bool WebGLContext::ValidateGLSLString(const nsAString& string, const char* info)
 {
     for (uint32_t i = 0; i < string.Length(); ++i) {
         if (!ValidateGLSLCharacter(string.CharAt(i))) {
-             ErrorInvalidValue("%s: string contains the illegal character '%d'", info, string.CharAt(i));
+             ErrorInvalidValue("%s: String contains the illegal character"
+                               " '%d'.", info, string.CharAt(i));
              return false;
         }
     }
@@ -343,17 +372,20 @@ bool WebGLContext::ValidateGLSLString(const nsAString& string, const char *info)
  * be one of depth/stencil/depth_stencil/color attachment.
  */
 bool
-WebGLContext::ValidateFramebufferAttachment(GLenum attachment, const char* funcName)
+WebGLContext::ValidateFramebufferAttachment(GLenum attachment,
+                                            const char* funcName)
 {
     if (!mBoundFramebuffer) {
         switch (attachment) {
-            case LOCAL_GL_COLOR:
-            case LOCAL_GL_DEPTH:
-            case LOCAL_GL_STENCIL:
-                return true;
-            default:
-                ErrorInvalidEnum("%s: attachment: invalid enum value 0x%x.", funcName, attachment);
-                return false;
+        case LOCAL_GL_COLOR:
+        case LOCAL_GL_DEPTH:
+        case LOCAL_GL_STENCIL:
+            return true;
+
+        default:
+            ErrorInvalidEnum("%s: attachment: invalid enum value 0x%x.",
+                             funcName, attachment);
+            return false;
         }
     }
 
@@ -374,7 +406,8 @@ WebGLContext::ValidateFramebufferAttachment(GLenum attachment, const char* funcN
         return true;
     }
 
-    ErrorInvalidEnum("%s: attachment: invalid enum value 0x%x.", funcName, attachment);
+    ErrorInvalidEnum("%s: attachment: invalid enum value 0x%x.", funcName,
+                     attachment);
     return false;
 }
 
@@ -495,7 +528,8 @@ WebGLContext::ValidateSamplerParameterParams(GLenum pname, const WebGLIntOrFloat
  * taking into account enabled WebGL extensions.
  */
 bool
-WebGLContext::ValidateTexImageFormat(GLenum format, WebGLTexImageFunc func, WebGLTexDimensions dims)
+WebGLContext::ValidateTexImageFormat(GLenum format, WebGLTexImageFunc func,
+                                     WebGLTexDimensions dims)
 {
     /* Core WebGL texture formats */
     if (format == LOCAL_GL_ALPHA ||
@@ -515,12 +549,12 @@ WebGLContext::ValidateTexImageFormat(GLenum format, WebGLTexImageFunc func, WebG
         format == LOCAL_GL_RGB_INTEGER ||
         format == LOCAL_GL_RGBA_INTEGER)
     {
-        bool valid = IsWebGL2();
-        if (!valid) {
-            ErrorInvalidEnum("%s:  invalid format %s: requires WebGL version 2.0 or newer",
-                             InfoFrom(func, dims), EnumName(format));
-        }
-        return valid;
+        if (IsWebGL2())
+            return true;
+
+        ErrorInvalidEnum("%s: Invalid format %s: Requires WebGL version 2.0 or"
+                         " newer.", InfoFrom(func, dims), EnumName(format));
+        return false;
     }
 
     /* WEBGL_depth_texture added formats */
@@ -528,19 +562,21 @@ WebGLContext::ValidateTexImageFormat(GLenum format, WebGLTexImageFunc func, WebG
         format == LOCAL_GL_DEPTH_STENCIL)
     {
         if (!IsExtensionEnabled(WebGLExtensionID::WEBGL_depth_texture)) {
-            ErrorInvalidEnum("%s: invalid format %s: need WEBGL_depth_texture enabled",
+            ErrorInvalidEnum("%s: Invalid format %s: Requires that"
+                             " WEBGL_depth_texture is enabled.",
                              InfoFrom(func, dims), EnumName(format));
             return false;
         }
 
-        // If WEBGL_depth_texture is enabled, then it is not allowed to be used with the
-        // copyTexImage, or copyTexSubImage methods, and it is not allowed with
-        // texSubImage in WebGL1.
+        // If WEBGL_depth_texture is enabled, then it is not allowed to be used
+        // with the copyTexImage, or copyTexSubImage methods, and it is not
+        // allowed with texSubImage in WebGL1.
         if ((func == WebGLTexImageFunc::TexSubImage && !IsWebGL2()) ||
             func == WebGLTexImageFunc::CopyTexImage ||
             func == WebGLTexImageFunc::CopyTexSubImage)
         {
-            ErrorInvalidOperation("%s: format %s is not supported", InfoFrom(func, dims), EnumName(format));
+            ErrorInvalidOperation("%s: format %s is not supported",
+                                  InfoFrom(func, dims), EnumName(format));
             return false;
         }
 
@@ -549,26 +585,27 @@ WebGLContext::ValidateTexImageFormat(GLenum format, WebGLTexImageFunc func, WebG
 
     // Needs to be below the depth_texture check because an invalid operation
     // error needs to be generated instead of invalid enum.
-    /* Only core formats are valid for CopyTex(Sub)?Image */
-    // TODO: Revisit this once color_buffer_(half_)?float lands
+    // Only core formats are valid for CopyTex[Sub]Image.
+    // TODO: Revisit this once color_buffer_[half_]float lands.
     if (IsCopyFunc(func)) {
         ErrorInvalidEnumWithName(this, "invalid format", format, func, dims);
         return false;
     }
 
-    /* EXT_sRGB added formats */
+    // EXT_sRGB added formats
     if (format == LOCAL_GL_SRGB ||
         format == LOCAL_GL_SRGB_ALPHA)
     {
-        bool validFormat = IsExtensionEnabled(WebGLExtensionID::EXT_sRGB);
-        if (!validFormat)
-            ErrorInvalidEnum("%s: invalid format %s: need EXT_sRGB enabled",
-                             InfoFrom(func, dims), WebGLContext::EnumName(format));
-        return validFormat;
+        if (IsExtensionEnabled(WebGLExtensionID::EXT_sRGB))
+            return true;
+
+        ErrorInvalidEnum("%s: Invalid format %s: Requires that EXT_sRGB is"
+                         " enabled.", InfoFrom(func, dims),
+                         WebGLContext::EnumName(format));
+        return false;
     }
 
     ErrorInvalidEnumWithName(this, "invalid format", format, func, dims);
-
     return false;
 }
 
@@ -576,8 +613,8 @@ WebGLContext::ValidateTexImageFormat(GLenum format, WebGLTexImageFunc func, WebG
  * Check if the given texture target is valid for TexImage.
  */
 bool
-WebGLContext::ValidateTexImageTarget(GLenum target,
-                                     WebGLTexImageFunc func, WebGLTexDimensions dims)
+WebGLContext::ValidateTexImageTarget(GLenum target, WebGLTexImageFunc func,
+                                     WebGLTexDimensions dims)
 {
     switch (dims) {
     case WebGLTexDimensions::Tex2D:
@@ -611,8 +648,7 @@ WebGLContext::ValidateTexImageTarget(GLenum target,
  * taking into account enabled WebGL extensions.
  */
 bool
-WebGLContext::ValidateTexImageType(GLenum type,
-                                   WebGLTexImageFunc func,
+WebGLContext::ValidateTexImageType(GLenum type, WebGLTexImageFunc func,
                                    WebGLTexDimensions dims)
 {
     /* Core WebGL texture types */
@@ -633,30 +669,35 @@ WebGLContext::ValidateTexImageType(GLenum type,
         type == LOCAL_GL_UNSIGNED_INT_10F_11F_11F_REV ||
         type == LOCAL_GL_UNSIGNED_INT_5_9_9_9_REV)
     {
-        bool validType = IsWebGL2();
-        if (!validType) {
-            ErrorInvalidEnum("%s: invalid type %s: requires WebGL version 2.0 or newer",
-                             InfoFrom(func, dims), WebGLContext::EnumName(type));
-        }
-        return validType;
+        if (IsWebGL2())
+            return true;
+
+        ErrorInvalidEnum("%s: Invalid type %s: Requires WebGL version 2.0 or"
+                         " newer.", InfoFrom(func, dims),
+                         WebGLContext::EnumName(type));
+        return false;
     }
 
     /* OES_texture_float added types */
     if (type == LOCAL_GL_FLOAT) {
-        bool validType = IsExtensionEnabled(WebGLExtensionID::OES_texture_float);
-        if (!validType)
-            ErrorInvalidEnum("%s: invalid type %s: need OES_texture_float enabled",
-                             InfoFrom(func, dims), WebGLContext::EnumName(type));
-        return validType;
+        if (IsExtensionEnabled(WebGLExtensionID::OES_texture_float))
+            return true;
+
+        ErrorInvalidEnum("%s: Invalid type %s: Requires that OES_texture_float"
+                         " is enabled.",
+                         InfoFrom(func, dims), WebGLContext::EnumName(type));
+        return false;
     }
 
     /* OES_texture_half_float add types */
     if (type == LOCAL_GL_HALF_FLOAT) {
-        bool validType = IsExtensionEnabled(WebGLExtensionID::OES_texture_half_float);
-        if (!validType)
-            ErrorInvalidEnum("%s: invalid type %s: need OES_texture_half_float enabled",
-                             InfoFrom(func, dims), WebGLContext::EnumName(type));
-        return validType;
+        if (IsExtensionEnabled(WebGLExtensionID::OES_texture_half_float))
+            return true;
+
+        ErrorInvalidEnum("%s: Invalid type %s: Requires that"
+                         " OES_texture_half_float is enabled.",
+                         InfoFrom(func, dims), WebGLContext::EnumName(type));
+        return false;
     }
 
     /* WEBGL_depth_texture added types */
@@ -664,11 +705,13 @@ WebGLContext::ValidateTexImageType(GLenum type,
         type == LOCAL_GL_UNSIGNED_INT ||
         type == LOCAL_GL_UNSIGNED_INT_24_8)
     {
-        bool validType = IsExtensionEnabled(WebGLExtensionID::WEBGL_depth_texture);
-        if (!validType)
-            ErrorInvalidEnum("%s: invalid type %s: need WEBGL_depth_texture enabled",
-                             InfoFrom(func, dims), WebGLContext::EnumName(type));
-        return validType;
+        if (IsExtensionEnabled(WebGLExtensionID::WEBGL_depth_texture))
+            return true;
+
+        ErrorInvalidEnum("%s: Invalid type %s: Requires that"
+                         " WEBGL_depth_texture is enabled.",
+                         InfoFrom(func, dims), WebGLContext::EnumName(type));
+        return false;
     }
 
     ErrorInvalidEnumWithName(this, "invalid type", type, func, dims);
@@ -681,8 +724,7 @@ WebGLContext::ValidateTexImageType(GLenum type,
  */
 // TODO: WebGL 2
 bool
-WebGLContext::ValidateCompTexImageSize(GLint level,
-                                       GLenum format,
+WebGLContext::ValidateCompTexImageSize(GLint level, GLenum format,
                                        GLint xoffset, GLint yoffset,
                                        GLsizei width, GLsizei height,
                                        GLsizei levelWidth, GLsizei levelHeight,
@@ -694,12 +736,14 @@ WebGLContext::ValidateCompTexImageSize(GLint level,
                width >= 0 && height >= 0);
 
     if (xoffset + width > (GLint) levelWidth) {
-        ErrorInvalidValue("%s: xoffset + width must be <= levelWidth", InfoFrom(func, dims));
+        ErrorInvalidValue("%s: xoffset + width must be <= levelWidth.",
+                          InfoFrom(func, dims));
         return false;
     }
 
     if (yoffset + height > (GLint) levelHeight) {
-        ErrorInvalidValue("%s: yoffset + height must be <= levelHeight", InfoFrom(func, dims));
+        ErrorInvalidValue("%s: yoffset + height must be <= levelHeight.",
+                          InfoFrom(func, dims));
         return false;
     }
 
@@ -707,57 +751,58 @@ WebGLContext::ValidateCompTexImageSize(GLint level,
     GLint blockHeight = 1;
     BlockSizeFor(format, &blockWidth, &blockHeight);
 
-    /* If blockWidth || blockHeight != 1, then the compressed format
-     * had block-based constraints to be checked. (For example, PVRTC is compressed but
-     * isn't a block-based format)
-     */
+    // If blockWidth || blockHeight != 1, then the compressed format had
+    // block-based constraints to be checked. (For example, PVRTC is compressed
+    // but isn't a block-based format)
     if (blockWidth != 1 || blockHeight != 1) {
-        /* offsets must be multiple of block size */
+        // Offsets must be multiple of block size.
         if (xoffset % blockWidth != 0) {
-            ErrorInvalidOperation("%s: xoffset must be multiple of %d",
+            ErrorInvalidOperation("%s: xoffset must be multiple of %d.",
                                   InfoFrom(func, dims), blockWidth);
             return false;
         }
 
         if (yoffset % blockHeight != 0) {
-            ErrorInvalidOperation("%s: yoffset must be multiple of %d",
+            ErrorInvalidOperation("%s: yoffset must be multiple of %d.",
                                   InfoFrom(func, dims), blockHeight);
             return false;
         }
 
-        /* The size must be a multiple of blockWidth and blockHeight,
-         * or must be using offset+size that exactly hits the edge.
-         * Important for small mipmap levels.
-         */
-        /* https://www.khronos.org/registry/webgl/extensions/WEBGL_compressed_texture_s3tc/
-         * "When level equals zero width and height must be a multiple of 4. When
-         *  level is greater than 0 width and height must be 0, 1, 2 or a multiple of 4.
-         *  If they are not an INVALID_OPERATION error is generated."
+        /* The size must be a multiple of blockWidth and blockHeight, or must be
+         * using offset+size that exactly hits the edge. Important for small
+         * mipmap levels.
+         *
+         * From the WEBGL_compressed_texture_s3tc spec:
+         *     When level equals zero width and height must be a multiple of 4.
+         *     When level is greater than 0 width and height must be 0, 1, 2 or
+         *     a multiple of 4. If they are not an INVALID_OPERATION error is
+         *     generated."
          */
         if (level == 0) {
             if (width % blockWidth != 0) {
-                ErrorInvalidOperation("%s: width of level 0 must be multple of %d",
-                                      InfoFrom(func, dims), blockWidth);
+                ErrorInvalidOperation("%s: Width of level 0 must be a multiple"
+                                      " of %d.", InfoFrom(func, dims),
+                                      blockWidth);
                 return false;
             }
 
             if (height % blockHeight != 0) {
-                ErrorInvalidOperation("%s: height of level 0 must be multipel of %d",
-                                      InfoFrom(func, dims), blockHeight);
+                ErrorInvalidOperation("%s: Height of level 0 must be a multiple"
+                                      " of %d.", InfoFrom(func, dims),
+                                      blockHeight);
                 return false;
             }
-        }
-        else if (level > 0) {
+        } else if (level > 0) {
             if (width % blockWidth != 0 && width > 2) {
-                ErrorInvalidOperation("%s: width of level %d must be multiple"
-                                      " of %d or 0, 1, 2",
+                ErrorInvalidOperation("%s: Width of level %d must be a multiple"
+                                      " of %d, or be 0, 1, or 2.",
                                       InfoFrom(func, dims), level, blockWidth);
                 return false;
             }
 
             if (height % blockHeight != 0 && height > 2) {
-                ErrorInvalidOperation("%s: height of level %d must be multiple"
-                                      " of %d or 0, 1, 2",
+                ErrorInvalidOperation("%s: Height of level %d must be a"
+                                      " multiple of %d, or be 0, 1, or 2.",
                                       InfoFrom(func, dims), level, blockHeight);
                 return false;
             }
@@ -765,13 +810,13 @@ WebGLContext::ValidateCompTexImageSize(GLint level,
 
         if (IsSubFunc(func)) {
             if ((xoffset % blockWidth) != 0) {
-                ErrorInvalidOperation("%s: xoffset must be multiple of %d",
+                ErrorInvalidOperation("%s: xoffset must be a multiple of %d.",
                                       InfoFrom(func, dims), blockWidth);
                 return false;
             }
 
             if (yoffset % blockHeight != 0) {
-                ErrorInvalidOperation("%s: yoffset must be multiple of %d",
+                ErrorInvalidOperation("%s: yoffset must be a multiple of %d.",
                                       InfoFrom(func, dims), blockHeight);
                 return false;
             }
@@ -783,10 +828,10 @@ WebGLContext::ValidateCompTexImageSize(GLint level,
     case LOCAL_GL_COMPRESSED_RGB_PVRTC_2BPPV1:
     case LOCAL_GL_COMPRESSED_RGBA_PVRTC_4BPPV1:
     case LOCAL_GL_COMPRESSED_RGBA_PVRTC_2BPPV1:
-        if (!is_pot_assuming_nonnegative(width) ||
-            !is_pot_assuming_nonnegative(height))
+        if (!IsPOTAssumingNonnegative(width) ||
+            !IsPOTAssumingNonnegative(height))
         {
-            ErrorInvalidValue("%s: width and height must be powers of two",
+            ErrorInvalidValue("%s: Width and height must be powers of two.",
                               InfoFrom(func, dims));
             return false;
         }
@@ -812,38 +857,40 @@ WebGLContext::ValidateCompTexImageDataSize(GLint level, GLenum format,
     CheckedUint32 required_byteLength = 0;
 
     switch (format) {
-        case LOCAL_GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
-        case LOCAL_GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
-        case LOCAL_GL_ATC_RGB:
-        case LOCAL_GL_ETC1_RGB8_OES:
-        {
-            required_byteLength = ((CheckedUint32(width) + 3) / 4) * ((CheckedUint32(height) + 3) / 4) * 8;
-            break;
-        }
-        case LOCAL_GL_COMPRESSED_RGBA_S3TC_DXT3_EXT:
-        case LOCAL_GL_COMPRESSED_RGBA_S3TC_DXT5_EXT:
-        case LOCAL_GL_ATC_RGBA_EXPLICIT_ALPHA:
-        case LOCAL_GL_ATC_RGBA_INTERPOLATED_ALPHA:
-        {
-            required_byteLength = ((CheckedUint32(width) + 3) / 4) * ((CheckedUint32(height) + 3) / 4) * 16;
-            break;
-        }
-        case LOCAL_GL_COMPRESSED_RGB_PVRTC_4BPPV1:
-        case LOCAL_GL_COMPRESSED_RGBA_PVRTC_4BPPV1:
-        {
-            required_byteLength = CheckedUint32(std::max(width, 8)) * CheckedUint32(std::max(height, 8)) / 2;
-            break;
-        }
-        case LOCAL_GL_COMPRESSED_RGB_PVRTC_2BPPV1:
-        case LOCAL_GL_COMPRESSED_RGBA_PVRTC_2BPPV1:
-        {
-            required_byteLength = CheckedUint32(std::max(width, 16)) * CheckedUint32(std::max(height, 8)) / 4;
-            break;
-        }
+    case LOCAL_GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
+    case LOCAL_GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
+    case LOCAL_GL_ATC_RGB:
+    case LOCAL_GL_ETC1_RGB8_OES:
+        required_byteLength = ((CheckedUint32(width) + 3) / 4) *
+                              ((CheckedUint32(height) + 3) / 4) * 8;
+        break;
+
+    case LOCAL_GL_COMPRESSED_RGBA_S3TC_DXT3_EXT:
+    case LOCAL_GL_COMPRESSED_RGBA_S3TC_DXT5_EXT:
+    case LOCAL_GL_ATC_RGBA_EXPLICIT_ALPHA:
+    case LOCAL_GL_ATC_RGBA_INTERPOLATED_ALPHA:
+        required_byteLength = ((CheckedUint32(width) + 3) / 4) *
+                              ((CheckedUint32(height) + 3) / 4) * 16;
+        break;
+
+    case LOCAL_GL_COMPRESSED_RGB_PVRTC_4BPPV1:
+    case LOCAL_GL_COMPRESSED_RGBA_PVRTC_4BPPV1:
+        required_byteLength = CheckedUint32(std::max(width, 8)) *
+                              CheckedUint32(std::max(height, 8)) / 2;
+        break;
+
+    case LOCAL_GL_COMPRESSED_RGB_PVRTC_2BPPV1:
+    case LOCAL_GL_COMPRESSED_RGBA_PVRTC_2BPPV1:
+        required_byteLength = CheckedUint32(std::max(width, 16)) *
+                              CheckedUint32(std::max(height, 8)) / 4;
+        break;
     }
 
-    if (!required_byteLength.isValid() || required_byteLength.value() != byteLength) {
-        ErrorInvalidValue("%s: data size does not match dimensions", InfoFrom(func, dims));
+    if (!required_byteLength.isValid() ||
+        required_byteLength.value() != byteLength)
+    {
+        ErrorInvalidValue("%s: Data size does not match dimensions.",
+                          InfoFrom(func, dims));
         return false;
     }
 
@@ -859,7 +906,8 @@ WebGLContext::ValidateCompTexImageDataSize(GLint level, GLenum format,
 bool
 WebGLContext::ValidateTexImageSize(TexImageTarget texImageTarget, GLint level,
                                    GLint width, GLint height, GLint depth,
-                                   WebGLTexImageFunc func, WebGLTexDimensions dims)
+                                   WebGLTexImageFunc func,
+                                   WebGLTexDimensions dims)
 {
     MOZ_ASSERT(level >= 0, "level should already be validated");
 
@@ -876,7 +924,9 @@ WebGLContext::ValidateTexImageSize(TexImageTarget texImageTarget, GLint level,
     if (level > 31)
         level = 31;
 
-    const GLuint maxTexImageSize = MaxTextureSizeForTarget(TexImageTargetToTexTarget(texImageTarget)) >> level;
+    auto texTarget = TexImageTargetToTexTarget(texImageTarget);
+    const GLuint maxTexImageSize = MaxTextureSizeForTarget(texTarget) >> level;
+
     const bool isCubemapTarget = IsTexImageCubemapTarget(texImageTarget.get());
     const bool isSub = IsSubFunc(func);
 
@@ -887,24 +937,24 @@ WebGLContext::ValidateTexImageSize(TexImageTarget texImageTarget, GLint level,
          *   INVALID_VALUE is generated if the width and height
          *   parameters are not equal."
          */
-        ErrorInvalidValue("%s: for cube map, width must equal height", InfoFrom(func, dims));
+        ErrorInvalidValue("%s: For cube maps, width must equal height.",
+                          InfoFrom(func, dims));
         return false;
     }
 
-    if (texImageTarget == LOCAL_GL_TEXTURE_2D || isCubemapTarget)
-    {
+    if (texImageTarget == LOCAL_GL_TEXTURE_2D || isCubemapTarget) {
         /* GL ES Version 2.0.25 - 3.7.1 Texture Image Specification
          *   "If wt and ht are the specified image width and height,
          *   and if either wt or ht are less than zero, then the error
          *   INVALID_VALUE is generated."
          */
         if (width < 0) {
-            ErrorInvalidValue("%s: width must be >= 0", InfoFrom(func, dims));
+            ErrorInvalidValue("%s: Width must be >= 0.", InfoFrom(func, dims));
             return false;
         }
 
         if (height < 0) {
-            ErrorInvalidValue("%s: height must be >= 0", InfoFrom(func, dims));
+            ErrorInvalidValue("%s: Height must be >= 0.", InfoFrom(func, dims));
             return false;
         }
 
@@ -919,13 +969,13 @@ WebGLContext::ValidateTexImageSize(TexImageTarget texImageTarget, GLint level,
          *   is too large to be stored under any conditions.
          */
         if (width > (int) maxTexImageSize) {
-            ErrorInvalidValue("%s: the maximum width for level %d is %u",
+            ErrorInvalidValue("%s: The maximum width for level %d is %u.",
                               InfoFrom(func, dims), level, maxTexImageSize);
             return false;
         }
 
         if (height > (int) maxTexImageSize) {
-            ErrorInvalidValue("%s: tex maximum height for level %d is %u",
+            ErrorInvalidValue("%s: The maximum height for level %d is %u.",
                               InfoFrom(func, dims), level, maxTexImageSize);
             return false;
         }
@@ -938,15 +988,17 @@ WebGLContext::ValidateTexImageSize(TexImageTarget texImageTarget, GLint level,
          * This restriction does not apply to GL ES Version 3.0+.
          */
         if (!IsWebGL2() && level > 0) {
-            if (!is_pot_assuming_nonnegative(width)) {
-                ErrorInvalidValue("%s: level >= 0, width of %d must be a power of two.",
-                                  InfoFrom(func, dims), width);
+            if (!IsPOTAssumingNonnegative(width)) {
+                ErrorInvalidValue("%s: For level > 0, width of %d must be a"
+                                  " power of two.", InfoFrom(func, dims),
+                                  width);
                 return false;
             }
 
-            if (!is_pot_assuming_nonnegative(height)) {
-                ErrorInvalidValue("%s: level >= 0, height of %d must be a power of two.",
-                                  InfoFrom(func, dims), height);
+            if (!IsPOTAssumingNonnegative(height)) {
+                ErrorInvalidValue("%s: For level > 0, height of %d must be a"
+                                  " power of two.", InfoFrom(func, dims),
+                                  height);
                 return false;
             }
         }
@@ -955,12 +1007,12 @@ WebGLContext::ValidateTexImageSize(TexImageTarget texImageTarget, GLint level,
     // TODO: WebGL 2
     if (texImageTarget == LOCAL_GL_TEXTURE_3D) {
         if (depth < 0) {
-            ErrorInvalidValue("%s: depth must be >= 0", InfoFrom(func, dims));
+            ErrorInvalidValue("%s: Depth must be >= 0.", InfoFrom(func, dims));
             return false;
         }
 
-        if (!IsWebGL2() && !is_pot_assuming_nonnegative(depth)) {
-            ErrorInvalidValue("%s: level >= 0, depth of %d must be a power of two.",
+        if (!IsWebGL2() && !IsPOTAssumingNonnegative(depth)) {
+            ErrorInvalidValue("%s: Depth of %d must be a power of two.",
                               InfoFrom(func, dims), depth);
             return false;
         }
@@ -974,10 +1026,13 @@ WebGLContext::ValidateTexImageSize(TexImageTarget texImageTarget, GLint level,
  */
 // TODO: WebGL 2. Update this to handle 3D textures.
 bool
-WebGLContext::ValidateTexSubImageSize(GLint xoffset, GLint yoffset, GLint /*zoffset*/,
-                                      GLsizei width, GLsizei height, GLsizei /*depth*/,
-                                      GLsizei baseWidth, GLsizei baseHeight, GLsizei /*baseDepth*/,
-                                      WebGLTexImageFunc func, WebGLTexDimensions dims)
+WebGLContext::ValidateTexSubImageSize(GLint xoffset, GLint yoffset,
+                                      GLint /*zoffset*/, GLsizei width,
+                                      GLsizei height, GLsizei /*depth*/,
+                                      GLsizei baseWidth, GLsizei baseHeight,
+                                      GLsizei /*baseDepth*/,
+                                      WebGLTexImageFunc func,
+                                      WebGLTexDimensions dims)
 {
     /* GL ES Version 2.0.25 - 3.7.1 Texture Image Specification
      *   "Taking wt and ht to be the specified width and height of the
@@ -991,17 +1046,20 @@ WebGLContext::ValidateTexSubImageSize(GLint xoffset, GLint yoffset, GLint /*zoff
      */
 
     if (xoffset < 0) {
-        ErrorInvalidValue("%s: xoffset must be >= 0", InfoFrom(func, dims));
+        ErrorInvalidValue("%s: xoffset must be >= 0.", InfoFrom(func, dims));
         return false;
     }
 
     if (yoffset < 0) {
-        ErrorInvalidValue("%s: yoffset must be >= 0", InfoFrom(func, dims));
+        ErrorInvalidValue("%s: yoffset must be >= 0.", InfoFrom(func, dims));
         return false;
     }
 
-    if (!CanvasUtils::CheckSaneSubrectSize(xoffset, yoffset, width, height, baseWidth, baseHeight)) {
-        ErrorInvalidValue("%s: subtexture rectangle out-of-bounds", InfoFrom(func, dims));
+    if (!CanvasUtils::CheckSaneSubrectSize(xoffset, yoffset, width, height,
+                                           baseWidth, baseHeight))
+    {
+        ErrorInvalidValue("%s: Subtexture rectangle out-of-bounds.",
+                          InfoFrom(func, dims));
         return false;
     }
 
@@ -1013,16 +1071,15 @@ WebGLContext::ValidateTexSubImageSize(GLint xoffset, GLint yoffset, GLint /*zoff
  * Returns true if the format/type is a valid combination, false otherwise.
  */
 bool
-WebGLContext::ValidateTexImageFormatAndType(GLenum format,
-                                            GLenum type,
+WebGLContext::ValidateTexImageFormatAndType(GLenum format, GLenum type,
                                             WebGLTexImageFunc func,
                                             WebGLTexDimensions dims)
 {
-    if (IsCompressedFunc(func) || IsCopyFunc(func))
-    {
+    if (IsCompressedFunc(func) || IsCopyFunc(func)) {
         MOZ_ASSERT(type == LOCAL_GL_NONE && format == LOCAL_GL_NONE);
         return true;
     }
+
     if (!ValidateTexImageFormat(format, func, dims) ||
         !ValidateTexImageType(type, func, dims))
     {
@@ -1034,13 +1091,14 @@ WebGLContext::ValidateTexImageFormatAndType(GLenum format,
     // same code implemented twice.
     TexInternalFormat effective =
         EffectiveInternalFormatFromInternalFormatAndType(format, type);
-    bool validCombo = effective != LOCAL_GL_NONE;
 
-    if (!validCombo)
-        ErrorInvalidOperation("%s: invalid combination of format %s and type %s",
-                              InfoFrom(func, dims), WebGLContext::EnumName(format), WebGLContext::EnumName(type));
+    if (effective != LOCAL_GL_NONE)
+        return true;
 
-    return validCombo;
+    ErrorInvalidOperation("%s: Invalid combination of format %s and type %s.",
+                          InfoFrom(func, dims), WebGLContext::EnumName(format),
+                          WebGLContext::EnumName(type));
+    return false;
 }
 
 bool
@@ -1049,7 +1107,7 @@ WebGLContext::ValidateCompTexImageInternalFormat(GLenum format,
                                                  WebGLTexDimensions dims)
 {
     if (!IsCompressedTextureFormat(format)) {
-        ErrorInvalidEnum("%s: invalid compressed texture format: %s",
+        ErrorInvalidEnum("%s: Invalid compressed texture format: %s",
                          InfoFrom(func, dims), WebGLContext::EnumName(format));
         return false;
     }
@@ -1059,20 +1117,24 @@ WebGLContext::ValidateCompTexImageInternalFormat(GLenum format,
         format == LOCAL_GL_ATC_RGBA_EXPLICIT_ALPHA ||
         format == LOCAL_GL_ATC_RGBA_INTERPOLATED_ALPHA)
     {
-        bool validFormat = IsExtensionEnabled(WebGLExtensionID::WEBGL_compressed_texture_atc);
-        if (!validFormat)
-            ErrorInvalidEnum("%s: invalid format %s: need WEBGL_compressed_texture_atc enabled",
-                             InfoFrom(func, dims), WebGLContext::EnumName(format));
-        return validFormat;
+        if (IsExtensionEnabled(WebGLExtensionID::WEBGL_compressed_texture_atc))
+            return true;
+
+        ErrorInvalidEnum("%s: Invalid format %s: Requires that"
+                         " WEBGL_compressed_texture_atc is enabled.",
+                         InfoFrom(func, dims), WebGLContext::EnumName(format));
+        return false;
     }
 
     // WEBGL_compressed_texture_etc1
     if (format == LOCAL_GL_ETC1_RGB8_OES) {
-        bool validFormat = IsExtensionEnabled(WebGLExtensionID::WEBGL_compressed_texture_etc1);
-        if (!validFormat)
-            ErrorInvalidEnum("%s: invalid format %s: need WEBGL_compressed_texture_etc1 enabled",
-                             InfoFrom(func, dims), WebGLContext::EnumName(format));
-        return validFormat;
+        if (IsExtensionEnabled(WebGLExtensionID::WEBGL_compressed_texture_etc1))
+            return true;
+
+        ErrorInvalidEnum("%s: Invalid format %s: Requires that"
+                         " WEBGL_compressed_texture_etc1 is enabled.",
+                         InfoFrom(func, dims), WebGLContext::EnumName(format));
+        return false;
     }
 
 
@@ -1081,11 +1143,13 @@ WebGLContext::ValidateCompTexImageInternalFormat(GLenum format,
         format == LOCAL_GL_COMPRESSED_RGBA_PVRTC_2BPPV1 ||
         format == LOCAL_GL_COMPRESSED_RGBA_PVRTC_4BPPV1)
     {
-        bool validFormat = IsExtensionEnabled(WebGLExtensionID::WEBGL_compressed_texture_pvrtc);
-        if (!validFormat)
-            ErrorInvalidEnum("%s: invalid format %s: need WEBGL_compressed_texture_pvrtc enabled",
-                             InfoFrom(func, dims), WebGLContext::EnumName(format));
-        return validFormat;
+        if (IsExtensionEnabled(WebGLExtensionID::WEBGL_compressed_texture_pvrtc))
+            return true;
+
+        ErrorInvalidEnum("%s: Invalid format %s: Requires that"
+                         " WEBGL_compressed_texture_pvrtc is enabled.",
+                         InfoFrom(func, dims), WebGLContext::EnumName(format));
+        return false;
     }
 
 
@@ -1094,13 +1158,16 @@ WebGLContext::ValidateCompTexImageInternalFormat(GLenum format,
         format == LOCAL_GL_COMPRESSED_RGBA_S3TC_DXT3_EXT ||
         format == LOCAL_GL_COMPRESSED_RGBA_S3TC_DXT5_EXT)
     {
-        bool validFormat = IsExtensionEnabled(WebGLExtensionID::WEBGL_compressed_texture_s3tc);
-        if (!validFormat)
-            ErrorInvalidEnum("%s: invalid format %s: need WEBGL_compressed_texture_s3tc enabled",
-                             InfoFrom(func, dims), WebGLContext::EnumName(format));
-        return validFormat;
+        if (IsExtensionEnabled(WebGLExtensionID::WEBGL_compressed_texture_s3tc))
+            return true;
+
+        ErrorInvalidEnum("%s: Invalid format %s: Requires that"
+                         " WEBGL_compressed_texture_s3tc is enabled.",
+                         InfoFrom(func, dims), WebGLContext::EnumName(format));
+        return false;
     }
 
+    MOZ_ASSERT(false);
     return false;
 }
 
@@ -1109,24 +1176,29 @@ WebGLContext::ValidateCopyTexImageInternalFormat(GLenum format,
                                                  WebGLTexImageFunc func,
                                                  WebGLTexDimensions dims)
 {
-    bool valid = format == LOCAL_GL_RGBA ||
-                 format == LOCAL_GL_RGB ||
-                 format == LOCAL_GL_LUMINANCE_ALPHA ||
-                 format == LOCAL_GL_LUMINANCE ||
-                 format == LOCAL_GL_ALPHA;
-    if (!valid)
-    {
-        // in CopyTexImage, the internalformat is a function parameter,
-        // so a bad value is an INVALID_ENUM error.
-        // in CopyTexSubImage, the internalformat is part of existing state,
-        // so this is an INVALID_OPERATION error.
-        GenerateWarning("%s: invalid texture internal format: %s",
-                        InfoFrom(func, dims), WebGLContext::EnumName(format));
-        SynthesizeGLError(func == WebGLTexImageFunc::CopyTexImage
-                          ? LOCAL_GL_INVALID_ENUM
-                          : LOCAL_GL_INVALID_OPERATION);
+    switch (format) {
+    case LOCAL_GL_RGBA:
+    case LOCAL_GL_RGB:
+    case LOCAL_GL_LUMINANCE_ALPHA:
+    case LOCAL_GL_LUMINANCE:
+    case LOCAL_GL_ALPHA:
+        return true;
     }
-    return valid;
+    // In CopyTexImage, internalFormat is a function parameter,
+    // so a bad value is an INVALID_ENUM error.
+    // In CopyTexSubImage, internalFormat is part of existing state,
+    // so this is an INVALID_OPERATION error.
+    GenerateWarning("%s: Invalid texture internal format: %s",
+                    InfoFrom(func, dims), WebGLContext::EnumName(format));
+
+    GLenum error;
+    if (func == WebGLTexImageFunc::CopyTexImage)
+        error = LOCAL_GL_INVALID_ENUM;
+    else
+        error = LOCAL_GL_INVALID_OPERATION;
+
+    SynthesizeGLError(error);
+    return false;
 }
 /**
  * Return true if format, type and jsArrayType are a valid combination.
@@ -1136,21 +1208,19 @@ WebGLContext::ValidateCopyTexImageInternalFormat(GLenum format,
  * It is assumed that type has previously been validated.
  */
 bool
-WebGLContext::ValidateTexInputData(GLenum type,
-                                   js::Scalar::Type jsArrayType,
+WebGLContext::ValidateTexInputData(GLenum type, js::Scalar::Type jsArrayType,
                                    WebGLTexImageFunc func,
                                    WebGLTexDimensions dims)
 {
-    bool validInput = false;
-    const char invalidTypedArray[] = "%s: invalid typed array type for given texture data type";
-
-    // We're using js::Scalar::TypeMax as dummy value when the tex source wasn't a
-    // typed array.
-    if (jsArrayType == js::Scalar::TypeMax) {
+    // We're using js::Scalar::TypeMax as dummy value for when the tex source
+    // wasn't a typed array.
+    if (jsArrayType == js::Scalar::TypeMax)
         return true;
-    }
 
-    // First, we check for packed types
+    const char invalidTypedArray[] = "%s: Invalid typed array type for given"
+                                     " texture data type.";
+
+    bool validInput = false;
     switch (type) {
     case LOCAL_GL_UNSIGNED_BYTE:
         validInput = jsArrayType == js::Scalar::Uint8;
@@ -1202,11 +1272,11 @@ WebGLContext::ValidateTexInputData(GLenum type,
  * Checks specific for the CopyTex[Sub]Image2D functions.
  * Verifies:
  * - Framebuffer is complete and has valid read planes
- * - Copy format is a subset of framebuffer format (i.e. all required components are available)
+ * - Copy format is a subset of framebuffer format (i.e. all required components
+ *   are available)
  */
 bool
-WebGLContext::ValidateCopyTexImage(GLenum format,
-                                   WebGLTexImageFunc func,
+WebGLContext::ValidateCopyTexImage(GLenum format, WebGLTexImageFunc func,
                                    WebGLTexDimensions dims)
 {
     MOZ_ASSERT(IsCopyFunc(func));
@@ -1216,29 +1286,36 @@ WebGLContext::ValidateCopyTexImage(GLenum format,
 
     if (mBoundFramebuffer) {
         if (!mBoundFramebuffer->CheckAndInitializeAttachments()) {
-            ErrorInvalidFramebufferOperation("%s: incomplete framebuffer", InfoFrom(func, dims));
+            ErrorInvalidFramebufferOperation("%s: Incomplete framebuffer.",
+                                             InfoFrom(func, dims));
             return false;
         }
 
         GLenum readPlaneBits = LOCAL_GL_COLOR_BUFFER_BIT;
         if (!mBoundFramebuffer->HasCompletePlanes(readPlaneBits)) {
             ErrorInvalidOperation("%s: Read source attachment doesn't have the"
-                                  " correct color/depth/stencil type.", InfoFrom(func, dims));
+                                  " correct color/depth/stencil type.",
+                                  InfoFrom(func, dims));
             return false;
         }
 
-        // Get the correct format for the framebuffer, as it's not the default one
-        const WebGLFramebuffer::Attachment& color0 = mBoundFramebuffer->GetAttachment(LOCAL_GL_COLOR_ATTACHMENT0);
+        // Get the correct format for the framebuffer, as it's not the default
+        // one.
+        const WebGLFramebuffer::Attachment& color0 =
+            mBoundFramebuffer->GetAttachment(LOCAL_GL_COLOR_ATTACHMENT0);
+
         fboFormat = mBoundFramebuffer->GetFormatForAttachment(color0);
     }
 
-    // Make sure the format of the framebuffer is a superset of
-    // the format requested by the CopyTex[Sub]Image2D functions.
+    // Make sure the format of the framebuffer is a superset of the format
+    // requested by the CopyTex[Sub]Image2D functions.
     const GLComponents formatComps = GLComponents(format);
     const GLComponents fboComps = GLComponents(fboFormat);
     if (!formatComps.IsSubsetOf(fboComps)) {
-        ErrorInvalidOperation("%s: format %s is not a subset of the current framebuffer format, which is %s.",
-                              InfoFrom(func, dims), EnumName(format), EnumName(fboFormat));
+        ErrorInvalidOperation("%s: Format %s is not a subset of the current"
+                              " framebuffer format, which is %s.",
+                              InfoFrom(func, dims), EnumName(format),
+                              EnumName(fboFormat));
         return false;
     }
 
@@ -1247,60 +1324,64 @@ WebGLContext::ValidateCopyTexImage(GLenum format,
 
 /**
  * Test the gl(Copy|Compressed)?Tex[Sub]?Image[23]() parameters for errors.
- * Verifies each of the parameters against the WebGL standard and enabled extensions.
+ * Verifies each of the parameters against the WebGL standard and enabled
+ * extensions.
  */
 // TODO: Texture dims is here for future expansion in WebGL 2.0
 bool
-WebGLContext::ValidateTexImage(TexImageTarget texImageTarget,
-                               GLint level,
-                               GLenum internalFormat,
-                               GLint xoffset, GLint yoffset, GLint zoffset,
-                               GLint width, GLint height, GLint depth,
-                               GLint border,
-                               GLenum format,
-                               GLenum type,
+WebGLContext::ValidateTexImage(TexImageTarget texImageTarget, GLint level,
+                               GLenum internalFormat, GLint xoffset,
+                               GLint yoffset, GLint zoffset, GLint width,
+                               GLint height, GLint depth, GLint border,
+                               GLenum format, GLenum type,
                                WebGLTexImageFunc func,
                                WebGLTexDimensions dims)
 {
     const char* info = InfoFrom(func, dims);
 
-    /* Check level */
+    // Check level
     if (level < 0) {
-        ErrorInvalidValue("%s: level must be >= 0", info);
+        ErrorInvalidValue("%s: `level` must be >= 0.", info);
         return false;
     }
 
-    /* Check border */
+    // Check border
     if (border != 0) {
-        ErrorInvalidValue("%s: border must be 0", info);
+        ErrorInvalidValue("%s: `border` must be 0.", info);
         return false;
     }
 
-    /* Check incoming image format and type */
+    // Check incoming image format and type
     if (!ValidateTexImageFormatAndType(format, type, func, dims))
         return false;
 
     if (!TexInternalFormat::IsValueLegal(internalFormat)) {
-        ErrorInvalidEnum("%s: invalid internalformat enum %s", info, EnumName(internalFormat));
+        ErrorInvalidEnum("%s: Invalid `internalformat` enum %s.", info,
+                         EnumName(internalFormat));
         return false;
     }
     TexInternalFormat unsizedInternalFormat =
         UnsizedInternalFormatFromInternalFormat(internalFormat);
 
     if (IsCompressedFunc(func)) {
-        if (!ValidateCompTexImageInternalFormat(internalFormat, func, dims)) {
+        if (!ValidateCompTexImageInternalFormat(internalFormat, func, dims))
             return false;
-        }
+
     } else if (IsCopyFunc(func)) {
-        if (!ValidateCopyTexImageInternalFormat(unsizedInternalFormat.get(), func, dims)) {
+        if (!ValidateCopyTexImageInternalFormat(unsizedInternalFormat.get(),
+                                                func, dims))
+        {
             return false;
         }
     } else if (format != unsizedInternalFormat) {
         if (IsWebGL2()) {
-            // In WebGL2, it's OK to have internalformat != format if internalformat is the sized
-            // internal format corresponding to the (format, type) pair according to Table 3.2
-            // in the OpenGL ES 3.0.3 spec.
-            if (internalFormat != EffectiveInternalFormatFromInternalFormatAndType(format, type)) {
+            // In WebGL2, it's OK to have `internalFormat != format` if
+            // internalFormat is the sized internal format corresponding to the
+            // (format, type) pair according to Table 3.2 in the OpenGL ES 3.0.3
+            // spec.
+            auto effectiveFormat = EffectiveInternalFormatFromInternalFormatAndType(format,
+                                                                                    type);
+            if (internalFormat != effectiveFormat) {
                 bool exceptionallyAllowed = false;
                 if (internalFormat == LOCAL_GL_SRGB8_ALPHA8 &&
                     format == LOCAL_GL_RGBA &&
@@ -1315,100 +1396,117 @@ WebGLContext::ValidateTexImage(TexImageTarget texImageTarget,
                     exceptionallyAllowed = true;
                 }
                 if (!exceptionallyAllowed) {
-                    ErrorInvalidOperation("%s: internalformat does not match format and type", info);
+                    ErrorInvalidOperation("%s: `internalformat` does not match"
+                                          " `format` and `type`.", info);
                     return false;
                 }
             }
         } else {
-            // in WebGL 1, format must be equal to internalformat
-            ErrorInvalidOperation("%s: internalformat does not match format", info);
+            // In WebGL 1, format must be equal to internalformat.
+            ErrorInvalidOperation("%s: `internalformat` does not match"
+                                  " `format`.", info);
             return false;
         }
     }
 
-    /* Check texture image size */
-    if (!ValidateTexImageSize(texImageTarget, level, width, height, 0, func, dims))
+    // Check texture image size
+    if (!ValidateTexImageSize(texImageTarget, level, width, height, 0, func,
+                              dims))
+    {
         return false;
+    }
 
     /* 5.14.8 Texture objects - WebGL Spec.
      *   "If an attempt is made to call these functions with no
      *    WebGLTexture bound (see above), an INVALID_OPERATION error
      *    is generated."
      */
-    WebGLTexture* tex = activeBoundTextureForTexImageTarget(texImageTarget);
+    WebGLTexture* tex = ActiveBoundTextureForTexImageTarget(texImageTarget);
     if (!tex) {
-        ErrorInvalidOperation("%s: no texture is bound to target %s",
-                              info, WebGLContext::EnumName(texImageTarget.get()));
+        ErrorInvalidOperation("%s: No texture is bound to target %s.", info,
+                              WebGLContext::EnumName(texImageTarget.get()));
         return false;
     }
 
     if (IsSubFunc(func)) {
         if (!tex->HasImageInfoAt(texImageTarget, level)) {
-            ErrorInvalidOperation("%s: no texture image previously defined for target %s at level %d",
-                                  info, WebGLContext::EnumName(texImageTarget.get()), level);
+            ErrorInvalidOperation("%s: No texture image previously defined for"
+                                  " target %s at level %d.", info,
+                                  WebGLContext::EnumName(texImageTarget.get()),
+                                                         level);
             return false;
         }
 
-        const WebGLTexture::ImageInfo& imageInfo = tex->ImageInfoAt(texImageTarget, level);
-
-        if (!ValidateTexSubImageSize(xoffset, yoffset, zoffset,
-                                     width, height, depth,
-                                     imageInfo.Width(), imageInfo.Height(), 0,
-                                     func, dims))
+        const auto& imageInfo = tex->ImageInfoAt(texImageTarget, level);
+        if (!ValidateTexSubImageSize(xoffset, yoffset, zoffset, width, height,
+                                     depth, imageInfo.Width(),
+                                     imageInfo.Height(), 0, func, dims))
         {
             return false;
         }
     }
 
-    /* Additional checks for depth textures */
+    // Additional checks for depth textures
     if (texImageTarget != LOCAL_GL_TEXTURE_2D &&
         (format == LOCAL_GL_DEPTH_COMPONENT ||
          format == LOCAL_GL_DEPTH_STENCIL))
     {
-        ErrorInvalidOperation("%s: with format of %s target must be TEXTURE_2D",
-                              info, WebGLContext::EnumName(format));
+        ErrorInvalidOperation("%s: With format of %s, target must be"
+                              " TEXTURE_2D.", info,
+                              WebGLContext::EnumName(format));
         return false;
     }
 
-    /* Additional checks for compressed textures */
+    // Additional checks for compressed textures
     if (!IsAllowedFromSource(internalFormat, func)) {
-        ErrorInvalidOperation("%s: Invalid format %s for this operation",
+        ErrorInvalidOperation("%s: Invalid format %s for this operation.",
                               info, WebGLContext::EnumName(format));
         return false;
     }
 
-    /* Parameters are OK */
+    // Parameters are OK
     return true;
 }
 
 bool
-WebGLContext::ValidateUniformLocation(const char* info, WebGLUniformLocation *location_object)
+WebGLContext::ValidateUniformLocation(const char* info,
+                                      WebGLUniformLocation* loc)
 {
-    if (!ValidateObjectAllowNull(info, location_object))
+    if (!ValidateObjectAllowNull(info, loc))
         return false;
-    if (!location_object)
+
+    if (!loc)
         return false;
-    /* the need to check specifically for !mCurrentProgram here is explained in bug 657556 */
+
+    // The need to check specifically for !mCurrentProgram here is explained in
+    // bug 657556.
     if (!mCurrentProgram) {
-        ErrorInvalidOperation("%s: no program is currently bound", info);
+        ErrorInvalidOperation("%s: No program is currently bound.", info);
         return false;
     }
-    if (mCurrentProgram != location_object->Program()) {
-        ErrorInvalidOperation("%s: this uniform location doesn't correspond to the current program", info);
+
+    if (mCurrentProgram != loc->Program()) {
+        ErrorInvalidOperation("%s: This uniform location doesn't correspond to"
+                              " the current program.", info);
         return false;
     }
-    if (mCurrentProgram->Generation() != location_object->ProgramGeneration()) {
-        ErrorInvalidOperation("%s: This uniform location is obsolete since the program has been relinked", info);
+
+    if (mCurrentProgram->Generation() != loc->ProgramGeneration()) {
+        ErrorInvalidOperation("%s: This uniform location is obsolete since the"
+                              " program has been relinked.", info);
         return false;
     }
+
     return true;
 }
 
 bool
-WebGLContext::ValidateSamplerUniformSetter(const char* info, WebGLUniformLocation *location, GLint value)
+WebGLContext::ValidateSamplerUniformSetter(const char* info,
+                                           WebGLUniformLocation* loc,
+                                           GLint value)
 {
-    if (location->Info().type != LOCAL_GL_SAMPLER_2D &&
-        location->Info().type != LOCAL_GL_SAMPLER_CUBE)
+    if (loc->Info().type != LOCAL_GL_SAMPLER_2D &&
+        loc->Info().type != LOCAL_GL_SAMPLER_CUBE)
     {
         return true;
     }
@@ -1416,21 +1514,23 @@ WebGLContext::ValidateSamplerUniformSetter(const char* info, WebGLUniformLocatio
     if (value >= 0 && value < mGLMaxTextureUnits)
         return true;
 
-    ErrorInvalidValue("%s: this uniform location is a sampler, but %d is not a valid texture unit",
-                      info, value);
+    ErrorInvalidValue("%s: This uniform location is a sampler, but %d is not a"
+                      " valid texture unit.", info, value);
     return false;
 }
 
 bool
-WebGLContext::ValidateAttribArraySetter(const char* name, uint32_t cnt, uint32_t arrayLength)
+WebGLContext::ValidateAttribArraySetter(const char* name, uint32_t cnt,
+                                        uint32_t arrayLength)
 {
-    if (IsContextLost()) {
+    if (IsContextLost())
         return false;
-    }
+
     if (arrayLength < cnt) {
-        ErrorInvalidOperation("%s: array must be >= %d elements", name, cnt);
+        ErrorInvalidOperation("%s: Array must be >= %d elements.", name, cnt);
         return false;
     }
+
     return true;
 }
 
@@ -1534,10 +1634,12 @@ WebGLContext::ValidateUniformSetter(WebGLUniformLocation* loc,
 
 bool
 WebGLContext::ValidateUniformArraySetter(WebGLUniformLocation* loc,
-                                         uint8_t setterElemSize, GLenum setterType,
+                                         uint8_t setterElemSize,
+                                         GLenum setterType,
                                          size_t setterArraySize,
-                                         const char* info, GLuint* out_rawLoc,
-                                         GLsizei* out_numElementsToUpload)
+                                         const char* info,
+                                         GLuint* const out_rawLoc,
+                                         GLsizei* const out_numElementsToUpload)
 {
     if (IsContextLost())
         return false;
@@ -1567,8 +1669,8 @@ WebGLContext::ValidateUniformMatrixArraySetter(WebGLUniformLocation* loc,
                                                size_t setterArraySize,
                                                bool setterTranspose,
                                                const char* info,
-                                               GLuint* out_rawLoc,
-                                               GLsizei* out_numElementsToUpload)
+                                               GLuint* const out_rawLoc,
+                                               GLsizei* const out_numElementsToUpload)
 {
     uint8_t setterElemSize = setterDims * setterDims;
 
@@ -1598,25 +1700,32 @@ WebGLContext::ValidateUniformMatrixArraySetter(WebGLUniformLocation* loc,
     return true;
 }
 
-bool WebGLContext::ValidateStencilParamsForDrawCall()
+bool
+WebGLContext::ValidateStencilParamsForDrawCall()
 {
-  const char *msg = "%s set different front and back stencil %s. Drawing in this configuration is not allowed.";
-  if (mStencilRefFront != mStencilRefBack) {
-      ErrorInvalidOperation(msg, "stencilFuncSeparate", "reference values");
-      return false;
-  }
-  if (mStencilValueMaskFront != mStencilValueMaskBack) {
-      ErrorInvalidOperation(msg, "stencilFuncSeparate", "value masks");
-      return false;
-  }
-  if (mStencilWriteMaskFront != mStencilWriteMaskBack) {
-      ErrorInvalidOperation(msg, "stencilMaskSeparate", "write masks");
-      return false;
-  }
-  return true;
+    const char msg[] = "%s set different front and back stencil %s. Drawing in"
+                       " this configuration is not allowed.";
+
+    if (mStencilRefFront != mStencilRefBack) {
+        ErrorInvalidOperation(msg, "stencilFuncSeparate", "reference values");
+        return false;
+    }
+
+    if (mStencilValueMaskFront != mStencilValueMaskBack) {
+        ErrorInvalidOperation(msg, "stencilFuncSeparate", "value masks");
+        return false;
+    }
+
+    if (mStencilWriteMaskFront != mStencilWriteMaskBack) {
+        ErrorInvalidOperation(msg, "stencilMaskSeparate", "write masks");
+        return false;
+    }
+
+    return true;
 }
 
-static inline int32_t floorPOT(int32_t x)
+static inline int32_t
+FloorPOT(int32_t x)
 {
     MOZ_ASSERT(x > 0);
     int32_t pot = 1;
@@ -1631,11 +1740,13 @@ static inline int32_t floorPOT(int32_t x)
 bool
 WebGLContext::InitAndValidateGL()
 {
-    if (!gl) return false;
+    if (!gl)
+        return false;
 
     GLenum error = gl->fGetError();
     if (error != LOCAL_GL_NO_ERROR) {
-        GenerateWarning("GL error 0x%x occurred during OpenGL context initialization, before WebGL initialization!", error);
+        GenerateWarning("GL error 0x%x occurred during OpenGL context"
+                        " initialization, before WebGL initialization!", error);
         return false;
     }
 
@@ -1645,9 +1756,8 @@ WebGLContext::InitAndValidateGL()
     mCanLoseContextInForeground = Preferences::GetBool("webgl.can-lose-context-in-foreground", true);
     mRestoreWhenVisible = Preferences::GetBool("webgl.restore-context-when-visible", true);
 
-    if (MinCapabilityMode()) {
-      mDisableFragHighP = true;
-    }
+    if (MinCapabilityMode())
+        mDisableFragHighP = true;
 
     // These are the default values, see 6.2 State tables in the
     // OpenGL ES 2.0.25 spec.
@@ -1711,30 +1821,31 @@ WebGLContext::InitAndValidateGL()
     MakeContextCurrent();
 
     // on desktop OpenGL, we always keep vertex attrib 0 array enabled
-    if (!gl->IsGLES()) {
+    if (!gl->IsGLES())
         gl->fEnableVertexAttribArray(0);
-    }
 
-    if (MinCapabilityMode()) {
+    if (MinCapabilityMode())
         mGLMaxVertexAttribs = MINVALUE_GL_MAX_VERTEX_ATTRIBS;
-    } else {
+    else
         gl->fGetIntegerv(LOCAL_GL_MAX_VERTEX_ATTRIBS, &mGLMaxVertexAttribs);
-    }
+
     if (mGLMaxVertexAttribs < 8) {
-        GenerateWarning("GL_MAX_VERTEX_ATTRIBS: %d is < 8!", mGLMaxVertexAttribs);
+        GenerateWarning("GL_MAX_VERTEX_ATTRIBS: %d is < 8!",
+                        mGLMaxVertexAttribs);
         return false;
     }
 
     // Note: GL_MAX_TEXTURE_UNITS is fixed at 4 for most desktop hardware,
     // even though the hardware supports much more.  The
     // GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS value is the accurate value.
-    if (MinCapabilityMode()) {
+    if (MinCapabilityMode())
         mGLMaxTextureUnits = MINVALUE_GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS;
-    } else {
+    else
         gl->fGetIntegerv(LOCAL_GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS, &mGLMaxTextureUnits);
-    }
+
     if (mGLMaxTextureUnits < 8) {
-        GenerateWarning("GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS: %d is < 8!", mGLMaxTextureUnits);
+        GenerateWarning("GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS: %d is < 8!",
+                        mGLMaxTextureUnits);
         return false;
     }
 
@@ -1769,8 +1880,8 @@ WebGLContext::InitAndValidateGL()
         ++mGLMaxCubeMapTextureSizeLog2;
     }
 
-    mGLMaxTextureSize = floorPOT(mGLMaxTextureSize);
-    mGLMaxRenderbufferSize = floorPOT(mGLMaxRenderbufferSize);
+    mGLMaxTextureSize = FloorPOT(mGLMaxTextureSize);
+    mGLMaxRenderbufferSize = FloorPOT(mGLMaxRenderbufferSize);
 
     if (MinCapabilityMode()) {
         mGLMaxFragmentUniformVectors = MINVALUE_GL_MAX_FRAGMENT_UNIFORM_VECTORS;
@@ -1787,12 +1898,16 @@ WebGLContext::InitAndValidateGL()
             gl->fGetIntegerv(LOCAL_GL_MAX_VERTEX_UNIFORM_COMPONENTS, &mGLMaxVertexUniformVectors);
             mGLMaxVertexUniformVectors /= 4;
 
-            // we are now going to try to read GL_MAX_VERTEX_OUTPUT_COMPONENTS and GL_MAX_FRAGMENT_INPUT_COMPONENTS,
-            // however these constants only entered the OpenGL standard at OpenGL 3.2. So we will try reading,
-            // and check OpenGL error for INVALID_ENUM.
-
-            // On the public_webgl list, "problematic GetParameter pnames" thread, the following formula was given:
-            //   mGLMaxVaryingVectors = min (GL_MAX_VERTEX_OUTPUT_COMPONENTS, GL_MAX_FRAGMENT_INPUT_COMPONENTS) / 4
+            /* We are now going to try to read GL_MAX_VERTEX_OUTPUT_COMPONENTS
+             * and GL_MAX_FRAGMENT_INPUT_COMPONENTS, however these constants
+             * only entered the OpenGL standard at OpenGL 3.2. So we will try
+             * reading, and check OpenGL error for INVALID_ENUM.
+             *
+             * On the public_webgl list, "problematic GetParameter pnames"
+             * thread, the following formula was given:
+             *   maxVaryingVectors = min(GL_MAX_VERTEX_OUTPUT_COMPONENTS,
+             *                           GL_MAX_FRAGMENT_INPUT_COMPONENTS) / 4
+             */
             GLint maxVertexOutputComponents = 0;
             GLint maxFragmentInputComponents = 0;
 
@@ -1806,7 +1921,8 @@ WebGLContext::InitAndValidateGL()
                                                 maxFragmentInputComponents) / 4;
             } else {
                 mGLMaxVaryingVectors = 16;
-                // = 64/4, 64 is the min value for maxVertexOutputComponents in OpenGL 3.2 spec
+                // 16 = 64/4, and 64 is the min value for
+                // maxVertexOutputComponents in the OpenGL 3.2 spec.
             }
         }
     }
@@ -1819,11 +1935,14 @@ WebGLContext::InitAndValidateGL()
         // specifically enabled on desktop GLSL.
         gl->fEnable(LOCAL_GL_VERTEX_PROGRAM_POINT_SIZE);
 
-        // gl_PointCoord is always available in ES2 GLSL and in newer desktop GLSL versions, but apparently
-        // not in OpenGL 2 and apparently not (due to a driver bug) on certain NVIDIA setups. See:
-        //   http://www.opengl.org/discussion_boards/ubbthreads.php?ubb=showflat&Number=261472
-        // Note that this used to cause crashes on old ATI drivers... hopefully not a significant
-        // problem anymore. See bug 602183.
+        /* gl_PointCoord is always available in ES2 GLSL and in newer desktop
+         * GLSL versions, but apparently not in OpenGL 2 and apparently not (due
+         * to a driver bug) on certain NVIDIA setups. See:
+         *   http://www.opengl.org/discussion_boards/ubbthreads.php?ubb=showflat&Number=261472
+         *
+         * Note that this used to cause crashes on old ATI drivers... Hopefully
+         * not a significant anymore. See bug 602183.
+         */
         gl->fEnable(LOCAL_GL_POINT_SPRITE);
     }
 
@@ -1832,17 +1951,18 @@ WebGLContext::InitAndValidateGL()
         gl->Vendor() == gl::GLVendor::ATI &&
         !nsCocoaFeatures::IsAtLeastVersion(10,9))
     {
-        // The Mac ATI driver, in all known OSX version up to and including 10.8,
-        // renders points sprites upside-down. Apple bug 11778921
-        gl->fPointParameterf(LOCAL_GL_POINT_SPRITE_COORD_ORIGIN, LOCAL_GL_LOWER_LEFT);
+        // The Mac ATI driver, in all known OSX version up to and including
+        // 10.8, renders points sprites upside-down. (Apple bug 11778921)
+        gl->fPointParameterf(LOCAL_GL_POINT_SPRITE_COORD_ORIGIN,
+                             LOCAL_GL_LOWER_LEFT);
     }
 #endif
 
     // Check the shader validator pref
     NS_ENSURE_TRUE(Preferences::GetRootBranch(), false);
 
-    mShaderValidation =
-        Preferences::GetBool("webgl.shader_validator", mShaderValidation);
+    mShaderValidation = Preferences::GetBool("webgl.shader_validator",
+                                             mShaderValidation);
 
     // initialize shader translator
     if (mShaderValidation) {
@@ -1852,15 +1972,18 @@ WebGLContext::InitAndValidateGL()
         }
     }
 
-    // Mesa can only be detected with the GL_VERSION string, of the form "2.1 Mesa 7.11.0"
-    mIsMesa = strstr((const char *)(gl->fGetString(LOCAL_GL_VERSION)), "Mesa");
+    // Mesa can only be detected with the GL_VERSION string, of the form
+    // "2.1 Mesa 7.11.0"
+    const char* versionStr = (const char*)(gl->fGetString(LOCAL_GL_VERSION));
+    mIsMesa = strstr(versionStr, "Mesa");
 
     // Notice that the point of calling fGetError here is not only to check for
     // errors, but also to reset the error flags so that a subsequent WebGL
     // getError call will give the correct result.
     error = gl->fGetError();
     if (error != LOCAL_GL_NO_ERROR) {
-        GenerateWarning("GL error 0x%x occurred during WebGL context initialization!", error);
+        GenerateWarning("GL error 0x%x occurred during WebGL context"
+                        " initialization!", error);
         return false;
     }
 
@@ -1880,9 +2003,10 @@ WebGLContext::InitAndValidateGL()
     mDefaultVertexArray->mAttribs.SetLength(mGLMaxVertexAttribs);
     mBoundVertexArray = mDefaultVertexArray;
 
-    if (mLoseContextOnMemoryPressure) {
+    if (mLoseContextOnMemoryPressure)
         mContextObserver->RegisterMemoryPressureEvent();
-    }
 
     return true;
 }
+
+} // namespace mozilla
diff --git a/dom/canvas/WebGLContextVertexArray.cpp b/dom/canvas/WebGLContextVertexArray.cpp
index b4ece82b8ea9..5e90abf754ac 100644
--- a/dom/canvas/WebGLContextVertexArray.cpp
+++ b/dom/canvas/WebGLContextVertexArray.cpp
@@ -4,15 +4,16 @@
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "WebGLContext.h"
-#include "WebGLBuffer.h"
-#include "WebGLVertexAttribData.h"
-#include "WebGLVertexArray.h"
-#include "GLContext.h"
 
-using namespace mozilla;
+#include "GLContext.h"
+#include "WebGLBuffer.h"
+#include "WebGLVertexArray.h"
+#include "WebGLVertexAttribData.h"
+
+namespace mozilla {
 
 void
-WebGLContext::BindVertexArray(WebGLVertexArray *array)
+WebGLContext::BindVertexArray(WebGLVertexArray* array)
 {
     if (IsContextLost())
         return;
@@ -59,7 +60,7 @@ WebGLContext::CreateVertexArray()
 }
 
 void
-WebGLContext::DeleteVertexArray(WebGLVertexArray *array)
+WebGLContext::DeleteVertexArray(WebGLVertexArray* array)
 {
     if (IsContextLost())
         return;
@@ -77,7 +78,7 @@ WebGLContext::DeleteVertexArray(WebGLVertexArray *array)
 }
 
 bool
-WebGLContext::IsVertexArray(WebGLVertexArray *array)
+WebGLContext::IsVertexArray(WebGLVertexArray* array)
 {
     if (IsContextLost())
         return false;
@@ -89,3 +90,5 @@ WebGLContext::IsVertexArray(WebGLVertexArray *array)
            !array->IsDeleted() &&
            array->HasEverBeenBound();
 }
+
+} // namespace mozilla
diff --git a/dom/canvas/WebGLContextVertices.cpp b/dom/canvas/WebGLContextVertices.cpp
index 201b7573583a..caa3bb1e2a8f 100644
--- a/dom/canvas/WebGLContextVertices.cpp
+++ b/dom/canvas/WebGLContextVertices.cpp
@@ -437,7 +437,7 @@ WebGLContext::VertexAttribPointer(GLuint index, GLint size, GLenum type,
      return ErrorInvalidOperation("vertexAttribPointer: type must match bound VBO type: %d != %d", type, mBoundArrayBuffer->GLType());
      */
 
-    WebGLVertexAttribData &vd = mBoundVertexArray->mAttribs[index];
+    WebGLVertexAttribData& vd = mBoundVertexArray->mAttribs[index];
 
     vd.buf = mBoundArrayBuffer;
     vd.stride = stride;
diff --git a/dom/canvas/WebGLElementArrayCache.cpp b/dom/canvas/WebGLElementArrayCache.cpp
index 6e0919b31271..0c2502809a37 100644
--- a/dom/canvas/WebGLElementArrayCache.cpp
+++ b/dom/canvas/WebGLElementArrayCache.cpp
@@ -5,54 +5,57 @@
 
 #include "WebGLElementArrayCache.h"
 
-#include "mozilla/Assertions.h"
-#include "mozilla/MemoryReporting.h"
-#include "mozilla/MathAlgorithms.h"
-
+#include 
 #include 
 #include 
 #include 
-#include 
+#include "mozilla/Assertions.h"
+#include "mozilla/MathAlgorithms.h"
+#include "mozilla/MemoryReporting.h"
 
 namespace mozilla {
 
 static void
-UpdateUpperBound(uint32_t* out_upperBound, uint32_t newBound)
+UpdateUpperBound(uint32_t* const out_upperBound, uint32_t newBound)
 {
-  MOZ_ASSERT(out_upperBound);
-  *out_upperBound = std::max(*out_upperBound, newBound);
+    MOZ_ASSERT(out_upperBound);
+    *out_upperBound = std::max(*out_upperBound, newBound);
 }
 
-/*
- * WebGLElementArrayCacheTree contains most of the implementation of WebGLElementArrayCache,
- * which performs WebGL element array buffer validation for drawElements.
+/* WebGLElementArrayCacheTree contains most of the implementation of
+ * WebGLElementArrayCache, which performs WebGL element array buffer validation
+ * for drawElements.
  *
- * Attention: Here lie nontrivial data structures, bug-prone algorithms, and non-canonical tweaks!
- * Whence the explanatory comments, and compiled unit test.
+ * Attention: Here lie nontrivial data structures, bug-prone algorithms, and
+ * non-canonical tweaks! Whence the explanatory comments, and compiled unit
+ * test.
  *
  * *** What problem are we solving here? ***
  *
- * WebGL::DrawElements has to validate that the elements are in range wrt the current vertex attribs.
- * This boils down to the problem, given an array of integers, of computing the maximum in an arbitrary
- * sub-array. The naive algorithm has linear complexity; this has been a major performance problem,
- * see bug 569431. In that bug, we took the approach of caching the max for the whole array, which
- * does cover most cases (DrawElements typically consumes the whole element array buffer) but doesn't
- * help in other use cases:
- *  - when doing "partial DrawElements" i.e. consuming only part of the element array buffer
- *  - when doing frequent "partial buffer updates" i.e. bufferSubData calls updating parts of the
- *    element array buffer
+ * WebGL::DrawElements has to validate that the elements are in range wrt the
+ * current vertex attribs. This boils down to the problem, given an array of
+ * integers, of computing the maximum in an arbitrary sub-array. The naive
+ * algorithm has linear complexity; this has been a major performance problem,
+ * see bug 569431. In that bug, we took the approach of caching the max for the
+ * whole array, which does cover most cases (DrawElements typically consumes the
+ * whole element array buffer) but doesn't help in other use cases:
+ *  - when doing "partial DrawElements" i.e. consuming only part of the element
+ *    array buffer
+ *  - when doing frequent "partial buffer updates" i.e. bufferSubData calls
+ *    updating parts of the element array buffer
  *
- * *** The solution: a binary tree ***
+ * *** The solution: A binary tree ***
  *
- * The solution implemented here is to use a binary tree as the cache data structure. Each tree node
- * contains the max of its two children nodes. In this way, finding the maximum in any contiguous sub-array
- * has log complexity instead of linear complexity.
+ * The solution implemented here is to use a binary tree as the cache data
+ * structure. Each tree node contains the max of its two children nodes. In this
+ * way, finding the maximum in any contiguous sub-array has log complexity
+ * instead of linear complexity.
  *
- * Simplistically, if the element array is
+ * Simplistically, if the element array is:
  *
- *     1   4   3   2
+ *    [1   4   3   2]
  *
- * then the corresponding tree is
+ * then the corresponding tree is:
  *
  *           4
  *         _/ \_
@@ -60,33 +63,35 @@ UpdateUpperBound(uint32_t* out_upperBound, uint32_t newBound)
  *      / \     / \
  *     1   4   3   2
  *
- * In practice, the bottom-most levels of the tree are both the largest to store (because they
- * have more nodes), and the least useful performance-wise (because each node in the bottom
- * levels concerns only few entries in the elements array buffer, it is cheap to compute).
+ * In practice, the bottom-most levels of the tree are both the largest to store
+ * (because they have more nodes), and the least useful performance-wise
+ * (because each node in the bottom levels concerns only few entries in the
+ * elements array buffer, it is cheap to compute).
  *
- * For this reason, we stop the tree a few levels above, so that each tree leaf actually corresponds
- * to more than one element array entry.
+ * For this reason, we stop the tree a few levels above, so that each tree leaf
+ * actually corresponds to more than one element array entry.
  *
- * The number of levels that we "drop" is |sSkippedBottomTreeLevels| and the number of element array entries
- * that each leaf corresponds to, is |sElementsPerLeaf|. This being a binary tree, we have
+ * The number of levels that we "drop" is |kSkippedBottomTreeLevels| and the
+ * number of element array entries that each leaf corresponds to, is
+ * |kElementsPerLeaf|. This being a binary tree, we have:
  *
- *   sElementsPerLeaf = 2 ^ sSkippedBottomTreeLevels.
+ *   kElementsPerLeaf = 2 ^ kSkippedBottomTreeLevels.
  *
  * *** Storage layout of the binary tree ***
  *
- * We take advantage of the specifics of the situation to avoid generalist tree storage and instead
- * store the tree entries in a vector, mTreeData.
+ * We take advantage of the specifics of the situation to avoid generalist tree
+ * storage and instead store the tree entries in a vector, mTreeData.
  *
- * TreeData is always a vector of length
+ * TreeData is always a vector of length:
  *
  *    2 * (number of leaves).
  *
- * Its data layout is as follows: mTreeData[0] is unused, mTreeData[1] is the root node,
- * then at offsets 2..3 is the tree level immediately below the root node, then at offsets 4..7
- * is the tree level below that, etc.
+ * Its data layout is as follows: mTreeData[0] is unused, mTreeData[1] is the
+ * root node, then at offsets 2..3 is the tree level immediately below the root
+ * node, then at offsets 4..7 is the tree level below that, etc.
  *
- * The figure below illustrates this by writing at each tree node the offset into mTreeData at
- * which it is stored:
+ * The figure below illustrates this by writing at each tree node the offset
+ * into mTreeData at which it is stored:
  *
  *           1
  *         _/ \_
@@ -95,202 +100,216 @@ UpdateUpperBound(uint32_t* out_upperBound, uint32_t newBound)
  *     4   5   6   7
  *    ...
  *
- * Thus, under the convention that the root level is level 0, we see that level N is stored at offsets
+ * Thus, under the convention that the root level is level 0, we see that level
+ * N is stored at offsets:
  *
  *    [ 2^n .. 2^(n+1) - 1 ]
  *
- * in mTreeData. Likewise, all the usual tree operations have simple mathematical expressions in
- * terms of mTreeData offsets, see all the methods such as ParentNode, LeftChildNode, etc.
+ * in mTreeData. Likewise, all the usual tree operations have simple
+ * mathematical expressions in terms of mTreeData offsets, see all the methods
+ * such as ParentNode, LeftChildNode, etc.
  *
- * *** Design constraint: element types aren't known at buffer-update time ***
+ * *** Design constraint: Element types aren't known at buffer-update time ***
  *
- * Note that a key constraint that we're operating under, is that we don't know the types of the elements
- * by the time WebGL bufferData/bufferSubData methods are called. The type of elements is only
- * specified in the drawElements call. This means that we may potentially have to store caches for
- * multiple element types, for the same element array buffer. Since we don't know yet how many
- * element types we'll eventually support (extensions add more), the concern about memory usage is serious.
- * This is addressed by sSkippedBottomTreeLevels as explained above. Of course, in the typical
- * case where each element array buffer is only ever used with one type, this is also addressed
- * by having WebGLElementArrayCache lazily create trees for each type only upon first use.
+ * Note that a key constraint that we're operating under, is that we don't know
+ * the types of the elements by the time WebGL bufferData/bufferSubData methods
+ * are called. The type of elements is only specified in the drawElements call.
+ * This means that we may potentially have to store caches for multiple element
+ * types, for the same element array buffer. Since we don't know yet how many
+ * element types we'll eventually support (extensions add more), the concern
+ * about memory usage is serious. This is addressed by kSkippedBottomTreeLevels
+ * as explained above. Of course, in the typical case where each element array
+ * buffer is only ever used with one type, this is also addressed by having
+ * WebGLElementArrayCache lazily create trees for each type only upon first use.
  *
- * Another consequence of this constraint is that when updating the trees, we have to update
- * all existing trees. So if trees for types uint8_t, uint16_t and uint32_t have ever been constructed for this buffer,
- * every subsequent update will have to update all trees even if one of the types is never
- * used again. That's inefficient, but content should not put indices of different types in the
- * same element array buffer anyways. Different index types can only be consumed in separate
- * drawElements calls, so nothing particular is to be achieved by lumping them in the same
- * buffer object.
+ * Another consequence of this constraint is that when updating the trees, we
+ * have to update all existing trees. So if trees for types uint8_t, uint16_t
+ * and uint32_t have ever been constructed for this buffer, every subsequent
+ * update will have to update all trees even if one of the types is never used
+ * again. That's inefficient, but content should not put indices of different
+ * types in the same element array buffer anyways. Different index types can
+ * only be consumed in separate drawElements calls, so nothing particular is
+ * to be achieved by lumping them in the same buffer object.
  */
 template
 struct WebGLElementArrayCacheTree
 {
-  // A too-high sSkippedBottomTreeLevels would harm the performance of small drawElements calls
-  // A too-low sSkippedBottomTreeLevels would cause undue memory usage.
-  // The current value has been validated by some benchmarking. See bug 732660.
-  static const size_t sSkippedBottomTreeLevels = 3;
-  static const size_t sElementsPerLeaf = 1 << sSkippedBottomTreeLevels;
-  static const size_t sElementsPerLeafMask = sElementsPerLeaf - 1; // sElementsPerLeaf is POT
+    /* A too-high kSkippedBottomTreeLevels would harm the performance of small
+     * drawElements calls. A too-low kSkippedBottomTreeLevels would cause undue
+     * memory usage. The current value has been validated by some benchmarking.
+     * See bug 732660.
+     */
+    static const size_t kSkippedBottomTreeLevels = 3;
+    static const size_t kElementsPerLeaf = 1 << kSkippedBottomTreeLevels;
+    // Since kElementsPerLeaf is POT:
+    static const size_t kElementsPerLeafMask = kElementsPerLeaf - 1;
 
 private:
+    // The WebGLElementArrayCache that owns this tree:
+    WebGLElementArrayCache& mParent;
 
-  // The WebGLElementArrayCache that owns this tree
-  WebGLElementArrayCache& mParent;
-
-  // The tree's internal data storage. Its length is 2 * (number of leaves)
-  // because of its data layout explained in the above class comment.
-  FallibleTArray mTreeData;
+    // The tree's internal data storage. Its length is 2 * (number of leaves)
+    // because of its data layout explained in the above class comment.
+    FallibleTArray mTreeData;
 
 public:
-  // Constructor. Takes a reference to the WebGLElementArrayCache that is to be
-  // the parent. Does not initialize the tree. Should be followed by a call
-  // to Update() to attempt initializing the tree.
-  explicit WebGLElementArrayCacheTree(WebGLElementArrayCache& aValue)
-    : mParent(aValue)
-  {
-  }
-
-  T GlobalMaximum() const {
-    return mTreeData[1];
-  }
-
-  // returns the index of the parent node; if treeIndex=1 (the root node),
-  // the return value is 0.
-  static size_t ParentNode(size_t treeIndex) {
-    MOZ_ASSERT(treeIndex > 1);
-    return treeIndex >> 1;
-  }
-
-  static bool IsRightNode(size_t treeIndex) {
-    MOZ_ASSERT(treeIndex > 1);
-    return treeIndex & 1;
-  }
-
-  static bool IsLeftNode(size_t treeIndex) {
-    MOZ_ASSERT(treeIndex > 1);
-    return !IsRightNode(treeIndex);
-  }
-
-  static size_t SiblingNode(size_t treeIndex) {
-    MOZ_ASSERT(treeIndex > 1);
-    return treeIndex ^ 1;
-  }
-
-  static size_t LeftChildNode(size_t treeIndex) {
-    MOZ_ASSERT(treeIndex);
-    return treeIndex << 1;
-  }
-
-  static size_t RightChildNode(size_t treeIndex) {
-    MOZ_ASSERT(treeIndex);
-    return SiblingNode(LeftChildNode(treeIndex));
-  }
-
-  static size_t LeftNeighborNode(size_t treeIndex, size_t distance = 1) {
-    MOZ_ASSERT(treeIndex > 1);
-    return treeIndex - distance;
-  }
-
-  static size_t RightNeighborNode(size_t treeIndex, size_t distance = 1) {
-    MOZ_ASSERT(treeIndex > 1);
-    return treeIndex + distance;
-  }
-
-  size_t NumLeaves() const {
-    // see class comment for why we the tree storage size is 2 * numLeaves
-    return mTreeData.Length() >> 1;
-  }
-
-  size_t LeafForElement(size_t element) const {
-    size_t leaf = element / sElementsPerLeaf;
-    MOZ_ASSERT(leaf < NumLeaves());
-    return leaf;
-  }
-
-  size_t LeafForByte(size_t byte) const {
-    return LeafForElement(byte / sizeof(T));
-  }
-
-  // Returns the index, into the tree storage, where a given leaf is stored
-  size_t TreeIndexForLeaf(size_t leaf) const {
-    // See above class comment. The tree storage is an array of length 2 * numLeaves.
-    // The leaves are stored in its second half.
-    return leaf + NumLeaves();
-  }
-
-  static size_t LastElementUnderSameLeaf(size_t element) {
-    return element | sElementsPerLeafMask;
-  }
-
-  static size_t FirstElementUnderSameLeaf(size_t element) {
-    return element & ~sElementsPerLeafMask;
-  }
-
-  static size_t NextMultipleOfElementsPerLeaf(size_t numElements) {
-    MOZ_ASSERT(numElements >= 1);
-    return ((numElements - 1) | sElementsPerLeafMask) + 1;
-  }
-
-  bool Validate(T maxAllowed, size_t firstLeaf, size_t lastLeaf,
-                uint32_t* out_upperBound)
-  {
-    size_t firstTreeIndex = TreeIndexForLeaf(firstLeaf);
-    size_t lastTreeIndex  = TreeIndexForLeaf(lastLeaf);
-
-    while (true) {
-      // given that we tweak these values in nontrivial ways, it doesn't hurt to do
-      // this sanity check
-      MOZ_ASSERT(firstTreeIndex <= lastTreeIndex);
-
-      // final case where there is only 1 node to validate at the current tree level
-      if (lastTreeIndex == firstTreeIndex) {
-        const T& curData = mTreeData[firstTreeIndex];
-        UpdateUpperBound(out_upperBound, curData);
-        return curData <= maxAllowed;
-      }
-
-      // if the first node at current tree level is a right node, handle it individually
-      // and replace it with its right neighbor, which is a left node
-      if (IsRightNode(firstTreeIndex)) {
-        const T& curData = mTreeData[firstTreeIndex];
-        UpdateUpperBound(out_upperBound, curData);
-        if (curData > maxAllowed)
-          return false;
-        firstTreeIndex = RightNeighborNode(firstTreeIndex);
-      }
-
-      // if the last node at current tree level is a left node, handle it individually
-      // and replace it with its left neighbor, which is a right node
-      if (IsLeftNode(lastTreeIndex)) {
-        const T& curData = mTreeData[lastTreeIndex];
-        UpdateUpperBound(out_upperBound, curData);
-        if (curData > maxAllowed)
-          return false;
-        lastTreeIndex = LeftNeighborNode(lastTreeIndex);
-      }
-
-      // at this point it can happen that firstTreeIndex and lastTreeIndex "crossed" each
-      // other. That happens if firstTreeIndex was a right node and lastTreeIndex was its
-      // right neighor: in that case, both above tweaks happened and as a result, they ended
-      // up being swapped: lastTreeIndex is now the _left_ neighbor of firstTreeIndex.
-      // When that happens, there is nothing left to validate.
-      if (lastTreeIndex == LeftNeighborNode(firstTreeIndex)) {
-        return true;
-      }
-
-      // walk up 1 level
-      firstTreeIndex = ParentNode(firstTreeIndex);
-      lastTreeIndex = ParentNode(lastTreeIndex);
+    // Constructor. Takes a reference to the WebGLElementArrayCache that is to be
+    // the parent. Does not initialize the tree. Should be followed by a call
+    // to Update() to attempt initializing the tree.
+    explicit WebGLElementArrayCacheTree(WebGLElementArrayCache& value)
+        : mParent(value)
+    {
     }
-  }
 
-  // Updates the tree from the parent's buffer contents. Fallible, as it
-  // may have to resize the tree storage.
-  bool Update(size_t firstByte, size_t lastByte);
+    T GlobalMaximum() const {
+        return mTreeData[1];
+    }
 
-  size_t SizeOfIncludingThis(mozilla::MallocSizeOf aMallocSizeOf) const
-  {
-    return aMallocSizeOf(this) + mTreeData.SizeOfExcludingThis(aMallocSizeOf);
-  }
+    // returns the index of the parent node; if treeIndex=1 (the root node),
+    // the return value is 0.
+    static size_t ParentNode(size_t treeIndex) {
+        MOZ_ASSERT(treeIndex > 1);
+        return treeIndex >> 1;
+    }
+
+    static bool IsRightNode(size_t treeIndex) {
+        MOZ_ASSERT(treeIndex > 1);
+        return treeIndex & 1;
+    }
+
+    static bool IsLeftNode(size_t treeIndex) {
+        MOZ_ASSERT(treeIndex > 1);
+        return !IsRightNode(treeIndex);
+    }
+
+    static size_t SiblingNode(size_t treeIndex) {
+        MOZ_ASSERT(treeIndex > 1);
+        return treeIndex ^ 1;
+    }
+
+    static size_t LeftChildNode(size_t treeIndex) {
+        MOZ_ASSERT(treeIndex);
+        return treeIndex << 1;
+    }
+
+    static size_t RightChildNode(size_t treeIndex) {
+        MOZ_ASSERT(treeIndex);
+        return SiblingNode(LeftChildNode(treeIndex));
+    }
+
+    static size_t LeftNeighborNode(size_t treeIndex, size_t distance = 1) {
+        MOZ_ASSERT(treeIndex > 1);
+        return treeIndex - distance;
+    }
+
+    static size_t RightNeighborNode(size_t treeIndex, size_t distance = 1) {
+        MOZ_ASSERT(treeIndex > 1);
+        return treeIndex + distance;
+    }
+
+    size_t NumLeaves() const {
+        // See class comment for why we the tree storage size is 2 * numLeaves.
+        return mTreeData.Length() >> 1;
+    }
+
+    size_t LeafForElement(size_t element) const {
+        size_t leaf = element / kElementsPerLeaf;
+        MOZ_ASSERT(leaf < NumLeaves());
+        return leaf;
+    }
+
+    size_t LeafForByte(size_t byte) const {
+        return LeafForElement(byte / sizeof(T));
+    }
+
+    // Returns the index, into the tree storage, where a given leaf is stored.
+    size_t TreeIndexForLeaf(size_t leaf) const {
+        // See above class comment. The tree storage is an array of length
+        // 2 * numLeaves. The leaves are stored in its second half.
+        return leaf + NumLeaves();
+    }
+
+    static size_t LastElementUnderSameLeaf(size_t element) {
+        return element | kElementsPerLeafMask;
+    }
+
+    static size_t FirstElementUnderSameLeaf(size_t element) {
+        return element & ~kElementsPerLeafMask;
+    }
+
+    static size_t NextMultipleOfElementsPerLeaf(size_t numElements) {
+        MOZ_ASSERT(numElements >= 1);
+        return ((numElements - 1) | kElementsPerLeafMask) + 1;
+    }
+
+    bool Validate(T maxAllowed, size_t firstLeaf, size_t lastLeaf,
+                  uint32_t* const out_upperBound)
+    {
+        size_t firstTreeIndex = TreeIndexForLeaf(firstLeaf);
+        size_t lastTreeIndex  = TreeIndexForLeaf(lastLeaf);
+
+        while (true) {
+            // Given that we tweak these values in nontrivial ways, it doesn't
+            // hurt to do this sanity check.
+            MOZ_ASSERT(firstTreeIndex <= lastTreeIndex);
+
+            // Final case where there is only one node to validate at the
+            // current tree level:
+            if (lastTreeIndex == firstTreeIndex) {
+                const T& curData = mTreeData[firstTreeIndex];
+                UpdateUpperBound(out_upperBound, curData);
+                return curData <= maxAllowed;
+            }
+
+            // If the first node at current tree level is a right node, handle
+            // it individually and replace it with its right neighbor, which is
+            // a left node.
+            if (IsRightNode(firstTreeIndex)) {
+                const T& curData = mTreeData[firstTreeIndex];
+                UpdateUpperBound(out_upperBound, curData);
+                if (curData > maxAllowed)
+                  return false;
+
+                firstTreeIndex = RightNeighborNode(firstTreeIndex);
+            }
+
+            // If the last node at current tree level is a left node, handle it
+            // individually and replace it with its left neighbor, which is a
+            // right node.
+            if (IsLeftNode(lastTreeIndex)) {
+                const T& curData = mTreeData[lastTreeIndex];
+                UpdateUpperBound(out_upperBound, curData);
+                if (curData > maxAllowed)
+                    return false;
+
+                lastTreeIndex = LeftNeighborNode(lastTreeIndex);
+            }
+
+            /* At this point it can happen that firstTreeIndex and lastTreeIndex
+             * "crossed" eachother. That happens if firstTreeIndex was a right
+             * node and lastTreeIndex was its right neighor: In that case, both
+             * above tweaks happened and as a result, they ended up being
+             * swapped: LastTreeIndex is now the _left_ neighbor of
+             * firstTreeIndex. When that happens, there is nothing left to
+             * validate.
+             */
+            if (lastTreeIndex == LeftNeighborNode(firstTreeIndex))
+                return true;
+
+            // Walk up one level.
+            firstTreeIndex = ParentNode(firstTreeIndex);
+            lastTreeIndex = ParentNode(lastTreeIndex);
+        }
+    }
+
+    // Updates the tree from the parent's buffer contents. Fallible, as it
+    // may have to resize the tree storage.
+    bool Update(size_t firstByte, size_t lastByte);
+
+    size_t SizeOfIncludingThis(mozilla::MallocSizeOf mallocSizeOf) const
+    {
+        return mallocSizeOf(this) + mTreeData.SizeOfExcludingThis(mallocSizeOf);
+    }
 };
 
 // TreeForType: just a template helper to select the right tree object for a given
@@ -301,287 +320,311 @@ struct TreeForType {};
 template<>
 struct TreeForType
 {
-  static ScopedDeletePtr>&
-  Value(WebGLElementArrayCache *b) {
-    return b->mUint8Tree;
-  }
+    static ScopedDeletePtr>&
+    Value(WebGLElementArrayCache* b) {
+        return b->mUint8Tree;
+    }
 };
 
 template<>
 struct TreeForType
 {
-  static ScopedDeletePtr>&
-  Value(WebGLElementArrayCache *b) {
-    return b->mUint16Tree;
-  }
+    static ScopedDeletePtr>&
+    Value(WebGLElementArrayCache* b) {
+        return b->mUint16Tree;
+    }
 };
 
 template<>
 struct TreeForType
 {
-  static ScopedDeletePtr>&
-  Value(WebGLElementArrayCache *b) {
-    return b->mUint32Tree;
-  }
+    static ScopedDeletePtr>&
+    Value(WebGLElementArrayCache* b) {
+        return b->mUint32Tree;
+    }
 };
 
 // Calling this method will 1) update the leaves in this interval
-// from the raw buffer data, and 2) propagate this update up the tree
+// from the raw buffer data, and 2) propagate this update up the tree.
 template
-bool WebGLElementArrayCacheTree::Update(size_t firstByte, size_t lastByte)
+bool
+WebGLElementArrayCacheTree::Update(size_t firstByte, size_t lastByte)
 {
-  MOZ_ASSERT(firstByte <= lastByte);
-  MOZ_ASSERT(lastByte < mParent.mBytes.Length());
+    MOZ_ASSERT(firstByte <= lastByte);
+    MOZ_ASSERT(lastByte < mParent.mBytes.Length());
 
-  size_t numberOfElements = mParent.mBytes.Length() / sizeof(T);
-  size_t requiredNumLeaves = 0;
-  if (numberOfElements > 0) {
-    // If we didn't require the number of leaves to be a power of two, then
-    // it would just be equal to
-    //
-    //    ceil(numberOfElements / sElementsPerLeaf)
-    //
-    // The way we implement this (division+ceil) operation in integer arithmetic
-    // is as follows:
-    size_t numLeavesNonPOT = (numberOfElements + sElementsPerLeaf - 1) / sElementsPerLeaf;
-    // It only remains to round that up to the next power of two:
-    requiredNumLeaves = RoundUpPow2(numLeavesNonPOT);
-  }
-
-  // Step #0: if needed, resize our tree data storage.
-  if (requiredNumLeaves != NumLeaves()) {
-    // see class comment for why we the tree storage size is 2 * numLeaves
-    if (!mTreeData.SetLength(2 * requiredNumLeaves)) {
-      mTreeData.SetLength(0);
-      return false;
-    }
-    MOZ_ASSERT(NumLeaves() == requiredNumLeaves);
-
-    if (NumLeaves()) {
-      // when resizing, update the whole tree, not just the subset corresponding
-      // to the part of the buffer being updated.
-      memset(mTreeData.Elements(), 0, mTreeData.Length() * sizeof(T));
-      firstByte = 0;
-      lastByte = mParent.mBytes.Length() - 1;
-    }
-  }
-
-  if (NumLeaves() == 0) {
-    return true;
-  }
-
-  lastByte = std::min(lastByte, NumLeaves() * sElementsPerLeaf * sizeof(T) - 1);
-  if (firstByte > lastByte) {
-    return true;
-  }
-
-  size_t firstLeaf = LeafForByte(firstByte);
-  size_t lastLeaf = LeafForByte(lastByte);
-
-  MOZ_ASSERT(firstLeaf <= lastLeaf && lastLeaf < NumLeaves());
-
-  size_t firstTreeIndex = TreeIndexForLeaf(firstLeaf);
-  size_t lastTreeIndex = TreeIndexForLeaf(lastLeaf);
-
-  // Step #1: initialize the tree leaves from plain buffer data.
-  // That is, each tree leaf must be set to the max of the |sElementsPerLeaf| corresponding
-  // buffer entries.
-  // condition-less scope to prevent leaking this scope's variables into the code below
-  {
-    // treeIndex is the index of the tree leaf we're writing, i.e. the destination index
-    size_t treeIndex = firstTreeIndex;
-    // srcIndex is the index in the source buffer
-    size_t srcIndex = firstLeaf * sElementsPerLeaf;
-    while (treeIndex <= lastTreeIndex) {
-      T m = 0;
-      size_t a = srcIndex;
-      size_t srcIndexNextLeaf = std::min(a + sElementsPerLeaf, numberOfElements);
-      for (; srcIndex < srcIndexNextLeaf; srcIndex++) {
-        m = std::max(m, mParent.Element(srcIndex));
-      }
-      mTreeData[treeIndex] = m;
-      treeIndex++;
-    }
-  }
-
-  // Step #2: propagate the values up the tree. This is simply a matter of walking up
-  // the tree and setting each node to the max of its two children.
-  while (firstTreeIndex > 1) {
-    // move up 1 level
-    firstTreeIndex = ParentNode(firstTreeIndex);
-    lastTreeIndex = ParentNode(lastTreeIndex);
-
-    // fast-exit case where only one node is updated at the current level
-    if (firstTreeIndex == lastTreeIndex) {
-      mTreeData[firstTreeIndex] = std::max(mTreeData[LeftChildNode(firstTreeIndex)], mTreeData[RightChildNode(firstTreeIndex)]);
-      continue;
+    size_t numberOfElements = mParent.mBytes.Length() / sizeof(T);
+    size_t requiredNumLeaves = 0;
+    if (numberOfElements > 0) {
+        /* If we didn't require the number of leaves to be a power of two, then
+         * it would just be equal to
+         *
+         *    ceil(numberOfElements / kElementsPerLeaf)
+         *
+         * The way we implement this (division+ceil) operation in integer
+         * arithmetic
+         * is as follows:
+         */
+        size_t numLeavesNonPOT = (numberOfElements + kElementsPerLeaf - 1) / kElementsPerLeaf;
+        // It only remains to round that up to the next power of two:
+        requiredNumLeaves = RoundUpPow2(numLeavesNonPOT);
     }
 
-    size_t child = LeftChildNode(firstTreeIndex);
-    size_t parent = firstTreeIndex;
-    while (parent <= lastTreeIndex)
+    // Step #0: If needed, resize our tree data storage.
+    if (requiredNumLeaves != NumLeaves()) {
+        // See class comment for why we the tree storage size is 2 * numLeaves.
+        if (!mTreeData.SetLength(2 * requiredNumLeaves)) {
+            mTreeData.SetLength(0);
+            return false;
+        }
+        MOZ_ASSERT(NumLeaves() == requiredNumLeaves);
+
+        if (NumLeaves()) {
+            // When resizing, update the whole tree, not just the subset
+            // corresponding to the part of the buffer being updated.
+            memset(mTreeData.Elements(), 0, mTreeData.Length() * sizeof(T));
+            firstByte = 0;
+            lastByte = mParent.mBytes.Length() - 1;
+        }
+    }
+
+    if (NumLeaves() == 0)
+        return true;
+
+    lastByte = std::min(lastByte, NumLeaves() * kElementsPerLeaf * sizeof(T) - 1);
+    if (firstByte > lastByte)
+        return true;
+
+    size_t firstLeaf = LeafForByte(firstByte);
+    size_t lastLeaf = LeafForByte(lastByte);
+
+    MOZ_ASSERT(firstLeaf <= lastLeaf && lastLeaf < NumLeaves());
+
+    size_t firstTreeIndex = TreeIndexForLeaf(firstLeaf);
+    size_t lastTreeIndex = TreeIndexForLeaf(lastLeaf);
+
+    // Step #1: Initialize the tree leaves from plain buffer data.
+    // That is, each tree leaf must be set to the max of the |kElementsPerLeaf|
+    // corresponding buffer entries.
+
+    // Condition-less scope to prevent leaking this scope's variables into the
+    // code below:
     {
-      T a = mTreeData[child];
-      child = RightNeighborNode(child);
-      T b = mTreeData[child];
-      child = RightNeighborNode(child);
-      mTreeData[parent] = std::max(a, b);
-      parent = RightNeighborNode(parent);
+        // TreeIndex is the index of the tree leaf we're writing, i.e. the
+        // destination index.
+        size_t treeIndex = firstTreeIndex;
+        // srcIndex is the index in the source buffer.
+        size_t srcIndex = firstLeaf * kElementsPerLeaf;
+        while (treeIndex <= lastTreeIndex) {
+            T m = 0;
+            size_t a = srcIndex;
+            size_t srcIndexNextLeaf = std::min(a + kElementsPerLeaf, numberOfElements);
+            for (; srcIndex < srcIndexNextLeaf; srcIndex++) {
+                m = std::max(m, mParent.Element(srcIndex));
+            }
+            mTreeData[treeIndex] = m;
+            treeIndex++;
+        }
     }
-  }
 
-  return true;
-}
+    // Step #2: Propagate the values up the tree. This is simply a matter of
+    // walking up the tree and setting each node to the max of its two children.
+    while (firstTreeIndex > 1) {
+        // Move up one level.
+        firstTreeIndex = ParentNode(firstTreeIndex);
+        lastTreeIndex = ParentNode(lastTreeIndex);
 
-WebGLElementArrayCache::WebGLElementArrayCache() {
-}
+        // Fast-exit case where only one node is updated at the current level.
+        if (firstTreeIndex == lastTreeIndex) {
+            mTreeData[firstTreeIndex] = std::max(mTreeData[LeftChildNode(firstTreeIndex)], mTreeData[RightChildNode(firstTreeIndex)]);
+            continue;
+        }
 
-WebGLElementArrayCache::~WebGLElementArrayCache() {
-}
-
-bool WebGLElementArrayCache::BufferData(const void* ptr, size_t byteLength) {
-  if (mBytes.Length() != byteLength) {
-    if (!mBytes.SetLength(byteLength)) {
-      mBytes.SetLength(0);
-      return false;
+        size_t child = LeftChildNode(firstTreeIndex);
+        size_t parent = firstTreeIndex;
+        while (parent <= lastTreeIndex) {
+            T a = mTreeData[child];
+            child = RightNeighborNode(child);
+            T b = mTreeData[child];
+            child = RightNeighborNode(child);
+            mTreeData[parent] = std::max(a, b);
+            parent = RightNeighborNode(parent);
+        }
     }
-  }
-  MOZ_ASSERT(mBytes.Length() == byteLength);
-  return BufferSubData(0, ptr, byteLength);
-}
 
-bool WebGLElementArrayCache::BufferSubData(size_t pos, const void* ptr, size_t updateByteLength) {
-  MOZ_ASSERT(pos + updateByteLength <= mBytes.Length());
-  if (!updateByteLength)
     return true;
-  if (ptr)
-    memcpy(mBytes.Elements() + pos, ptr, updateByteLength);
-  else
-    memset(mBytes.Elements() + pos, 0, updateByteLength);
-  return UpdateTrees(pos, pos + updateByteLength - 1);
 }
 
-bool WebGLElementArrayCache::UpdateTrees(size_t firstByte, size_t lastByte)
+WebGLElementArrayCache::WebGLElementArrayCache()
 {
-  bool result = true;
-  if (mUint8Tree)
-    result &= mUint8Tree->Update(firstByte, lastByte);
-  if (mUint16Tree)
-    result &= mUint16Tree->Update(firstByte, lastByte);
-  if (mUint32Tree)
-    result &= mUint32Tree->Update(firstByte, lastByte);
-  return result;
+}
+
+WebGLElementArrayCache::~WebGLElementArrayCache()
+{
+}
+
+bool
+WebGLElementArrayCache::BufferData(const void* ptr, size_t byteLength)
+{
+    if (mBytes.Length() != byteLength) {
+        if (!mBytes.SetLength(byteLength)) {
+            mBytes.SetLength(0);
+            return false;
+        }
+    }
+    MOZ_ASSERT(mBytes.Length() == byteLength);
+    return BufferSubData(0, ptr, byteLength);
+}
+
+bool
+WebGLElementArrayCache::BufferSubData(size_t pos, const void* ptr,
+                                      size_t updateByteLength)
+{
+    MOZ_ASSERT(pos + updateByteLength <= mBytes.Length());
+    if (!updateByteLength)
+        return true;
+
+    if (ptr)
+        memcpy(mBytes.Elements() + pos, ptr, updateByteLength);
+    else
+        memset(mBytes.Elements() + pos, 0, updateByteLength);
+    return UpdateTrees(pos, pos + updateByteLength - 1);
+}
+
+bool
+WebGLElementArrayCache::UpdateTrees(size_t firstByte, size_t lastByte)
+{
+    bool result = true;
+    if (mUint8Tree)
+        result &= mUint8Tree->Update(firstByte, lastByte);
+    if (mUint16Tree)
+        result &= mUint16Tree->Update(firstByte, lastByte);
+    if (mUint32Tree)
+        result &= mUint32Tree->Update(firstByte, lastByte);
+    return result;
 }
 
 template
 bool
 WebGLElementArrayCache::Validate(uint32_t maxAllowed, size_t firstElement,
-                                 size_t countElements, uint32_t* out_upperBound)
+                                 size_t countElements,
+                                 uint32_t* const out_upperBound)
 {
-  *out_upperBound = 0;
+    *out_upperBound = 0;
 
-  // if maxAllowed is >= the max T value, then there is no way that a T index could be invalid
-  uint32_t maxTSize = std::numeric_limits::max();
-  if (maxAllowed >= maxTSize) {
-    UpdateUpperBound(out_upperBound, maxTSize);
-    return true;
-  }
-
-  T maxAllowedT(maxAllowed);
-
-  // integer overflow must have been handled earlier, so we assert that maxAllowedT
-  // is exactly the max allowed value.
-  MOZ_ASSERT(uint32_t(maxAllowedT) == maxAllowed);
-
-  if (!mBytes.Length() || !countElements)
-    return true;
-
-  ScopedDeletePtr>& tree = TreeForType::Value(this);
-  if (!tree) {
-    tree = new WebGLElementArrayCacheTree(*this);
-    if (mBytes.Length()) {
-      bool valid = tree->Update(0, mBytes.Length() - 1);
-      if (!valid) {
-        // Do not assert here. This case would happen if an allocation failed.
-        // We've already settled on fallible allocations around here.
-        tree = nullptr;
-        return false;
-      }
+    // If maxAllowed is >= the max T value, then there is no way that a T index
+    // could be invalid.
+    uint32_t maxTSize = std::numeric_limits::max();
+    if (maxAllowed >= maxTSize) {
+        UpdateUpperBound(out_upperBound, maxTSize);
+        return true;
     }
-  }
 
-  size_t lastElement = firstElement + countElements - 1;
+    T maxAllowedT(maxAllowed);
 
-  // fast exit path when the global maximum for the whole element array buffer
-  // falls in the allowed range
-  T globalMax = tree->GlobalMaximum();
-  if (globalMax <= maxAllowedT)
-  {
-    UpdateUpperBound(out_upperBound, globalMax);
-    return true;
-  }
+    // Integer overflow must have been handled earlier, so we assert that
+    // maxAllowedT is exactly the max allowed value.
+    MOZ_ASSERT(uint32_t(maxAllowedT) == maxAllowed);
 
-  const T* elements = Elements();
+    if (!mBytes.Length() || !countElements)
+      return true;
 
-  // before calling tree->Validate, we have to validate ourselves the boundaries of the elements span,
-  // to round them to the nearest multiple of sElementsPerLeaf.
-  size_t firstElementAdjustmentEnd = std::min(lastElement,
-                                              tree->LastElementUnderSameLeaf(firstElement));
-  while (firstElement <= firstElementAdjustmentEnd) {
-    const T& curData = elements[firstElement];
-    UpdateUpperBound(out_upperBound, curData);
-    if (curData > maxAllowedT)
-      return false;
-    firstElement++;
-  }
-  size_t lastElementAdjustmentEnd = std::max(firstElement,
-                                             tree->FirstElementUnderSameLeaf(lastElement));
-  while (lastElement >= lastElementAdjustmentEnd) {
-    const T& curData = elements[lastElement];
-    UpdateUpperBound(out_upperBound, curData);
-    if (curData > maxAllowedT)
-      return false;
-    lastElement--;
-  }
+    ScopedDeletePtr>& tree = TreeForType::Value(this);
+    if (!tree) {
+        tree = new WebGLElementArrayCacheTree(*this);
+        if (mBytes.Length()) {
+            bool valid = tree->Update(0, mBytes.Length() - 1);
+            if (!valid) {
+                // Do not assert here. This case would happen if an allocation
+                // failed. We've already settled on fallible allocations around
+                // here.
+                tree = nullptr;
+                return false;
+            }
+        }
+    }
 
-  // at this point, for many tiny validations, we're already done.
-  if (firstElement > lastElement)
-    return true;
+    size_t lastElement = firstElement + countElements - 1;
 
-  // general case
-  return tree->Validate(maxAllowedT,
-                        tree->LeafForElement(firstElement),
-                        tree->LeafForElement(lastElement),
-                        out_upperBound);
+    // Fast-exit path when the global maximum for the whole element array buffer
+    // falls in the allowed range:
+    T globalMax = tree->GlobalMaximum();
+    if (globalMax <= maxAllowedT) {
+        UpdateUpperBound(out_upperBound, globalMax);
+        return true;
+    }
+
+    const T* elements = Elements();
+
+    // Before calling tree->Validate, we have to validate ourselves the
+    // boundaries of the elements span, to round them to the nearest multiple of
+    // kElementsPerLeaf.
+    size_t firstElementAdjustmentEnd = std::min(lastElement,
+                                                tree->LastElementUnderSameLeaf(firstElement));
+    while (firstElement <= firstElementAdjustmentEnd) {
+        const T& curData = elements[firstElement];
+        UpdateUpperBound(out_upperBound, curData);
+        if (curData > maxAllowedT)
+            return false;
+
+        firstElement++;
+    }
+    size_t lastElementAdjustmentEnd = std::max(firstElement,
+                                               tree->FirstElementUnderSameLeaf(lastElement));
+    while (lastElement >= lastElementAdjustmentEnd) {
+        const T& curData = elements[lastElement];
+        UpdateUpperBound(out_upperBound, curData);
+        if (curData > maxAllowedT)
+            return false;
+
+        lastElement--;
+    }
+
+    // at this point, for many tiny validations, we're already done.
+    if (firstElement > lastElement)
+        return true;
+
+    // general case
+    return tree->Validate(maxAllowedT, tree->LeafForElement(firstElement),
+                          tree->LeafForElement(lastElement), out_upperBound);
 }
 
 bool
 WebGLElementArrayCache::Validate(GLenum type, uint32_t maxAllowed,
                                  size_t firstElement, size_t countElements,
-                                 uint32_t* out_upperBound)
+                                 uint32_t* const out_upperBound)
 {
-  if (type == LOCAL_GL_UNSIGNED_BYTE)
-    return Validate(maxAllowed, firstElement, countElements, out_upperBound);
-  if (type == LOCAL_GL_UNSIGNED_SHORT)
-    return Validate(maxAllowed, firstElement, countElements, out_upperBound);
-  if (type == LOCAL_GL_UNSIGNED_INT)
-    return Validate(maxAllowed, firstElement, countElements, out_upperBound);
+    if (type == LOCAL_GL_UNSIGNED_BYTE)
+        return Validate(maxAllowed, firstElement, countElements,
+                                 out_upperBound);
+    if (type == LOCAL_GL_UNSIGNED_SHORT)
+        return Validate(maxAllowed, firstElement, countElements,
+                                  out_upperBound);
+    if (type == LOCAL_GL_UNSIGNED_INT)
+        return Validate(maxAllowed, firstElement, countElements,
+                                  out_upperBound);
 
-  MOZ_ASSERT(false, "Invalid type.");
-  return false;
+    MOZ_ASSERT(false, "Invalid type.");
+    return false;
+}
+
+template
+static size_t
+SizeOfNullable(mozilla::MallocSizeOf mallocSizeOf, const T& obj)
+{
+    if (!obj)
+        return 0;
+    return obj->SizeOfIncludingThis(mallocSizeOf);
 }
 
 size_t
-WebGLElementArrayCache::SizeOfIncludingThis(mozilla::MallocSizeOf aMallocSizeOf) const
+WebGLElementArrayCache::SizeOfIncludingThis(mozilla::MallocSizeOf mallocSizeOf) const
 {
-  size_t uint8TreeSize  = mUint8Tree  ? mUint8Tree->SizeOfIncludingThis(aMallocSizeOf) : 0;
-  size_t uint16TreeSize = mUint16Tree ? mUint16Tree->SizeOfIncludingThis(aMallocSizeOf) : 0;
-  size_t uint32TreeSize = mUint32Tree ? mUint32Tree->SizeOfIncludingThis(aMallocSizeOf) : 0;
-  return aMallocSizeOf(this) +
-          mBytes.SizeOfExcludingThis(aMallocSizeOf) +
-          uint8TreeSize +
-          uint16TreeSize +
-          uint32TreeSize;
+    return mallocSizeOf(this) +
+           mBytes.SizeOfExcludingThis(mallocSizeOf) +
+           SizeOfNullable(mallocSizeOf, mUint8Tree) +
+           SizeOfNullable(mallocSizeOf, mUint16Tree) +
+           SizeOfNullable(mallocSizeOf, mUint32Tree);
 }
 
 bool
diff --git a/dom/canvas/WebGLElementArrayCache.h b/dom/canvas/WebGLElementArrayCache.h
index 7a472c446195..3ff2eac005fe 100644
--- a/dom/canvas/WebGLElementArrayCache.h
+++ b/dom/canvas/WebGLElementArrayCache.h
@@ -3,98 +3,101 @@
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
-#ifndef WEBGLELEMENTARRAYCACHE_H
-#define WEBGLELEMENTARRAYCACHE_H
+#ifndef WEBGL_ELEMENT_ARRAY_CACHE_H
+#define WEBGL_ELEMENT_ARRAY_CACHE_H
 
+#include "GLDefs.h"
 #include "mozilla/MemoryReporting.h"
 #include "mozilla/Scoped.h"
+#include "nscore.h"
 #include "nsTArray.h"
 #include 
-#include "nscore.h"
-#include "GLDefs.h"
 
 namespace mozilla {
 
 template
 struct WebGLElementArrayCacheTree;
 
-/*
- * WebGLElementArrayCache implements WebGL element array buffer validation for drawElements.
+/* WebGLElementArrayCache implements WebGL element array buffer validation for
+ * drawElements.
  *
  * Its exposes methods meant to be called by WebGL method implementations:
- *  - Validate, to be called by WebGLContext::DrawElements, is where we use the cache
- *  - BufferData and BufferSubData, to be called by eponymous WebGL methods, are how
- *    data is fed into the cache
  *
- * Most of the implementation is hidden in the auxilary class template, WebGLElementArrayCacheTree.
- * Refer to its code for design comments.
+ * - Validate, to be called by WebGLContext::DrawElements, is where we use the
+ *   cache.
+ *
+ * - BufferData and BufferSubData, to be called by eponymous WebGL methods, are
+ *   how data is fed into the cache.
+ *
+ * Most of the implementation is hidden in the auxilary class template,
+ * WebGLElementArrayCacheTree. Refer to its code for design comments.
  */
 class WebGLElementArrayCache {
-
 public:
-  bool BufferData(const void* ptr, size_t byteLength);
-  bool BufferSubData(size_t pos, const void* ptr, size_t updateByteSize);
+    bool BufferData(const void* ptr, size_t byteLength);
+    bool BufferSubData(size_t pos, const void* ptr, size_t updateByteSize);
 
-  bool Validate(GLenum type, uint32_t maxAllowed, size_t first, size_t count,
-                uint32_t* out_upperBound);
+    bool Validate(GLenum type, uint32_t maxAllowed, size_t first, size_t count,
+                  uint32_t* const out_upperBound);
 
-  template
-  T Element(size_t i) const { return Elements()[i]; }
+    template
+    T Element(size_t i) const { return Elements()[i]; }
 
-  WebGLElementArrayCache();
+    WebGLElementArrayCache();
+    ~WebGLElementArrayCache();
 
-  ~WebGLElementArrayCache();
-
-  size_t SizeOfIncludingThis(mozilla::MallocSizeOf aMallocSizeOf) const;
-
-  bool BeenUsedWithMultipleTypes() const;
+    size_t SizeOfIncludingThis(mozilla::MallocSizeOf mallocSizeOf) const;
+    bool BeenUsedWithMultipleTypes() const;
 
 private:
+    /* Returns true if a drawElements call with the given parameters should
+     * succeed, false otherwise.
+     *
+     * In other words, this returns true if all entries in the element array at
+     * positions:
+     *
+     *    first .. first+count-1
+     *
+     * are less than or equal to maxAllowed.
+     *
+     * Input parameters:
+     *   maxAllowed: Maximum value to be allowed in the specificied portion of
+     *               the element array.
+     *   first: Start of the portion of the element array to consume.
+     *   count: Number of entries from the element array to consume.
+     *
+     * Output parameter:
+     *   out_upperBound: Upon success, is set to the actual maximum value in the
+     *                   specified range, which is then guaranteed to be less
+     *                   than or equal to maxAllowed. upon failure, is set to
+     *                   the first value in the specified range, that is greater
+     *                   than maxAllowed.
+     */
+    template
+    bool Validate(uint32_t maxAllowed, size_t first, size_t count,
+                  uint32_t* const out_upperBound);
 
-  /*
-   * Returns true if a drawElements call with the given parameters should succeed,
-   * false otherwise.
-   *
-   * In other words, this returns true if all entries in the element array at positions
-   *
-   *    first .. first+count-1
-   *
-   * are less than or equal to maxAllowed.
-   *
-   * Input parameters:
-   *   maxAllowed: maximum value to be allowed in the specificied portion of the element array.
-   *   first: start of the portion of the element array to consume.
-   *   count: number of entries from the element array to consume.
-   *
-   * Output parameter:
-   *   out_upperBound: upon success, is set to the actual maximum value in the specified range,
-   *                   which is then guaranteed to be less than or equal to maxAllowed.
-   *                   upon failure, is set to the first value in the specified range, that
-   *                   is greater than maxAllowed.
-   */
-  template
-  bool Validate(uint32_t maxAllowed, size_t first, size_t count,
-                uint32_t* out_upperBound);
+    template
+    const T* Elements() const {
+        return reinterpret_cast(mBytes.Elements());
+    }
 
-  template
-  const T* Elements() const { return reinterpret_cast(mBytes.Elements()); }
-  template
-  T* Elements() { return reinterpret_cast(mBytes.Elements()); }
+    template
+    T* Elements() { return reinterpret_cast(mBytes.Elements()); }
 
-  bool UpdateTrees(size_t firstByte, size_t lastByte);
+    bool UpdateTrees(size_t firstByte, size_t lastByte);
 
-  template
-  friend struct WebGLElementArrayCacheTree;
-  template
-  friend struct TreeForType;
+    template
+    friend struct WebGLElementArrayCacheTree;
+    template
+    friend struct TreeForType;
 
-  FallibleTArray mBytes;
-  ScopedDeletePtr> mUint8Tree;
-  ScopedDeletePtr> mUint16Tree;
-  ScopedDeletePtr> mUint32Tree;
+    FallibleTArray mBytes;
+    ScopedDeletePtr> mUint8Tree;
+    ScopedDeletePtr> mUint16Tree;
+    ScopedDeletePtr> mUint32Tree;
 };
 
-
 } // end namespace mozilla
 
-#endif // WEBGLELEMENTARRAYCACHE_H
+#endif // WEBGL_ELEMENT_ARRAY_CACHE_H
diff --git a/dom/canvas/WebGLExtensionBlendMinMax.cpp b/dom/canvas/WebGLExtensionBlendMinMax.cpp
index a8697b8aecd8..f2ca63e52e17 100644
--- a/dom/canvas/WebGLExtensionBlendMinMax.cpp
+++ b/dom/canvas/WebGLExtensionBlendMinMax.cpp
@@ -2,27 +2,30 @@
  * License, v. 2.0. If a copy of the MPL was not distributed with this file,
  * You can obtain one at http://mozilla.org/MPL/2.0/. */
 
-#include "WebGLContext.h"
 #include "WebGLExtensions.h"
 
 #include "GLContext.h"
-
 #include "mozilla/dom/WebGLRenderingContextBinding.h"
+#include "WebGLContext.h"
 
-using namespace mozilla;
+namespace mozilla {
 
-WebGLExtensionBlendMinMax::WebGLExtensionBlendMinMax(WebGLContext* context)
-    : WebGLExtensionBase(context)
+WebGLExtensionBlendMinMax::WebGLExtensionBlendMinMax(WebGLContext* webgl)
+    : WebGLExtensionBase(webgl)
 {
+    MOZ_ASSERT(IsSupported(webgl), "Don't construct extension if unsupported.");
 }
 
 WebGLExtensionBlendMinMax::~WebGLExtensionBlendMinMax()
 {
 }
 
-bool WebGLExtensionBlendMinMax::IsSupported(const WebGLContext* context)
+bool
+WebGLExtensionBlendMinMax::IsSupported(const WebGLContext* webgl)
 {
-    return context->GL()->IsSupported(gl::GLFeature::blend_minmax);
+    return webgl->GL()->IsSupported(gl::GLFeature::blend_minmax);
 }
 
 IMPL_WEBGL_EXTENSION_GOOP(WebGLExtensionBlendMinMax)
+
+} // namespace mozilla
diff --git a/dom/canvas/WebGLExtensionColorBufferFloat.cpp b/dom/canvas/WebGLExtensionColorBufferFloat.cpp
index cc3ea7153129..6258d13ed05e 100644
--- a/dom/canvas/WebGLExtensionColorBufferFloat.cpp
+++ b/dom/canvas/WebGLExtensionColorBufferFloat.cpp
@@ -8,12 +8,12 @@
 #include "mozilla/dom/WebGLRenderingContextBinding.h"
 #include "WebGLContext.h"
 
-using namespace mozilla;
+namespace mozilla {
 
-WebGLExtensionColorBufferFloat::WebGLExtensionColorBufferFloat(WebGLContext* context)
-    : WebGLExtensionBase(context)
+WebGLExtensionColorBufferFloat::WebGLExtensionColorBufferFloat(WebGLContext* webgl)
+    : WebGLExtensionBase(webgl)
 {
-    MOZ_ASSERT(IsSupported(context));
+    MOZ_ASSERT(IsSupported(webgl), "Don't construct extension if unsupported.");
 }
 
 WebGLExtensionColorBufferFloat::~WebGLExtensionColorBufferFloat()
@@ -21,9 +21,9 @@ WebGLExtensionColorBufferFloat::~WebGLExtensionColorBufferFloat()
 }
 
 bool
-WebGLExtensionColorBufferFloat::IsSupported(const WebGLContext* context)
+WebGLExtensionColorBufferFloat::IsSupported(const WebGLContext* webgl)
 {
-    gl::GLContext* gl = context->GL();
+    gl::GLContext* gl = webgl->GL();
 
     // ANGLE supports this, but doesn't have a way to advertize its support,
     // since it's compliant with WEBGL_color_buffer_float's clamping, but not
@@ -33,3 +33,5 @@ WebGLExtensionColorBufferFloat::IsSupported(const WebGLContext* context)
 }
 
 IMPL_WEBGL_EXTENSION_GOOP(WebGLExtensionColorBufferFloat)
+
+} // namespace mozilla
diff --git a/dom/canvas/WebGLExtensionColorBufferHalfFloat.cpp b/dom/canvas/WebGLExtensionColorBufferHalfFloat.cpp
index 8b63ac6fb640..51329c37dce0 100644
--- a/dom/canvas/WebGLExtensionColorBufferHalfFloat.cpp
+++ b/dom/canvas/WebGLExtensionColorBufferHalfFloat.cpp
@@ -8,12 +8,12 @@
 #include "mozilla/dom/WebGLRenderingContextBinding.h"
 #include "WebGLContext.h"
 
-using namespace mozilla;
+namespace mozilla {
 
-WebGLExtensionColorBufferHalfFloat::WebGLExtensionColorBufferHalfFloat(WebGLContext* context)
-    : WebGLExtensionBase(context)
+WebGLExtensionColorBufferHalfFloat::WebGLExtensionColorBufferHalfFloat(WebGLContext* webgl)
+    : WebGLExtensionBase(webgl)
 {
-    MOZ_ASSERT(IsSupported(context));
+    MOZ_ASSERT(IsSupported(webgl), "Don't construct extension if unsupported.");
 }
 
 WebGLExtensionColorBufferHalfFloat::~WebGLExtensionColorBufferHalfFloat()
@@ -21,12 +21,14 @@ WebGLExtensionColorBufferHalfFloat::~WebGLExtensionColorBufferHalfFloat()
 }
 
 bool
-WebGLExtensionColorBufferHalfFloat::IsSupported(const WebGLContext* context)
+WebGLExtensionColorBufferHalfFloat::IsSupported(const WebGLContext* webgl)
 {
-    gl::GLContext* gl = context->GL();
+    gl::GLContext* gl = webgl->GL();
 
     // ANGLE doesn't support ReadPixels from a RGBA16F with RGBA/FLOAT.
     return gl->IsSupported(gl::GLFeature::renderbuffer_color_half_float);
 }
 
 IMPL_WEBGL_EXTENSION_GOOP(WebGLExtensionColorBufferHalfFloat)
+
+} // namespace mozilla
diff --git a/dom/canvas/WebGLExtensionCompressedTextureATC.cpp b/dom/canvas/WebGLExtensionCompressedTextureATC.cpp
index 15b018b405ec..bdc39339988c 100644
--- a/dom/canvas/WebGLExtensionCompressedTextureATC.cpp
+++ b/dom/canvas/WebGLExtensionCompressedTextureATC.cpp
@@ -2,18 +2,19 @@
  * License, v. 2.0. If a copy of the MPL was not distributed with this file,
  * You can obtain one at http://mozilla.org/MPL/2.0/. */
 
-#include "WebGLContext.h"
 #include "WebGLExtensions.h"
+
 #include "mozilla/dom/WebGLRenderingContextBinding.h"
+#include "WebGLContext.h"
 
-using namespace mozilla;
+namespace mozilla {
 
-WebGLExtensionCompressedTextureATC::WebGLExtensionCompressedTextureATC(WebGLContext* context)
-    : WebGLExtensionBase(context)
+WebGLExtensionCompressedTextureATC::WebGLExtensionCompressedTextureATC(WebGLContext* webgl)
+    : WebGLExtensionBase(webgl)
 {
-    context->mCompressedTextureFormats.AppendElement(LOCAL_GL_ATC_RGB);
-    context->mCompressedTextureFormats.AppendElement(LOCAL_GL_ATC_RGBA_EXPLICIT_ALPHA);
-    context->mCompressedTextureFormats.AppendElement(LOCAL_GL_ATC_RGBA_INTERPOLATED_ALPHA);
+    webgl->mCompressedTextureFormats.AppendElement(LOCAL_GL_ATC_RGB);
+    webgl->mCompressedTextureFormats.AppendElement(LOCAL_GL_ATC_RGBA_EXPLICIT_ALPHA);
+    webgl->mCompressedTextureFormats.AppendElement(LOCAL_GL_ATC_RGBA_INTERPOLATED_ALPHA);
 }
 
 WebGLExtensionCompressedTextureATC::~WebGLExtensionCompressedTextureATC()
@@ -21,3 +22,5 @@ WebGLExtensionCompressedTextureATC::~WebGLExtensionCompressedTextureATC()
 }
 
 IMPL_WEBGL_EXTENSION_GOOP(WebGLExtensionCompressedTextureATC)
+
+} // namespace mozilla
diff --git a/dom/canvas/WebGLExtensionCompressedTextureETC1.cpp b/dom/canvas/WebGLExtensionCompressedTextureETC1.cpp
index 232a74f09d42..a26450961f46 100644
--- a/dom/canvas/WebGLExtensionCompressedTextureETC1.cpp
+++ b/dom/canvas/WebGLExtensionCompressedTextureETC1.cpp
@@ -7,12 +7,12 @@
 #include "mozilla/dom/WebGLRenderingContextBinding.h"
 #include "WebGLContext.h"
 
-using namespace mozilla;
+namespace mozilla {
 
-WebGLExtensionCompressedTextureETC1::WebGLExtensionCompressedTextureETC1(WebGLContext* context)
-    : WebGLExtensionBase(context)
+WebGLExtensionCompressedTextureETC1::WebGLExtensionCompressedTextureETC1(WebGLContext* webgl)
+    : WebGLExtensionBase(webgl)
 {
-    context->mCompressedTextureFormats.AppendElement(LOCAL_GL_ETC1_RGB8_OES);
+    webgl->mCompressedTextureFormats.AppendElement(LOCAL_GL_ETC1_RGB8_OES);
 }
 
 WebGLExtensionCompressedTextureETC1::~WebGLExtensionCompressedTextureETC1()
@@ -20,3 +20,5 @@ WebGLExtensionCompressedTextureETC1::~WebGLExtensionCompressedTextureETC1()
 }
 
 IMPL_WEBGL_EXTENSION_GOOP(WebGLExtensionCompressedTextureETC1)
+
+} // namespace mozilla
diff --git a/dom/canvas/WebGLExtensionCompressedTexturePVRTC.cpp b/dom/canvas/WebGLExtensionCompressedTexturePVRTC.cpp
index 3f41e41e1717..bdd6f629afb7 100644
--- a/dom/canvas/WebGLExtensionCompressedTexturePVRTC.cpp
+++ b/dom/canvas/WebGLExtensionCompressedTexturePVRTC.cpp
@@ -2,19 +2,20 @@
  * License, v. 2.0. If a copy of the MPL was not distributed with this file,
  * You can obtain one at http://mozilla.org/MPL/2.0/. */
 
-#include "WebGLContext.h"
 #include "WebGLExtensions.h"
+
 #include "mozilla/dom/WebGLRenderingContextBinding.h"
+#include "WebGLContext.h"
 
-using namespace mozilla;
+namespace mozilla {
 
-WebGLExtensionCompressedTexturePVRTC::WebGLExtensionCompressedTexturePVRTC(WebGLContext* context)
-    : WebGLExtensionBase(context)
+WebGLExtensionCompressedTexturePVRTC::WebGLExtensionCompressedTexturePVRTC(WebGLContext* webgl)
+    : WebGLExtensionBase(webgl)
 {
-    context->mCompressedTextureFormats.AppendElement(LOCAL_GL_COMPRESSED_RGB_PVRTC_4BPPV1);
-    context->mCompressedTextureFormats.AppendElement(LOCAL_GL_COMPRESSED_RGB_PVRTC_2BPPV1);
-    context->mCompressedTextureFormats.AppendElement(LOCAL_GL_COMPRESSED_RGBA_PVRTC_4BPPV1);
-    context->mCompressedTextureFormats.AppendElement(LOCAL_GL_COMPRESSED_RGBA_PVRTC_2BPPV1);
+    webgl->mCompressedTextureFormats.AppendElement(LOCAL_GL_COMPRESSED_RGB_PVRTC_4BPPV1);
+    webgl->mCompressedTextureFormats.AppendElement(LOCAL_GL_COMPRESSED_RGB_PVRTC_2BPPV1);
+    webgl->mCompressedTextureFormats.AppendElement(LOCAL_GL_COMPRESSED_RGBA_PVRTC_4BPPV1);
+    webgl->mCompressedTextureFormats.AppendElement(LOCAL_GL_COMPRESSED_RGBA_PVRTC_2BPPV1);
 }
 
 WebGLExtensionCompressedTexturePVRTC::~WebGLExtensionCompressedTexturePVRTC()
@@ -22,3 +23,5 @@ WebGLExtensionCompressedTexturePVRTC::~WebGLExtensionCompressedTexturePVRTC()
 }
 
 IMPL_WEBGL_EXTENSION_GOOP(WebGLExtensionCompressedTexturePVRTC)
+
+} // namespace mozilla
diff --git a/dom/canvas/WebGLExtensionCompressedTextureS3TC.cpp b/dom/canvas/WebGLExtensionCompressedTextureS3TC.cpp
index 3a90537a8ca6..d18f1870c4b2 100644
--- a/dom/canvas/WebGLExtensionCompressedTextureS3TC.cpp
+++ b/dom/canvas/WebGLExtensionCompressedTextureS3TC.cpp
@@ -2,19 +2,20 @@
  * License, v. 2.0. If a copy of the MPL was not distributed with this file,
  * You can obtain one at http://mozilla.org/MPL/2.0/. */
 
-#include "WebGLContext.h"
 #include "WebGLExtensions.h"
+
 #include "mozilla/dom/WebGLRenderingContextBinding.h"
+#include "WebGLContext.h"
 
-using namespace mozilla;
+namespace mozilla {
 
-WebGLExtensionCompressedTextureS3TC::WebGLExtensionCompressedTextureS3TC(WebGLContext* context)
-    : WebGLExtensionBase(context)
+WebGLExtensionCompressedTextureS3TC::WebGLExtensionCompressedTextureS3TC(WebGLContext* webgl)
+    : WebGLExtensionBase(webgl)
 {
-    context->mCompressedTextureFormats.AppendElement(LOCAL_GL_COMPRESSED_RGB_S3TC_DXT1_EXT);
-    context->mCompressedTextureFormats.AppendElement(LOCAL_GL_COMPRESSED_RGBA_S3TC_DXT1_EXT);
-    context->mCompressedTextureFormats.AppendElement(LOCAL_GL_COMPRESSED_RGBA_S3TC_DXT3_EXT);
-    context->mCompressedTextureFormats.AppendElement(LOCAL_GL_COMPRESSED_RGBA_S3TC_DXT5_EXT);
+    webgl->mCompressedTextureFormats.AppendElement(LOCAL_GL_COMPRESSED_RGB_S3TC_DXT1_EXT);
+    webgl->mCompressedTextureFormats.AppendElement(LOCAL_GL_COMPRESSED_RGBA_S3TC_DXT1_EXT);
+    webgl->mCompressedTextureFormats.AppendElement(LOCAL_GL_COMPRESSED_RGBA_S3TC_DXT3_EXT);
+    webgl->mCompressedTextureFormats.AppendElement(LOCAL_GL_COMPRESSED_RGBA_S3TC_DXT5_EXT);
 }
 
 WebGLExtensionCompressedTextureS3TC::~WebGLExtensionCompressedTextureS3TC()
@@ -22,3 +23,5 @@ WebGLExtensionCompressedTextureS3TC::~WebGLExtensionCompressedTextureS3TC()
 }
 
 IMPL_WEBGL_EXTENSION_GOOP(WebGLExtensionCompressedTextureS3TC)
+
+} // namespace mozilla
diff --git a/dom/canvas/WebGLExtensionDebugRendererInfo.cpp b/dom/canvas/WebGLExtensionDebugRendererInfo.cpp
index 9d400edc2fe5..00b369142c09 100644
--- a/dom/canvas/WebGLExtensionDebugRendererInfo.cpp
+++ b/dom/canvas/WebGLExtensionDebugRendererInfo.cpp
@@ -3,14 +3,15 @@
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
-#include "WebGLContext.h"
 #include "WebGLExtensions.h"
+
 #include "mozilla/dom/WebGLRenderingContextBinding.h"
+#include "WebGLContext.h"
 
-using namespace mozilla;
+namespace mozilla {
 
-WebGLExtensionDebugRendererInfo::WebGLExtensionDebugRendererInfo(WebGLContext* context)
-    : WebGLExtensionBase(context)
+WebGLExtensionDebugRendererInfo::WebGLExtensionDebugRendererInfo(WebGLContext* webgl)
+    : WebGLExtensionBase(webgl)
 {
 }
 
@@ -19,3 +20,5 @@ WebGLExtensionDebugRendererInfo::~WebGLExtensionDebugRendererInfo()
 }
 
 IMPL_WEBGL_EXTENSION_GOOP(WebGLExtensionDebugRendererInfo)
+
+} // namespace mozilla
diff --git a/dom/canvas/WebGLExtensionDebugShaders.cpp b/dom/canvas/WebGLExtensionDebugShaders.cpp
index e1a4e742a53b..cc3753b89380 100644
--- a/dom/canvas/WebGLExtensionDebugShaders.cpp
+++ b/dom/canvas/WebGLExtensionDebugShaders.cpp
@@ -3,14 +3,15 @@
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
-#include "WebGLContext.h"
 #include "WebGLExtensions.h"
+
 #include "mozilla/dom/WebGLRenderingContextBinding.h"
+#include "WebGLContext.h"
 
-using namespace mozilla;
+namespace mozilla {
 
-WebGLExtensionDebugShaders::WebGLExtensionDebugShaders(WebGLContext* context)
-    : WebGLExtensionBase(context)
+WebGLExtensionDebugShaders::WebGLExtensionDebugShaders(WebGLContext* webgl)
+    : WebGLExtensionBase(webgl)
 {
 }
 
@@ -18,24 +19,25 @@ WebGLExtensionDebugShaders::~WebGLExtensionDebugShaders()
 {
 }
 
-/* If no source has been defined, compileShader() has not been called,
- * or the translation has failed for shader, an empty string is
- * returned; otherwise, return the translated source.
- */
+// If no source has been defined, compileShader() has not been called, or the
+// translation has failed for shader, an empty string is returned; otherwise,
+// return the translated source.
 void
 WebGLExtensionDebugShaders::GetTranslatedShaderSource(WebGLShader* shader,
                                                       nsAString& retval)
 {
+    retval.SetIsVoid(true);
+
     if (mIsLost) {
-        return mContext->ErrorInvalidOperation("getTranslatedShaderSource: "
-                                               "Extension is lost.");
+        mContext->ErrorInvalidOperation("%s: Extension is lost.",
+                                        "getTranslatedShaderSource");
+        return;
     }
 
+    retval.SetIsVoid(false);
     mContext->GetShaderTranslatedSource(shader, retval);
-
-    if (retval.IsVoid()) {
-        CopyASCIItoUTF16("", retval);
-    }
 }
 
 IMPL_WEBGL_EXTENSION_GOOP(WebGLExtensionDebugShaders)
+
+} // namespace mozilla
diff --git a/dom/canvas/WebGLExtensionDepthTexture.cpp b/dom/canvas/WebGLExtensionDepthTexture.cpp
index ac7a9bd17188..6c22e0d20ec1 100644
--- a/dom/canvas/WebGLExtensionDepthTexture.cpp
+++ b/dom/canvas/WebGLExtensionDepthTexture.cpp
@@ -3,14 +3,15 @@
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
-#include "WebGLContext.h"
 #include "WebGLExtensions.h"
+
 #include "mozilla/dom/WebGLRenderingContextBinding.h"
+#include "WebGLContext.h"
 
-using namespace mozilla;
+namespace mozilla {
 
-WebGLExtensionDepthTexture::WebGLExtensionDepthTexture(WebGLContext* context)
-    : WebGLExtensionBase(context)
+WebGLExtensionDepthTexture::WebGLExtensionDepthTexture(WebGLContext* webgl)
+    : WebGLExtensionBase(webgl)
 {
 }
 
@@ -19,3 +20,5 @@ WebGLExtensionDepthTexture::~WebGLExtensionDepthTexture()
 }
 
 IMPL_WEBGL_EXTENSION_GOOP(WebGLExtensionDepthTexture)
+
+} // namespace mozilla
diff --git a/dom/canvas/WebGLExtensionDrawBuffers.cpp b/dom/canvas/WebGLExtensionDrawBuffers.cpp
index e26a34a25ac0..ca04a2be9e23 100644
--- a/dom/canvas/WebGLExtensionDrawBuffers.cpp
+++ b/dom/canvas/WebGLExtensionDrawBuffers.cpp
@@ -3,28 +3,28 @@
  * License, v. 2.0. If a copy of the MPL was not distributed with this file,
  * You can obtain one at http://mozilla.org/MPL/2.0/. */
 
-#include "WebGLContext.h"
 #include "WebGLExtensions.h"
-#include "mozilla/dom/WebGLRenderingContextBinding.h"
-#include "WebGLTexture.h"
-#include "WebGLRenderbuffer.h"
-#include "WebGLFramebuffer.h"
-#include "GLContext.h"
 
 #include 
+#include "GLContext.h"
+#include "mozilla/dom/WebGLRenderingContextBinding.h"
+#include "WebGLContext.h"
+#include "WebGLFramebuffer.h"
+#include "WebGLRenderbuffer.h"
+#include "WebGLTexture.h"
 
-using namespace mozilla;
-using namespace gl;
+namespace mozilla {
 
-WebGLExtensionDrawBuffers::WebGLExtensionDrawBuffers(WebGLContext* context)
-    : WebGLExtensionBase(context)
+WebGLExtensionDrawBuffers::WebGLExtensionDrawBuffers(WebGLContext* webgl)
+    : WebGLExtensionBase(webgl)
 {
+    MOZ_ASSERT(IsSupported(webgl), "Don't construct extension if unsupported.");
+
     GLint maxColorAttachments = 0;
     GLint maxDrawBuffers = 0;
 
-    gl::GLContext* gl = context->GL();
-
-    context->MakeContextCurrent();
+    webgl->MakeContextCurrent();
+    gl::GLContext* gl = webgl->GL();
 
     gl->fGetIntegerv(LOCAL_GL_MAX_COLOR_ATTACHMENTS, &maxColorAttachments);
     gl->fGetIntegerv(LOCAL_GL_MAX_DRAW_BUFFERS, &maxDrawBuffers);
@@ -32,56 +32,57 @@ WebGLExtensionDrawBuffers::WebGLExtensionDrawBuffers(WebGLContext* context)
     // WEBGL_draw_buffers specifications don't give a maximal value reachable by MAX_COLOR_ATTACHMENTS.
     maxColorAttachments = std::min(maxColorAttachments, GLint(WebGLContext::kMaxColorAttachments));
 
-    if (context->MinCapabilityMode())
-    {
-        maxColorAttachments = std::min(maxColorAttachments, GLint(sMinColorAttachments));
-    }
+    if (webgl->MinCapabilityMode())
+        maxColorAttachments = std::min(maxColorAttachments, GLint(kMinColorAttachments));
 
     // WEBGL_draw_buffers specifications request MAX_COLOR_ATTACHMENTS >= MAX_DRAW_BUFFERS.
     maxDrawBuffers = std::min(maxDrawBuffers, GLint(maxColorAttachments));
 
-    context->mGLMaxColorAttachments = maxColorAttachments;
-    context->mGLMaxDrawBuffers = maxDrawBuffers;
+    webgl->mGLMaxColorAttachments = maxColorAttachments;
+    webgl->mGLMaxDrawBuffers = maxDrawBuffers;
 }
 
 WebGLExtensionDrawBuffers::~WebGLExtensionDrawBuffers()
 {
 }
 
-void WebGLExtensionDrawBuffers::DrawBuffersWEBGL(const dom::Sequence& buffers)
+void
+WebGLExtensionDrawBuffers::DrawBuffersWEBGL(const dom::Sequence& buffers)
 {
-    if (mIsLost)
-        return mContext->ErrorInvalidOperation("drawBuffersWEBGL: Extension is lost.");
+    if (mIsLost) {
+        mContext->ErrorInvalidOperation("drawBuffersWEBGL: Extension is lost.");
+        return;
+    }
 
     mContext->DrawBuffers(buffers);
 }
 
-bool WebGLExtensionDrawBuffers::IsSupported(const WebGLContext* context)
+bool
+WebGLExtensionDrawBuffers::IsSupported(const WebGLContext* webgl)
 {
-    gl::GLContext * gl = context->GL();
+    gl::GLContext* gl = webgl->GL();
 
-    if (!gl->IsSupported(GLFeature::draw_buffers)) {
+    if (!gl->IsSupported(gl::GLFeature::draw_buffers))
         return false;
-    }
 
     GLint supportedColorAttachments = 0;
     GLint supportedDrawBuffers = 0;
 
-    context->MakeContextCurrent();
+    webgl->MakeContextCurrent();
 
     gl->fGetIntegerv(LOCAL_GL_MAX_COLOR_ATTACHMENTS, &supportedColorAttachments);
     gl->fGetIntegerv(LOCAL_GL_MAX_COLOR_ATTACHMENTS, &supportedDrawBuffers);
 
-    if (size_t(supportedColorAttachments) < sMinColorAttachments){
-        // WEBGL_draw_buffers specifications request for 4 color attachments at least.
+    // WEBGL_draw_buffers requires at least 4 color attachments.
+    if (size_t(supportedColorAttachments) < kMinColorAttachments)
         return false;
-    }
 
-    if (size_t(supportedDrawBuffers) < sMinDrawBuffers){
+    if (size_t(supportedDrawBuffers) < kMinDrawBuffers)
         return false;
-    }
 
     return true;
 }
 
 IMPL_WEBGL_EXTENSION_GOOP(WebGLExtensionDrawBuffers)
+
+} // namespace mozilla
diff --git a/dom/canvas/WebGLExtensionElementIndexUint.cpp b/dom/canvas/WebGLExtensionElementIndexUint.cpp
index 49ab44527e3a..1ff22e593dcb 100644
--- a/dom/canvas/WebGLExtensionElementIndexUint.cpp
+++ b/dom/canvas/WebGLExtensionElementIndexUint.cpp
@@ -3,14 +3,15 @@
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
-#include "WebGLContext.h"
 #include "WebGLExtensions.h"
+
 #include "mozilla/dom/WebGLRenderingContextBinding.h"
+#include "WebGLContext.h"
 
-using namespace mozilla;
+namespace mozilla {
 
-WebGLExtensionElementIndexUint::WebGLExtensionElementIndexUint(WebGLContext* context)
-    : WebGLExtensionBase(context)
+WebGLExtensionElementIndexUint::WebGLExtensionElementIndexUint(WebGLContext* webgl)
+    : WebGLExtensionBase(webgl)
 {
 }
 
@@ -19,3 +20,5 @@ WebGLExtensionElementIndexUint::~WebGLExtensionElementIndexUint()
 }
 
 IMPL_WEBGL_EXTENSION_GOOP(WebGLExtensionElementIndexUint)
+
+} // namespace mozilla
diff --git a/dom/canvas/WebGLExtensionFragDepth.cpp b/dom/canvas/WebGLExtensionFragDepth.cpp
index d1e704d8cb30..51faffb33580 100644
--- a/dom/canvas/WebGLExtensionFragDepth.cpp
+++ b/dom/canvas/WebGLExtensionFragDepth.cpp
@@ -3,18 +3,18 @@
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
-#include "WebGLContext.h"
 #include "WebGLExtensions.h"
-#include "mozilla/dom/WebGLRenderingContextBinding.h"
+
 #include "GLContext.h"
+#include "mozilla/dom/WebGLRenderingContextBinding.h"
+#include "WebGLContext.h"
 
-using namespace mozilla;
+namespace mozilla {
 
-WebGLExtensionFragDepth::WebGLExtensionFragDepth(WebGLContext* context)
-    : WebGLExtensionBase(context)
+WebGLExtensionFragDepth::WebGLExtensionFragDepth(WebGLContext* webgl)
+    : WebGLExtensionBase(webgl)
 {
-    MOZ_ASSERT(IsSupported(context),
-               "Should not construct extension object if unsupported.");
+    MOZ_ASSERT(IsSupported(webgl), "Don't construct extension if unsupported.");
 }
 
 WebGLExtensionFragDepth::~WebGLExtensionFragDepth()
@@ -22,12 +22,13 @@ WebGLExtensionFragDepth::~WebGLExtensionFragDepth()
 }
 
 bool
-WebGLExtensionFragDepth::IsSupported(const WebGLContext* context)
+WebGLExtensionFragDepth::IsSupported(const WebGLContext* webgl)
 {
-    gl::GLContext* gl = context->GL();
-
+    gl::GLContext* gl = webgl->GL();
     return gl->IsSupported(gl::GLFeature::frag_depth);
 }
 
 
 IMPL_WEBGL_EXTENSION_GOOP(WebGLExtensionFragDepth)
+
+} // namespace mozilla
diff --git a/dom/canvas/WebGLExtensionInstancedArrays.cpp b/dom/canvas/WebGLExtensionInstancedArrays.cpp
index 162fd7b5640d..b8dfa939027b 100644
--- a/dom/canvas/WebGLExtensionInstancedArrays.cpp
+++ b/dom/canvas/WebGLExtensionInstancedArrays.cpp
@@ -3,18 +3,18 @@
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
-#include "WebGLContext.h"
 #include "WebGLExtensions.h"
-#include "mozilla/dom/WebGLRenderingContextBinding.h"
+
 #include "GLContext.h"
+#include "mozilla/dom/WebGLRenderingContextBinding.h"
+#include "WebGLContext.h"
 
-using namespace mozilla;
+namespace mozilla {
 
-WebGLExtensionInstancedArrays::WebGLExtensionInstancedArrays(WebGLContext* context)
-  : WebGLExtensionBase(context)
+WebGLExtensionInstancedArrays::WebGLExtensionInstancedArrays(WebGLContext* webgl)
+  : WebGLExtensionBase(webgl)
 {
-    MOZ_ASSERT(IsSupported(context), "should not construct WebGLExtensionInstancedArrays: "
-                                     "ANGLE_instanced_arrays unsupported.");
+    MOZ_ASSERT(IsSupported(webgl), "Don't construct extension if unsupported.");
 }
 
 WebGLExtensionInstancedArrays::~WebGLExtensionInstancedArrays()
@@ -22,42 +22,57 @@ WebGLExtensionInstancedArrays::~WebGLExtensionInstancedArrays()
 }
 
 void
-WebGLExtensionInstancedArrays::DrawArraysInstancedANGLE(GLenum mode, GLint first,
-                                                        GLsizei count, GLsizei primcount)
+WebGLExtensionInstancedArrays::DrawArraysInstancedANGLE(GLenum mode,
+                                                        GLint first,
+                                                        GLsizei count,
+                                                        GLsizei primcount)
 {
-    if (mIsLost)
-        return mContext->GenerateWarning("drawArraysInstancedANGLE: Extension is lost.");
+    if (mIsLost) {
+        mContext->ErrorInvalidOperation("%s: Extension is lost.",
+                                        "drawArraysInstancedANGLE");
+        return;
+    }
 
     mContext->DrawArraysInstanced(mode, first, count, primcount);
 }
 
 void
-WebGLExtensionInstancedArrays::DrawElementsInstancedANGLE(GLenum mode, GLsizei count,
-                                                          GLenum type, WebGLintptr offset,
+WebGLExtensionInstancedArrays::DrawElementsInstancedANGLE(GLenum mode,
+                                                          GLsizei count,
+                                                          GLenum type,
+                                                          WebGLintptr offset,
                                                           GLsizei primcount)
 {
-    if (mIsLost)
-        return mContext->GenerateWarning("drawElementsInstancedANGLE: Extension is lost.");
+    if (mIsLost) {
+        mContext->ErrorInvalidOperation("%s: Extension is lost.",
+                                        "drawElementsInstancedANGLE");
+        return;
+    }
 
     mContext->DrawElementsInstanced(mode, count, type, offset, primcount);
 }
 
 void
-WebGLExtensionInstancedArrays::VertexAttribDivisorANGLE(GLuint index, GLuint divisor)
+WebGLExtensionInstancedArrays::VertexAttribDivisorANGLE(GLuint index,
+                                                        GLuint divisor)
 {
-    if (mIsLost)
-        return mContext->GenerateWarning("vertexAttribDivisorANGLE: Extension is lost.");
+    if (mIsLost) {
+        mContext->ErrorInvalidOperation("%s: Extension is lost.",
+                                        "vertexAttribDivisorANGLE");
+        return;
+    }
 
     mContext->VertexAttribDivisor(index, divisor);
 }
 
 bool
-WebGLExtensionInstancedArrays::IsSupported(const WebGLContext* context)
+WebGLExtensionInstancedArrays::IsSupported(const WebGLContext* webgl)
 {
-    gl::GLContext* gl = context->GL();
-
+    gl::GLContext* gl = webgl->GL();
     return gl->IsSupported(gl::GLFeature::draw_instanced) &&
            gl->IsSupported(gl::GLFeature::instanced_arrays);
 }
 
 IMPL_WEBGL_EXTENSION_GOOP(WebGLExtensionInstancedArrays)
+
+} // namespace mozilla
diff --git a/dom/canvas/WebGLExtensionLoseContext.cpp b/dom/canvas/WebGLExtensionLoseContext.cpp
index 8871d6b408bf..609eed7a97e2 100644
--- a/dom/canvas/WebGLExtensionLoseContext.cpp
+++ b/dom/canvas/WebGLExtensionLoseContext.cpp
@@ -3,14 +3,15 @@
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
-#include "WebGLContext.h"
 #include "WebGLExtensions.h"
+
 #include "mozilla/dom/WebGLRenderingContextBinding.h"
+#include "WebGLContext.h"
 
-using namespace mozilla;
+namespace mozilla {
 
-WebGLExtensionLoseContext::WebGLExtensionLoseContext(WebGLContext* context)
-    : WebGLExtensionBase(context)
+WebGLExtensionLoseContext::WebGLExtensionLoseContext(WebGLContext* webgl)
+    : WebGLExtensionBase(webgl)
 {
 }
 
@@ -31,3 +32,5 @@ WebGLExtensionLoseContext::RestoreContext()
 }
 
 IMPL_WEBGL_EXTENSION_GOOP(WebGLExtensionLoseContext)
+
+} // namespace mozilla
diff --git a/dom/canvas/WebGLExtensionSRGB.cpp b/dom/canvas/WebGLExtensionSRGB.cpp
index 68ba16d645c1..b1e3e1559515 100644
--- a/dom/canvas/WebGLExtensionSRGB.cpp
+++ b/dom/canvas/WebGLExtensionSRGB.cpp
@@ -3,22 +3,23 @@
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
-#include "WebGLContext.h"
 #include "WebGLExtensions.h"
-#include "mozilla/dom/WebGLRenderingContextBinding.h"
+
 #include "GLContext.h"
+#include "mozilla/dom/WebGLRenderingContextBinding.h"
+#include "WebGLContext.h"
 
-using namespace mozilla;
+namespace mozilla {
 
-WebGLExtensionSRGB::WebGLExtensionSRGB(WebGLContext* context)
-    : WebGLExtensionBase(context)
+WebGLExtensionSRGB::WebGLExtensionSRGB(WebGLContext* webgl)
+    : WebGLExtensionBase(webgl)
 {
-    MOZ_ASSERT(IsSupported(context), "should not construct WebGLExtensionSRGB: "
-                                     "sRGB is unsupported.");
-    gl::GLContext* gl = context->GL();
+    MOZ_ASSERT(IsSupported(webgl), "Don't construct extension if unsupported.");
+
+    gl::GLContext* gl = webgl->GL();
     if (!gl->IsGLES()) {
-        // Desktop OpenGL requires the following to be enabled to support
-        // sRGB operations on framebuffers
+        // Desktop OpenGL requires the following to be enabled in order to
+        // support sRGB operations on framebuffers.
         gl->MakeCurrent();
         gl->fEnable(LOCAL_GL_FRAMEBUFFER_SRGB_EXT);
     }
@@ -29,12 +30,14 @@ WebGLExtensionSRGB::~WebGLExtensionSRGB()
 }
 
 bool
-WebGLExtensionSRGB::IsSupported(const WebGLContext* context)
+WebGLExtensionSRGB::IsSupported(const WebGLContext* webgl)
 {
-    gl::GLContext* gl = context->GL();
+    gl::GLContext* gl = webgl->GL();
 
     return gl->IsSupported(gl::GLFeature::sRGB);
 }
 
 
 IMPL_WEBGL_EXTENSION_GOOP(WebGLExtensionSRGB)
+
+} // namespace mozilla
diff --git a/dom/canvas/WebGLExtensionShaderTextureLod.cpp b/dom/canvas/WebGLExtensionShaderTextureLod.cpp
index 2dcef6168a07..2af8557ced50 100644
--- a/dom/canvas/WebGLExtensionShaderTextureLod.cpp
+++ b/dom/canvas/WebGLExtensionShaderTextureLod.cpp
@@ -3,14 +3,15 @@
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
-#include "WebGLContext.h"
 #include "WebGLExtensions.h"
+
 #include "mozilla/dom/WebGLRenderingContextBinding.h"
+#include "WebGLContext.h"
 
-using namespace mozilla;
+namespace mozilla {
 
-WebGLExtensionShaderTextureLod::WebGLExtensionShaderTextureLod(WebGLContext* context)
-    : WebGLExtensionBase(context)
+WebGLExtensionShaderTextureLod::WebGLExtensionShaderTextureLod(WebGLContext* webgl)
+    : WebGLExtensionBase(webgl)
 {
 }
 
@@ -19,3 +20,5 @@ WebGLExtensionShaderTextureLod::~WebGLExtensionShaderTextureLod()
 }
 
 IMPL_WEBGL_EXTENSION_GOOP(WebGLExtensionShaderTextureLod)
+
+} // namespace mozilla
diff --git a/dom/canvas/WebGLExtensionStandardDerivatives.cpp b/dom/canvas/WebGLExtensionStandardDerivatives.cpp
index 762f14c62a9e..ffbda05baf4a 100644
--- a/dom/canvas/WebGLExtensionStandardDerivatives.cpp
+++ b/dom/canvas/WebGLExtensionStandardDerivatives.cpp
@@ -3,14 +3,15 @@
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
-#include "WebGLContext.h"
 #include "WebGLExtensions.h"
+
 #include "mozilla/dom/WebGLRenderingContextBinding.h"
+#include "WebGLContext.h"
 
-using namespace mozilla;
+namespace mozilla {
 
-WebGLExtensionStandardDerivatives::WebGLExtensionStandardDerivatives(WebGLContext* context)
-    : WebGLExtensionBase(context)
+WebGLExtensionStandardDerivatives::WebGLExtensionStandardDerivatives(WebGLContext* webgl)
+    : WebGLExtensionBase(webgl)
 {
 }
 
@@ -19,3 +20,5 @@ WebGLExtensionStandardDerivatives::~WebGLExtensionStandardDerivatives()
 }
 
 IMPL_WEBGL_EXTENSION_GOOP(WebGLExtensionStandardDerivatives)
+
+} // namespace mozilla
diff --git a/dom/canvas/WebGLExtensionTextureFilterAnisotropic.cpp b/dom/canvas/WebGLExtensionTextureFilterAnisotropic.cpp
index 39dc20f800be..6ad2bef1bca6 100644
--- a/dom/canvas/WebGLExtensionTextureFilterAnisotropic.cpp
+++ b/dom/canvas/WebGLExtensionTextureFilterAnisotropic.cpp
@@ -3,14 +3,15 @@
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
-#include "WebGLContext.h"
 #include "WebGLExtensions.h"
+
 #include "mozilla/dom/WebGLRenderingContextBinding.h"
+#include "WebGLContext.h"
 
-using namespace mozilla;
+namespace mozilla {
 
-WebGLExtensionTextureFilterAnisotropic::WebGLExtensionTextureFilterAnisotropic(WebGLContext* context)
-    : WebGLExtensionBase(context)
+WebGLExtensionTextureFilterAnisotropic::WebGLExtensionTextureFilterAnisotropic(WebGLContext* webgl)
+    : WebGLExtensionBase(webgl)
 {
 }
 
@@ -19,3 +20,5 @@ WebGLExtensionTextureFilterAnisotropic::~WebGLExtensionTextureFilterAnisotropic(
 }
 
 IMPL_WEBGL_EXTENSION_GOOP(WebGLExtensionTextureFilterAnisotropic)
+
+} // namespace mozilla
diff --git a/dom/canvas/WebGLExtensionTextureFloat.cpp b/dom/canvas/WebGLExtensionTextureFloat.cpp
index 266f691ced86..6f1befe1ae44 100644
--- a/dom/canvas/WebGLExtensionTextureFloat.cpp
+++ b/dom/canvas/WebGLExtensionTextureFloat.cpp
@@ -2,14 +2,15 @@
  * License, v. 2.0. If a copy of the MPL was not distributed with this file,
  * You can obtain one at http://mozilla.org/MPL/2.0/. */
 
-#include "WebGLContext.h"
 #include "WebGLExtensions.h"
+
 #include "mozilla/dom/WebGLRenderingContextBinding.h"
+#include "WebGLContext.h"
 
-using namespace mozilla;
+namespace mozilla {
 
-WebGLExtensionTextureFloat::WebGLExtensionTextureFloat(WebGLContext* context)
-    : WebGLExtensionBase(context)
+WebGLExtensionTextureFloat::WebGLExtensionTextureFloat(WebGLContext* webgl)
+    : WebGLExtensionBase(webgl)
 {
 }
 
@@ -18,3 +19,5 @@ WebGLExtensionTextureFloat::~WebGLExtensionTextureFloat()
 }
 
 IMPL_WEBGL_EXTENSION_GOOP(WebGLExtensionTextureFloat)
+
+} // namespace mozilla
diff --git a/dom/canvas/WebGLExtensionTextureFloatLinear.cpp b/dom/canvas/WebGLExtensionTextureFloatLinear.cpp
index 8bcf647b169e..e5d408c79ca0 100644
--- a/dom/canvas/WebGLExtensionTextureFloatLinear.cpp
+++ b/dom/canvas/WebGLExtensionTextureFloatLinear.cpp
@@ -2,14 +2,15 @@
  * License, v. 2.0. If a copy of the MPL was not distributed with this file,
  * You can obtain one at http://mozilla.org/MPL/2.0/. */
 
-#include "WebGLContext.h"
 #include "WebGLExtensions.h"
+
 #include "mozilla/dom/WebGLRenderingContextBinding.h"
+#include "WebGLContext.h"
 
-using namespace mozilla;
+namespace mozilla {
 
-WebGLExtensionTextureFloatLinear::WebGLExtensionTextureFloatLinear(WebGLContext* context)
-    : WebGLExtensionBase(context)
+WebGLExtensionTextureFloatLinear::WebGLExtensionTextureFloatLinear(WebGLContext* webgl)
+    : WebGLExtensionBase(webgl)
 {
 }
 
@@ -18,3 +19,5 @@ WebGLExtensionTextureFloatLinear::~WebGLExtensionTextureFloatLinear()
 }
 
 IMPL_WEBGL_EXTENSION_GOOP(WebGLExtensionTextureFloatLinear)
+
+} // namespace mozilla
diff --git a/dom/canvas/WebGLExtensionTextureHalfFloat.cpp b/dom/canvas/WebGLExtensionTextureHalfFloat.cpp
index 5710e9a9e055..eaabf7637e49 100644
--- a/dom/canvas/WebGLExtensionTextureHalfFloat.cpp
+++ b/dom/canvas/WebGLExtensionTextureHalfFloat.cpp
@@ -2,14 +2,15 @@
  * License, v. 2.0. If a copy of the MPL was not distributed with this file,
  * You can obtain one at http://mozilla.org/MPL/2.0/. */
 
-#include "WebGLContext.h"
 #include "WebGLExtensions.h"
+
 #include "mozilla/dom/WebGLRenderingContextBinding.h"
+#include "WebGLContext.h"
 
-using namespace mozilla;
+namespace mozilla {
 
-WebGLExtensionTextureHalfFloat::WebGLExtensionTextureHalfFloat(WebGLContext* context)
-    : WebGLExtensionBase(context)
+WebGLExtensionTextureHalfFloat::WebGLExtensionTextureHalfFloat(WebGLContext* webgl)
+    : WebGLExtensionBase(webgl)
 {
 }
 
@@ -18,3 +19,5 @@ WebGLExtensionTextureHalfFloat::~WebGLExtensionTextureHalfFloat()
 }
 
 IMPL_WEBGL_EXTENSION_GOOP(WebGLExtensionTextureHalfFloat)
+
+} // namespace mozilla
diff --git a/dom/canvas/WebGLExtensionTextureHalfFloatLinear.cpp b/dom/canvas/WebGLExtensionTextureHalfFloatLinear.cpp
index d3c3383f731e..f97eb39b2270 100644
--- a/dom/canvas/WebGLExtensionTextureHalfFloatLinear.cpp
+++ b/dom/canvas/WebGLExtensionTextureHalfFloatLinear.cpp
@@ -2,14 +2,15 @@
  * License, v. 2.0. If a copy of the MPL was not distributed with this file,
  * You can obtain one at http://mozilla.org/MPL/2.0/. */
 
-#include "WebGLContext.h"
 #include "WebGLExtensions.h"
+
 #include "mozilla/dom/WebGLRenderingContextBinding.h"
+#include "WebGLContext.h"
 
-using namespace mozilla;
+namespace mozilla {
 
-WebGLExtensionTextureHalfFloatLinear::WebGLExtensionTextureHalfFloatLinear(WebGLContext* context)
-    : WebGLExtensionBase(context)
+WebGLExtensionTextureHalfFloatLinear::WebGLExtensionTextureHalfFloatLinear(WebGLContext* webgl)
+    : WebGLExtensionBase(webgl)
 {
 }
 
@@ -18,3 +19,5 @@ WebGLExtensionTextureHalfFloatLinear::~WebGLExtensionTextureHalfFloatLinear()
 }
 
 IMPL_WEBGL_EXTENSION_GOOP(WebGLExtensionTextureHalfFloatLinear)
+
+} // namespace mozilla
diff --git a/dom/canvas/WebGLExtensionVertexArray.cpp b/dom/canvas/WebGLExtensionVertexArray.cpp
index bbd4fa693fdd..0b75bd1e070d 100644
--- a/dom/canvas/WebGLExtensionVertexArray.cpp
+++ b/dom/canvas/WebGLExtensionVertexArray.cpp
@@ -3,67 +3,73 @@
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
-#include "WebGLContext.h"
-#include "WebGLBuffer.h"
-#include "WebGLVertexArray.h"
 #include "WebGLExtensions.h"
-#include "mozilla/dom/WebGLRenderingContextBinding.h"
+
 #include "GLContext.h"
+#include "mozilla/dom/WebGLRenderingContextBinding.h"
+#include "WebGLBuffer.h"
+#include "WebGLContext.h"
+#include "WebGLVertexArray.h"
 
-using namespace mozilla;
+namespace mozilla {
 
-WebGLExtensionVertexArray::WebGLExtensionVertexArray(WebGLContext* context)
-  : WebGLExtensionBase(context)
+WebGLExtensionVertexArray::WebGLExtensionVertexArray(WebGLContext* webgl)
+  : WebGLExtensionBase(webgl)
 {
-    MOZ_ASSERT(IsSupported(context), "should not construct WebGLExtensionVertexArray :"
-                                     "OES_vertex_array_object unsuported.");
 }
 
 WebGLExtensionVertexArray::~WebGLExtensionVertexArray()
 {
 }
 
-already_AddRefed WebGLExtensionVertexArray::CreateVertexArrayOES()
+already_AddRefed
+WebGLExtensionVertexArray::CreateVertexArrayOES()
 {
     if (mIsLost) {
-        mContext->GenerateWarning("createVertexArrayOES: Extension is lost. Returning null.");
+        mContext->ErrorInvalidOperation("%s: Extension is lost.",
+                                        "createVertexArrayOES");
         return nullptr;
     }
 
     return mContext->CreateVertexArray();
 }
 
-void WebGLExtensionVertexArray::DeleteVertexArrayOES(WebGLVertexArray* array)
+void
+WebGLExtensionVertexArray::DeleteVertexArrayOES(WebGLVertexArray* array)
 {
-    if (mIsLost)
-        return mContext->GenerateWarning("deleteVertexArrayOES: Extension is lost.");
+    if (mIsLost) {
+        mContext->ErrorInvalidOperation("%s: Extension is lost.",
+                                        "deleteVertexArrayOES");
+        return;
+    }
 
     mContext->DeleteVertexArray(array);
 }
 
-bool WebGLExtensionVertexArray::IsVertexArrayOES(WebGLVertexArray* array)
+bool
+WebGLExtensionVertexArray::IsVertexArrayOES(WebGLVertexArray* array)
 {
     if (mIsLost) {
-        mContext->GenerateWarning("isVertexArrayOES: Extension is lost. Returning false.");
+        mContext->ErrorInvalidOperation("%s: Extension is lost.",
+                                        "isVertexArrayOES");
         return false;
     }
 
     return mContext->IsVertexArray(array);
 }
 
-void WebGLExtensionVertexArray::BindVertexArrayOES(WebGLVertexArray* array)
+void
+WebGLExtensionVertexArray::BindVertexArrayOES(WebGLVertexArray* array)
 {
-    if (mIsLost)
-        return mContext->GenerateWarning("bindVertexArrayOES: Extension is lost.");
+    if (mIsLost) {
+        mContext->ErrorInvalidOperation("%s: Extension is lost.",
+                                        "bindVertexArrayOES");
+        return;
+    }
 
     mContext->BindVertexArray(array);
 }
 
-bool WebGLExtensionVertexArray::IsSupported(const WebGLContext* context)
-{
-    // If it is not supported then it's emulated, therefore it's always 'supported'
-    // See - WebGLVertexArrayFake.h/cpp for the emulation
-    return true;
-}
-
 IMPL_WEBGL_EXTENSION_GOOP(WebGLExtensionVertexArray)
+
+} // namespace mozilla
diff --git a/dom/canvas/WebGLExtensions.h b/dom/canvas/WebGLExtensions.h
index d89ba2b17614..4fa432602d6f 100644
--- a/dom/canvas/WebGLExtensions.h
+++ b/dom/canvas/WebGLExtensions.h
@@ -3,8 +3,8 @@
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
-#ifndef WEBGLEXTENSIONS_H_
-#define WEBGLEXTENSIONS_H_
+#ifndef WEBGL_EXTENSIONS_H_
+#define WEBGL_EXTENSIONS_H_
 
 #include "jsapi.h"
 #include "mozilla/Attributes.h"
@@ -23,9 +23,9 @@ class WebGLExtensionBase
     , public WebGLContextBoundObject
 {
 public:
-    explicit WebGLExtensionBase(WebGLContext* aValue);
+    explicit WebGLExtensionBase(WebGLContext* webgl);
 
-    WebGLContext *GetParentObject() const {
+    WebGLContext* GetParentObject() const {
         return Context();
     }
 
@@ -40,12 +40,12 @@ protected:
     bool mIsLost;
 };
 
-#define DECL_WEBGL_EXTENSION_GOOP                                           \
-    virtual JSObject* WrapObject(JSContext *cx) MOZ_OVERRIDE;
+#define DECL_WEBGL_EXTENSION_GOOP \
+    virtual JSObject* WrapObject(JSContext* cx) MOZ_OVERRIDE;
 
-#define IMPL_WEBGL_EXTENSION_GOOP(WebGLExtensionType) \
-    JSObject* \
-    WebGLExtensionType::WrapObject(JSContext *cx) { \
+#define IMPL_WEBGL_EXTENSION_GOOP(WebGLExtensionType)            \
+    JSObject*                                                    \
+    WebGLExtensionType::WrapObject(JSContext* cx) {              \
         return dom::WebGLExtensionType##Binding::Wrap(cx, this); \
     }
 
@@ -273,8 +273,8 @@ public:
 
     static bool IsSupported(const WebGLContext*);
 
-    static const size_t sMinColorAttachments = 4;
-    static const size_t sMinDrawBuffers = 4;
+    static const size_t kMinColorAttachments = 4;
+    static const size_t kMinDrawBuffers = 4;
     /*
      WEBGL_draw_buffers does not give a minal value for GL_MAX_DRAW_BUFFERS. But, we request
      for GL_MAX_DRAW_BUFFERS = 4 at least to be able to use all requested color attachments.
@@ -288,7 +288,7 @@ class WebGLExtensionVertexArray
     : public WebGLExtensionBase
 {
 public:
-    explicit WebGLExtensionVertexArray(WebGLContext* aValue);
+    explicit WebGLExtensionVertexArray(WebGLContext* webgl);
     virtual ~WebGLExtensionVertexArray();
 
     already_AddRefed CreateVertexArrayOES();
@@ -296,8 +296,6 @@ public:
     bool IsVertexArrayOES(WebGLVertexArray* array);
     void BindVertexArrayOES(WebGLVertexArray* array);
 
-    static bool IsSupported(const WebGLContext* context);
-
     DECL_WEBGL_EXTENSION_GOOP
 };
 
@@ -305,17 +303,16 @@ class WebGLExtensionInstancedArrays
     : public WebGLExtensionBase
 {
 public:
-    explicit WebGLExtensionInstancedArrays(WebGLContext* aContext);
+    explicit WebGLExtensionInstancedArrays(WebGLContext* webgl);
     virtual ~WebGLExtensionInstancedArrays();
 
-    void DrawArraysInstancedANGLE(GLenum mode, GLint first,
-                                  GLsizei count, GLsizei primcount);
-    void DrawElementsInstancedANGLE(GLenum mode, GLsizei count,
-                                    GLenum type, WebGLintptr offset,
-                                    GLsizei primcount);
+    void DrawArraysInstancedANGLE(GLenum mode, GLint first, GLsizei count,
+                                  GLsizei primcount);
+    void DrawElementsInstancedANGLE(GLenum mode, GLsizei count, GLenum type,
+                                    WebGLintptr offset, GLsizei primcount);
     void VertexAttribDivisorANGLE(GLuint index, GLuint divisor);
 
-    static bool IsSupported(const WebGLContext* context);
+    static bool IsSupported(const WebGLContext* webgl);
 
     DECL_WEBGL_EXTENSION_GOOP
 };
@@ -324,7 +321,7 @@ class WebGLExtensionBlendMinMax
     : public WebGLExtensionBase
 {
 public:
-    explicit WebGLExtensionBlendMinMax(WebGLContext* aValue);
+    explicit WebGLExtensionBlendMinMax(WebGLContext* webgl);
     virtual ~WebGLExtensionBlendMinMax();
 
     static bool IsSupported(const WebGLContext*);
@@ -334,4 +331,4 @@ public:
 
 } // namespace mozilla
 
-#endif // WEBGLEXTENSIONS_H_
+#endif // WEBGL_EXTENSIONS_H_
diff --git a/dom/canvas/WebGLFramebuffer.cpp b/dom/canvas/WebGLFramebuffer.cpp
index d52862ac1ca2..67f0bf2899c1 100644
--- a/dom/canvas/WebGLFramebuffer.cpp
+++ b/dom/canvas/WebGLFramebuffer.cpp
@@ -5,20 +5,15 @@
 
 #include "WebGLFramebuffer.h"
 
+#include "GLContext.h"
+#include "mozilla/dom/WebGLRenderingContextBinding.h"
 #include "WebGLContext.h"
 #include "WebGLContextUtils.h"
 #include "WebGLExtensions.h"
 #include "WebGLRenderbuffer.h"
-#include "WebGLRenderbuffer.h"
-#include "WebGLTexture.h"
 #include "WebGLTexture.h"
 
-#include "GLContext.h"
-
-#include "mozilla/dom/WebGLRenderingContextBinding.h"
-
-using namespace mozilla;
-using namespace mozilla::gl;
+namespace mozilla {
 
 JSObject*
 WebGLFramebuffer::WrapObject(JSContext* cx)
@@ -26,9 +21,9 @@ WebGLFramebuffer::WrapObject(JSContext* cx)
     return dom::WebGLFramebufferBinding::Wrap(cx, this);
 }
 
-WebGLFramebuffer::WebGLFramebuffer(WebGLContext* context, GLuint fbo)
+WebGLFramebuffer::WebGLFramebuffer(WebGLContext* webgl, GLuint fbo)
     : WebGLBindableName(fbo)
-    , WebGLContextBoundObject(context)
+    , WebGLContextBoundObject(webgl)
     , mStatus(0)
     , mDepthAttachment(LOCAL_GL_DEPTH_ATTACHMENT)
     , mStencilAttachment(LOCAL_GL_STENCIL_ATTACHMENT)
@@ -40,8 +35,8 @@ WebGLFramebuffer::WebGLFramebuffer(WebGLContext* context, GLuint fbo)
     mColorAttachments[0].mAttachmentPoint = LOCAL_GL_COLOR_ATTACHMENT0;
 }
 
-WebGLFramebuffer::Attachment::Attachment(FBAttachment aAttachmentPoint)
-    : mAttachmentPoint(aAttachmentPoint)
+WebGLFramebuffer::Attachment::Attachment(FBAttachment attachmentPoint)
+    : mAttachmentPoint(attachmentPoint)
     , mTexImageTarget(LOCAL_GL_NONE)
     , mNeedsFinalize(false)
 {}
@@ -76,11 +71,17 @@ WebGLFramebuffer::Attachment::HasAlpha() const
 {
     MOZ_ASSERT(HasImage());
 
-    if (Texture() && Texture()->HasImageInfoAt(mTexImageTarget, mTexImageLevel))
-        return FormatHasAlpha(Texture()->ImageInfoAt(mTexImageTarget, mTexImageLevel).EffectiveInternalFormat());
-    else if (Renderbuffer())
+    if (Texture() &&
+        Texture()->HasImageInfoAt(mTexImageTarget, mTexImageLevel))
+    {
+        return FormatHasAlpha(Texture()->ImageInfoAt(mTexImageTarget,
+                                                     mTexImageLevel).EffectiveInternalFormat());
+    }
+
+    if (Renderbuffer())
         return FormatHasAlpha(Renderbuffer()->InternalFormat());
-    else return false;
+
+    return false;
 }
 
 GLenum
@@ -93,7 +94,8 @@ WebGLFramebuffer::GetFormatForAttachment(const WebGLFramebuffer::Attachment& att
         const WebGLTexture& tex = *attachment.Texture();
         MOZ_ASSERT(tex.HasImageInfoAt(attachment.ImageTarget(), 0));
 
-        const WebGLTexture::ImageInfo& imgInfo = tex.ImageInfoAt(attachment.ImageTarget(), 0);
+        const WebGLTexture::ImageInfo& imgInfo = tex.ImageInfoAt(attachment.ImageTarget(),
+                                                                 0);
         return imgInfo.EffectiveInternalFormat().get();
     }
 
@@ -108,13 +110,13 @@ WebGLFramebuffer::Attachment::EffectiveInternalFormat() const
 {
     const WebGLTexture* tex = Texture();
     if (tex && tex->HasImageInfoAt(mTexImageTarget, mTexImageLevel)) {
-        return tex->ImageInfoAt(mTexImageTarget, mTexImageLevel).EffectiveInternalFormat();
+        return tex->ImageInfoAt(mTexImageTarget,
+                                mTexImageLevel).EffectiveInternalFormat();
     }
 
     const WebGLRenderbuffer* rb = Renderbuffer();
-    if (rb) {
+    if (rb)
         return rb->InternalFormat();
-    }
 
     return LOCAL_GL_NONE;
 }
@@ -130,7 +132,8 @@ WebGLFramebuffer::Attachment::IsReadableFloat() const
 }
 
 void
-WebGLFramebuffer::Attachment::SetTexImage(WebGLTexture* tex, TexImageTarget target, GLint level)
+WebGLFramebuffer::Attachment::SetTexImage(WebGLTexture* tex,
+                                          TexImageTarget target, GLint level)
 {
     mTexturePtr = tex;
     mRenderbufferPtr = nullptr;
@@ -155,13 +158,13 @@ WebGLFramebuffer::Attachment::HasUninitializedImageData() const
     if (!HasImage())
         return false;
 
-    if (Renderbuffer()) {
+    if (Renderbuffer())
         return Renderbuffer()->HasUninitializedImageData();
-    }
 
     if (Texture()) {
         MOZ_ASSERT(Texture()->HasImageInfoAt(mTexImageTarget, mTexImageLevel));
-        return Texture()->ImageInfoAt(mTexImageTarget, mTexImageLevel).HasUninitializedImageData();
+        return Texture()->ImageInfoAt(mTexImageTarget,
+                                      mTexImageLevel).HasUninitializedImageData();
     }
 
     MOZ_ASSERT(false, "Should not get here.");
@@ -180,7 +183,8 @@ WebGLFramebuffer::Attachment::SetImageDataStatus(WebGLImageDataStatus newStatus)
     }
 
     if (Texture()) {
-        Texture()->SetImageDataStatus(mTexImageTarget, mTexImageLevel, newStatus);
+        Texture()->SetImageDataStatus(mTexImageTarget, mTexImageLevel,
+                                      newStatus);
         return;
     }
 
@@ -202,30 +206,29 @@ WebGLFramebuffer::Attachment::HasImage() const
 const WebGLRectangleObject&
 WebGLFramebuffer::Attachment::RectangleObject() const
 {
-    MOZ_ASSERT(HasImage(), "Make sure it has an image before requesting the rectangle.");
+    MOZ_ASSERT(HasImage(),
+               "Make sure it has an image before requesting the rectangle.");
 
     if (Texture()) {
         MOZ_ASSERT(Texture()->HasImageInfoAt(mTexImageTarget, mTexImageLevel));
         return Texture()->ImageInfoAt(mTexImageTarget, mTexImageLevel);
     }
 
-    if (Renderbuffer()) {
+    if (Renderbuffer())
         return *Renderbuffer();
-    }
 
     MOZ_CRASH("Should not get here.");
 }
 
-/* The following IsValidFBOTextureXXX functions check the internal
-   format that is used by GL or GL ES texture formats.  This
-   corresponds to the state that is stored in
-   WebGLTexture::ImageInfo::InternalFormat()*/
+// The following IsValidFBOTextureXXX functions check the internal format that
+// is used by GL or GL ES texture formats.  This corresponds to the state that
+// is stored in WebGLTexture::ImageInfo::InternalFormat()
 static inline bool
 IsValidFBOTextureColorFormat(TexInternalFormat internalformat)
 {
-    /* These formats are internal formats for each texture -- the actual
-     * low level format, which we might have to do conversions for when
-     * running against desktop GL (e.g. GL_RGBA + GL_FLOAT -> GL_RGBA32F).
+    /* These formats are internal formats for each texture -- the actual low
+     * level format, which we might have to do conversions for when running
+     * against desktop GL (e.g. GL_RGBA + GL_FLOAT -> GL_RGBA32F).
      *
      * This function just handles all of them whether desktop GL or ES.
      */
@@ -252,17 +255,16 @@ IsValidFBOTextureDepthStencilFormat(GLenum internalformat)
     return IsGLDepthStencilFormat(internalformat);
 }
 
-/* The following IsValidFBORenderbufferXXX functions check the internal
-   format that is stored by WebGLRenderbuffer::InternalFormat(). Valid
-   values can be found in WebGLContext::RenderbufferStorage. */
+// The following IsValidFBORenderbufferXXX functions check the internal format
+// that is stored by WebGLRenderbuffer::InternalFormat(). Valid values can be
+// found in WebGLContext::RenderbufferStorage.
 static inline bool
 IsValidFBORenderbufferColorFormat(GLenum internalFormat)
 {
-    return (
-        internalFormat == LOCAL_GL_RGB565 ||
-        internalFormat == LOCAL_GL_RGB5_A1 ||
-        internalFormat == LOCAL_GL_RGBA4 ||
-        internalFormat == LOCAL_GL_SRGB8_ALPHA8_EXT);
+    return  internalFormat == LOCAL_GL_RGB565 ||
+            internalFormat == LOCAL_GL_RGB5_A1 ||
+            internalFormat == LOCAL_GL_RGBA4 ||
+            internalFormat == LOCAL_GL_SRGB8_ALPHA8_EXT;
 }
 
 static inline bool
@@ -336,13 +338,14 @@ WebGLFramebuffer::Attachment::IsComplete() const
         if (mAttachmentPoint == LOCAL_GL_DEPTH_ATTACHMENT)
             return IsValidFBOTextureDepthFormat(sizedFormat);
 
-        if (mAttachmentPoint == LOCAL_GL_STENCIL_ATTACHMENT)
-            return false; // Textures can't have the correct format for stencil buffers
-
-        if (mAttachmentPoint == LOCAL_GL_DEPTH_STENCIL_ATTACHMENT) {
-            return IsValidFBOTextureDepthStencilFormat(sizedFormat);
+        if (mAttachmentPoint == LOCAL_GL_STENCIL_ATTACHMENT) {
+            // Textures can't have the correct format for stencil buffers.
+            return false;
         }
 
+        if (mAttachmentPoint == LOCAL_GL_DEPTH_STENCIL_ATTACHMENT)
+            return IsValidFBOTextureDepthStencilFormat(sizedFormat);
+
         if (mAttachmentPoint >= LOCAL_GL_COLOR_ATTACHMENT0 &&
             mAttachmentPoint <= FBAttachment(LOCAL_GL_COLOR_ATTACHMENT0 - 1 +
                                              WebGLContext::kMaxColorAttachments))
@@ -376,13 +379,13 @@ WebGLFramebuffer::Attachment::IsComplete() const
         MOZ_ASSERT(false, "Invalid WebGL attachment point?");
         return false;
     }
-
     MOZ_ASSERT(false, "Should not get here.");
     return false;
 }
 
 void
-WebGLFramebuffer::Attachment::FinalizeAttachment(GLContext* gl, FBAttachment attachmentLoc) const
+WebGLFramebuffer::Attachment::FinalizeAttachment(gl::GLContext* gl,
+                                                 FBAttachment attachmentLoc) const
 {
     if (!mNeedsFinalize)
         return;
@@ -391,12 +394,15 @@ WebGLFramebuffer::Attachment::FinalizeAttachment(GLContext* gl, FBAttachment att
 
     if (!HasImage()) {
         if (attachmentLoc == LOCAL_GL_DEPTH_STENCIL_ATTACHMENT) {
-            gl->fFramebufferRenderbuffer(LOCAL_GL_FRAMEBUFFER, LOCAL_GL_DEPTH_ATTACHMENT,
+            gl->fFramebufferRenderbuffer(LOCAL_GL_FRAMEBUFFER,
+                                         LOCAL_GL_DEPTH_ATTACHMENT,
                                          LOCAL_GL_RENDERBUFFER, 0);
-            gl->fFramebufferRenderbuffer(LOCAL_GL_FRAMEBUFFER, LOCAL_GL_STENCIL_ATTACHMENT,
+            gl->fFramebufferRenderbuffer(LOCAL_GL_FRAMEBUFFER,
+                                         LOCAL_GL_STENCIL_ATTACHMENT,
                                          LOCAL_GL_RENDERBUFFER, 0);
         } else {
-            gl->fFramebufferRenderbuffer(LOCAL_GL_FRAMEBUFFER, attachmentLoc.get(),
+            gl->fFramebufferRenderbuffer(LOCAL_GL_FRAMEBUFFER,
+                                         attachmentLoc.get(),
                                          LOCAL_GL_RENDERBUFFER, 0);
         }
 
@@ -412,10 +418,12 @@ WebGLFramebuffer::Attachment::FinalizeAttachment(GLContext* gl, FBAttachment att
         const GLuint glName = Texture()->GLName();
 
         if (attachmentLoc == LOCAL_GL_DEPTH_STENCIL_ATTACHMENT) {
-            gl->fFramebufferTexture2D(LOCAL_GL_FRAMEBUFFER, LOCAL_GL_DEPTH_ATTACHMENT,
-                                      imageTarget, glName, mipLevel);
-            gl->fFramebufferTexture2D(LOCAL_GL_FRAMEBUFFER, LOCAL_GL_STENCIL_ATTACHMENT,
-                                      imageTarget, glName, mipLevel);
+            gl->fFramebufferTexture2D(LOCAL_GL_FRAMEBUFFER,
+                                      LOCAL_GL_DEPTH_ATTACHMENT, imageTarget,
+                                      glName, mipLevel);
+            gl->fFramebufferTexture2D(LOCAL_GL_FRAMEBUFFER,
+                                      LOCAL_GL_STENCIL_ATTACHMENT, imageTarget,
+                                      glName, mipLevel);
         } else {
             gl->fFramebufferTexture2D(LOCAL_GL_FRAMEBUFFER, attachmentLoc.get(),
                                       imageTarget, glName, mipLevel);
@@ -451,15 +459,16 @@ WebGLFramebuffer::DetachAttachment(WebGLFramebuffer::Attachment& attachment)
     if (attachment.Texture())
         attachment.Texture()->DetachFrom(this, attachment.mAttachmentPoint);
 
-    if (attachment.Renderbuffer())
-        attachment.Renderbuffer()->DetachFrom(this, attachment.mAttachmentPoint);
+    if (attachment.Renderbuffer()) {
+        attachment.Renderbuffer()->DetachFrom(this,
+                                              attachment.mAttachmentPoint);
+    }
 }
 
 void
 WebGLFramebuffer::DetachAllAttachments()
 {
-    size_t count = mColorAttachments.Length();
-    for (size_t i = 0; i < count; i++) {
+    for (size_t i = 0; i < mColorAttachments.Length(); i++) {
         DetachAttachment(mColorAttachments[i]);
     }
 
@@ -469,130 +478,156 @@ WebGLFramebuffer::DetachAllAttachments()
 }
 
 void
-WebGLFramebuffer::FramebufferRenderbuffer(FBAttachment attachment,
+WebGLFramebuffer::FramebufferRenderbuffer(FBAttachment attachPoint,
                                           RBTarget rbtarget,
-                                          WebGLRenderbuffer* wrb)
+                                          WebGLRenderbuffer* rb)
 {
     MOZ_ASSERT(mContext->mBoundFramebuffer == this);
 
-    if (!mContext->ValidateObjectAllowNull("framebufferRenderbuffer: renderbuffer", wrb))
+    if (!mContext->ValidateObjectAllowNull("framebufferRenderbuffer: renderbuffer",
+                                           rb))
+    {
         return;
+    }
 
-    /* Get the requested attachment. If result is NULL, attachment is
-     * invalid and an error is generated.
+    /* Get the requested attachment. If result is NULL, attachment is invalid
+     * and an error is generated.
      *
-     * Don't use GetAttachment(...) here because it opt builds it
-     * returns mColorAttachment[0] for invalid attachment, which we
-     * really don't want to mess with.
+     * Don't use GetAttachment(...) here because it opt builds it returns
+     * mColorAttachment[0] for invalid attachment, which we really don't want to
+     * mess with.
      */
-    Attachment* a = GetAttachmentOrNull(attachment);
-    if (!a)
+    Attachment* attachment = GetAttachmentOrNull(attachPoint);
+    if (!attachment)
         return; // Error generated internally to GetAttachmentOrNull.
 
-    /* Invalidate cached framebuffer status and inform texture of it's
-     * new attachment
-     */
+    // Invalidate cached framebuffer status and inform texture of its new
+    // attachment.
     mStatus = 0;
-    // Detach current
-    if (a->Texture())
-        a->Texture()->DetachFrom(this, attachment);
-    else if (a->Renderbuffer())
-        a->Renderbuffer()->DetachFrom(this, attachment);
 
-    // Attach new
-    if (wrb)
-        wrb->AttachTo(this, attachment);
+    // Detach current:
+    if (attachment->Texture())
+        attachment->Texture()->DetachFrom(this, attachPoint);
+    else if (attachment->Renderbuffer())
+        attachment->Renderbuffer()->DetachFrom(this, attachPoint);
 
-    a->SetRenderbuffer(wrb);
+    // Attach new:
+    if (rb)
+        rb->AttachTo(this, attachPoint);
+
+    attachment->SetRenderbuffer(rb);
 }
 
 void
-WebGLFramebuffer::FramebufferTexture2D(FBAttachment attachment,
+WebGLFramebuffer::FramebufferTexture2D(FBAttachment attachPoint,
                                        TexImageTarget texImageTarget,
-                                       WebGLTexture* wtex,
-                                       GLint level)
+                                       WebGLTexture* tex, GLint level)
 {
     MOZ_ASSERT(mContext->mBoundFramebuffer == this);
 
-    if (!mContext->ValidateObjectAllowNull("framebufferTexture2D: texture", wtex))
+    if (!mContext->ValidateObjectAllowNull("framebufferTexture2D: texture",
+                                           tex))
+    {
         return;
+    }
 
-    if (wtex) {
-        bool isTexture2D = wtex->Target() == LOCAL_GL_TEXTURE_2D;
+    if (tex) {
+        bool isTexture2D = tex->Target() == LOCAL_GL_TEXTURE_2D;
         bool isTexTarget2D = texImageTarget == LOCAL_GL_TEXTURE_2D;
         if (isTexture2D != isTexTarget2D) {
-            return mContext->ErrorInvalidOperation("framebufferTexture2D: mismatched texture and texture target");
+            mContext->ErrorInvalidOperation("framebufferTexture2D: Mismatched"
+                                            " texture and texture target.");
+            return;
         }
     }
 
-    if (level != 0)
-        return mContext->ErrorInvalidValue("framebufferTexture2D: level must be 0");
+    if (level != 0) {
+        mContext->ErrorInvalidValue("framebufferTexture2D: Level must be 0.");
+        return;
+    }
 
-    /* Get the requested attachment. If result is NULL, attachment is
-     * invalid and an error is generated.
+    /* Get the requested attachment. If result is NULL, attachment is invalid
+     * and an error is generated.
      *
-     * Don't use GetAttachment(...) here because it opt builds it
-     * returns mColorAttachment[0] for invalid attachment, which we
-     * really don't want to mess with.
+     * Don't use GetAttachment(...) here because it opt builds it returns
+     * mColorAttachment[0] for invalid attachment, which we really don't want to
+     * mess with.
      */
-    Attachment* a = GetAttachmentOrNull(attachment);
-    if (!a)
+    Attachment* attachment = GetAttachmentOrNull(attachPoint);
+    if (!attachment)
         return; // Error generated internally to GetAttachmentOrNull.
 
-    /* Invalidate cached framebuffer status and inform texture of it's
-     * new attachment
-     */
+    // Invalidate cached framebuffer status and inform texture of its new
+    // attachment.
     mStatus = 0;
-    // Detach current
-    if (a->Texture())
-        a->Texture()->DetachFrom(this, attachment);
-    else if (a->Renderbuffer())
-        a->Renderbuffer()->DetachFrom(this, attachment);
 
-    // Attach new
-    if (wtex)
-        wtex->AttachTo(this, attachment);
+    // Detach current:
+    if (attachment->Texture())
+        attachment->Texture()->DetachFrom(this, attachPoint);
+    else if (attachment->Renderbuffer())
+        attachment->Renderbuffer()->DetachFrom(this, attachPoint);
 
-    a->SetTexImage(wtex, texImageTarget, level);
+    // Attach new:
+    if (tex)
+        tex->AttachTo(this, attachPoint);
+
+    attachment->SetTexImage(tex, texImageTarget, level);
 }
 
 WebGLFramebuffer::Attachment*
-WebGLFramebuffer::GetAttachmentOrNull(FBAttachment attachment)
+WebGLFramebuffer::GetAttachmentOrNull(FBAttachment attachPoint)
 {
-    if (attachment == LOCAL_GL_DEPTH_STENCIL_ATTACHMENT)
+    switch (attachPoint.get()) {
+    case LOCAL_GL_DEPTH_STENCIL_ATTACHMENT:
         return &mDepthStencilAttachment;
 
-    if (attachment == LOCAL_GL_DEPTH_ATTACHMENT)
+    case LOCAL_GL_DEPTH_ATTACHMENT:
         return &mDepthAttachment;
 
-    if (attachment == LOCAL_GL_STENCIL_ATTACHMENT)
+    case LOCAL_GL_STENCIL_ATTACHMENT:
         return &mStencilAttachment;
 
-    if (!mContext->ValidateFramebufferAttachment(attachment.get(), "getAttachmentOrNull"))
-        return nullptr;
+    default:
+        break;
+    }
 
-    size_t colorAttachmentId = attachment.get() - LOCAL_GL_COLOR_ATTACHMENT0;
+    if (!mContext->ValidateFramebufferAttachment(attachPoint.get(),
+                                                 "getAttachmentOrNull"))
+    {
+        return nullptr;
+    }
+
+    size_t colorAttachmentId = attachPoint.get() - LOCAL_GL_COLOR_ATTACHMENT0;
     EnsureColorAttachments(colorAttachmentId);
 
     return &mColorAttachments[colorAttachmentId];
 }
 
 const WebGLFramebuffer::Attachment&
-WebGLFramebuffer::GetAttachment(FBAttachment attachment) const
+WebGLFramebuffer::GetAttachment(FBAttachment attachPoint) const
 {
-    if (attachment == LOCAL_GL_DEPTH_STENCIL_ATTACHMENT)
+    switch (attachPoint.get()) {
+    case LOCAL_GL_DEPTH_STENCIL_ATTACHMENT:
         return mDepthStencilAttachment;
-    if (attachment == LOCAL_GL_DEPTH_ATTACHMENT)
+
+    case LOCAL_GL_DEPTH_ATTACHMENT:
         return mDepthAttachment;
-    if (attachment == LOCAL_GL_STENCIL_ATTACHMENT)
+
+    case LOCAL_GL_STENCIL_ATTACHMENT:
         return mStencilAttachment;
 
-    if (!mContext->ValidateFramebufferAttachment(attachment.get(), "getAttachment")) {
+    default:
+        break;
+    }
+
+    if (!mContext->ValidateFramebufferAttachment(attachPoint.get(),
+                                                 "getAttachment"))
+    {
         MOZ_ASSERT(false);
         return mColorAttachments[0];
     }
 
-    size_t colorAttachmentId = attachment.get() - LOCAL_GL_COLOR_ATTACHMENT0;
+    size_t colorAttachmentId = attachPoint.get() - LOCAL_GL_COLOR_ATTACHMENT0;
     if (colorAttachmentId >= mColorAttachments.Length()) {
         MOZ_ASSERT(false);
         return mColorAttachments[0];
@@ -604,39 +639,51 @@ WebGLFramebuffer::GetAttachment(FBAttachment attachment) const
 void
 WebGLFramebuffer::DetachTexture(const WebGLTexture* tex)
 {
-    size_t count = mColorAttachments.Length();
-    for (size_t i = 0; i < count; i++) {
+    for (size_t i = 0; i < (size_t)mColorAttachments.Length(); i++) {
         if (mColorAttachments[i].Texture() == tex) {
-            FramebufferTexture2D(LOCAL_GL_COLOR_ATTACHMENT0+i, LOCAL_GL_TEXTURE_2D, nullptr, 0);
-            // a texture might be attached more that once while editing the framebuffer
+            FramebufferTexture2D(LOCAL_GL_COLOR_ATTACHMENT0+i,
+                                 LOCAL_GL_TEXTURE_2D, nullptr, 0);
+            // It might be attached in multiple places, so don't break.
         }
     }
 
-    if (mDepthAttachment.Texture() == tex)
-        FramebufferTexture2D(LOCAL_GL_DEPTH_ATTACHMENT, LOCAL_GL_TEXTURE_2D, nullptr, 0);
-    if (mStencilAttachment.Texture() == tex)
-        FramebufferTexture2D(LOCAL_GL_STENCIL_ATTACHMENT, LOCAL_GL_TEXTURE_2D, nullptr, 0);
-    if (mDepthStencilAttachment.Texture() == tex)
-        FramebufferTexture2D(LOCAL_GL_DEPTH_STENCIL_ATTACHMENT, LOCAL_GL_TEXTURE_2D, nullptr, 0);
+    if (mDepthAttachment.Texture() == tex) {
+        FramebufferTexture2D(LOCAL_GL_DEPTH_ATTACHMENT, LOCAL_GL_TEXTURE_2D,
+                             nullptr, 0);
+    }
+    if (mStencilAttachment.Texture() == tex) {
+        FramebufferTexture2D(LOCAL_GL_STENCIL_ATTACHMENT, LOCAL_GL_TEXTURE_2D,
+                             nullptr, 0);
+    }
+    if (mDepthStencilAttachment.Texture() == tex) {
+        FramebufferTexture2D(LOCAL_GL_DEPTH_STENCIL_ATTACHMENT,
+                             LOCAL_GL_TEXTURE_2D, nullptr, 0);
+    }
 }
 
 void
 WebGLFramebuffer::DetachRenderbuffer(const WebGLRenderbuffer* rb)
 {
-    size_t count = mColorAttachments.Length();
-    for (size_t i = 0; i < count; i++) {
+    for (size_t i = 0; i < (size_t)mColorAttachments.Length(); i++) {
         if (mColorAttachments[i].Renderbuffer() == rb) {
-            FramebufferRenderbuffer(LOCAL_GL_COLOR_ATTACHMENT0+i, LOCAL_GL_RENDERBUFFER, nullptr);
-            // a renderbuffer might be attached more that once while editing the framebuffer
+            FramebufferRenderbuffer(LOCAL_GL_COLOR_ATTACHMENT0+i,
+                                    LOCAL_GL_RENDERBUFFER, nullptr);
+            // It might be attached in multiple places, so don't break.
         }
     }
 
-    if (mDepthAttachment.Renderbuffer() == rb)
-        FramebufferRenderbuffer(LOCAL_GL_DEPTH_ATTACHMENT, LOCAL_GL_RENDERBUFFER, nullptr);
-    if (mStencilAttachment.Renderbuffer() == rb)
-        FramebufferRenderbuffer(LOCAL_GL_STENCIL_ATTACHMENT, LOCAL_GL_RENDERBUFFER, nullptr);
-    if (mDepthStencilAttachment.Renderbuffer() == rb)
-        FramebufferRenderbuffer(LOCAL_GL_DEPTH_STENCIL_ATTACHMENT, LOCAL_GL_RENDERBUFFER, nullptr);
+    if (mDepthAttachment.Renderbuffer() == rb) {
+        FramebufferRenderbuffer(LOCAL_GL_DEPTH_ATTACHMENT,
+                                LOCAL_GL_RENDERBUFFER, nullptr);
+    }
+    if (mStencilAttachment.Renderbuffer() == rb) {
+        FramebufferRenderbuffer(LOCAL_GL_STENCIL_ATTACHMENT,
+                                LOCAL_GL_RENDERBUFFER, nullptr);
+    }
+    if (mDepthStencilAttachment.Renderbuffer() == rb) {
+        FramebufferRenderbuffer(LOCAL_GL_DEPTH_STENCIL_ATTACHMENT,
+                                LOCAL_GL_RENDERBUFFER, nullptr);
+    }
 }
 
 bool
@@ -644,8 +691,7 @@ WebGLFramebuffer::HasDefinedAttachments() const
 {
     bool hasAttachments = false;
 
-    size_t count = mColorAttachments.Length();
-    for (size_t i = 0; i < count; i++) {
+    for (size_t i = 0; i < (size_t)mColorAttachments.Length(); i++) {
         hasAttachments |= mColorAttachments[i].IsDefined();
     }
 
@@ -668,8 +714,7 @@ WebGLFramebuffer::HasIncompleteAttachments() const
 {
     bool hasIncomplete = false;
 
-    size_t count = mColorAttachments.Length();
-    for (size_t i = 0; i < count; i++) {
+    for (size_t i = 0; i < (size_t)mColorAttachments.Length(); i++) {
         hasIncomplete |= IsIncomplete(mColorAttachments[i]);
     }
 
@@ -680,14 +725,12 @@ WebGLFramebuffer::HasIncompleteAttachments() const
     return hasIncomplete;
 }
 
-
 const WebGLRectangleObject&
 WebGLFramebuffer::GetAnyRectObject() const
 {
     MOZ_ASSERT(HasDefinedAttachments());
 
-    size_t count = mColorAttachments.Length();
-    for (size_t i = 0; i < count; i++) {
+    for (size_t i = 0; i < (size_t)mColorAttachments.Length(); i++) {
         if (mColorAttachments[i].HasImage())
             return mColorAttachments[i].RectangleObject();
     }
@@ -704,7 +747,6 @@ WebGLFramebuffer::GetAnyRectObject() const
     MOZ_CRASH("Should not get here.");
 }
 
-
 static bool
 RectsMatch(const WebGLFramebuffer::Attachment& attachment,
            const WebGLRectangleObject& rect)
@@ -723,8 +765,7 @@ WebGLFramebuffer::AllImageRectsMatch() const
     // Alright, we have *a* rect, let's check all the others.
     bool imageRectsMatch = true;
 
-    size_t count = mColorAttachments.Length();
-    for (size_t i = 0; i < count; i++) {
+    for (size_t i = 0; i < (size_t)mColorAttachments.Length(); i++) {
         if (mColorAttachments[i].HasImage())
             imageRectsMatch &= RectsMatch(mColorAttachments[i], rect);
     }
@@ -826,7 +867,7 @@ WebGLFramebuffer::CheckAndInitializeAttachments()
         return false;
 
     // Cool! We've checked out ok. Just need to initialize.
-    size_t colorAttachmentCount = mColorAttachments.Length();
+    const size_t colorAttachmentCount = mColorAttachments.Length();
 
     // Check if we need to initialize anything
     {
@@ -914,9 +955,9 @@ WebGLFramebuffer::NotifyAttachableChanged() const
 }
 
 static void
-FinalizeDrawAndReadBuffers(GLContext* aGL, bool aColorBufferDefined)
+FinalizeDrawAndReadBuffers(gl::GLContext* gl, bool isColorBufferDefined)
 {
-    MOZ_ASSERT(aGL, "Expected a valid GLContext ptr.");
+    MOZ_ASSERT(gl, "Expected a valid GLContext ptr.");
     // GLES don't support DrawBuffer()/ReadBuffer.
     // According to http://www.opengl.org/wiki/Framebuffer_Object
     //
@@ -928,61 +969,62 @@ FinalizeDrawAndReadBuffers(GLContext* aGL, bool aColorBufferDefined)
     //
     // Note that this test is not performed if OpenGL 4.2 or ARB_ES2_compatibility is
     // available.
-    if (aGL->IsGLES() ||
-        aGL->IsSupported(GLFeature::ES2_compatibility) ||
-        aGL->IsAtLeast(ContextProfile::OpenGL, 420))
+    if (gl->IsGLES() ||
+        gl->IsSupported(gl::GLFeature::ES2_compatibility) ||
+        gl->IsAtLeast(gl::ContextProfile::OpenGL, 420))
     {
         return;
     }
 
     // TODO(djg): Assert that fDrawBuffer/fReadBuffer is not NULL.
-    GLenum colorBufferSource = aColorBufferDefined ? LOCAL_GL_COLOR_ATTACHMENT0 : LOCAL_GL_NONE;
-    aGL->fDrawBuffer(colorBufferSource);
-    aGL->fReadBuffer(colorBufferSource);
+    GLenum colorBufferSource = isColorBufferDefined ? LOCAL_GL_COLOR_ATTACHMENT0
+                                                    : LOCAL_GL_NONE;
+    gl->fDrawBuffer(colorBufferSource);
+    gl->fReadBuffer(colorBufferSource);
 }
 
 void
 WebGLFramebuffer::FinalizeAttachments() const
 {
-    GLContext* gl = mContext->gl;
+    gl::GLContext* gl = mContext->gl;
 
-    size_t count = ColorAttachmentCount();
-    for (size_t i = 0; i < count; i++) {
-        ColorAttachment(i).FinalizeAttachment(gl, LOCAL_GL_COLOR_ATTACHMENT0 + i);
+    for (size_t i = 0; i < ColorAttachmentCount(); i++) {
+        ColorAttachment(i).FinalizeAttachment(gl, LOCAL_GL_COLOR_ATTACHMENT0+i);
     }
 
     DepthAttachment().FinalizeAttachment(gl, LOCAL_GL_DEPTH_ATTACHMENT);
     StencilAttachment().FinalizeAttachment(gl, LOCAL_GL_STENCIL_ATTACHMENT);
-    DepthStencilAttachment().FinalizeAttachment(gl, LOCAL_GL_DEPTH_STENCIL_ATTACHMENT);
+    DepthStencilAttachment().FinalizeAttachment(gl,
+                                                LOCAL_GL_DEPTH_STENCIL_ATTACHMENT);
 
     FinalizeDrawAndReadBuffers(gl, ColorAttachment(0).IsDefined());
 }
 
 inline void
-ImplCycleCollectionUnlink(mozilla::WebGLFramebuffer::Attachment& aField)
+ImplCycleCollectionUnlink(mozilla::WebGLFramebuffer::Attachment& field)
 {
-    aField.mTexturePtr = nullptr;
-    aField.mRenderbufferPtr = nullptr;
+    field.mTexturePtr = nullptr;
+    field.mRenderbufferPtr = nullptr;
 }
 
 inline void
-ImplCycleCollectionTraverse(nsCycleCollectionTraversalCallback& aCallback,
-                            mozilla::WebGLFramebuffer::Attachment& aField,
-                            const char* aName,
-                            uint32_t aFlags = 0)
+ImplCycleCollectionTraverse(nsCycleCollectionTraversalCallback& callback,
+                            mozilla::WebGLFramebuffer::Attachment& field,
+                            const char* name,
+                            uint32_t flags = 0)
 {
-    CycleCollectionNoteChild(aCallback, aField.mTexturePtr.get(),
-                             aName, aFlags);
-
-    CycleCollectionNoteChild(aCallback, aField.mRenderbufferPtr.get(),
-                             aName, aFlags);
+    CycleCollectionNoteChild(callback, field.mTexturePtr.get(), name, flags);
+    CycleCollectionNoteChild(callback, field.mRenderbufferPtr.get(), name,
+                             flags);
 }
 
 NS_IMPL_CYCLE_COLLECTION_WRAPPERCACHE(WebGLFramebuffer,
-  mColorAttachments,
-  mDepthAttachment,
-  mStencilAttachment,
-  mDepthStencilAttachment)
+                                      mColorAttachments,
+                                      mDepthAttachment,
+                                      mStencilAttachment,
+                                      mDepthStencilAttachment)
 
 NS_IMPL_CYCLE_COLLECTION_ROOT_NATIVE(WebGLFramebuffer, AddRef)
 NS_IMPL_CYCLE_COLLECTION_UNROOT_NATIVE(WebGLFramebuffer, Release)
+
+} // namespace mozilla
diff --git a/dom/canvas/WebGLFramebuffer.h b/dom/canvas/WebGLFramebuffer.h
index 3421e1e51dab..a0b652a754ca 100644
--- a/dom/canvas/WebGLFramebuffer.h
+++ b/dom/canvas/WebGLFramebuffer.h
@@ -3,22 +3,21 @@
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
-#ifndef WEBGLFRAMEBUFFER_H_
-#define WEBGLFRAMEBUFFER_H_
+#ifndef WEBGL_FRAMEBUFFER_H_
+#define WEBGL_FRAMEBUFFER_H_
 
+#include "mozilla/LinkedList.h"
+#include "nsWrapperCache.h"
 #include "WebGLBindableName.h"
 #include "WebGLObjectModel.h"
 #include "WebGLStrongTypes.h"
 
-#include "nsWrapperCache.h"
-
-#include "mozilla/LinkedList.h"
-
 namespace mozilla {
 
 class WebGLFramebufferAttachable;
-class WebGLTexture;
 class WebGLRenderbuffer;
+class WebGLTexture;
+
 namespace gl {
     class GLContext;
 }
@@ -34,7 +33,7 @@ class WebGLFramebuffer MOZ_FINAL
 public:
     MOZ_DECLARE_REFCOUNTED_TYPENAME(WebGLFramebuffer)
 
-    explicit WebGLFramebuffer(WebGLContext* context, GLuint fbo);
+    explicit WebGLFramebuffer(WebGLContext* webgl, GLuint fbo);
 
     struct Attachment
     {
@@ -46,7 +45,7 @@ public:
         GLint mTexImageLevel;
         mutable bool mNeedsFinalize;
 
-        explicit Attachment(FBAttachment aAttachmentPoint = LOCAL_GL_COLOR_ATTACHMENT0);
+        explicit Attachment(FBAttachment attachmentPoint = LOCAL_GL_COLOR_ATTACHMENT0);
         ~Attachment();
 
         bool IsDefined() const;
@@ -90,18 +89,17 @@ public:
         bool HasImage() const;
         bool IsComplete() const;
 
-        void FinalizeAttachment(gl::GLContext* gl, FBAttachment attachmentLoc) const;
+        void FinalizeAttachment(gl::GLContext* gl,
+                                FBAttachment attachmentLoc) const;
     };
 
     void Delete();
 
-    void FramebufferRenderbuffer(FBAttachment attachment,
-                                 RBTarget rbtarget,
-                                 WebGLRenderbuffer* wrb);
+    void FramebufferRenderbuffer(FBAttachment attachment, RBTarget rbtarget,
+                                 WebGLRenderbuffer* rb);
 
     void FramebufferTexture2D(FBAttachment attachment,
-                              TexImageTarget texImageTarget,
-                              WebGLTexture* wtex,
+                              TexImageTarget texImageTarget, WebGLTexture* tex,
                               GLint level);
 
 private:
@@ -116,7 +114,9 @@ public:
     bool AllImageRectsMatch() const;
     FBStatus PrecheckFramebufferStatus() const;
     FBStatus CheckFramebufferStatus() const;
-    GLenum GetFormatForAttachment(const WebGLFramebuffer::Attachment& attachment) const;
+
+    GLenum
+    GetFormatForAttachment(const WebGLFramebuffer::Attachment& attachment) const;
 
     bool HasDepthStencilConflict() const {
         return int(mDepthAttachment.IsDefined()) +
@@ -167,7 +167,8 @@ public:
 
     bool CheckAndInitializeAttachments();
 
-    bool CheckColorAttachmentNumber(FBAttachment attachment, const char* functionName) const;
+    bool CheckColorAttachmentNumber(FBAttachment attachment,
+                                    const char* funcName) const;
 
     void EnsureColorAttachments(size_t colorAttachmentId);
 
@@ -183,11 +184,11 @@ private:
     // we only store pointers to attached renderbuffers, not to attached textures, because
     // we will only need to initialize renderbuffers. Textures are already initialized.
     nsTArray mColorAttachments;
-    Attachment mDepthAttachment,
-               mStencilAttachment,
-               mDepthStencilAttachment;
+    Attachment mDepthAttachment;
+    Attachment mStencilAttachment;
+    Attachment mDepthStencilAttachment;
 };
 
 } // namespace mozilla
 
-#endif
+#endif // WEBGL_FRAMEBUFFER_H_
diff --git a/dom/canvas/WebGLMemoryTracker.h b/dom/canvas/WebGLMemoryTracker.h
index d48fd6a744a0..1c35cbef2fcb 100644
--- a/dom/canvas/WebGLMemoryTracker.h
+++ b/dom/canvas/WebGLMemoryTracker.h
@@ -3,19 +3,19 @@
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
-#ifndef WEBGLMEMORYTRACKER_H_
-#define WEBGLMEMORYTRACKER_H_
+#ifndef WEBGL_MEMORY_TRACKER_H_
+#define WEBGL_MEMORY_TRACKER_H_
 
-#include "WebGLContext.h"
-#include "WebGLBuffer.h"
-#include "WebGLVertexAttribData.h"
-#include "WebGLShader.h"
-#include "WebGLProgram.h"
-#include "WebGLUniformLocation.h"
-#include "WebGLTexture.h"
-#include "WebGLRenderbuffer.h"
 #include "mozilla/StaticPtr.h"
 #include "nsIMemoryReporter.h"
+#include "WebGLBuffer.h"
+#include "WebGLContext.h"
+#include "WebGLVertexAttribData.h"
+#include "WebGLProgram.h"
+#include "WebGLRenderbuffer.h"
+#include "WebGLShader.h"
+#include "WebGLTexture.h"
+#include "WebGLUniformLocation.h"
 
 namespace mozilla {
 
@@ -37,7 +37,7 @@ class WebGLMemoryTracker : public nsIMemoryReporter
 
     static WebGLMemoryTracker* UniqueInstance();
 
-    static ContextsArrayType & Contexts() { return UniqueInstance()->mContexts; }
+    static ContextsArrayType& Contexts() { return UniqueInstance()->mContexts; }
 
     friend class WebGLContext;
 
@@ -62,7 +62,7 @@ class WebGLMemoryTracker : public nsIMemoryReporter
         const ContextsArrayType & contexts = Contexts();
         int64_t result = 0;
         for(size_t i = 0; i < contexts.Length(); ++i) {
-            for (const WebGLTexture *texture = contexts[i]->mTextures.getFirst();
+            for (const WebGLTexture* texture = contexts[i]->mTextures.getFirst();
                  texture;
                  texture = texture->getNext())
             {
@@ -76,7 +76,7 @@ class WebGLMemoryTracker : public nsIMemoryReporter
         const ContextsArrayType & contexts = Contexts();
         int64_t result = 0;
         for(size_t i = 0; i < contexts.Length(); ++i) {
-            for (const WebGLTexture *texture = contexts[i]->mTextures.getFirst();
+            for (const WebGLTexture* texture = contexts[i]->mTextures.getFirst();
                  texture;
                  texture = texture->getNext())
             {
@@ -90,7 +90,7 @@ class WebGLMemoryTracker : public nsIMemoryReporter
         const ContextsArrayType & contexts = Contexts();
         int64_t result = 0;
         for(size_t i = 0; i < contexts.Length(); ++i) {
-            for (const WebGLBuffer *buffer = contexts[i]->mBuffers.getFirst();
+            for (const WebGLBuffer* buffer = contexts[i]->mBuffers.getFirst();
                  buffer;
                  buffer = buffer->getNext())
             {
@@ -106,7 +106,7 @@ class WebGLMemoryTracker : public nsIMemoryReporter
         const ContextsArrayType & contexts = Contexts();
         int64_t result = 0;
         for(size_t i = 0; i < contexts.Length(); ++i) {
-            for (const WebGLBuffer *buffer = contexts[i]->mBuffers.getFirst();
+            for (const WebGLBuffer* buffer = contexts[i]->mBuffers.getFirst();
                  buffer;
                  buffer = buffer->getNext())
             {
@@ -120,7 +120,7 @@ class WebGLMemoryTracker : public nsIMemoryReporter
         const ContextsArrayType & contexts = Contexts();
         int64_t result = 0;
         for(size_t i = 0; i < contexts.Length(); ++i) {
-            for (const WebGLRenderbuffer *rb = contexts[i]->mRenderbuffers.getFirst();
+            for (const WebGLRenderbuffer* rb = contexts[i]->mRenderbuffers.getFirst();
                  rb;
                  rb = rb->getNext())
             {
@@ -134,7 +134,7 @@ class WebGLMemoryTracker : public nsIMemoryReporter
         const ContextsArrayType & contexts = Contexts();
         int64_t result = 0;
         for(size_t i = 0; i < contexts.Length(); ++i) {
-            for (const WebGLRenderbuffer *rb = contexts[i]->mRenderbuffers.getFirst();
+            for (const WebGLRenderbuffer* rb = contexts[i]->mRenderbuffers.getFirst();
                  rb;
                  rb = rb->getNext())
             {
@@ -150,7 +150,7 @@ class WebGLMemoryTracker : public nsIMemoryReporter
         const ContextsArrayType & contexts = Contexts();
         int64_t result = 0;
         for(size_t i = 0; i < contexts.Length(); ++i) {
-            for (const WebGLShader *shader = contexts[i]->mShaders.getFirst();
+            for (const WebGLShader* shader = contexts[i]->mShaders.getFirst();
                  shader;
                  shader = shader->getNext())
             {
@@ -165,7 +165,6 @@ class WebGLMemoryTracker : public nsIMemoryReporter
     }
 };
 
-
 } // namespace mozilla
 
-#endif
+#endif // WEBGL_MEMORY_TRACKER_H_
diff --git a/dom/canvas/WebGLObjectModel.cpp b/dom/canvas/WebGLObjectModel.cpp
index eb640a3f56cf..7ad62aec46e1 100644
--- a/dom/canvas/WebGLObjectModel.cpp
+++ b/dom/canvas/WebGLObjectModel.cpp
@@ -4,16 +4,22 @@
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "WebGLObjectModel.h"
+
 #include "WebGLContext.h"
 
-using namespace mozilla;
+namespace mozilla {
 
-WebGLContextBoundObject::WebGLContextBoundObject(WebGLContext *context) {
-    mContext = context;
-    mContextGeneration = context->Generation();
+WebGLContextBoundObject::WebGLContextBoundObject(WebGLContext* webgl)
+    : mContext(webgl)
+    , mContextGeneration(webgl->Generation())
+{
 }
+
 bool
-WebGLContextBoundObject::IsCompatibleWithContext(WebGLContext *other) {
-    return mContext == other &&
-        mContextGeneration == other->Generation();
+WebGLContextBoundObject::IsCompatibleWithContext(WebGLContext* other)
+{
+    return (mContext == other &&
+            mContextGeneration == other->Generation());
 }
+
+} // namespace mozilla
diff --git a/dom/canvas/WebGLObjectModel.h b/dom/canvas/WebGLObjectModel.h
index 29b328b2eacb..361a3ee4a437 100644
--- a/dom/canvas/WebGLObjectModel.h
+++ b/dom/canvas/WebGLObjectModel.h
@@ -60,36 +60,37 @@ class WebGLContext;
  ***** 2. OpenGL deletion statuses *****
  *
  * In OpenGL, an object can go through 3 different deletion statuses during its
- * lifetime, which correspond to the 3 enum values for DeletionStatus in this class:
- *  - the Default status, which it has from its creation to when the
- *    suitable glDeleteXxx function is called on it;
- *  - the DeleteRequested status, which is has from when the suitable glDeleteXxx
- *    function is called on it to when it is no longer referenced by other OpenGL
- *    objects. For example, a texture that is attached to a non-current FBO
- *    will enter that status when glDeleteTexture is called on it. For objects
- *    with that status, GL_DELETE_STATUS queries return true, but glIsXxx
- *    functions still return true.
- *  - the Deleted status, which is the status of objects on which the
- *    suitable glDeleteXxx function has been called, and that are not referenced
- *    by other OpenGL objects.
+ * lifetime, which correspond to the 3 enum values for DeletionStatus in this
+ * class:
+ *  - the Default status, which it has from its creation to when the suitable
+ *    glDeleteXxx function is called on it;
+ *  - the DeleteRequested status, which is has from when the suitable
+ *    glDeleteXxx function is called on it to when it is no longer referenced by
+ *    other OpenGL objects. For example, a texture that is attached to a
+ *    non-current FBO will enter that status when glDeleteTexture is called on
+ *    it. For objects with that status, GL_DELETE_STATUS queries return true,
+ *    but glIsXxx functions still return true.
+ *  - the Deleted status, which is the status of objects on which the suitable
+ *    glDeleteXxx function has been called, and that are not referenced by other
+ *    OpenGL objects.
  *
  * This state is stored in the mDeletionStatus member of this class.
  *
  * When the GL refcount hits zero, if the status is DeleteRequested then we call
- * the Delete() method on the derived class and the status becomes Deleted. This is
- * what the MaybeDelete() function does.
+ * the Delete() method on the derived class and the status becomes Deleted. This
+ * is what the MaybeDelete() function does.
  *
- * The DeleteOnce() function implemented here is a helper to ensure that we don't
- * call Delete() twice on the same object. Since the derived class' destructor
- * needs to call DeleteOnce() which calls Delete(), we can't allow either to be
- * virtual. Strictly speaking, we could let them be virtual if the derived class
- * were final, but that would be impossible to enforce and would lead to strange
- * bugs if it were subclassed.
+ * The DeleteOnce() function implemented here is a helper to ensure that we
+ * don't call Delete() twice on the same object. Since the derived class's
+ * destructor needs to call DeleteOnce() which calls Delete(), we can't allow
+ * either to be virtual. Strictly speaking, we could let them be virtual if the
+ * derived class were final, but that would be impossible to enforce and would
+ * lead to strange bugs if it were subclassed.
  *
- * This WebGLRefCountedObject class takes the Derived type
- * as template parameter, as a means to allow DeleteOnce to call Delete()
- * on the Derived class, without either method being virtual. This is a common
- * C++ pattern known as the "curiously recursive template pattern (CRTP)".
+ * This WebGLRefCountedObject class takes the Derived type as template
+ * parameter, as a means to allow DeleteOnce to call Delete() on the Derived
+ * class, without either method being virtual. This is a common C++ pattern
+ * known as the "curiously recursive template pattern (CRTP)".
  */
 template
 class WebGLRefCountedObject
@@ -99,11 +100,14 @@ public:
 
     WebGLRefCountedObject()
       : mDeletionStatus(Default)
-    { }
+    {}
 
     ~WebGLRefCountedObject() {
-        MOZ_ASSERT(mWebGLRefCnt == 0, "destroying WebGL object still referenced by other WebGL objects");
-        MOZ_ASSERT(mDeletionStatus == Deleted, "Derived class destructor must call DeleteOnce()");
+        MOZ_ASSERT(mWebGLRefCnt == 0,
+                   "Destroying WebGL object still referenced by other WebGL"
+                   " objects.");
+        MOZ_ASSERT(mDeletionStatus == Deleted,
+                   "Derived class destructor must call DeleteOnce().");
     }
 
     // called by WebGLRefPtr
@@ -113,7 +117,8 @@ public:
 
     // called by WebGLRefPtr
     void WebGLRelease() {
-        MOZ_ASSERT(mWebGLRefCnt > 0, "releasing WebGL object with WebGL refcnt already zero");
+        MOZ_ASSERT(mWebGLRefCnt > 0,
+                   "Releasing WebGL object with WebGL refcnt already zero");
         --mWebGLRefCnt;
         MaybeDelete();
     }
@@ -154,12 +159,12 @@ protected:
     DeletionStatus mDeletionStatus;
 };
 
-/* This WebGLRefPtr class is meant to be used for references between WebGL objects.
- * For example, a WebGLProgram holds WebGLRefPtr's to the WebGLShader's attached
- * to it.
+/* This WebGLRefPtr class is meant to be used for references between WebGL
+ * objects. For example, a WebGLProgram holds WebGLRefPtr's to the WebGLShader's
+ * attached to it.
  *
- * Why the need for a separate refptr class? The only special thing that WebGLRefPtr
- * does is that it increments and decrements the WebGL refcount of
+ * Why the need for a separate refptr class? The only special thing that
+ * WebGLRefPtr does is that it increments and decrements the WebGL refcount of
  * WebGLRefCountedObject's, in addition to incrementing and decrementing the
  * usual XPCOM refcount.
  *
@@ -174,16 +179,16 @@ class WebGLRefPtr
 public:
     WebGLRefPtr()
         : mRawPtr(0)
-    { }
+    {}
 
-    WebGLRefPtr(const WebGLRefPtr& aSmartPtr)
-        : mRawPtr(aSmartPtr.mRawPtr)
+    WebGLRefPtr(const WebGLRefPtr& smartPtr)
+        : mRawPtr(smartPtr.mRawPtr)
     {
         AddRefOnPtr(mRawPtr);
     }
 
-    explicit WebGLRefPtr(T* aRawPtr)
-        : mRawPtr(aRawPtr)
+    explicit WebGLRefPtr(T* rawPtr)
+        : mRawPtr(rawPtr)
     {
         AddRefOnPtr(mRawPtr);
     }
@@ -252,7 +257,7 @@ private:
     }
 
 protected:
-    T *mRawPtr;
+    T* mRawPtr;
 };
 
 // This class is a mixin for objects that are tied to a specific
@@ -261,15 +266,15 @@ protected:
 class WebGLContextBoundObject
 {
 public:
-    explicit WebGLContextBoundObject(WebGLContext* context);
+    explicit WebGLContextBoundObject(WebGLContext* webgl);
 
-    bool IsCompatibleWithContext(WebGLContext *other);
+    bool IsCompatibleWithContext(WebGLContext* other);
 
-    WebGLContext *Context() const { return mContext; }
+    WebGLContext* Context() const { return mContext; }
 
 protected:
-    WebGLContext *mContext;
-    uint32_t mContextGeneration;
+    WebGLContext* const mContext;
+    const uint32_t mContextGeneration;
 };
 
 // this class is a mixin for GL objects that have dimensions
@@ -278,10 +283,14 @@ class WebGLRectangleObject
 {
 public:
     WebGLRectangleObject()
-        : mWidth(0), mHeight(0) { }
+        : mWidth(0)
+        , mHeight(0)
+    {}
 
     WebGLRectangleObject(GLsizei width, GLsizei height)
-        : mWidth(width), mHeight(height) { }
+        : mWidth(width)
+        , mHeight(height)
+    {}
 
     GLsizei Width() const { return mWidth; }
     void width(GLsizei value) { mWidth = value; }
@@ -294,7 +303,7 @@ public:
         mHeight = height;
     }
 
-    void setDimensions(WebGLRectangleObject *rect) {
+    void setDimensions(WebGLRectangleObject* rect) {
         if (rect) {
             mWidth = rect->Width();
             mHeight = rect->Height();
@@ -317,19 +326,19 @@ protected:
 
 template 
 inline void
-ImplCycleCollectionUnlink(mozilla::WebGLRefPtr& aField)
+ImplCycleCollectionUnlink(mozilla::WebGLRefPtr& field)
 {
-  aField = nullptr;
+    field = nullptr;
 }
 
 template 
 inline void
-ImplCycleCollectionTraverse(nsCycleCollectionTraversalCallback& aCallback,
-                            mozilla::WebGLRefPtr& aField,
-                            const char* aName,
-                            uint32_t aFlags = 0)
+ImplCycleCollectionTraverse(nsCycleCollectionTraversalCallback& callback,
+                            mozilla::WebGLRefPtr& field,
+                            const char* name,
+                            uint32_t flags = 0)
 {
-  CycleCollectionNoteChild(aCallback, aField.get(), aName, aFlags);
+    CycleCollectionNoteChild(callback, field.get(), name, flags);
 }
 
 #endif
diff --git a/dom/canvas/WebGLProgram.cpp b/dom/canvas/WebGLProgram.cpp
index e2cb43693c19..68ae164bae64 100644
--- a/dom/canvas/WebGLProgram.cpp
+++ b/dom/canvas/WebGLProgram.cpp
@@ -3,32 +3,38 @@
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
+#include "WebGLProgram.h"
+
+#include "GLContext.h"
+#include "mozilla/dom/WebGLRenderingContextBinding.h"
+#include "MurmurHash3.h"
 #include "WebGLContext.h"
 #include "WebGLShader.h"
-#include "WebGLProgram.h"
-#include "mozilla/dom/WebGLRenderingContextBinding.h"
-#include "GLContext.h"
 
-#include "MurmurHash3.h"
+namespace mozilla {
 
-using namespace mozilla;
-
-/** Takes an ASCII string like "foo[i]", turns it into "foo" and returns "[i]" in bracketPart
+/** Takes an ASCII string like "foo[i]", turns it into "foo" and returns "[i]"
+  * in bracketPart.
   *
-  * \param string input/output: the string to split, becomes the string without the bracket part
-  * \param bracketPart output: gets the bracket part.
+  * \param string input/output: The string to split, becomes the string without
+  *                             the bracket part.
+  * \param bracketPart output: Gets the bracket part.
   *
-  * Notice that if there are multiple brackets like "foo[i].bar[j]", only the last bracket is split.
+  * Notice that if there are multiple brackets like "foo[i].bar[j]", only the
+  * last bracket is split.
   */
-static bool SplitLastSquareBracket(nsACString& string, nsCString& bracketPart)
+static bool
+SplitLastSquareBracket(nsACString& string, nsCString& bracketPart)
 {
-    MOZ_ASSERT(bracketPart.IsEmpty(), "SplitLastSquareBracket must be called with empty bracketPart string");
+    MOZ_ASSERT(bracketPart.IsEmpty(),
+               "SplitLastSquareBracket must be called with empty bracketPart"
+               " string.");
 
     if (string.IsEmpty())
         return false;
 
-    char *string_start = string.BeginWriting();
-    char *s = string_start + string.Length() - 1;
+    char* string_start = string.BeginWriting();
+    char* s = string_start + string.Length() - 1;
 
     if (*s != ']')
         return false;
@@ -47,12 +53,12 @@ static bool SplitLastSquareBracket(nsACString& string, nsCString& bracketPart)
 }
 
 JSObject*
-WebGLProgram::WrapObject(JSContext *cx) {
+WebGLProgram::WrapObject(JSContext* cx) {
     return dom::WebGLProgramBinding::Wrap(cx, this);
 }
 
-WebGLProgram::WebGLProgram(WebGLContext *context)
-    : WebGLContextBoundObject(context)
+WebGLProgram::WebGLProgram(WebGLContext* webgl)
+    : WebGLContextBoundObject(webgl)
     , mLinkStatus(false)
     , mGeneration(0)
     , mIdentifierMap(new CStringMap)
@@ -66,7 +72,8 @@ WebGLProgram::WebGLProgram(WebGLContext *context)
 }
 
 void
-WebGLProgram::Delete() {
+WebGLProgram::Delete()
+{
     DetachShaders();
     mContext->MakeContextCurrent();
     mContext->gl->fDeleteProgram(mGLName);
@@ -74,9 +81,11 @@ WebGLProgram::Delete() {
 }
 
 bool
-WebGLProgram::AttachShader(WebGLShader *shader) {
+WebGLProgram::AttachShader(WebGLShader* shader)
+{
     if (ContainsShader(shader))
         return false;
+
     mAttachedShaders.AppendElement(shader);
 
     mContext->MakeContextCurrent();
@@ -86,7 +95,8 @@ WebGLProgram::AttachShader(WebGLShader *shader) {
 }
 
 bool
-WebGLProgram::DetachShader(WebGLShader *shader) {
+WebGLProgram::DetachShader(WebGLShader* shader)
+{
     if (!mAttachedShaders.RemoveElement(shader))
         return false;
 
@@ -97,32 +107,37 @@ WebGLProgram::DetachShader(WebGLShader *shader) {
 }
 
 bool
-WebGLProgram::HasAttachedShaderOfType(GLenum shaderType) {
+WebGLProgram::HasAttachedShaderOfType(GLenum shaderType)
+{
     for (uint32_t i = 0; i < mAttachedShaders.Length(); ++i) {
-        if (mAttachedShaders[i] && mAttachedShaders[i]->ShaderType() == shaderType) {
+        if (mAttachedShaders[i] && mAttachedShaders[i]->ShaderType() == shaderType)
             return true;
-        }
     }
+
     return false;
 }
 
 bool
-WebGLProgram::HasBadShaderAttached() {
+WebGLProgram::HasBadShaderAttached()
+{
     for (uint32_t i = 0; i < mAttachedShaders.Length(); ++i) {
-        if (mAttachedShaders[i] && !mAttachedShaders[i]->CompileStatus()) {
+        if (mAttachedShaders[i] && !mAttachedShaders[i]->CompileStatus())
             return true;
-        }
     }
+
     return false;
 }
 
 size_t
-WebGLProgram::UpperBoundNumSamplerUniforms() {
+WebGLProgram::UpperBoundNumSamplerUniforms()
+{
     size_t numSamplerUniforms = 0;
+
     for (size_t i = 0; i < mAttachedShaders.Length(); ++i) {
-        const WebGLShader *shader = mAttachedShaders[i];
+        const WebGLShader* shader = mAttachedShaders[i];
         if (!shader)
             continue;
+
         for (size_t j = 0; j < shader->mUniformInfos.Length(); ++j) {
             WebGLUniformInfo u = shader->mUniformInfos[j];
             if (u.type == LOCAL_GL_SAMPLER_2D ||
@@ -132,11 +147,14 @@ WebGLProgram::UpperBoundNumSamplerUniforms() {
             }
         }
     }
+
     return numSamplerUniforms;
 }
 
 void
-WebGLProgram::MapIdentifier(const nsACString& name, nsCString *mappedName) {
+WebGLProgram::MapIdentifier(const nsACString& name,
+                            nsCString* const out_mappedName)
+{
     MOZ_ASSERT(mIdentifierMap);
 
     nsCString mutableName(name);
@@ -145,30 +163,36 @@ WebGLProgram::MapIdentifier(const nsACString& name, nsCString *mappedName) {
     if (hadBracketPart)
         mutableName.AppendLiteral("[0]");
 
-    if (mIdentifierMap->Get(mutableName, mappedName)) {
+    if (mIdentifierMap->Get(mutableName, out_mappedName)) {
         if (hadBracketPart) {
             nsCString mappedBracketPart;
-            bool mappedHadBracketPart = SplitLastSquareBracket(*mappedName, mappedBracketPart);
+            bool mappedHadBracketPart = SplitLastSquareBracket(*out_mappedName,
+                                                               mappedBracketPart);
             if (mappedHadBracketPart)
-                mappedName->Append(bracketPart);
+                out_mappedName->Append(bracketPart);
         }
         return;
     }
 
-    // not found? We might be in the situation we have a uniform array name and the GL's glGetActiveUniform
-    // returned its name without [0], as is allowed by desktop GL but not in ES. Let's then try with [0].
+    // Not found? We might be in the situation we have a uniform array name and
+    // the GL's glGetActiveUniform returned its name without [0], as is allowed
+    // by desktop GL but not in ES. Let's then try with [0].
     mutableName.AppendLiteral("[0]");
-    if (mIdentifierMap->Get(mutableName, mappedName))
+    if (mIdentifierMap->Get(mutableName, out_mappedName))
         return;
 
-    // not found? return name unchanged. This case happens e.g. on bad user input, or when
-    // we're not using identifier mapping, or if we didn't store an identifier in the map because
-    // e.g. its mapping is trivial (as happens for short identifiers)
-    mappedName->Assign(name);
+    /* Not found? Return name unchanged. This case happens e.g. on bad user
+     * input, or when we're not using identifier mapping, or if we didn't store
+     * an identifier in the map because e.g. its mapping is trivial. (as happens
+     * for short identifiers)
+     */
+    out_mappedName->Assign(name);
 }
 
 void
-WebGLProgram::ReverseMapIdentifier(const nsACString& name, nsCString *reverseMappedName) {
+WebGLProgram::ReverseMapIdentifier(const nsACString& name,
+                                   nsCString* const out_reverseMappedName)
+{
     MOZ_ASSERT(mIdentifierReverseMap);
 
     nsCString mutableName(name);
@@ -177,42 +201,48 @@ WebGLProgram::ReverseMapIdentifier(const nsACString& name, nsCString *reverseMap
     if (hadBracketPart)
         mutableName.AppendLiteral("[0]");
 
-    if (mIdentifierReverseMap->Get(mutableName, reverseMappedName)) {
+    if (mIdentifierReverseMap->Get(mutableName, out_reverseMappedName)) {
         if (hadBracketPart) {
             nsCString reverseMappedBracketPart;
-            bool reverseMappedHadBracketPart = SplitLastSquareBracket(*reverseMappedName, reverseMappedBracketPart);
+            bool reverseMappedHadBracketPart = SplitLastSquareBracket(*out_reverseMappedName,
+                                                                      reverseMappedBracketPart);
             if (reverseMappedHadBracketPart)
-                reverseMappedName->Append(bracketPart);
+                out_reverseMappedName->Append(bracketPart);
         }
         return;
     }
 
-    // not found? We might be in the situation we have a uniform array name and the GL's glGetActiveUniform
-    // returned its name without [0], as is allowed by desktop GL but not in ES. Let's then try with [0].
+    // Not found? We might be in the situation we have a uniform array name and
+    // the GL's glGetActiveUniform returned its name without [0], as is allowed
+    // by desktop GL but not in ES. Let's then try with [0].
     mutableName.AppendLiteral("[0]");
-    if (mIdentifierReverseMap->Get(mutableName, reverseMappedName))
+    if (mIdentifierReverseMap->Get(mutableName, out_reverseMappedName))
         return;
 
-    // not found? return name unchanged. This case happens e.g. on bad user input, or when
-    // we're not using identifier mapping, or if we didn't store an identifier in the map because
-    // e.g. its mapping is trivial (as happens for short identifiers)
-    reverseMappedName->Assign(name);
+    /* Not found? Return name unchanged. This case happens e.g. on bad user
+     * input, or when we're not using identifier mapping, or if we didn't store
+     * an identifier in the map because e.g. its mapping is trivial. (as happens
+     * for short identifiers)
+     */
+    out_reverseMappedName->Assign(name);
 }
 
 WebGLUniformInfo
-WebGLProgram::GetUniformInfoForMappedIdentifier(const nsACString& name) {
+WebGLProgram::GetUniformInfoForMappedIdentifier(const nsACString& name)
+{
     MOZ_ASSERT(mUniformInfoMap);
 
     nsCString mutableName(name);
     nsCString bracketPart;
     bool hadBracketPart = SplitLastSquareBracket(mutableName, bracketPart);
-    // if there is a bracket, we're either an array or an entry in an array.
+    // If there is a bracket, we're either an array or an entry in an array.
     if (hadBracketPart)
         mutableName.AppendLiteral("[0]");
 
     WebGLUniformInfo info;
     mUniformInfoMap->Get(mutableName, &info);
-    // we don't check if that Get failed, as if it did, it left info with default values
+    // We don't check if that Get failed, as if it did, it left info with
+    // default values.
 
     return info;
 }
@@ -221,14 +251,17 @@ bool
 WebGLProgram::UpdateInfo()
 {
     mAttribMaxNameLength = 0;
-    for (size_t i = 0; i < mAttachedShaders.Length(); i++)
-        mAttribMaxNameLength = std::max(mAttribMaxNameLength, mAttachedShaders[i]->mAttribMaxNameLength);
+    for (size_t i = 0; i < mAttachedShaders.Length(); i++) {
+        mAttribMaxNameLength = std::max(mAttribMaxNameLength,
+                                        mAttachedShaders[i]->mAttribMaxNameLength);
+    }
 
     GLint attribCount;
     mContext->gl->fGetProgramiv(mGLName, LOCAL_GL_ACTIVE_ATTRIBUTES, &attribCount);
 
     if (!mAttribsInUse.SetLength(mContext->mGLMaxVertexAttribs)) {
-        mContext->ErrorOutOfMemory("updateInfo: out of memory to allocate %d attribs", mContext->mGLMaxVertexAttribs);
+        mContext->ErrorOutOfMemory("updateInfo: Out of memory to allocate %d"
+                                   " attribs.", mContext->mGLMaxVertexAttribs);
         return false;
     }
 
@@ -241,14 +274,17 @@ WebGLProgram::UpdateInfo()
         GLint attrnamelen;
         GLint attrsize;
         GLenum attrtype;
-        mContext->gl->fGetActiveAttrib(mGLName, i, mAttribMaxNameLength, &attrnamelen, &attrsize, &attrtype, nameBuf);
+        mContext->gl->fGetActiveAttrib(mGLName, i, mAttribMaxNameLength,
+                                       &attrnamelen, &attrsize, &attrtype,
+                                       nameBuf);
         if (attrnamelen > 0) {
             GLint loc = mContext->gl->fGetAttribLocation(mGLName, nameBuf);
-            MOZ_ASSERT(loc >= 0, "major oops in managing the attributes of a WebGL program");
+            MOZ_ASSERT(loc >= 0, "Major oops in managing the attributes of a"
+                                 " WebGL program.");
             if (loc < mContext->mGLMaxVertexAttribs) {
                 mAttribsInUse[loc] = true;
             } else {
-                mContext->GenerateWarning("program exceeds MAX_VERTEX_ATTRIBS");
+                mContext->GenerateWarning("Program exceeds MAX_VERTEX_ATTRIBS.");
                 return false;
             }
         }
@@ -262,16 +298,22 @@ WebGLProgram::UpdateInfo()
         // Loop through ATTRIBUTES
         for (size_t j = 0; j < mAttachedShaders[i]->mAttributes.Length(); j++) {
             const WebGLMappedIdentifier& attrib = mAttachedShaders[i]->mAttributes[j];
-            mIdentifierMap->Put(attrib.original, attrib.mapped); // FORWARD MAPPING
-            mIdentifierReverseMap->Put(attrib.mapped, attrib.original); // REVERSE MAPPING
+
+            // FORWARD MAPPING
+            mIdentifierMap->Put(attrib.original, attrib.mapped);
+            // REVERSE MAPPING
+            mIdentifierReverseMap->Put(attrib.mapped, attrib.original);
         }
 
         // Loop through UNIFORMS
         for (size_t j = 0; j < mAttachedShaders[i]->mUniforms.Length(); j++) {
             // Add the uniforms name mapping to mIdentifier[Reverse]Map
             const WebGLMappedIdentifier& uniform = mAttachedShaders[i]->mUniforms[j];
-            mIdentifierMap->Put(uniform.original, uniform.mapped); // FOWARD MAPPING
-            mIdentifierReverseMap->Put(uniform.mapped, uniform.original); // REVERSE MAPPING
+
+            // FOWARD MAPPING
+            mIdentifierMap->Put(uniform.original, uniform.mapped);
+            // REVERSE MAPPING
+            mIdentifierReverseMap->Put(uniform.mapped, uniform.original);
 
             // Add uniform info to mUniformInfoMap
             const WebGLUniformInfo& info = mAttachedShaders[i]->mUniformInfos[j];
@@ -301,8 +343,8 @@ WebGLProgram::UpdateInfo()
     return true;
 }
 
-/* static */ uint64_t
-WebGLProgram::IdentifierHashFunction(const char *ident, size_t size)
+/*static*/ uint64_t
+WebGLProgram::IdentifierHashFunction(const char* ident, size_t size)
 {
     uint64_t outhash[2];
     // NB: we use the x86 function everywhere, even though it's suboptimal perf
@@ -311,16 +353,20 @@ WebGLProgram::IdentifierHashFunction(const char *ident, size_t size)
     return outhash[0];
 }
 
-/* static */ void
-WebGLProgram::HashMapIdentifier(const nsACString& name, nsCString *hashedName)
+/*static*/ void
+WebGLProgram::HashMapIdentifier(const nsACString& name,
+                                nsCString* const out_hashedName)
 {
     uint64_t hash = IdentifierHashFunction(name.BeginReading(), name.Length());
-    hashedName->Truncate();
-    // This MUST MATCH angle/src/compiler/translator/HashNames.h HASHED_NAME_PREFIX
-    hashedName->AppendPrintf("webgl_%llx", hash);
+    out_hashedName->Truncate();
+    // This MUST MATCH HASHED_NAME_PREFIX from
+    // angle/src/compiler/translator/HashNames.h .
+    out_hashedName->AppendPrintf("webgl_%llx", hash);
 }
 
 NS_IMPL_CYCLE_COLLECTION_WRAPPERCACHE(WebGLProgram, mAttachedShaders)
 
 NS_IMPL_CYCLE_COLLECTION_ROOT_NATIVE(WebGLProgram, AddRef)
 NS_IMPL_CYCLE_COLLECTION_UNROOT_NATIVE(WebGLProgram, Release)
+
+} // namespace mozilla
diff --git a/dom/canvas/WebGLProgram.h b/dom/canvas/WebGLProgram.h
index 0a11b5938e2f..f72ba895f207 100644
--- a/dom/canvas/WebGLProgram.h
+++ b/dom/canvas/WebGLProgram.h
@@ -3,16 +3,14 @@
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
-#ifndef WEBGLPROGRAM_H_
-#define WEBGLPROGRAM_H_
-
-#include "WebGLObjectModel.h"
+#ifndef WEBGL_PROGRAM_H_
+#define WEBGL_PROGRAM_H_
 
 #include 
-
 #include "mozilla/CheckedInt.h"
 #include "mozilla/LinkedList.h"
 #include "nsWrapperCache.h"
+#include "WebGLObjectModel.h"
 #include "WebGLShader.h"
 #include "WebGLUniformInfo.h"
 
@@ -22,7 +20,8 @@ class WebGLShader;
 struct WebGLUniformInfo;
 
 typedef nsDataHashtable CStringMap;
-typedef nsDataHashtable CStringToUniformInfoMap;
+typedef nsDataHashtable CStringToUniformInfoMap;
 
 class WebGLProgram MOZ_FINAL
     : public nsWrapperCache
@@ -31,7 +30,7 @@ class WebGLProgram MOZ_FINAL
     , public WebGLContextBoundObject
 {
 public:
-    explicit WebGLProgram(WebGLContext* aContext);
+    explicit WebGLProgram(WebGLContext* webgl);
 
     void Delete();
 
@@ -40,69 +39,71 @@ public:
     }
 
     GLuint GLName() { return mGLName; }
-    const nsTArray >& AttachedShaders() const { return mAttachedShaders; }
+    const nsTArray >& AttachedShaders() const {
+        return mAttachedShaders;
+    }
     bool LinkStatus() { return mLinkStatus; }
     uint32_t Generation() const { return mGeneration.value(); }
     void SetLinkStatus(bool val) { mLinkStatus = val; }
 
-    bool ContainsShader(WebGLShader *shader) {
+    bool ContainsShader(WebGLShader* shader) {
         return mAttachedShaders.Contains(shader);
     }
 
     // return true if the shader wasn't already attached
-    bool AttachShader(WebGLShader *shader);
+    bool AttachShader(WebGLShader* shader);
 
     // return true if the shader was found and removed
-    bool DetachShader(WebGLShader *shader);
+    bool DetachShader(WebGLShader* shader);
 
     bool HasAttachedShaderOfType(GLenum shaderType);
 
     bool HasBothShaderTypesAttached() {
-        return
-            HasAttachedShaderOfType(LOCAL_GL_VERTEX_SHADER) &&
-            HasAttachedShaderOfType(LOCAL_GL_FRAGMENT_SHADER);
+        return HasAttachedShaderOfType(LOCAL_GL_VERTEX_SHADER) &&
+               HasAttachedShaderOfType(LOCAL_GL_FRAGMENT_SHADER);
     }
 
     bool HasBadShaderAttached();
 
     size_t UpperBoundNumSamplerUniforms();
 
-    bool NextGeneration()
-    {
+    bool NextGeneration() {
         if (!(mGeneration + 1).isValid())
             return false; // must exit without changing mGeneration
+
         ++mGeneration;
         return true;
     }
 
-    /* Called only after LinkProgram */
+    // Called only after LinkProgram
     bool UpdateInfo();
 
-    /* Getters for cached program info */
-    bool IsAttribInUse(unsigned i) const { return mAttribsInUse[i]; }
+    // Getters for cached program info
+    bool IsAttribInUse(uint32_t i) const { return mAttribsInUse[i]; }
 
-    /* Maps identifier |name| to the mapped identifier |*mappedName|
-     * Both are ASCII strings.
-     */
-    void MapIdentifier(const nsACString& name, nsCString *mappedName);
+    // Maps identifier |name| to the mapped identifier |*mappedName|
+    // Both are ASCII strings.
+    void MapIdentifier(const nsACString& name, nsCString* out_mappedName);
 
-    /* Un-maps mapped identifier |name| to the original identifier |*reverseMappedName|
-     * Both are ASCII strings.
-     */
-    void ReverseMapIdentifier(const nsACString& name, nsCString *reverseMappedName);
+    // Un-maps mapped identifier |name| to the original identifier
+    // |*reverseMappedName|.
+    // Both are ASCII strings.
+    void ReverseMapIdentifier(const nsACString& name,
+                              nsCString* out_reverseMappedName);
 
     /* Returns the uniform array size (or 1 if the uniform is not an array) of
      * the uniform with given mapped identifier.
      *
-     * Note: the input string |name| is the mapped identifier, not the original identifier.
+     * Note: The input string |name| is the mapped identifier, not the original
+     * identifier.
      */
     WebGLUniformInfo GetUniformInfoForMappedIdentifier(const nsACString& name);
 
-    WebGLContext *GetParentObject() const {
+    WebGLContext* GetParentObject() const {
         return Context();
     }
 
-    virtual JSObject* WrapObject(JSContext *cx) MOZ_OVERRIDE;
+    virtual JSObject* WrapObject(JSContext* cx) MOZ_OVERRIDE;
 
     NS_INLINE_DECL_CYCLE_COLLECTING_NATIVE_REFCOUNTING(WebGLProgram)
     NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_NATIVE_CLASS(WebGLProgram)
@@ -110,8 +111,9 @@ public:
     // public post-link data
     std::map mActiveAttribMap;
 
-    static uint64_t IdentifierHashFunction(const char *ident, size_t size);
-    static void HashMapIdentifier(const nsACString& name, nsCString *hashedName);
+    static uint64_t IdentifierHashFunction(const char* ident, size_t size);
+    static void HashMapIdentifier(const nsACString& name,
+                                  nsCString* const out_hashedName);
 
 protected:
     ~WebGLProgram() {
@@ -133,4 +135,4 @@ protected:
 
 } // namespace mozilla
 
-#endif
+#endif // WEBGL_PROGRAM_H_
diff --git a/dom/canvas/WebGLQuery.cpp b/dom/canvas/WebGLQuery.cpp
index 39868eaf43c0..74e3e0e6a757 100644
--- a/dom/canvas/WebGLQuery.cpp
+++ b/dom/canvas/WebGLQuery.cpp
@@ -6,11 +6,11 @@
 #include "WebGLQuery.h"
 
 #include "GLContext.h"
-#include "WebGLContext.h"
 #include "mozilla/dom/WebGL2RenderingContextBinding.h"
 #include "nsContentUtils.h"
+#include "WebGLContext.h"
 
-using namespace mozilla;
+namespace mozilla {
 
 JSObject*
 WebGLQuery::WrapObject(JSContext* cx)
@@ -18,8 +18,8 @@ WebGLQuery::WrapObject(JSContext* cx)
     return dom::WebGLQueryBinding::Wrap(cx, this);
 }
 
-WebGLQuery::WebGLQuery(WebGLContext* context)
-    : WebGLContextBoundObject(context)
+WebGLQuery::WebGLQuery(WebGLContext* webgl)
+    : WebGLContextBoundObject(webgl)
     , mGLName(0)
     , mType(0)
 {
@@ -43,12 +43,12 @@ WebGLQuery::IsActive() const
     WebGLRefPtr* targetSlot = mContext->GetQueryTargetSlot(mType);
 
     MOZ_ASSERT(targetSlot, "unknown query object's type");
-
     return targetSlot && *targetSlot == this;
 }
 
-
 NS_IMPL_CYCLE_COLLECTION_WRAPPERCACHE_0(WebGLQuery)
 
 NS_IMPL_CYCLE_COLLECTION_ROOT_NATIVE(WebGLQuery, AddRef)
 NS_IMPL_CYCLE_COLLECTION_UNROOT_NATIVE(WebGLQuery, Release)
+
+} // namespace mozilla
diff --git a/dom/canvas/WebGLQuery.h b/dom/canvas/WebGLQuery.h
index d8c98e84d502..c11adf4fbf39 100644
--- a/dom/canvas/WebGLQuery.h
+++ b/dom/canvas/WebGLQuery.h
@@ -3,14 +3,12 @@
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
-#ifndef WEBGLQUERY_H_
-#define WEBGLQUERY_H_
-
-#include "WebGLObjectModel.h"
-
-#include "nsWrapperCache.h"
+#ifndef WEBGL_QUERY_H_
+#define WEBGL_QUERY_H_
 
 #include "mozilla/LinkedList.h"
+#include "nsWrapperCache.h"
+#include "WebGLObjectModel.h"
 
 namespace mozilla {
 
@@ -20,62 +18,41 @@ class WebGLQuery MOZ_FINAL
     , public LinkedListElement
     , public WebGLContextBoundObject
 {
-// -----------------------------------------------------------------------------
-// PUBLIC
 public:
-
-    // -------------------------------------------------------------------------
-    // CONSTRUCTOR
-
-    explicit WebGLQuery(WebGLContext* aContext);
-
-    // -------------------------------------------------------------------------
-    // MEMBER FUNCTIONS
+    explicit WebGLQuery(WebGLContext* webgl);
 
     bool IsActive() const;
 
-    bool HasEverBeenActive()
-    {
+    bool HasEverBeenActive() {
         return mType != 0;
     }
 
-
-    // -------------------------------------------------------------------------
-    // IMPLEMENT WebGLRefCountedObject and WebGLContextBoundObject
-
+    // WebGLRefCountedObject
     void Delete();
 
-    WebGLContext* GetParentObject() const
-    {
+    // nsWrapperCache
+    WebGLContext* GetParentObject() const {
         return Context();
     }
 
-
-    // -------------------------------------------------------------------------
-    // IMPLEMENT NS
-    virtual JSObject* WrapObject(JSContext *cx) MOZ_OVERRIDE;
+    // NS
+    virtual JSObject* WrapObject(JSContext* cx) MOZ_OVERRIDE;
 
     NS_INLINE_DECL_CYCLE_COLLECTING_NATIVE_REFCOUNTING(WebGLQuery)
     NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_NATIVE_CLASS(WebGLQuery)
 
 
-// -----------------------------------------------------------------------------
-// PRIVATE
 private:
     ~WebGLQuery() {
         DeleteOnce();
     };
 
-    // -------------------------------------------------------------------------
-    // MEMBERS
     GLuint mGLName;
     GLenum mType;
 
-    // -------------------------------------------------------------------------
-    // FRIENDSHIPS
     friend class WebGL2Context;
 };
 
 } // namespace mozilla
 
-#endif
+#endif // WEBGL_QUERY_H_
diff --git a/dom/canvas/WebGLRenderbuffer.cpp b/dom/canvas/WebGLRenderbuffer.cpp
index d85f62da3bf4..c94e515bca86 100644
--- a/dom/canvas/WebGLRenderbuffer.cpp
+++ b/dom/canvas/WebGLRenderbuffer.cpp
@@ -3,18 +3,19 @@
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
-#include "WebGLContext.h"
 #include "WebGLRenderbuffer.h"
-#include "WebGLTexture.h"
-#include "mozilla/dom/WebGLRenderingContextBinding.h"
-#include "GLContext.h"
-#include "ScopedGLHelpers.h"
 
-using namespace mozilla;
-using namespace mozilla::gl;
+#include "GLContext.h"
+#include "mozilla/dom/WebGLRenderingContextBinding.h"
+#include "ScopedGLHelpers.h"
+#include "WebGLContext.h"
+#include "WebGLTexture.h"
+
+namespace mozilla {
 
 static GLenum
-DepthStencilDepthFormat(GLContext* gl) {
+DepthStencilDepthFormat(gl::GLContext* gl)
+{
     // We might not be able to get 24-bit, so let's pretend!
     if (gl->IsGLES() && !gl->IsExtensionSupported(gl::GLContext::OES_depth24))
         return LOCAL_GL_DEPTH_COMPONENT16;
@@ -23,13 +24,15 @@ DepthStencilDepthFormat(GLContext* gl) {
 }
 
 static bool
-SupportsDepthStencil(GLContext* gl) {
-    return gl->IsExtensionSupported(GLContext::EXT_packed_depth_stencil) ||
-           gl->IsExtensionSupported(GLContext::OES_packed_depth_stencil);
+SupportsDepthStencil(gl::GLContext* gl)
+{
+    return gl->IsExtensionSupported(gl::GLContext::EXT_packed_depth_stencil) ||
+           gl->IsExtensionSupported(gl::GLContext::OES_packed_depth_stencil);
 }
 
 static bool
-NeedsDepthStencilEmu(GLContext* gl, GLenum internalFormat) {
+NeedsDepthStencilEmu(gl::GLContext* gl, GLenum internalFormat)
+{
     MOZ_ASSERT(internalFormat != LOCAL_GL_DEPTH_STENCIL);
     if (internalFormat != LOCAL_GL_DEPTH24_STENCIL8)
         return false;
@@ -38,13 +41,14 @@ NeedsDepthStencilEmu(GLContext* gl, GLenum internalFormat) {
 }
 
 JSObject*
-WebGLRenderbuffer::WrapObject(JSContext *cx) {
+WebGLRenderbuffer::WrapObject(JSContext* cx)
+{
     return dom::WebGLRenderbufferBinding::Wrap(cx, this);
 }
 
-WebGLRenderbuffer::WebGLRenderbuffer(WebGLContext* context)
+WebGLRenderbuffer::WebGLRenderbuffer(WebGLContext* webgl)
     : WebGLBindable()
-    , WebGLContextBoundObject(context)
+    , WebGLContextBoundObject(webgl)
     , mPrimaryRB(0)
     , mSecondaryRB(0)
     , mInternalFormat(0)
@@ -61,7 +65,8 @@ WebGLRenderbuffer::WebGLRenderbuffer(WebGLContext* context)
 }
 
 void
-WebGLRenderbuffer::Delete() {
+WebGLRenderbuffer::Delete()
+{
     mContext->MakeContextCurrent();
 
     mContext->gl->fDeleteRenderbuffers(1, &mPrimaryRB);
@@ -72,14 +77,14 @@ WebGLRenderbuffer::Delete() {
 }
 
 int64_t
-WebGLRenderbuffer::MemoryUsage() const {
+WebGLRenderbuffer::MemoryUsage() const
+{
     int64_t pixels = int64_t(Width()) * int64_t(Height());
 
     GLenum primaryFormat = InternalFormatForGL();
     // If there is no defined format, we're not taking up any memory
-    if (!primaryFormat) {
+    if (!primaryFormat)
         return 0;
-    }
 
     int64_t secondarySize = 0;
     if (mSecondaryRB) {
@@ -133,7 +138,8 @@ WebGLRenderbuffer::MemoryUsage() const {
 }
 
 void
-WebGLRenderbuffer::BindRenderbuffer() const {
+WebGLRenderbuffer::BindRenderbuffer() const
+{
     /* Do this explicitly here, since the meaning changes for depth-stencil emu.
      * Under normal circumstances, there's only one RB: `mPrimaryRB`.
      * `mSecondaryRB` is used when we have to pretend that the renderbuffer is
@@ -151,8 +157,10 @@ WebGLRenderbuffer::BindRenderbuffer() const {
 }
 
 void
-WebGLRenderbuffer::RenderbufferStorage(GLenum internalFormat, GLsizei width, GLsizei height) const {
-    GLContext* gl = mContext->gl;
+WebGLRenderbuffer::RenderbufferStorage(GLenum internalFormat, GLsizei width,
+                                       GLsizei height) const
+{
+    gl::GLContext* gl = mContext->gl;
 
     GLenum primaryFormat = internalFormat;
     GLenum secondaryFormat = 0;
@@ -172,7 +180,7 @@ WebGLRenderbuffer::RenderbufferStorage(GLenum internalFormat, GLsizei width, GLs
     // handle the case where we attach a non-depth-stencil RB to a
     // depth-stencil attachment point, or attach this depth-stencil RB to a
     // non-depth-stencil attachment point.
-    ScopedBindRenderbuffer autoRB(gl, mSecondaryRB);
+    gl::ScopedBindRenderbuffer autoRB(gl, mSecondaryRB);
     if (secondaryFormat) {
         gl->fRenderbufferStorage(LOCAL_GL_RENDERBUFFER, secondaryFormat, width, height);
     } else {
@@ -181,63 +189,73 @@ WebGLRenderbuffer::RenderbufferStorage(GLenum internalFormat, GLsizei width, GLs
 }
 
 void
-WebGLRenderbuffer::FramebufferRenderbuffer(FBAttachment attachment) const {
-    GLContext* gl = mContext->gl;
+WebGLRenderbuffer::FramebufferRenderbuffer(FBAttachment attachment) const
+{
+    gl::GLContext* gl = mContext->gl;
     if (attachment != LOCAL_GL_DEPTH_STENCIL_ATTACHMENT) {
-        gl->fFramebufferRenderbuffer(LOCAL_GL_FRAMEBUFFER, attachment.get(), LOCAL_GL_RENDERBUFFER, mPrimaryRB);
+        gl->fFramebufferRenderbuffer(LOCAL_GL_FRAMEBUFFER, attachment.get(),
+                                     LOCAL_GL_RENDERBUFFER, mPrimaryRB);
         return;
     }
 
     GLuint stencilRB = mPrimaryRB;
     if (NeedsDepthStencilEmu(mContext->gl, InternalFormatForGL())) {
-        printf_stderr("DEV-ONLY: Using secondary buffer to emulate DepthStencil.\n");
         MOZ_ASSERT(mSecondaryRB);
         stencilRB = mSecondaryRB;
     }
-    gl->fFramebufferRenderbuffer(LOCAL_GL_FRAMEBUFFER, LOCAL_GL_DEPTH_ATTACHMENT,   LOCAL_GL_RENDERBUFFER, mPrimaryRB);
-    gl->fFramebufferRenderbuffer(LOCAL_GL_FRAMEBUFFER, LOCAL_GL_STENCIL_ATTACHMENT, LOCAL_GL_RENDERBUFFER, stencilRB);
+    gl->fFramebufferRenderbuffer(LOCAL_GL_FRAMEBUFFER,
+                                 LOCAL_GL_DEPTH_ATTACHMENT,
+                                 LOCAL_GL_RENDERBUFFER, mPrimaryRB);
+    gl->fFramebufferRenderbuffer(LOCAL_GL_FRAMEBUFFER,
+                                 LOCAL_GL_STENCIL_ATTACHMENT,
+                                 LOCAL_GL_RENDERBUFFER, stencilRB);
 }
 
 GLint
-WebGLRenderbuffer::GetRenderbufferParameter(RBTarget target, RBParam pname) const {
-    GLContext* gl = mContext->gl;
+WebGLRenderbuffer::GetRenderbufferParameter(RBTarget target,
+                                            RBParam pname) const
+{
+    gl::GLContext* gl = mContext->gl;
 
     switch (pname.get()) {
-        case LOCAL_GL_RENDERBUFFER_STENCIL_SIZE: {
-            if (NeedsDepthStencilEmu(mContext->gl, InternalFormatForGL())) {
-                if (gl->WorkAroundDriverBugs() &&
-                    gl->Renderer() == GLRenderer::Tegra)
-                {
-                    return 8;
-                }
-
-                ScopedBindRenderbuffer autoRB(gl, mSecondaryRB);
-
-                GLint i = 0;
-                gl->fGetRenderbufferParameteriv(target.get(), pname.get(), &i);
-                return i;
+    case LOCAL_GL_RENDERBUFFER_STENCIL_SIZE:
+        if (NeedsDepthStencilEmu(mContext->gl, InternalFormatForGL())) {
+            if (gl->WorkAroundDriverBugs() &&
+                gl->Renderer() == gl::GLRenderer::Tegra)
+            {
+                return 8;
             }
-            // Fall through otherwise.
+
+            gl::ScopedBindRenderbuffer autoRB(gl, mSecondaryRB);
+
+            GLint i = 0;
+            gl->fGetRenderbufferParameteriv(target.get(), pname.get(), &i);
+            return i;
         }
-        case LOCAL_GL_RENDERBUFFER_WIDTH:
-        case LOCAL_GL_RENDERBUFFER_HEIGHT:
-        case LOCAL_GL_RENDERBUFFER_RED_SIZE:
-        case LOCAL_GL_RENDERBUFFER_GREEN_SIZE:
-        case LOCAL_GL_RENDERBUFFER_BLUE_SIZE:
-        case LOCAL_GL_RENDERBUFFER_ALPHA_SIZE:
-        case LOCAL_GL_RENDERBUFFER_DEPTH_SIZE: {
+        // Fall through otherwise.
+
+    case LOCAL_GL_RENDERBUFFER_WIDTH:
+    case LOCAL_GL_RENDERBUFFER_HEIGHT:
+    case LOCAL_GL_RENDERBUFFER_RED_SIZE:
+    case LOCAL_GL_RENDERBUFFER_GREEN_SIZE:
+    case LOCAL_GL_RENDERBUFFER_BLUE_SIZE:
+    case LOCAL_GL_RENDERBUFFER_ALPHA_SIZE:
+    case LOCAL_GL_RENDERBUFFER_DEPTH_SIZE:
+        {
             GLint i = 0;
             gl->fGetRenderbufferParameteriv(target.get(), pname.get(), &i);
             return i;
         }
     }
 
-    MOZ_ASSERT(false, "This function should only be called with valid `pname`.");
+    MOZ_ASSERT(false,
+               "This function should only be called with valid `pname`.");
     return 0;
 }
 
-
 NS_IMPL_CYCLE_COLLECTION_WRAPPERCACHE_0(WebGLRenderbuffer)
 
 NS_IMPL_CYCLE_COLLECTION_ROOT_NATIVE(WebGLRenderbuffer, AddRef)
 NS_IMPL_CYCLE_COLLECTION_UNROOT_NATIVE(WebGLRenderbuffer, Release)
+
+} // namespace mozilla
diff --git a/dom/canvas/WebGLRenderbuffer.h b/dom/canvas/WebGLRenderbuffer.h
index 62209d3d9871..7b201476711d 100644
--- a/dom/canvas/WebGLRenderbuffer.h
+++ b/dom/canvas/WebGLRenderbuffer.h
@@ -3,16 +3,14 @@
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
-#ifndef WEBGLRENDERBUFFER_H_
-#define WEBGLRENDERBUFFER_H_
-
-#include "WebGLBindableName.h"
-#include "WebGLObjectModel.h"
-#include "WebGLFramebufferAttachable.h"
-
-#include "nsWrapperCache.h"
+#ifndef WEBGL_RENDERBUFFER_H_
+#define WEBGL_RENDERBUFFER_H_
 
 #include "mozilla/LinkedList.h"
+#include "nsWrapperCache.h"
+#include "WebGLBindableName.h"
+#include "WebGLFramebufferAttachable.h"
+#include "WebGLObjectModel.h"
 
 namespace mozilla {
 
@@ -26,11 +24,13 @@ class WebGLRenderbuffer MOZ_FINAL
     , public WebGLFramebufferAttachable
 {
 public:
-    explicit WebGLRenderbuffer(WebGLContext* context);
+    explicit WebGLRenderbuffer(WebGLContext* webgl);
 
     void Delete();
 
-    bool HasUninitializedImageData() const { return mImageDataStatus == WebGLImageDataStatus::UninitializedImageData; }
+    bool HasUninitializedImageData() const {
+        return mImageDataStatus == WebGLImageDataStatus::UninitializedImageData;
+    }
     void SetImageDataStatus(WebGLImageDataStatus x) {
         // there is no way to go from having image data to not having any
         MOZ_ASSERT(x != WebGLImageDataStatus::NoImageData ||
@@ -39,24 +39,29 @@ public:
     }
 
     GLenum InternalFormat() const { return mInternalFormat; }
-    void SetInternalFormat(GLenum aInternalFormat) { mInternalFormat = aInternalFormat; }
+    void SetInternalFormat(GLenum internalFormat) {
+        mInternalFormat = internalFormat;
+    }
 
     GLenum InternalFormatForGL() const { return mInternalFormatForGL; }
-    void SetInternalFormatForGL(GLenum aInternalFormatForGL) { mInternalFormatForGL = aInternalFormatForGL; }
+    void SetInternalFormatForGL(GLenum internalFormatForGL) {
+        mInternalFormatForGL = internalFormatForGL;
+    }
 
     int64_t MemoryUsage() const;
 
-    WebGLContext *GetParentObject() const {
+    WebGLContext* GetParentObject() const {
         return Context();
     }
 
     void BindRenderbuffer() const;
-    void RenderbufferStorage(GLenum internalFormat, GLsizei width, GLsizei height) const;
+    void RenderbufferStorage(GLenum internalFormat, GLsizei width,
+                             GLsizei height) const;
     void FramebufferRenderbuffer(FBAttachment attachment) const;
     // Only handles a subset of `pname`s.
     GLint GetRenderbufferParameter(RBTarget target, RBParam pname) const;
 
-    virtual JSObject* WrapObject(JSContext *cx) MOZ_OVERRIDE;
+    virtual JSObject* WrapObject(JSContext* cx) MOZ_OVERRIDE;
 
     NS_INLINE_DECL_CYCLE_COLLECTING_NATIVE_REFCOUNTING(WebGLRenderbuffer)
     NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_NATIVE_CLASS(WebGLRenderbuffer)
@@ -74,6 +79,7 @@ protected:
 
     friend class WebGLFramebuffer;
 };
+
 } // namespace mozilla
 
-#endif
+#endif // WEBGL_RENDERBUFFER_H_
diff --git a/dom/canvas/WebGLSampler.cpp b/dom/canvas/WebGLSampler.cpp
index 71923ad4cf36..e2bfa5bf5895 100644
--- a/dom/canvas/WebGLSampler.cpp
+++ b/dom/canvas/WebGLSampler.cpp
@@ -3,18 +3,17 @@
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
-#include "WebGLContext.h"
 #include "WebGLSampler.h"
 
 #include "GLContext.h"
-
 #include "mozilla/dom/WebGL2RenderingContextBinding.h"
+#include "WebGLContext.h"
 
-using namespace mozilla;
+namespace mozilla {
 
-WebGLSampler::WebGLSampler(WebGLContext* context, GLuint sampler)
+WebGLSampler::WebGLSampler(WebGLContext* webgl, GLuint sampler)
     : WebGLBindableName(sampler),
-      WebGLContextBoundObject(context)
+      WebGLContextBoundObject(webgl)
 {
     mContext->mSamplers.insertBack(this);
 }
@@ -49,3 +48,5 @@ WebGLSampler::WrapObject(JSContext* cx)
 NS_IMPL_CYCLE_COLLECTION_WRAPPERCACHE_0(WebGLSampler)
 NS_IMPL_CYCLE_COLLECTION_ROOT_NATIVE(WebGLSampler, AddRef)
 NS_IMPL_CYCLE_COLLECTION_UNROOT_NATIVE(WebGLSampler, Release)
+
+} // namespace mozilla
diff --git a/dom/canvas/WebGLSampler.h b/dom/canvas/WebGLSampler.h
index 874960eb29dd..7b50375e1412 100644
--- a/dom/canvas/WebGLSampler.h
+++ b/dom/canvas/WebGLSampler.h
@@ -3,15 +3,13 @@
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
-#ifndef WEBGLSAMPLER_H_
-#define WEBGLSAMPLER_H_
-
-#include "WebGLBindableName.h"
-#include "WebGLObjectModel.h"
-
-#include "nsWrapperCache.h"
+#ifndef WEBGL_SAMPLER_H_
+#define WEBGL_SAMPLER_H_
 
 #include "mozilla/LinkedList.h"
+#include "nsWrapperCache.h"
+#include "WebGLBindableName.h"
+#include "WebGLObjectModel.h"
 
 namespace mozilla {
 
@@ -25,8 +23,7 @@ class WebGLSampler MOZ_FINAL
     friend class WebGLContext2;
 
 public:
-
-    explicit WebGLSampler(WebGLContext* aContext, GLuint sampler);
+    explicit WebGLSampler(WebGLContext* webgl, GLuint sampler);
 
     void Delete();
     WebGLContext* GetParentObject() const;
@@ -39,10 +36,9 @@ private:
     NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_NATIVE_CLASS(WebGLSampler)
 
 private:
-
     ~WebGLSampler();
 };
 
 } // namespace mozilla
 
-#endif // !WEBGLSAMPLER_H_
+#endif // WEBGL_SAMPLER_H_
diff --git a/dom/canvas/WebGLShader.cpp b/dom/canvas/WebGLShader.cpp
index cbe0ace5f049..bbdb301d6bdb 100644
--- a/dom/canvas/WebGLShader.cpp
+++ b/dom/canvas/WebGLShader.cpp
@@ -3,23 +3,25 @@
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
-#include "WebGLObjectModel.h"
 #include "WebGLShader.h"
-#include "WebGLContext.h"
-#include "mozilla/MemoryReporting.h"
-#include "mozilla/dom/WebGLRenderingContextBinding.h"
-#include "GLContext.h"
 
-using namespace mozilla;
+#include "angle/ShaderLang.h"
+#include "GLContext.h"
+#include "mozilla/dom/WebGLRenderingContextBinding.h"
+#include "mozilla/MemoryReporting.h"
+#include "WebGLContext.h"
+#include "WebGLObjectModel.h"
+
+namespace mozilla {
 
 JSObject*
-WebGLShader::WrapObject(JSContext *cx) {
+WebGLShader::WrapObject(JSContext* cx) {
     return dom::WebGLShaderBinding::Wrap(cx, this);
 }
 
-WebGLShader::WebGLShader(WebGLContext *context, GLenum stype)
-    : WebGLContextBoundObject(context)
-    , mType(stype)
+WebGLShader::WebGLShader(WebGLContext* webgl, GLenum type)
+    : WebGLContextBoundObject(webgl)
+    , mType(type)
     , mNeedsTranslation(true)
     , mAttribMaxNameLength(0)
     , mCompileStatus(false)
@@ -30,7 +32,8 @@ WebGLShader::WebGLShader(WebGLContext *context, GLenum stype)
 }
 
 void
-WebGLShader::Delete() {
+WebGLShader::Delete()
+{
     mSource.Truncate();
     mTranslationLog.Truncate();
     mContext->MakeContextCurrent();
@@ -39,14 +42,16 @@ WebGLShader::Delete() {
 }
 
 size_t
-WebGLShader::SizeOfIncludingThis(MallocSizeOf aMallocSizeOf) const {
-    return aMallocSizeOf(this) +
-           mSource.SizeOfExcludingThisIfUnshared(aMallocSizeOf) +
-           mTranslationLog.SizeOfExcludingThisIfUnshared(aMallocSizeOf);
+WebGLShader::SizeOfIncludingThis(MallocSizeOf mallocSizeOf) const
+{
+    return mallocSizeOf(this) +
+           mSource.SizeOfExcludingThisIfUnshared(mallocSizeOf) +
+           mTranslationLog.SizeOfExcludingThisIfUnshared(mallocSizeOf);
 }
 
 void
-WebGLShader::SetTranslationSuccess() {
+WebGLShader::SetTranslationSuccess()
+{
     mTranslationLog.SetIsVoid(true);
     mNeedsTranslation = false;
 }
@@ -55,3 +60,5 @@ NS_IMPL_CYCLE_COLLECTION_WRAPPERCACHE_0(WebGLShader)
 
 NS_IMPL_CYCLE_COLLECTION_ROOT_NATIVE(WebGLShader, AddRef)
 NS_IMPL_CYCLE_COLLECTION_UNROOT_NATIVE(WebGLShader, Release)
+
+} // namespace mozilla
diff --git a/dom/canvas/WebGLShader.h b/dom/canvas/WebGLShader.h
index 048078e0eddd..f1ddacf862d9 100644
--- a/dom/canvas/WebGLShader.h
+++ b/dom/canvas/WebGLShader.h
@@ -3,24 +3,27 @@
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
-#ifndef WEBGLSHADER_H_
-#define WEBGLSHADER_H_
-
-#include "WebGLObjectModel.h"
-#include "WebGLUniformInfo.h"
-
-#include "nsWrapperCache.h"
-
-#include "angle/ShaderLang.h"
+#ifndef WEBGL_SHADER_H_
+#define WEBGL_SHADER_H_
 
 #include "mozilla/LinkedList.h"
 #include "mozilla/MemoryReporting.h"
+#include "nsWrapperCache.h"
+#include "WebGLObjectModel.h"
+#include "WebGLUniformInfo.h"
 
 namespace mozilla {
 
-struct WebGLMappedIdentifier {
-    nsCString original, mapped; // ASCII strings
-    WebGLMappedIdentifier(const nsACString& o, const nsACString& m) : original(o), mapped(m) {}
+struct WebGLMappedIdentifier
+{
+    // ASCII strings
+    nsCString original;
+    nsCString mapped;
+
+    WebGLMappedIdentifier(const nsACString& o, const nsACString& m)
+        : original(o)
+        , mapped(m)
+    {}
 };
 
 class WebGLShader MOZ_FINAL
@@ -33,15 +36,16 @@ class WebGLShader MOZ_FINAL
     friend class WebGLProgram;
 
 public:
-    WebGLShader(WebGLContext *context, GLenum stype);
+    WebGLShader(WebGLContext* webgl, GLenum type);
 
-    size_t SizeOfIncludingThis(mozilla::MallocSizeOf aMallocSizeOf) const;
+    size_t SizeOfIncludingThis(mozilla::MallocSizeOf mallocSizeOf) const;
 
     GLuint GLName() { return mGLName; }
     sh::GLenum ShaderType() { return mType; }
 
     void SetSource(const nsAString& src) {
-        // XXX do some quick gzip here maybe -- getting this will be very rare
+        // TODO: Do some quick gzip here maybe? Getting this will be very rare,
+        // and we have to keep it forever.
         mSource.Assign(src);
     }
 
@@ -63,18 +67,18 @@ public:
     void SetTranslationSuccess();
 
     void SetTranslationFailure(const nsCString& msg) {
-        mTranslationLog.Assign(msg); 
+        mTranslationLog.Assign(msg);
     }
 
     const nsCString& TranslationLog() const { return mTranslationLog; }
 
     const nsString& TranslatedSource() const { return mTranslatedSource; }
 
-    WebGLContext *GetParentObject() const {
+    WebGLContext* GetParentObject() const {
         return Context();
     }
 
-    virtual JSObject* WrapObject(JSContext *cx) MOZ_OVERRIDE;
+    virtual JSObject* WrapObject(JSContext* cx) MOZ_OVERRIDE;
 
     NS_INLINE_DECL_CYCLE_COLLECTING_NATIVE_REFCOUNTING(WebGLShader)
     NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_NATIVE_CLASS(WebGLShader)
@@ -85,7 +89,7 @@ protected:
     }
 
     GLuint mGLName;
-    sh::GLenum mType;
+    GLenum mType;
     nsString mSource;
     nsString mTranslatedSource;
     nsCString mTranslationLog; // The translation log should contain only ASCII characters
@@ -96,6 +100,7 @@ protected:
     int mAttribMaxNameLength;
     bool mCompileStatus;
 };
+
 } // namespace mozilla
 
-#endif
+#endif // WEBGL_SHADER_H_
diff --git a/dom/canvas/WebGLShaderPrecisionFormat.cpp b/dom/canvas/WebGLShaderPrecisionFormat.cpp
index e3ad94eb534f..31742cfb11af 100644
--- a/dom/canvas/WebGLShaderPrecisionFormat.cpp
+++ b/dom/canvas/WebGLShaderPrecisionFormat.cpp
@@ -3,14 +3,17 @@
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
-#include "WebGLContext.h"
 #include "WebGLShaderPrecisionFormat.h"
-#include "mozilla/dom/WebGLRenderingContextBinding.h"
 
-using namespace mozilla;
+#include "mozilla/dom/WebGLRenderingContextBinding.h"
+#include "WebGLContext.h"
+
+namespace mozilla {
 
 JSObject*
-WebGLShaderPrecisionFormat::WrapObject(JSContext *cx)
+WebGLShaderPrecisionFormat::WrapObject(JSContext* cx)
 {
     return dom::WebGLShaderPrecisionFormatBinding::Wrap(cx, this);
 }
+
+} // namespace mozilla
diff --git a/dom/canvas/WebGLShaderPrecisionFormat.h b/dom/canvas/WebGLShaderPrecisionFormat.h
index d57fa378f26b..891dbaa0a4d2 100644
--- a/dom/canvas/WebGLShaderPrecisionFormat.h
+++ b/dom/canvas/WebGLShaderPrecisionFormat.h
@@ -3,8 +3,8 @@
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
-#ifndef WEBGLSHADERPRECISIONFORMAT_H_
-#define WEBGLSHADERPRECISIONFORMAT_H_
+#ifndef WEBGL_SHADER_PRECISION_FORMAT_H_
+#define WEBGL_SHADER_PRECISION_FORMAT_H_
 
 #include "WebGLObjectModel.h"
 
@@ -16,23 +16,25 @@ class WebGLShaderPrecisionFormat MOZ_FINAL
     : public WebGLContextBoundObject
 {
 public:
-    WebGLShaderPrecisionFormat(WebGLContext *context, GLint rangeMin, GLint rangeMax, GLint precision) :
-        WebGLContextBoundObject(context),
-        mRangeMin(rangeMin),
-        mRangeMax(rangeMax),
-        mPrecision(precision)
-    {
-    }
+    WebGLShaderPrecisionFormat(WebGLContext* context, GLint rangeMin,
+                               GLint rangeMax, GLint precision)
+        : WebGLContextBoundObject(context)
+        , mRangeMin(rangeMin)
+        , mRangeMax(rangeMax)
+        , mPrecision(precision)
+    { }
 
-    JSObject* WrapObject(JSContext *cx);
+    JSObject* WrapObject(JSContext* cx);
 
     // WebIDL WebGLShaderPrecisionFormat API
     GLint RangeMin() const {
         return mRangeMin;
     }
+
     GLint RangeMax() const {
         return mRangeMax;
     }
+
     GLint Precision() const {
         return mPrecision;
     }
@@ -41,9 +43,7 @@ public:
 
 private:
     // Private destructor, to discourage deletion outside of Release():
-    ~WebGLShaderPrecisionFormat()
-    {
-    }
+    ~WebGLShaderPrecisionFormat() { }
 
     GLint mRangeMin;
     GLint mRangeMax;
@@ -52,4 +52,4 @@ private:
 
 } // namespace mozilla
 
-#endif
+#endif // WEBGL_SHADER_PRECISION_FORMAT_H_
diff --git a/dom/canvas/WebGLStrongTypes.h b/dom/canvas/WebGLStrongTypes.h
index 88151385585a..25cab6284eaf 100644
--- a/dom/canvas/WebGLStrongTypes.h
+++ b/dom/canvas/WebGLStrongTypes.h
@@ -1,99 +1,100 @@
-
 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
-#ifndef WEBGLSTRONGTYPES_H_
-#define WEBGLSTRONGTYPES_H_
+#ifndef WEBGL_STRONG_TYPES_H_
+#define WEBGL_STRONG_TYPES_H_
 
 #include "GLDefs.h"
 #include "mozilla/ArrayUtils.h"
 #include "mozilla/Assertions.h"
 #include "mozilla/Attributes.h"
 
-// Usage:
-// ===========
-//
-// To create a new type from a set of GLenums do the following:
-//
-//   STRONG_GLENUM_BEGIN(TypeName)
-//     STRONG_GLENUM_VALUE(ENUM1),
-//     STRONG_GLENUM_VALUE(ENUM2),
-//     ...
-//   STRONG_GLENUM_END()
-//
-// where TypeName is the name you want to give the type. Now simply use TypeName
-// instead of GLenum. The enum values must be given without GL_ prefix.
-//
-// ~~~~~~~~~~~~~~~~
-// Important Notes:
-// ~~~~~~~~~~~~~~~~
-//
-// Boolean operators (==, !=) are provided in an effort to prevent some mistakes
-// when using constants. For example we want to make sure that GL_ENUM_X is
-// a valid value for the type in code like:
-//
-//   if (myNewType == STRONG_GLENUM_VALUE(SOME_ENUM))
-//       ...
-//
-// The operators will assert that STRONG_GLENUM_VALUE(SOME_ENUM) is a value that myNewType
-// can have.
-//
-// ----
-//
-// A get() method is provided to allow access to the underlying GLenum. This
-// method should ideally only be called when passing parameters to the gl->fXXXX
-// functions, and be used very minimally everywhere else.
-//
-// Definitely XXX - DO NOT DO - XXX:
-//
-//   if (myNewType.get() == STRONG_GLENUM_VALUE(SOME_ENUM))
-//       ...
-//
-// As that undermines the debug checks that were implemented in the ==, and !=
-// operators. If you see code like this it should be treated with suspicion.
-//
-// Background:
-// ===========
-//
-// This macro is the first step in an effort to make the WebGL code safer.
-// Many of the different functions take GLenum as their parameter which leads
-// to bugs because of subtle differences in the enums purpose. For example there
-// are two types of 'texture targets'. One is the texture binding locations:
-//
-//   GL_TEXTURE_2D
-//   GL_TEXTURE_CUBE_MAP
-//
-// Yet, this is not the same as texture image targets:
-//
-//   GL_TEXTURE_2D
-//   GL_TEXTURE_CUBE_MAP_POSITIVE_X
-//   GL_TEXTURE_CUBE_MAP_NEGATIVE_X
-//   GL_TEXTURE_CUBE_MAP_POSITIVE_Y
-//   ...
-//
-// This subtle distinction has already led to many bugs in the texture code
-// because of invalid assumptions about what type goes where. The macro below
-// is an attempt at fixing this by providing a small wrapper around GLenum that
-// validates its values.
-//
-// Comparison between STRONG_GLENUM's vs. enum classes
-// ===================================================
-//
-// The present STRONG_GLENUM's differ from ordinary enum classes
-// in that they assert at runtime that their values are legal, and in that they
-// allow implicit conversion from integers to STRONG_GLENUM's but disallow
-// implicit conversion from STRONG_GLENUM's to integers (enum classes are the opposite).
-//
-// When to use GLenum's vs. STRONG_GLENUM's vs. enum classes
-// =========================================================
-//
-// Rule of thumb:
-// * For unchecked GLenum constants, such as WebGL method parameters that haven't been
-//   validated yet, use GLenum.
-// * For already-validated GLenum constants, use STRONG_GLENUM's.
-// * For custom constants that aren't GL enum values, use enum classes.
+/* Usage:
+ * ===========
+ *
+ * To create a new type from a set of GLenums do the following:
+ *
+ *   STRONG_GLENUM_BEGIN(TypeName)
+ *     STRONG_GLENUM_VALUE(ENUM1),
+ *     STRONG_GLENUM_VALUE(ENUM2),
+ *     ...
+ *   STRONG_GLENUM_END()
+ *
+ * where TypeName is the name you want to give the type. Now simply use TypeName
+ * instead of GLenum. The enum values must be given without GL_ prefix.
+ *
+ * ~~~~~~~~~~~~~~~~
+ * Important Notes:
+ * ~~~~~~~~~~~~~~~~
+ *
+ * Boolean operators (==, !=) are provided in an effort to prevent some mistakes
+ * when using constants. For example we want to make sure that GL_ENUM_X is
+ * a valid value for the type in code like:
+ *
+ *   if (myNewType == STRONG_GLENUM_VALUE(SOME_ENUM))
+ *       ...
+ *
+ * The operators will assert that STRONG_GLENUM_VALUE(SOME_ENUM) is a value that
+ * myNewType can have.
+ *
+ * ----
+ *
+ * A get() method is provided to allow access to the underlying GLenum. This
+ * method should ideally only be called when passing parameters to the gl->fXXXX
+ * functions, and be used very minimally everywhere else.
+ *
+ * Definitely XXX - DO NOT DO - XXX:
+ *
+ *   if (myNewType.get() == STRONG_GLENUM_VALUE(SOME_ENUM))
+ *       ...
+ *
+ * As that undermines the debug checks that were implemented in the ==, and !=
+ * operators. If you see code like this it should be treated with suspicion.
+ *
+ * Background:
+ * ===========
+ *
+ * This macro is the first step in an effort to make the WebGL code safer.
+ * Many of the different functions take GLenum as their parameter which leads
+ * to bugs because of subtle differences in the enums purpose. For example there
+ * are two types of 'texture targets'. One is the texture binding locations:
+ *
+ *   GL_TEXTURE_2D
+ *   GL_TEXTURE_CUBE_MAP
+ *
+ * Yet, this is not the same as texture image targets:
+ *
+ *   GL_TEXTURE_2D
+ *   GL_TEXTURE_CUBE_MAP_POSITIVE_X
+ *   GL_TEXTURE_CUBE_MAP_NEGATIVE_X
+ *   GL_TEXTURE_CUBE_MAP_POSITIVE_Y
+ *   ...
+ *
+ * This subtle distinction has already led to many bugs in the texture code
+ * because of invalid assumptions about what type goes where. The macro below
+ * is an attempt at fixing this by providing a small wrapper around GLenum that
+ * validates its values.
+ *
+ * Comparison between STRONG_GLENUM's vs. enum classes
+ * ===================================================
+ *
+ * The present STRONG_GLENUM's differ from ordinary enum classes
+ * in that they assert at runtime that their values are legal, and in that they
+ * allow implicit conversion from integers to STRONG_GLENUM's but disallow
+ * implicit conversion from STRONG_GLENUM's to integers (enum classes are the
+ * opposite).
+ *
+ * When to use GLenum's vs. STRONG_GLENUM's vs. enum classes
+ * =========================================================
+ *
+ * Rule of thumb:
+ * * For unchecked GLenum constants, such as WebGL method parameters that
+ *   haven't been validated yet, use GLenum.
+ * * For already-validated GLenum constants, use STRONG_GLENUM's.
+ * * For custom constants that aren't GL enum values, use enum classes.
+ */
 
 template
 class StrongGLenum MOZ_FINAL
@@ -103,8 +104,7 @@ private:
 
     GLenum mValue;
 
-    static void AssertOnceThatEnumValuesAreSorted()
-    {
+    static void AssertOnceThatEnumValuesAreSorted() {
 #ifdef DEBUG
         static bool alreadyChecked = false;
         if (alreadyChecked) {
@@ -133,8 +133,8 @@ public:
         AssertOnceThatEnumValuesAreSorted();
     }
 
-    MOZ_IMPLICIT StrongGLenum(GLenum aVal)
-        : mValue(aVal)
+    MOZ_IMPLICIT StrongGLenum(GLenum value)
+        : mValue(value)
     {
         AssertOnceThatEnumValuesAreSorted();
         MOZ_ASSERT(IsValueLegal(mValue));
@@ -208,9 +208,8 @@ bool operator!=(StrongGLenum
a, GLenum b) }; \ typedef StrongGLenum NAME; -/****************************************************************************** - * Add your types after this comment - *****************************************************************************/ +//////////////////////////////////////////////////////////////////////////////// +// Add types below. STRONG_GLENUM_BEGIN(TexImageTarget) STRONG_GLENUM_VALUE(NONE), @@ -451,4 +450,4 @@ STRONG_GLENUM_BEGIN(BufferBinding) STRONG_GLENUM_VALUE(ELEMENT_ARRAY_BUFFER), STRONG_GLENUM_END(BufferBinding) -#endif +#endif // WEBGL_STRONG_TYPES_H_ diff --git a/dom/canvas/WebGLSync.cpp b/dom/canvas/WebGLSync.cpp index eace461fc80b..9109bf977f8b 100644 --- a/dom/canvas/WebGLSync.cpp +++ b/dom/canvas/WebGLSync.cpp @@ -7,10 +7,10 @@ #include "mozilla/dom/WebGL2RenderingContextBinding.h" -using namespace mozilla; +namespace mozilla { -WebGLSync::WebGLSync(WebGLContext* context) : - WebGLContextBoundObject(context) +WebGLSync::WebGLSync(WebGLContext* webgl): + WebGLContextBoundObject(webgl) { MOZ_CRASH("Not Implemented."); } @@ -34,7 +34,7 @@ WebGLSync::GetParentObject() const // ------------------------------------------------------------------------- // IMPLEMENT NS JSObject* -WebGLSync::WrapObject(JSContext *cx) +WebGLSync::WrapObject(JSContext* cx) { return dom::WebGLSyncBinding::Wrap(cx, this); } @@ -42,3 +42,5 @@ WebGLSync::WrapObject(JSContext *cx) NS_IMPL_CYCLE_COLLECTION_WRAPPERCACHE_0(WebGLSync) NS_IMPL_CYCLE_COLLECTION_ROOT_NATIVE(WebGLSync, AddRef) NS_IMPL_CYCLE_COLLECTION_UNROOT_NATIVE(WebGLSync, Release); + +} // namespace mozilla diff --git a/dom/canvas/WebGLSync.h b/dom/canvas/WebGLSync.h index 54b41faf8527..5a369cd00f19 100644 --- a/dom/canvas/WebGLSync.h +++ b/dom/canvas/WebGLSync.h @@ -3,14 +3,12 @@ * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ -#ifndef WEBGLSYNC_H_ -#define WEBGLSYNC_H_ - -#include "WebGLObjectModel.h" - -#include "nsWrapperCache.h" +#ifndef WEBGL_SYNC_H_ +#define WEBGL_SYNC_H_ #include "mozilla/LinkedList.h" +#include "nsWrapperCache.h" +#include "WebGLObjectModel.h" namespace mozilla { @@ -23,24 +21,20 @@ class WebGLSync MOZ_FINAL friend class WebGL2Context; public: - - explicit WebGLSync(WebGLContext* aContext); + explicit WebGLSync(WebGLContext* webgl); void Delete(); WebGLContext* GetParentObject() const; - // ------------------------------------------------------------------------- - // IMPLEMENT NS virtual JSObject* WrapObject(JSContext* cx) MOZ_OVERRIDE; NS_INLINE_DECL_CYCLE_COLLECTING_NATIVE_REFCOUNTING(WebGLSync) NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_NATIVE_CLASS(WebGLSync) private: - ~WebGLSync(); }; } // namespace mozilla -#endif // !WEBGLSYNC_H_ +#endif // WEBGL_SYNC_H_ diff --git a/dom/canvas/WebGLTexelConversions.cpp b/dom/canvas/WebGLTexelConversions.cpp index 33ac6b551109..99b177e6bfb8 100644 --- a/dom/canvas/WebGLTexelConversions.cpp +++ b/dom/canvas/WebGLTexelConversions.cpp @@ -180,14 +180,14 @@ class WebGLImageConverter const ptrdiff_t srcStrideInElements = mSrcStride / sizeof(SrcType); const ptrdiff_t dstStrideInElements = mDstStride / sizeof(DstType); - const SrcType *srcRowStart = static_cast(mSrcStart); - DstType *dstRowStart = static_cast(mDstStart); + const SrcType* srcRowStart = static_cast(mSrcStart); + DstType* dstRowStart = static_cast(mDstStart); // the loop performing the texture format conversion for (size_t i = 0; i < mHeight; ++i) { - const SrcType *srcRowEnd = srcRowStart + mWidth * NumElementsPerSrcTexel; - const SrcType *srcPtr = srcRowStart; - DstType *dstPtr = dstRowStart; + const SrcType* srcRowEnd = srcRowStart + mWidth * NumElementsPerSrcTexel; + const SrcType* srcPtr = srcRowStart; + DstType* dstPtr = dstRowStart; while (srcPtr != srcRowEnd) { // convert a single texel. We proceed in 3 steps: unpack the source texel // so the corresponding interchange format (e.g. unpack RGB565 to RGBA8), @@ -327,7 +327,7 @@ public: bool WebGLContext::ConvertImage(size_t width, size_t height, size_t srcStride, size_t dstStride, - const uint8_t* src, uint8_t *dst, + const uint8_t* src, uint8_t* dst, WebGLTexelFormat srcFormat, bool srcPremultiplied, WebGLTexelFormat dstFormat, bool dstPremultiplied, size_t dstTexelSize) diff --git a/dom/canvas/WebGLTexture.cpp b/dom/canvas/WebGLTexture.cpp index 33d97f11cebd..c4ed77228187 100644 --- a/dom/canvas/WebGLTexture.cpp +++ b/dom/canvas/WebGLTexture.cpp @@ -5,27 +5,26 @@ #include "WebGLTexture.h" +#include #include "GLContext.h" #include "mozilla/dom/WebGLRenderingContextBinding.h" +#include "mozilla/MathAlgorithms.h" #include "mozilla/Scoped.h" #include "ScopedGLHelpers.h" #include "WebGLContext.h" #include "WebGLContextUtils.h" #include "WebGLTexelConversions.h" -#include -#include "mozilla/MathAlgorithms.h" - -using namespace mozilla; +namespace mozilla { JSObject* WebGLTexture::WrapObject(JSContext* cx) { return dom::WebGLTextureBinding::Wrap(cx, this); } -WebGLTexture::WebGLTexture(WebGLContext* context, GLuint tex) +WebGLTexture::WebGLTexture(WebGLContext* webgl, GLuint tex) : WebGLBindableName(tex) - , WebGLContextBoundObject(context) + , WebGLContextBoundObject(webgl) , mMinFilter(LOCAL_GL_NEAREST_MIPMAP_LINEAR) , mMagFilter(LOCAL_GL_LINEAR) , mWrapS(LOCAL_GL_REPEAT) @@ -42,7 +41,8 @@ WebGLTexture::WebGLTexture(WebGLContext* context, GLuint tex) } void -WebGLTexture::Delete() { +WebGLTexture::Delete() +{ mImageInfos.Clear(); mContext->MakeContextCurrent(); mContext->gl->fDeleteTextures(1, &mGLName); @@ -50,27 +50,32 @@ WebGLTexture::Delete() { } size_t -WebGLTexture::ImageInfo::MemoryUsage() const { +WebGLTexture::ImageInfo::MemoryUsage() const +{ if (mImageDataStatus == WebGLImageDataStatus::NoImageData) return 0; + size_t bitsPerTexel = GetBitsPerTexel(mEffectiveInternalFormat); return size_t(mWidth) * size_t(mHeight) * size_t(mDepth) * bitsPerTexel / 8; } size_t -WebGLTexture::MemoryUsage() const { +WebGLTexture::MemoryUsage() const +{ if (IsDeleted()) return 0; + size_t result = 0; for(size_t face = 0; face < mFacesCount; face++) { - for(size_t level = 0; level <= mMaxLevelWithCustomImages; level++) - result += ImageInfoAtFace(face, level).MemoryUsage(); + for(size_t level = 0; level <= mMaxLevelWithCustomImages; level++) { + result += ImageInfoAtFace(face, level).MemoryUsage(); } + } return result; } static inline size_t -MipmapLevelsForSize(const WebGLTexture::ImageInfo &info) +MipmapLevelsForSize(const WebGLTexture::ImageInfo& info) { GLsizei size = std::max(std::max(info.Width(), info.Height()), info.Depth()); @@ -89,7 +94,8 @@ WebGLTexture::DoesMipmapHaveAllLevelsConsistentlyDefined(TexImageTarget texImage return false; // We want a copy here so we can modify it temporarily. - ImageInfo expected = ImageInfoAt(texImageTarget, EffectiveBaseMipmapLevel()); + ImageInfo expected = ImageInfoAt(texImageTarget, + EffectiveBaseMipmapLevel()); if (!expected.IsPositive()) return false; @@ -102,7 +108,9 @@ WebGLTexture::DoesMipmapHaveAllLevelsConsistentlyDefined(TexImageTarget texImage // Checks if custom images are all defined up to the highest level and // have the expected dimensions. - for (size_t level = EffectiveBaseMipmapLevel(); level <= EffectiveMaxMipmapLevel(); ++level) { + for (size_t level = EffectiveBaseMipmapLevel(); + level <= EffectiveMaxMipmapLevel(); ++level) + { const ImageInfo& actual = ImageInfoAt(texImageTarget, level); if (actual != expected) return false; @@ -111,8 +119,8 @@ WebGLTexture::DoesMipmapHaveAllLevelsConsistentlyDefined(TexImageTarget texImage expected.mHeight = std::max(1, expected.mHeight / 2); expected.mDepth = std::max(1, expected.mDepth / 2); - // if the current level has size 1x1, we can stop here: the spec doesn't seem to forbid the existence - // of extra useless levels. + // If the current level has size 1x1, we can stop here: The spec doesn't + // seem to forbid the existence of extra useless levels. if (actual.mWidth == 1 && actual.mHeight == 1 && actual.mDepth == 1) @@ -125,61 +133,72 @@ WebGLTexture::DoesMipmapHaveAllLevelsConsistentlyDefined(TexImageTarget texImage } void -WebGLTexture::Bind(TexTarget aTexTarget) { - // this function should only be called by bindTexture(). - // it assumes that the GL context is already current. +WebGLTexture::Bind(TexTarget texTarget) +{ + // This function should only be called by bindTexture(). It assumes that the + // GL context is already current. bool firstTimeThisTextureIsBound = !HasEverBeenBound(); if (firstTimeThisTextureIsBound) { - BindTo(aTexTarget); - } else if (aTexTarget != Target()) { - mContext->ErrorInvalidOperation("bindTexture: this texture has already been bound to a different target"); - // very important to return here before modifying texture state! This was the place when I lost a whole day figuring - // very strange 'invalid write' crashes. + BindTo(texTarget); + } else if (texTarget != Target()) { + mContext->ErrorInvalidOperation("bindTexture: This texture has already" + " been bound to a different target."); + // Very important to return here before modifying texture state! This + // was the place when I lost a whole day figuring very strange "invalid + // write" crashes. return; } GLuint name = GLName(); - mContext->gl->fBindTexture(aTexTarget.get(), name); + mContext->gl->fBindTexture(texTarget.get(), name); if (firstTimeThisTextureIsBound) { - mFacesCount = (aTexTarget == LOCAL_GL_TEXTURE_CUBE_MAP) ? 6 : 1; + mFacesCount = (texTarget == LOCAL_GL_TEXTURE_CUBE_MAP) ? 6 : 1; EnsureMaxLevelWithCustomImagesAtLeast(0); SetFakeBlackStatus(WebGLTextureFakeBlackStatus::Unknown); - // thanks to the WebKit people for finding this out: GL_TEXTURE_WRAP_R is not - // present in GLES 2, but is present in GL and it seems as if for cube maps - // we need to set it to GL_CLAMP_TO_EDGE to get the expected GLES behavior. - if (mTarget == LOCAL_GL_TEXTURE_CUBE_MAP && !mContext->gl->IsGLES()) - mContext->gl->fTexParameteri(aTexTarget.get(), LOCAL_GL_TEXTURE_WRAP_R, LOCAL_GL_CLAMP_TO_EDGE); + // Thanks to the WebKit people for finding this out: GL_TEXTURE_WRAP_R + // is not present in GLES 2, but is present in GL and it seems as if for + // cube maps we need to set it to GL_CLAMP_TO_EDGE to get the expected + // GLES behavior. + if (mTarget == LOCAL_GL_TEXTURE_CUBE_MAP && !mContext->gl->IsGLES()) { + mContext->gl->fTexParameteri(texTarget.get(), + LOCAL_GL_TEXTURE_WRAP_R, + LOCAL_GL_CLAMP_TO_EDGE); + } } } void -WebGLTexture::SetImageInfo(TexImageTarget aTexImageTarget, GLint aLevel, - GLsizei aWidth, GLsizei aHeight, GLsizei aDepth, - TexInternalFormat aEffectiveInternalFormat, WebGLImageDataStatus aStatus) +WebGLTexture::SetImageInfo(TexImageTarget texImageTarget, GLint level, + GLsizei width, GLsizei height, GLsizei depth, + TexInternalFormat effectiveInternalFormat, + WebGLImageDataStatus status) { - MOZ_ASSERT(aDepth == 1 || aTexImageTarget == LOCAL_GL_TEXTURE_3D); - MOZ_ASSERT(TexImageTargetToTexTarget(aTexImageTarget) == mTarget); + MOZ_ASSERT(depth == 1 || texImageTarget == LOCAL_GL_TEXTURE_3D); + MOZ_ASSERT(TexImageTargetToTexTarget(texImageTarget) == mTarget); - EnsureMaxLevelWithCustomImagesAtLeast(aLevel); + EnsureMaxLevelWithCustomImagesAtLeast(level); - ImageInfoAt(aTexImageTarget, aLevel) = ImageInfo(aWidth, aHeight, aDepth, aEffectiveInternalFormat, aStatus); + ImageInfoAt(texImageTarget, level) = ImageInfo(width, height, depth, + effectiveInternalFormat, + status); - if (aLevel > 0) + if (level > 0) SetCustomMipmap(); - // Invalidate framebuffer status cache + // Invalidate framebuffer status cache. NotifyFBsStatusChanged(); SetFakeBlackStatus(WebGLTextureFakeBlackStatus::Unknown); } void -WebGLTexture::SetGeneratedMipmap() { +WebGLTexture::SetGeneratedMipmap() +{ if (!mHaveGeneratedMipmap) { mHaveGeneratedMipmap = true; SetFakeBlackStatus(WebGLTextureFakeBlackStatus::Unknown); @@ -187,33 +206,40 @@ WebGLTexture::SetGeneratedMipmap() { } void -WebGLTexture::SetCustomMipmap() { +WebGLTexture::SetCustomMipmap() +{ if (mHaveGeneratedMipmap) { if (!IsMipmapRangeValid()) return; - // If we were in GeneratedMipmap mode and are now switching to CustomMipmap mode, - // we now need to compute all the mipmap image info. + // If we were in GeneratedMipmap mode and are now switching to + // CustomMipmap mode, we now need to compute all the mipmap image info. ImageInfo imageInfo = ImageInfoAtFace(0, EffectiveBaseMipmapLevel()); - NS_ASSERTION(mContext->IsWebGL2() || imageInfo.IsPowerOfTwo(), - "this texture is NPOT, so how could GenerateMipmap() ever accept it?"); + MOZ_ASSERT(mContext->IsWebGL2() || imageInfo.IsPowerOfTwo(), + "This texture is NPOT, so how could GenerateMipmap() ever" + " accept it?"); - size_t maxLevel = MipmapLevelsForSize(imageInfo); - EnsureMaxLevelWithCustomImagesAtLeast(EffectiveBaseMipmapLevel() + maxLevel); + size_t maxRelativeLevel = MipmapLevelsForSize(imageInfo); + size_t maxLevel = EffectiveBaseMipmapLevel() + maxRelativeLevel; + EnsureMaxLevelWithCustomImagesAtLeast(maxLevel); - for (size_t level = EffectiveBaseMipmapLevel() + 1; level <= EffectiveMaxMipmapLevel(); ++level) { + for (size_t level = EffectiveBaseMipmapLevel() + 1; + level <= EffectiveMaxMipmapLevel(); ++level) + { imageInfo.mWidth = std::max(imageInfo.mWidth / 2, 1); imageInfo.mHeight = std::max(imageInfo.mHeight / 2, 1); imageInfo.mDepth = std::max(imageInfo.mDepth / 2, 1); - for(size_t face = 0; face < mFacesCount; ++face) + for(size_t face = 0; face < mFacesCount; ++face) { ImageInfoAtFace(face, level) = imageInfo; + } } } mHaveGeneratedMipmap = false; } bool -WebGLTexture::AreAllLevel0ImageInfosEqual() const { +WebGLTexture::AreAllLevel0ImageInfosEqual() const +{ for (size_t face = 1; face < mFacesCount; ++face) { if (ImageInfoAtFace(face, 0) != ImageInfoAtFace(0, 0)) return false; @@ -222,28 +248,36 @@ WebGLTexture::AreAllLevel0ImageInfosEqual() const { } bool -WebGLTexture::IsMipmapComplete() const { +WebGLTexture::IsMipmapComplete() const +{ MOZ_ASSERT(mTarget == LOCAL_GL_TEXTURE_2D || mTarget == LOCAL_GL_TEXTURE_3D); return DoesMipmapHaveAllLevelsConsistentlyDefined(LOCAL_GL_TEXTURE_2D); } bool -WebGLTexture::IsCubeComplete() const { +WebGLTexture::IsCubeComplete() const +{ MOZ_ASSERT(mTarget == LOCAL_GL_TEXTURE_CUBE_MAP); - const ImageInfo &first = ImageInfoAt(LOCAL_GL_TEXTURE_CUBE_MAP_POSITIVE_X, 0); + const ImageInfo& first = ImageInfoAt(LOCAL_GL_TEXTURE_CUBE_MAP_POSITIVE_X, + 0); if (!first.IsPositive() || !first.IsSquare()) return false; + return AreAllLevel0ImageInfosEqual(); } bool -WebGLTexture::IsMipmapCubeComplete() const { - if (!IsCubeComplete()) // in particular, this checks that this is a cube map +WebGLTexture::IsMipmapCubeComplete() const +{ + // In particular, this checks that this is a cube map: + if (!IsCubeComplete()) return false; + for (int i = 0; i < 6; i++) { - const TexImageTarget face = TexImageTargetForTargetAndFace(LOCAL_GL_TEXTURE_CUBE_MAP, i); + const TexImageTarget face = TexImageTargetForTargetAndFace(LOCAL_GL_TEXTURE_CUBE_MAP, + i); if (!DoesMipmapHaveAllLevelsConsistentlyDefined(face)) return false; } @@ -262,10 +296,10 @@ WebGLTexture::IsMipmapRangeValid() const } WebGLTextureFakeBlackStatus -WebGLTexture::ResolvedFakeBlackStatus() { - if (MOZ_LIKELY(mFakeBlackStatus != WebGLTextureFakeBlackStatus::Unknown)) { +WebGLTexture::ResolvedFakeBlackStatus() +{ + if (MOZ_LIKELY(mFakeBlackStatus != WebGLTextureFakeBlackStatus::Unknown)) return mFakeBlackStatus; - } // Determine if the texture needs to be faked as a black texture. // See 3.8.2 Shader Execution in the OpenGL ES 2.0.24 spec, and 3.8.13 in @@ -274,86 +308,106 @@ WebGLTexture::ResolvedFakeBlackStatus() { mFakeBlackStatus = WebGLTextureFakeBlackStatus::IncompleteTexture; return mFakeBlackStatus; } + for (size_t face = 0; face < mFacesCount; ++face) { - if (ImageInfoAtFace(face, EffectiveBaseMipmapLevel()).mImageDataStatus == WebGLImageDataStatus::NoImageData) { - // In case of undefined texture image, we don't print any message because this is a very common - // and often legitimate case (asynchronous texture loading). + WebGLImageDataStatus status = ImageInfoAtFace(face, EffectiveBaseMipmapLevel()).mImageDataStatus; + if (status == WebGLImageDataStatus::NoImageData) { + // In case of undefined texture image, we don't print any message + // because this is a very common and often legitimate case + // (asynchronous texture loading). mFakeBlackStatus = WebGLTextureFakeBlackStatus::IncompleteTexture; return mFakeBlackStatus; } } - const char *msg_rendering_as_black - = "A texture is going to be rendered as if it were black, as per the OpenGL ES 2.0.24 spec section 3.8.2, " - "because it"; + const char preamble[] = "A texture is going to be rendered as if it were" + " black, as per the OpenGL ES 2.0.24 spec section" + " 3.8.2, because it"; if (mTarget == LOCAL_GL_TEXTURE_2D || mTarget == LOCAL_GL_TEXTURE_3D) { int dim = mTarget == LOCAL_GL_TEXTURE_2D ? 2 : 3; - if (DoesMinFilterRequireMipmap()) - { + if (DoesMinFilterRequireMipmap()) { if (!IsMipmapComplete()) { - mContext->GenerateWarning - ("%s is a %dD texture, with a minification filter requiring a mipmap, " - "and is not mipmap complete (as defined in section 3.7.10).", msg_rendering_as_black, dim); + mContext->GenerateWarning("%s is a %dD texture, with a" + " minification filter requiring a" + " mipmap, and is not mipmap complete" + " (as defined in section 3.7.10).", + preamble, dim); mFakeBlackStatus = WebGLTextureFakeBlackStatus::IncompleteTexture; - } else if (!mContext->IsWebGL2() && !ImageInfoBase().IsPowerOfTwo()) { - mContext->GenerateWarning - ("%s is a %dD texture, with a minification filter requiring a mipmap, " - "and either its width or height is not a power of two.", msg_rendering_as_black); + } else if (!mContext->IsWebGL2() && + !ImageInfoBase().IsPowerOfTwo()) + { + mContext->GenerateWarning("%s is a %dD texture, with a" + " minification filter requiring a" + " mipmap, and either its width or" + " height is not a power of two.", + preamble, dim); mFakeBlackStatus = WebGLTextureFakeBlackStatus::IncompleteTexture; } - } - else // no mipmap required - { + } else { + // No mipmap required here. if (!ImageInfoBase().IsPositive()) { - mContext->GenerateWarning - ("%s is a %dD texture and its width or height is equal to zero.", - msg_rendering_as_black, dim); + mContext->GenerateWarning("%s is a %dD texture and its width or" + " height is equal to zero.", + preamble, dim); mFakeBlackStatus = WebGLTextureFakeBlackStatus::IncompleteTexture; - } else if (!AreBothWrapModesClampToEdge() && !mContext->IsWebGL2() && !ImageInfoBase().IsPowerOfTwo()) { - mContext->GenerateWarning - ("%s is a %dD texture, with a minification filter not requiring a mipmap, " - "with its width or height not a power of two, and with a wrap mode " - "different from CLAMP_TO_EDGE.", msg_rendering_as_black, dim); + } else if (!AreBothWrapModesClampToEdge() && + !mContext->IsWebGL2() && + !ImageInfoBase().IsPowerOfTwo()) + { + mContext->GenerateWarning("%s is a %dD texture, with a" + " minification filter not requiring a" + " mipmap, with its width or height" + " not a power of two, and with a wrap" + " mode different from CLAMP_TO_EDGE.", + preamble, dim); mFakeBlackStatus = WebGLTextureFakeBlackStatus::IncompleteTexture; } } - } - else // cube map - { + } else { + // Cube map bool legalImageSize = true; if (!mContext->IsWebGL2()) { for (size_t face = 0; face < mFacesCount; ++face) legalImageSize &= ImageInfoAtFace(face, 0).IsPowerOfTwo(); } - if (DoesMinFilterRequireMipmap()) - { + if (DoesMinFilterRequireMipmap()) { if (!IsMipmapCubeComplete()) { - mContext->GenerateWarning("%s is a cube map texture, with a minification filter requiring a mipmap, " - "and is not mipmap cube complete (as defined in section 3.7.10).", - msg_rendering_as_black); + mContext->GenerateWarning("%s is a cube map texture, with a" + " minification filter requiring a" + " mipmap, and is not mipmap cube" + " complete (as defined in section" + " 3.7.10).", preamble); mFakeBlackStatus = WebGLTextureFakeBlackStatus::IncompleteTexture; } else if (!legalImageSize) { - mContext->GenerateWarning("%s is a cube map texture, with a minification filter requiring a mipmap, " - "and either the width or the height of some level 0 image is not a power of two.", - msg_rendering_as_black); + mContext->GenerateWarning("%s is a cube map texture, with a" + " minification filter requiring a" + " mipmap, and either the width or the" + " height of some level 0 image is not" + " a power of two.", preamble); mFakeBlackStatus = WebGLTextureFakeBlackStatus::IncompleteTexture; } } else // no mipmap required { if (!IsCubeComplete()) { - mContext->GenerateWarning("%s is a cube map texture, with a minification filter not requiring a mipmap, " - "and is not cube complete (as defined in section 3.7.10).", - msg_rendering_as_black); + mContext->GenerateWarning("%s is a cube map texture, with a" + " minification filter not requiring a" + " mipmap, and is not cube complete" + " (as defined in section 3.7.10).", + preamble); mFakeBlackStatus = WebGLTextureFakeBlackStatus::IncompleteTexture; } else if (!AreBothWrapModesClampToEdge() && !legalImageSize) { - mContext->GenerateWarning("%s is a cube map texture, with a minification filter not requiring a mipmap, " - "with some level 0 image having width or height not a power of two, and with a wrap mode " - "different from CLAMP_TO_EDGE.", msg_rendering_as_black); + mContext->GenerateWarning("%s is a cube map texture, with a" + " minification filter not requiring a" + " mipmap, with some level 0 image" + " having width or height not a power" + " of two, and with a wrap mode" + " different from CLAMP_TO_EDGE.", + preamble); mFakeBlackStatus = WebGLTextureFakeBlackStatus::IncompleteTexture; } } @@ -361,54 +415,50 @@ WebGLTexture::ResolvedFakeBlackStatus() { TexType type = TypeFromInternalFormat(ImageInfoBase().mEffectiveInternalFormat); + const char* badFormatText = nullptr; + const char* extText = nullptr; + if (type == LOCAL_GL_FLOAT && !Context()->IsExtensionEnabled(WebGLExtensionID::OES_texture_float_linear)) { - if (mMinFilter == LOCAL_GL_LINEAR || - mMinFilter == LOCAL_GL_LINEAR_MIPMAP_LINEAR || - mMinFilter == LOCAL_GL_LINEAR_MIPMAP_NEAREST || - mMinFilter == LOCAL_GL_NEAREST_MIPMAP_LINEAR) - { - mContext->GenerateWarning("%s is a texture with a linear minification filter, " - "which is not compatible with gl.FLOAT by default. " - "Try enabling the OES_texture_float_linear extension if supported.", msg_rendering_as_black); - mFakeBlackStatus = WebGLTextureFakeBlackStatus::IncompleteTexture; - } - else if (mMagFilter == LOCAL_GL_LINEAR) - { - mContext->GenerateWarning("%s is a texture with a linear magnification filter, " - "which is not compatible with gl.FLOAT by default. " - "Try enabling the OES_texture_float_linear extension if supported.", msg_rendering_as_black); - mFakeBlackStatus = WebGLTextureFakeBlackStatus::IncompleteTexture; - } + badFormatText = "FLOAT"; + extText = "OES_texture_float_linear"; } else if (type == LOCAL_GL_HALF_FLOAT && !Context()->IsExtensionEnabled(WebGLExtensionID::OES_texture_half_float_linear)) { + badFormatText = "HALF_FLOAT"; + extText = "OES_texture_half_float_linear"; + } + + const char* badFilterText = nullptr; + if (badFormatText) { if (mMinFilter == LOCAL_GL_LINEAR || mMinFilter == LOCAL_GL_LINEAR_MIPMAP_LINEAR || mMinFilter == LOCAL_GL_LINEAR_MIPMAP_NEAREST || mMinFilter == LOCAL_GL_NEAREST_MIPMAP_LINEAR) { - mContext->GenerateWarning("%s is a texture with a linear minification filter, " - "which is not compatible with gl.HALF_FLOAT by default. " - "Try enabling the OES_texture_half_float_linear extension if supported.", msg_rendering_as_black); - mFakeBlackStatus = WebGLTextureFakeBlackStatus::IncompleteTexture; - } - else if (mMagFilter == LOCAL_GL_LINEAR) - { - mContext->GenerateWarning("%s is a texture with a linear magnification filter, " - "which is not compatible with gl.HALF_FLOAT by default. " - "Try enabling the OES_texture_half_float_linear extension if supported.", msg_rendering_as_black); - mFakeBlackStatus = WebGLTextureFakeBlackStatus::IncompleteTexture; + badFilterText = "minification"; + } else if (mMagFilter == LOCAL_GL_LINEAR) { + badFilterText = "magnification"; } } + if (badFilterText) { + mContext->GenerateWarning("%s is a texture with a linear %s filter," + " which is not compatible with format %s by" + " default. Try enabling the %s extension, if" + " supported.", preamble, badFilterText, + badFormatText, extText); + mFakeBlackStatus = WebGLTextureFakeBlackStatus::IncompleteTexture; + } + // We have exhausted all cases of incomplete textures, where we would need opaque black. // We may still need transparent black in case of uninitialized image data. bool hasUninitializedImageData = false; for (size_t level = 0; level <= mMaxLevelWithCustomImages; ++level) { for (size_t face = 0; face < mFacesCount; ++face) { - hasUninitializedImageData |= (ImageInfoAtFace(face, level).mImageDataStatus == WebGLImageDataStatus::UninitializedImageData); + bool cur = (ImageInfoAtFace(face, level).mImageDataStatus == WebGLImageDataStatus::UninitializedImageData); + hasUninitializedImageData |= cur; } } @@ -427,16 +477,22 @@ WebGLTexture::ResolvedFakeBlackStatus() { } if (hasAnyInitializedImageData) { - // The texture contains some initialized image data, and some uninitialized image data. - // In this case, we have no choice but to initialize all image data now. Fortunately, - // in this case we know that we can't be dealing with a depth texture per WEBGL_depth_texture - // and ANGLE_depth_texture (which allow only one image per texture) so we can assume that - // glTexImage2D is able to upload data to images. - for (size_t level = 0; level <= mMaxLevelWithCustomImages; ++level) { + /* The texture contains some initialized image data, and some + * uninitialized image data. In this case, we have no choice but to + * initialize all image data now. Fortunately, in this case we know + * that we can't be dealing with a depth texture per + * WEBGL_depth_texture and ANGLE_depth_texture (which allow only one + * image per texture) so we can assume that glTexImage2D is able to + * upload data to images. + */ + for (size_t level = 0; level <= mMaxLevelWithCustomImages; ++level) + { for (size_t face = 0; face < mFacesCount; ++face) { - TexImageTarget imageTarget = TexImageTargetForTargetAndFace(mTarget, face); + TexImageTarget imageTarget = TexImageTargetForTargetAndFace(mTarget, + face); const ImageInfo& imageInfo = ImageInfoAt(imageTarget, level); - if (imageInfo.mImageDataStatus == WebGLImageDataStatus::UninitializedImageData) { + if (imageInfo.mImageDataStatus == WebGLImageDataStatus::UninitializedImageData) + { EnsureNoUninitializedImageData(imageTarget, level); } } @@ -459,11 +515,10 @@ WebGLTexture::ResolvedFakeBlackStatus() { return mFakeBlackStatus; } - static bool -ClearByMask(WebGLContext* context, GLbitfield mask) +ClearByMask(WebGLContext* webgl, GLbitfield mask) { - gl::GLContext* gl = context->GL(); + gl::GLContext* gl = webgl->GL(); MOZ_ASSERT(gl->IsCurrent()); GLenum status = gl->fCheckFramebufferStatus(LOCAL_GL_FRAMEBUFFER); @@ -475,20 +530,20 @@ ClearByMask(WebGLContext* context, GLbitfield mask) colorAttachmentsMask[0] = true; } - context->ForceClearFramebufferWithDefaultValues(mask, colorAttachmentsMask); + webgl->ForceClearFramebufferWithDefaultValues(mask, colorAttachmentsMask); return true; } // `mask` from glClear. static bool -ClearWithTempFB(WebGLContext* context, GLuint tex, +ClearWithTempFB(WebGLContext* webgl, GLuint tex, TexImageTarget texImageTarget, GLint level, TexInternalFormat baseInternalFormat, GLsizei width, GLsizei height) { MOZ_ASSERT(texImageTarget == LOCAL_GL_TEXTURE_2D); - gl::GLContext* gl = context->GL(); + gl::GLContext* gl = webgl->GL(); MOZ_ASSERT(gl->IsCurrent()); gl::ScopedFramebuffer fb(gl); @@ -528,7 +583,7 @@ ClearWithTempFB(WebGLContext* context, GLuint tex, } MOZ_ASSERT(mask); - if (ClearByMask(context, mask)) + if (ClearByMask(webgl, mask)) return true; // Failed to simply build an FB from the tex, but maybe it needs a @@ -552,12 +607,13 @@ ClearWithTempFB(WebGLContext* context, GLuint tex, mask |= LOCAL_GL_COLOR_BUFFER_BIT; // Last chance! - return ClearByMask(context, mask); + return ClearByMask(webgl, mask); } void -WebGLTexture::EnsureNoUninitializedImageData(TexImageTarget imageTarget, GLint level) +WebGLTexture::EnsureNoUninitializedImageData(TexImageTarget imageTarget, + GLint level) { const ImageInfo& imageInfo = ImageInfoAt(imageTarget, level); if (!imageInfo.HasUninitializedImageData()) @@ -565,15 +621,14 @@ WebGLTexture::EnsureNoUninitializedImageData(TexImageTarget imageTarget, GLint l mContext->MakeContextCurrent(); - // Try to clear with glCLear. - + // Try to clear with glClear. if (imageTarget == LOCAL_GL_TEXTURE_2D) { - bool cleared = ClearWithTempFB(mContext, GLName(), - imageTarget, level, + bool cleared = ClearWithTempFB(mContext, GLName(), imageTarget, level, imageInfo.mEffectiveInternalFormat, imageInfo.mHeight, imageInfo.mWidth); if (cleared) { - SetImageDataStatus(imageTarget, level, WebGLImageDataStatus::InitializedImageData); + SetImageDataStatus(imageTarget, level, + WebGLImageDataStatus::InitializedImageData); return; } } @@ -582,8 +637,9 @@ WebGLTexture::EnsureNoUninitializedImageData(TexImageTarget imageTarget, GLint l gl::ScopedBindTexture autoBindTex(mContext->gl, GLName(), mTarget.get()); size_t bitspertexel = GetBitsPerTexel(imageInfo.mEffectiveInternalFormat); - MOZ_ASSERT((bitspertexel % 8) == 0); // that would only happen for compressed images, which - // cannot use deferred initialization. + MOZ_ASSERT((bitspertexel % 8) == 0); // That would only happen for + // compressed images, which cannot use + // deferred initialization. size_t bytespertexel = bitspertexel / 8; CheckedUint32 checked_byteLength = WebGLContext::GetImageSize( @@ -592,42 +648,48 @@ WebGLTexture::EnsureNoUninitializedImageData(TexImageTarget imageTarget, GLint l imageInfo.mDepth, bytespertexel, mContext->mPixelStoreUnpackAlignment); - MOZ_ASSERT(checked_byteLength.isValid()); // should have been checked earlier + MOZ_ASSERT(checked_byteLength.isValid()); // Should have been checked + // earlier. - UniquePtr zeros((uint8_t*)moz_xcalloc(1, checked_byteLength.value())); // Infallible for now. + // Infallible for now. + UniquePtr zeros((uint8_t*)moz_xcalloc(1, + checked_byteLength.value())); gl::GLContext* gl = mContext->gl; GLenum driverInternalFormat = LOCAL_GL_NONE; GLenum driverFormat = LOCAL_GL_NONE; GLenum driverType = LOCAL_GL_NONE; - DriverFormatsFromEffectiveInternalFormat(gl, imageInfo.mEffectiveInternalFormat, - &driverInternalFormat, &driverFormat, &driverType); + DriverFormatsFromEffectiveInternalFormat(gl, + imageInfo.mEffectiveInternalFormat, + &driverInternalFormat, + &driverFormat, &driverType); mContext->GetAndFlushUnderlyingGLErrors(); if (imageTarget == LOCAL_GL_TEXTURE_3D) { - MOZ_ASSERT(mImmutable, "Shouldn't be possible to have non-immutable-format 3D textures in WebGL"); - gl->fTexSubImage3D(imageTarget.get(), level, 0, 0, 0, - imageInfo.mWidth, imageInfo.mHeight, imageInfo.mDepth, - driverFormat, driverType, - zeros.get()); + MOZ_ASSERT(mImmutable, + "Shouldn't be possible to have non-immutable-format 3D" + " textures in WebGL"); + gl->fTexSubImage3D(imageTarget.get(), level, 0, 0, 0, imageInfo.mWidth, + imageInfo.mHeight, imageInfo.mDepth, driverFormat, + driverType, zeros.get()); } else { if (mImmutable) { - gl->fTexSubImage2D(imageTarget.get(), level, 0, 0, - imageInfo.mWidth, imageInfo.mHeight, - driverFormat, driverType, - zeros.get()); + gl->fTexSubImage2D(imageTarget.get(), level, 0, 0, imageInfo.mWidth, + imageInfo.mHeight, driverFormat, driverType, + zeros.get()); } else { gl->fTexImage2D(imageTarget.get(), level, driverInternalFormat, - imageInfo.mWidth, imageInfo.mHeight, - 0, driverFormat, driverType, - zeros.get()); + imageInfo.mWidth, imageInfo.mHeight, 0, + driverFormat, driverType, zeros.get()); } } GLenum error = mContext->GetAndFlushUnderlyingGLErrors(); if (error) { - // Should only be OUT_OF_MEMORY. Anyway, there's no good way to recover from this here. + // Should only be OUT_OF_MEMORY. Anyway, there's no good way to recover + // from this here. printf_stderr("Error: 0x%4x\n", error); - MOZ_CRASH(); // errors on texture upload have been related to video memory exposure in the past. + MOZ_CRASH(); // Errors on texture upload have been related to video + // memory exposure in the past. } SetImageDataStatus(imageTarget, level, WebGLImageDataStatus::InitializedImageData); @@ -644,3 +706,5 @@ NS_IMPL_CYCLE_COLLECTION_WRAPPERCACHE_0(WebGLTexture) NS_IMPL_CYCLE_COLLECTION_ROOT_NATIVE(WebGLTexture, AddRef) NS_IMPL_CYCLE_COLLECTION_UNROOT_NATIVE(WebGLTexture, Release) + +} // namespace mozilla diff --git a/dom/canvas/WebGLTexture.h b/dom/canvas/WebGLTexture.h index a9e773240c2d..c8b99867d21b 100644 --- a/dom/canvas/WebGLTexture.h +++ b/dom/canvas/WebGLTexture.h @@ -3,27 +3,27 @@ * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ -#ifndef WEBGLTEXTURE_H_ -#define WEBGLTEXTURE_H_ +#ifndef WEBGL_TEXTURE_H_ +#define WEBGL_TEXTURE_H_ +#include +#include "mozilla/Assertions.h" +#include "mozilla/CheckedInt.h" +#include "mozilla/LinkedList.h" +#include "nsAlgorithm.h" +#include "nsWrapperCache.h" #include "WebGLBindableName.h" #include "WebGLFramebufferAttachable.h" #include "WebGLObjectModel.h" #include "WebGLStrongTypes.h" -#include "nsWrapperCache.h" - -#include "mozilla/CheckedInt.h" -#include "mozilla/LinkedList.h" -#include "mozilla/Assertions.h" -#include -#include "nsAlgorithm.h" - namespace mozilla { // Zero is not an integer power of two. -inline bool is_pot_assuming_nonnegative(GLsizei x) +inline bool +IsPOTAssumingNonnegative(GLsizei x) { + MOZ_ASSERT(x >= 0); return x && (x & (x-1)) == 0; } @@ -38,15 +38,15 @@ class WebGLTexture MOZ_FINAL , public WebGLFramebufferAttachable { public: - explicit WebGLTexture(WebGLContext* aContext, GLuint tex); + explicit WebGLTexture(WebGLContext* webgl, GLuint tex); void Delete(); - WebGLContext *GetParentObject() const { + WebGLContext* GetParentObject() const { return Context(); } - virtual JSObject* WrapObject(JSContext *cx) MOZ_OVERRIDE; + virtual JSObject* WrapObject(JSContext* cx) MOZ_OVERRIDE; NS_INLINE_DECL_CYCLE_COLLECTING_NATIVE_REFCOUNTING(WebGLTexture) NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_NATIVE_CLASS(WebGLTexture) @@ -59,11 +59,10 @@ protected: friend class WebGLContext; friend class WebGLFramebuffer; - // we store information about the various images that are part of - // this texture (cubemap faces, mipmap levels) + // We store information about the various images that are part of this + // texture. (cubemap faces, mipmap levels) public: - class ImageInfo : public WebGLRectangleObject { @@ -74,9 +73,7 @@ public: , mImageDataStatus(WebGLImageDataStatus::NoImageData) {} - ImageInfo(GLsizei width, - GLsizei height, - GLsizei depth, + ImageInfo(GLsizei width, GLsizei height, GLsizei depth, TexInternalFormat effectiveInternalFormat, WebGLImageDataStatus status) : WebGLRectangleObject(width, height) @@ -105,27 +102,28 @@ public: return mWidth > 0 && mHeight > 0 && mDepth > 0; } bool IsPowerOfTwo() const { - return is_pot_assuming_nonnegative(mWidth) && - is_pot_assuming_nonnegative(mHeight); // negative sizes should never happen (caught in texImage2D...) + MOZ_ASSERT(mWidth >= 0); + MOZ_ASSERT(mHeight >= 0); + return IsPOTAssumingNonnegative(mWidth) && + IsPOTAssumingNonnegative(mHeight); } bool HasUninitializedImageData() const { return mImageDataStatus == WebGLImageDataStatus::UninitializedImageData; } size_t MemoryUsage() const; - TexInternalFormat EffectiveInternalFormat() const { return mEffectiveInternalFormat; } + TexInternalFormat EffectiveInternalFormat() const { + return mEffectiveInternalFormat; + } GLsizei Depth() const { return mDepth; } protected: - /* - * This is the "effective internal format" of the texture, - * an official OpenGL spec concept, see - * OpenGL ES 3.0.3 spec, section 3.8.3, page 126 and below. - */ + // This is the "effective internal format" of the texture, an official + // OpenGL spec concept, see OpenGL ES 3.0.3 spec, section 3.8.3, page + // 126 and below. TexInternalFormat mEffectiveInternalFormat; - /* - * Used only for 3D textures. + /* Used only for 3D textures. * Note that mWidth and mHeight are inherited from WebGLRectangleObject. * It's a pity to store a useless mDepth on non-3D texture images, but * the size of GLsizei is negligible compared to the typical size of a texture image. @@ -148,9 +146,12 @@ private: } ImageInfo& ImageInfoAtFace(size_t face, GLint level) { - MOZ_ASSERT(face < mFacesCount, "wrong face index, must be 0 for TEXTURE_2D or TEXTURE_3D, and at most 5 for cube maps"); + MOZ_ASSERT(face < mFacesCount, + "Wrong face index, must be 0 for TEXTURE_2D or TEXTURE_3D," + " and at most 5 for cube maps."); - // no need to check level as a wrong value would be caught by ElementAt(). + // No need to check level as a wrong value would be caught by + // ElementAt(). return mImageInfos.ElementAt(level * mFacesCount + face); } @@ -166,7 +167,8 @@ public: return ImageInfoAtFace(face, level); } - const ImageInfo& ImageInfoAt(TexImageTarget imageTarget, GLint level) const { + const ImageInfo& ImageInfoAt(TexImageTarget imageTarget, GLint level) const + { return const_cast(this)->ImageInfoAt(imageTarget, level); } @@ -188,22 +190,24 @@ public: size_t MemoryUsage() const; - void SetImageDataStatus(TexImageTarget imageTarget, GLint level, WebGLImageDataStatus newStatus) { + void SetImageDataStatus(TexImageTarget imageTarget, GLint level, + WebGLImageDataStatus newStatus) + { MOZ_ASSERT(HasImageInfoAt(imageTarget, level)); ImageInfo& imageInfo = ImageInfoAt(imageTarget, level); - // there is no way to go from having image data to not having any + // There is no way to go from having image data to not having any. MOZ_ASSERT(newStatus != WebGLImageDataStatus::NoImageData || imageInfo.mImageDataStatus == WebGLImageDataStatus::NoImageData); - if (imageInfo.mImageDataStatus != newStatus) { + + if (imageInfo.mImageDataStatus != newStatus) SetFakeBlackStatus(WebGLTextureFakeBlackStatus::Unknown); - } + imageInfo.mImageDataStatus = newStatus; } void EnsureNoUninitializedImageData(TexImageTarget imageTarget, GLint level); protected: - TexMinFilter mMinFilter; TexMagFilter mMagFilter; TexWrap mWrapS, mWrapT; @@ -211,59 +215,63 @@ protected: size_t mFacesCount, mMaxLevelWithCustomImages; nsTArray mImageInfos; - bool mHaveGeneratedMipmap; // set by generateMipmap - bool mImmutable; // set by texStorage* + bool mHaveGeneratedMipmap; // Set by generateMipmap + bool mImmutable; // Set by texStorage* - size_t mBaseMipmapLevel; // set by texParameter (defaults to 0) - size_t mMaxMipmapLevel; // set by texParameter (defaults to 1000) + size_t mBaseMipmapLevel; // Set by texParameter (defaults to 0) + size_t mMaxMipmapLevel; // Set by texParameter (defaults to 1000) WebGLTextureFakeBlackStatus mFakeBlackStatus; - void EnsureMaxLevelWithCustomImagesAtLeast(size_t aMaxLevelWithCustomImages) { - mMaxLevelWithCustomImages = std::max(mMaxLevelWithCustomImages, aMaxLevelWithCustomImages); + void EnsureMaxLevelWithCustomImagesAtLeast(size_t maxLevelWithCustomImages) { + mMaxLevelWithCustomImages = std::max(mMaxLevelWithCustomImages, + maxLevelWithCustomImages); mImageInfos.EnsureLengthAtLeast((mMaxLevelWithCustomImages + 1) * mFacesCount); } bool CheckFloatTextureFilterParams() const { - // Without OES_texture_float_linear, only NEAREST and NEAREST_MIMPAMP_NEAREST are supported - return (mMagFilter == LOCAL_GL_NEAREST) && - (mMinFilter == LOCAL_GL_NEAREST || mMinFilter == LOCAL_GL_NEAREST_MIPMAP_NEAREST); + // Without OES_texture_float_linear, only NEAREST and + // NEAREST_MIMPAMP_NEAREST are supported. + return mMagFilter == LOCAL_GL_NEAREST && + (mMinFilter == LOCAL_GL_NEAREST || + mMinFilter == LOCAL_GL_NEAREST_MIPMAP_NEAREST); } bool AreBothWrapModesClampToEdge() const { - return mWrapS == LOCAL_GL_CLAMP_TO_EDGE && mWrapT == LOCAL_GL_CLAMP_TO_EDGE; + return mWrapS == LOCAL_GL_CLAMP_TO_EDGE && + mWrapT == LOCAL_GL_CLAMP_TO_EDGE; } bool DoesMipmapHaveAllLevelsConsistentlyDefined(TexImageTarget texImageTarget) const; public: + void Bind(TexTarget texTarget); - void Bind(TexTarget aTexTarget); + void SetImageInfo(TexImageTarget target, GLint level, GLsizei width, + GLsizei height, GLsizei depth, TexInternalFormat format, + WebGLImageDataStatus status); - void SetImageInfo(TexImageTarget aTarget, GLint aLevel, - GLsizei aWidth, GLsizei aHeight, GLsizei aDepth, - TexInternalFormat aFormat, WebGLImageDataStatus aStatus); - - void SetMinFilter(TexMinFilter aMinFilter) { - mMinFilter = aMinFilter; + void SetMinFilter(TexMinFilter minFilter) { + mMinFilter = minFilter; SetFakeBlackStatus(WebGLTextureFakeBlackStatus::Unknown); } - void SetMagFilter(TexMagFilter aMagFilter) { - mMagFilter = aMagFilter; + void SetMagFilter(TexMagFilter magFilter) { + mMagFilter = magFilter; SetFakeBlackStatus(WebGLTextureFakeBlackStatus::Unknown); } - void SetWrapS(TexWrap aWrapS) { - mWrapS = aWrapS; + void SetWrapS(TexWrap wrapS) { + mWrapS = wrapS; SetFakeBlackStatus(WebGLTextureFakeBlackStatus::Unknown); } - void SetWrapT(TexWrap aWrapT) { - mWrapT = aWrapT; + void SetWrapT(TexWrap wrapT) { + mWrapT = wrapT; SetFakeBlackStatus(WebGLTextureFakeBlackStatus::Unknown); } TexMinFilter MinFilter() const { return mMinFilter; } bool DoesMinFilterRequireMipmap() const { - return !(mMinFilter == LOCAL_GL_NEAREST || mMinFilter == LOCAL_GL_LINEAR); + return !(mMinFilter == LOCAL_GL_NEAREST || + mMinFilter == LOCAL_GL_LINEAR); } void SetGeneratedMipmap(); @@ -298,8 +306,10 @@ public: return mBaseMipmapLevel; } size_t EffectiveMaxMipmapLevel() const { - if (IsImmutable()) - return mozilla::clamped(mMaxMipmapLevel, EffectiveBaseMipmapLevel(), mMaxLevelWithCustomImages); + if (IsImmutable()) { + return mozilla::clamped(mMaxMipmapLevel, EffectiveBaseMipmapLevel(), + mMaxLevelWithCustomImages); + } return std::min(mMaxMipmapLevel, mMaxLevelWithCustomImages); } bool IsMipmapRangeValid() const; @@ -315,18 +325,18 @@ inline TexImageTarget TexImageTargetForTargetAndFace(TexTarget target, size_t face) { switch (target.get()) { - case LOCAL_GL_TEXTURE_2D: - case LOCAL_GL_TEXTURE_3D: - MOZ_ASSERT(face == 0); - return target.get(); - case LOCAL_GL_TEXTURE_CUBE_MAP: - MOZ_ASSERT(face < 6); - return LOCAL_GL_TEXTURE_CUBE_MAP_POSITIVE_X + face; - default: - MOZ_CRASH(); + case LOCAL_GL_TEXTURE_2D: + case LOCAL_GL_TEXTURE_3D: + MOZ_ASSERT(face == 0); + return target.get(); + case LOCAL_GL_TEXTURE_CUBE_MAP: + MOZ_ASSERT(face < 6); + return LOCAL_GL_TEXTURE_CUBE_MAP_POSITIVE_X + face; + default: + MOZ_CRASH(); } } } // namespace mozilla -#endif +#endif // WEBGL_TEXTURE_H_ diff --git a/dom/canvas/WebGLTransformFeedback.cpp b/dom/canvas/WebGLTransformFeedback.cpp index 196508aecab7..bd950e246ae7 100644 --- a/dom/canvas/WebGLTransformFeedback.cpp +++ b/dom/canvas/WebGLTransformFeedback.cpp @@ -3,18 +3,17 @@ * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ -#include "WebGL2Context.h" #include "WebGLTransformFeedback.h" #include "GLContext.h" - #include "mozilla/dom/WebGL2RenderingContextBinding.h" +#include "WebGL2Context.h" -using namespace mozilla; +namespace mozilla { -WebGLTransformFeedback::WebGLTransformFeedback(WebGLContext* context) +WebGLTransformFeedback::WebGLTransformFeedback(WebGLContext* webgl) : WebGLBindableName(0) - , WebGLContextBoundObject(context) + , WebGLContextBoundObject(webgl) { MOZ_CRASH("Not Implemented."); } @@ -45,3 +44,5 @@ WebGLTransformFeedback::WrapObject(JSContext* cx) NS_IMPL_CYCLE_COLLECTION_WRAPPERCACHE_0(WebGLTransformFeedback) NS_IMPL_CYCLE_COLLECTION_ROOT_NATIVE(WebGLTransformFeedback, AddRef) NS_IMPL_CYCLE_COLLECTION_UNROOT_NATIVE(WebGLTransformFeedback, Release) + +} // namespace mozilla diff --git a/dom/canvas/WebGLTransformFeedback.h b/dom/canvas/WebGLTransformFeedback.h index e394f8d530b5..cd079f10c14a 100644 --- a/dom/canvas/WebGLTransformFeedback.h +++ b/dom/canvas/WebGLTransformFeedback.h @@ -3,15 +3,13 @@ * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ -#ifndef WEBGLTRANSFORMFEEDBACK_H_ -#define WEBGLTRANSFORMFEEDBACK_H_ - -#include "WebGLBindableName.h" -#include "WebGLObjectModel.h" - -#include "nsWrapperCache.h" +#ifndef WEBGL_TRANSFORM_FEEDBACK_H_ +#define WEBGL_TRANSFORM_FEEDBACK_H_ #include "mozilla/LinkedList.h" +#include "nsWrapperCache.h" +#include "WebGLBindableName.h" +#include "WebGLObjectModel.h" namespace mozilla { @@ -25,24 +23,19 @@ class WebGLTransformFeedback MOZ_FINAL friend class WebGLContext; public: - - explicit WebGLTransformFeedback(WebGLContext* aContext); + explicit WebGLTransformFeedback(WebGLContext* webgl); void Delete(); WebGLContext* GetParentObject() const; - - // ------------------------------------------------------------------------- - // IMPLEMENT NS virtual JSObject* WrapObject(JSContext* cx) MOZ_OVERRIDE; NS_INLINE_DECL_CYCLE_COLLECTING_NATIVE_REFCOUNTING(WebGLTransformFeedback) NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_NATIVE_CLASS(WebGLTransformFeedback) private: - ~WebGLTransformFeedback(); }; -} +} // namespace mozilla -#endif // !WEBGLTRANSFORMFEEDBACK_H_ +#endif // WEBGL_TRANSFORM_FEEDBACK_H_ diff --git a/dom/canvas/WebGLUniformLocation.cpp b/dom/canvas/WebGLUniformLocation.cpp index 89e9b7341708..992f1cd64f93 100644 --- a/dom/canvas/WebGLUniformLocation.cpp +++ b/dom/canvas/WebGLUniformLocation.cpp @@ -3,21 +3,25 @@ * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ -#include "WebGLContext.h" #include "WebGLUniformLocation.h" -#include "WebGLShader.h" -#include "WebGLProgram.h" -#include "mozilla/dom/WebGLRenderingContextBinding.h" -using namespace mozilla; +#include "mozilla/dom/WebGLRenderingContextBinding.h" +#include "WebGLContext.h" +#include "WebGLProgram.h" +#include "WebGLShader.h" + +namespace mozilla { JSObject* -WebGLUniformLocation::WrapObject(JSContext *cx) +WebGLUniformLocation::WrapObject(JSContext* cx) { return dom::WebGLUniformLocationBinding::Wrap(cx, this); } -WebGLUniformLocation::WebGLUniformLocation(WebGLContext *context, WebGLProgram *program, GLint location, const WebGLUniformInfo& info) +WebGLUniformLocation::WebGLUniformLocation(WebGLContext* context, + WebGLProgram* program, + GLint location, + const WebGLUniformInfo& info) : WebGLContextBoundObject(context) , mProgram(program) , mProgramGeneration(program->Generation()) @@ -31,3 +35,5 @@ NS_IMPL_CYCLE_COLLECTION(WebGLUniformLocation, mProgram) NS_IMPL_CYCLE_COLLECTION_ROOT_NATIVE(WebGLUniformLocation, AddRef) NS_IMPL_CYCLE_COLLECTION_UNROOT_NATIVE(WebGLUniformLocation, Release) + +} // namespace mozilla diff --git a/dom/canvas/WebGLUniformLocation.h b/dom/canvas/WebGLUniformLocation.h index 62acb9febd87..f8cfdec65052 100644 --- a/dom/canvas/WebGLUniformLocation.h +++ b/dom/canvas/WebGLUniformLocation.h @@ -3,8 +3,8 @@ * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ -#ifndef WEBGLUNIFORMLOCATION_H_ -#define WEBGLUNIFORMLOCATION_H_ +#ifndef WEBGL_UNIFORM_LOCATION_H_ +#define WEBGL_UNIFORM_LOCATION_H_ #include "WebGLObjectModel.h" #include "WebGLUniformInfo.h" @@ -17,27 +17,27 @@ class WebGLUniformLocation MOZ_FINAL : public WebGLContextBoundObject { public: - WebGLUniformLocation(WebGLContext *context, WebGLProgram *program, GLint location, const WebGLUniformInfo& info); + WebGLUniformLocation(WebGLContext* context, WebGLProgram* program, + GLint location, const WebGLUniformInfo& info); // needed for certain helper functions like ValidateObject. // WebGLUniformLocation's can't be 'Deleted' in the WebGL sense. bool IsDeleted() const { return false; } - const WebGLUniformInfo &Info() const { return mInfo; } + const WebGLUniformInfo& Info() const { return mInfo; } - WebGLProgram *Program() const { return mProgram; } + WebGLProgram* Program() const { return mProgram; } GLint Location() const { return mLocation; } uint32_t ProgramGeneration() const { return mProgramGeneration; } int ElementSize() const { return mElementSize; } - JSObject* WrapObject(JSContext *cx); + JSObject* WrapObject(JSContext* cx); NS_INLINE_DECL_CYCLE_COLLECTING_NATIVE_REFCOUNTING(WebGLUniformLocation) NS_DECL_CYCLE_COLLECTION_NATIVE_CLASS(WebGLUniformLocation) protected: - ~WebGLUniformLocation() { - } + ~WebGLUniformLocation() { } // nsRefPtr, not WebGLRefPtr, so that we don't prevent the program from being explicitly deleted. // we just want to avoid having a dangling pointer. @@ -52,4 +52,4 @@ protected: } // namespace mozilla -#endif +#endif // WEBGL_UNIFORM_LOCATION_H_ diff --git a/dom/canvas/WebGLValidateStrings.h b/dom/canvas/WebGLValidateStrings.h index e4f592783486..3112e056cef4 100644 --- a/dom/canvas/WebGLValidateStrings.h +++ b/dom/canvas/WebGLValidateStrings.h @@ -24,8 +24,8 @@ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#ifndef WEBGLVALIDATESTRINGS_H_ -#define WEBGLVALIDATESTRINGS_H_ +#ifndef WEBGL_VALIDATE_STRINGS_H_ +#define WEBGL_VALIDATE_STRINGS_H_ #include "WebGLContext.h" @@ -45,7 +45,8 @@ namespace mozilla { return true; } - // Horizontal tab, line feed, vertical tab, form feed, carriage return are also valid. + // Horizontal tab, line feed, vertical tab, form feed, carriage return + // are also valid. if (c >= 9 && c <= 13) { return true; } @@ -58,13 +59,13 @@ namespace mozilla { // implementations not expecting characters outside the GLSL ES set. class StripComments { public: - explicit StripComments(const nsAString& aStr) + explicit StripComments(const nsAString& str) : m_parseState(BeginningOfLine) - , m_end(aStr.EndReading()) - , m_current(aStr.BeginReading()) + , m_end(str.EndReading()) + , m_current(str.BeginReading()) , m_position(0) { - m_result.SetLength(aStr.Length()); + m_result.SetLength(str.Length()); parse(); } @@ -246,6 +247,6 @@ namespace mozilla { /****** END CODE TAKEN FROM WEBKIT ******/ -} // end namespace mozilla +} // namespace mozilla -#endif // WEBGLVALIDATESTRINGS_H_ +#endif // WEBGL_VALIDATE_STRINGS_H_ diff --git a/dom/canvas/WebGLVertexArray.cpp b/dom/canvas/WebGLVertexArray.cpp index f00a9dacd5c7..3b756cde63a5 100644 --- a/dom/canvas/WebGLVertexArray.cpp +++ b/dom/canvas/WebGLVertexArray.cpp @@ -5,38 +5,38 @@ #include "WebGLVertexArray.h" -#include "WebGLContext.h" +#include "GLContext.h" +#include "mozilla/dom/WebGLRenderingContextBinding.h" #include "WebGLBuffer.h" +#include "WebGLContext.h" #include "WebGLVertexArrayGL.h" #include "WebGLVertexArrayFake.h" -#include "mozilla/dom/WebGLRenderingContextBinding.h" -#include "GLContext.h" -using namespace mozilla; +namespace mozilla { JSObject* -WebGLVertexArray::WrapObject(JSContext *cx) { +WebGLVertexArray::WrapObject(JSContext* cx) +{ return dom::WebGLVertexArrayBinding::Wrap(cx, this); } -WebGLVertexArray::WebGLVertexArray(WebGLContext* context) +WebGLVertexArray::WebGLVertexArray(WebGLContext* webgl) : WebGLBindable() - , WebGLContextBoundObject(context) + , WebGLContextBoundObject(webgl) , mGLName(0) { - context->mVertexArrays.insertBack(this); + mContext->mVertexArrays.insertBack(this); } WebGLVertexArray* -WebGLVertexArray::Create(WebGLContext* context) +WebGLVertexArray::Create(WebGLContext* webgl) { WebGLVertexArray* array; - if (context->gl->IsSupported(gl::GLFeature::vertex_array_object)) { - array = new WebGLVertexArrayGL(context); + if (webgl->gl->IsSupported(gl::GLFeature::vertex_array_object)) { + array = new WebGLVertexArrayGL(webgl); } else { - array = new WebGLVertexArrayFake(context); + array = new WebGLVertexArrayFake(webgl); } - return array; } @@ -61,8 +61,10 @@ WebGLVertexArray::EnsureAttrib(GLuint index) } NS_IMPL_CYCLE_COLLECTION_WRAPPERCACHE(WebGLVertexArray, - mAttribs, - mElementArrayBuffer) + mAttribs, + mElementArrayBuffer) NS_IMPL_CYCLE_COLLECTION_ROOT_NATIVE(WebGLVertexArray, AddRef) NS_IMPL_CYCLE_COLLECTION_UNROOT_NATIVE(WebGLVertexArray, Release) + +} // namespace mozilla diff --git a/dom/canvas/WebGLVertexArray.h b/dom/canvas/WebGLVertexArray.h index bd4974e68ada..ce659151070e 100644 --- a/dom/canvas/WebGLVertexArray.h +++ b/dom/canvas/WebGLVertexArray.h @@ -3,18 +3,16 @@ * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ -#ifndef WEBGLVERTEXARRAY_H_ -#define WEBGLVERTEXARRAY_H_ - -#include "WebGLBindableName.h" -#include "WebGLObjectModel.h" -#include "WebGLBuffer.h" -#include "WebGLVertexAttribData.h" -#include "WebGLStrongTypes.h" - -#include "nsWrapperCache.h" +#ifndef WEBGL_VERTEX_ARRAY_H_ +#define WEBGL_VERTEX_ARRAY_H_ #include "mozilla/LinkedList.h" +#include "nsWrapperCache.h" +#include "WebGLBindableName.h" +#include "WebGLBuffer.h" +#include "WebGLObjectModel.h" +#include "WebGLStrongTypes.h" +#include "WebGLVertexAttribData.h" namespace mozilla { @@ -27,74 +25,57 @@ class WebGLVertexArray , public LinkedListElement , public WebGLContextBoundObject { -// ----------------------------------------------------------------------------- -// PUBLIC public: - static WebGLVertexArray* Create(WebGLContext* context); + static WebGLVertexArray* Create(WebGLContext* webgl); void BindVertexArray() { - /* Bind to dummy value to signal that this vertex array has - ever been bound */ + // Bind to dummy value to signal that this vertex array has ever been + // bound. BindTo(LOCAL_GL_VERTEX_ARRAY_BINDING); BindVertexArrayImpl(); }; virtual void GenVertexArray() = 0; virtual void BindVertexArrayImpl() = 0; - - // ------------------------------------------------------------------------- - // IMPLEMENT PARENT CLASSES - - void Delete(); - virtual void DeleteImpl() = 0; + void EnsureAttrib(GLuint index); + bool HasAttrib(GLuint index) const { + return index < mAttribs.Length(); + } + bool IsAttribArrayEnabled(GLuint index) const { + return HasAttrib(index) && mAttribs[index].enabled; + } + + // Implement parent classes: + void Delete(); + WebGLContext* GetParentObject() const { return Context(); } - virtual JSObject* WrapObject(JSContext *cx) MOZ_OVERRIDE; + virtual JSObject* WrapObject(JSContext* cx) MOZ_OVERRIDE; NS_INLINE_DECL_CYCLE_COLLECTING_NATIVE_REFCOUNTING(WebGLVertexArray) NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_NATIVE_CLASS(WebGLVertexArray) - // ------------------------------------------------------------------------- - // MEMBER FUNCTIONS - GLuint GLName() const { return mGLName; } - void EnsureAttrib(GLuint index); - bool HasAttrib(GLuint index) { - return index < mAttribs.Length(); - } - bool IsAttribArrayEnabled(GLuint index) { - return HasAttrib(index) && mAttribs[index].enabled; - } - - -// ----------------------------------------------------------------------------- -// PROTECTED protected: - explicit WebGLVertexArray(WebGLContext* aContext); + explicit WebGLVertexArray(WebGLContext* webgl); virtual ~WebGLVertexArray() { MOZ_ASSERT(IsDeleted()); - }; - - // ------------------------------------------------------------------------- - // MEMBERS + } GLuint mGLName; nsTArray mAttribs; WebGLRefPtr mElementArrayBuffer; - // ------------------------------------------------------------------------- - // FRIENDSHIPS - - friend class WebGLVertexArrayFake; friend class WebGLContext; + friend class WebGLVertexArrayFake; }; } // namespace mozilla -#endif +#endif // WEBGL_VERTEX_ARRAY_H_ diff --git a/dom/canvas/WebGLVertexArrayFake.cpp b/dom/canvas/WebGLVertexArrayFake.cpp index c83e7e076657..d8cf4a675c21 100644 --- a/dom/canvas/WebGLVertexArrayFake.cpp +++ b/dom/canvas/WebGLVertexArrayFake.cpp @@ -5,8 +5,8 @@ #include "WebGLVertexArrayFake.h" -#include "WebGLContext.h" #include "GLContext.h" +#include "WebGLContext.h" namespace mozilla { @@ -29,26 +29,24 @@ WebGLVertexArrayFake::BindVertexArrayImpl() mContext->BindBuffer(LOCAL_GL_ARRAY_BUFFER, vd.buf); - gl->fVertexAttribPointer(i, vd.size, vd.type, vd.normalized, - vd.stride, reinterpret_cast(vd.byteOffset)); + gl->fVertexAttribPointer(i, vd.size, vd.type, vd.normalized, vd.stride, + reinterpret_cast(vd.byteOffset)); - if (vd.enabled) { + if (vd.enabled) gl->fEnableVertexAttribArray(i); - } else { + else gl->fDisableVertexAttribArray(i); - } } - for (size_t i = mAttribs.Length(); i < prevVertexArray->mAttribs.Length(); ++i) { + size_t len = prevVertexArray->mAttribs.Length(); + for (size_t i = mAttribs.Length(); i < len; ++i) { const WebGLVertexAttribData& vd = prevVertexArray->mAttribs[i]; - if (vd.enabled) { + if (vd.enabled) gl->fDisableVertexAttribArray(i); - } } mContext->BindBuffer(LOCAL_GL_ARRAY_BUFFER, prevBuffer); } } // namespace mozilla - diff --git a/dom/canvas/WebGLVertexArrayFake.h b/dom/canvas/WebGLVertexArrayFake.h index 898aa28632ed..760207997d11 100644 --- a/dom/canvas/WebGLVertexArrayFake.h +++ b/dom/canvas/WebGLVertexArrayFake.h @@ -3,8 +3,8 @@ * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ -#ifndef WEBGLVERTEXARRAYFAKE_H_ -#define WEBGLVERTEXARRAYFAKE_H_ +#ifndef WEBGL_VERTEX_ARRAY_FAKE_H_ +#define WEBGL_VERTEX_ARRAY_FAKE_H_ #include "WebGLVertexArray.h" @@ -15,12 +15,12 @@ class WebGLVertexArrayFake MOZ_FINAL { public: virtual void BindVertexArrayImpl() MOZ_OVERRIDE; - virtual void DeleteImpl() MOZ_OVERRIDE { }; - virtual void GenVertexArray() MOZ_OVERRIDE { }; + virtual void DeleteImpl() MOZ_OVERRIDE {}; + virtual void GenVertexArray() MOZ_OVERRIDE {}; private: - explicit WebGLVertexArrayFake(WebGLContext* aContext) - : WebGLVertexArray(aContext) + explicit WebGLVertexArrayFake(WebGLContext* webgl) + : WebGLVertexArray(webgl) { } ~WebGLVertexArrayFake() { @@ -32,4 +32,4 @@ private: } // namespace mozilla -#endif +#endif // WEBGL_VERTEX_ARRAY_FAKE_H_ diff --git a/dom/canvas/WebGLVertexArrayGL.cpp b/dom/canvas/WebGLVertexArrayGL.cpp index ca93a9321771..06d1f76c1716 100644 --- a/dom/canvas/WebGLVertexArrayGL.cpp +++ b/dom/canvas/WebGLVertexArrayGL.cpp @@ -5,8 +5,8 @@ #include "WebGLVertexArrayGL.h" -#include "WebGLContext.h" #include "GLContext.h" +#include "WebGLContext.h" namespace mozilla { diff --git a/dom/canvas/WebGLVertexArrayGL.h b/dom/canvas/WebGLVertexArrayGL.h index 41c82a036509..367712a29ceb 100644 --- a/dom/canvas/WebGLVertexArrayGL.h +++ b/dom/canvas/WebGLVertexArrayGL.h @@ -3,8 +3,8 @@ * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ -#ifndef WEBGLVERTEXARRAYGL_H_ -#define WEBGLVERTEXARRAYGL_H_ +#ifndef WEBGL_VERTEX_ARRAY_GL_H_ +#define WEBGL_VERTEX_ARRAY_GL_H_ #include "WebGLVertexArray.h" @@ -19,8 +19,8 @@ public: virtual void GenVertexArray() MOZ_OVERRIDE; private: - explicit WebGLVertexArrayGL(WebGLContext* aContext) - : WebGLVertexArray(aContext) + explicit WebGLVertexArrayGL(WebGLContext* webgl) + : WebGLVertexArray(webgl) { } ~WebGLVertexArrayGL() { @@ -32,4 +32,4 @@ private: } // namespace mozilla -#endif +#endif // WEBGL_VERTEX_ARRAY_GL_H_ diff --git a/dom/canvas/WebGLVertexAttribData.h b/dom/canvas/WebGLVertexAttribData.h index 86f4233b358b..e42bd110cc5b 100644 --- a/dom/canvas/WebGLVertexAttribData.h +++ b/dom/canvas/WebGLVertexAttribData.h @@ -3,14 +3,18 @@ * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ -#ifndef WEBGLVERTEXATTRIBDATA_H_ -#define WEBGLVERTEXATTRIBDATA_H_ +#ifndef WEBGL_VERTEX_ATTRIB_DATA_H_ +#define WEBGL_VERTEX_ATTRIB_DATA_H_ + +#include "GLDefs.h" +#include "WebGLObjectModel.h" namespace mozilla { class WebGLBuffer; -struct WebGLVertexAttribData { +struct WebGLVertexAttribData +{ // note that these initial values are what GL initializes vertex attribs to WebGLVertexAttribData() : buf(0) @@ -21,7 +25,7 @@ struct WebGLVertexAttribData { , type(LOCAL_GL_FLOAT) , enabled(false) , normalized(false) - { } + {} WebGLRefPtr buf; GLuint stride; @@ -34,48 +38,51 @@ struct WebGLVertexAttribData { GLuint componentSize() const { switch(type) { - case LOCAL_GL_BYTE: - return sizeof(GLbyte); - break; - case LOCAL_GL_UNSIGNED_BYTE: - return sizeof(GLubyte); - break; - case LOCAL_GL_SHORT: - return sizeof(GLshort); - break; - case LOCAL_GL_UNSIGNED_SHORT: - return sizeof(GLushort); - break; - // XXX case LOCAL_GL_FIXED: - case LOCAL_GL_FLOAT: - return sizeof(GLfloat); - break; - default: - NS_ERROR("Should never get here!"); - return 0; + case LOCAL_GL_BYTE: + return sizeof(GLbyte); + + case LOCAL_GL_UNSIGNED_BYTE: + return sizeof(GLubyte); + + case LOCAL_GL_SHORT: + return sizeof(GLshort); + + case LOCAL_GL_UNSIGNED_SHORT: + return sizeof(GLushort); + + // case LOCAL_GL_FIXED: + case LOCAL_GL_FLOAT: + return sizeof(GLfloat); + + default: + NS_ERROR("Should never get here!"); + return 0; } } GLuint actualStride() const { - if (stride) return stride; + if (stride) + return stride; + return size * componentSize(); } }; } // namespace mozilla -inline void ImplCycleCollectionUnlink(mozilla::WebGLVertexAttribData& aField) +inline void +ImplCycleCollectionUnlink(mozilla::WebGLVertexAttribData& field) { - aField.buf = nullptr; + field.buf = nullptr; } inline void -ImplCycleCollectionTraverse(nsCycleCollectionTraversalCallback& aCallback, - mozilla::WebGLVertexAttribData& aField, - const char* aName, - uint32_t aFlags = 0) +ImplCycleCollectionTraverse(nsCycleCollectionTraversalCallback& callback, + mozilla::WebGLVertexAttribData& field, + const char* name, + uint32_t flags = 0) { - CycleCollectionNoteChild(aCallback, aField.buf.get(), aName, aFlags); + CycleCollectionNoteChild(callback, field.buf.get(), name, flags); } -#endif \ No newline at end of file +#endif // WEBGL_VERTEX_ATTRIB_DATA_H_ diff --git a/dom/canvas/compiledtest/TestWebGLElementArrayCache.cpp b/dom/canvas/compiledtest/TestWebGLElementArrayCache.cpp index c29a9bfef922..242cf4f2c1e6 100644 --- a/dom/canvas/compiledtest/TestWebGLElementArrayCache.cpp +++ b/dom/canvas/compiledtest/TestWebGLElementArrayCache.cpp @@ -16,7 +16,8 @@ using namespace mozilla; int gTestsPassed = 0; -void VerifyImplFunction(bool condition, const char* file, int line) +void +VerifyImplFunction(bool condition, const char* file, int line) { if (condition) { gTestsPassed++; @@ -29,7 +30,9 @@ void VerifyImplFunction(bool condition, const char* file, int line) #define VERIFY(condition) \ VerifyImplFunction((condition), __FILE__, __LINE__) -void MakeRandomVector(nsTArray& a, size_t size) { +void +MakeRandomVector(nsTArray& a, size_t size) +{ a.SetLength(size); // only the most-significant bits of rand() are reasonably random. // RAND_MAX can be as low as 0x7fff, and we need 8 bits for the result, so we can only @@ -39,32 +42,30 @@ void MakeRandomVector(nsTArray& a, size_t size) { } template -T RandomInteger(T a, T b) +T +RandomInteger(T a, T b) { T result(a + rand() % (b - a + 1)); return result; } template -GLenum GLType() +GLenum +GLType() { - switch (sizeof(T)) - { - case 4: return LOCAL_GL_UNSIGNED_INT; - case 2: return LOCAL_GL_UNSIGNED_SHORT; - case 1: return LOCAL_GL_UNSIGNED_BYTE; - default: - VERIFY(false); - return 0; + switch (sizeof(T)) { + case 4: return LOCAL_GL_UNSIGNED_INT; + case 2: return LOCAL_GL_UNSIGNED_SHORT; + case 1: return LOCAL_GL_UNSIGNED_BYTE; + default: + VERIFY(false); + return 0; } } -void CheckValidate(bool expectSuccess, - WebGLElementArrayCache& c, - GLenum type, - uint32_t maxAllowed, - size_t first, - size_t count) +void +CheckValidate(bool expectSuccess, WebGLElementArrayCache& c, GLenum type, + uint32_t maxAllowed, size_t first, size_t count) { uint32_t out_upperBound = 0; const bool success = c.Validate(type, maxAllowed, first, count, &out_upperBound); @@ -77,7 +78,8 @@ void CheckValidate(bool expectSuccess, } template -void CheckValidateOneTypeVariousBounds(WebGLElementArrayCache& c, size_t firstByte, size_t countBytes) +void +CheckValidateOneTypeVariousBounds(WebGLElementArrayCache& c, size_t firstByte, size_t countBytes) { size_t first = firstByte / sizeof(T); size_t count = countBytes / sizeof(T); @@ -106,7 +108,8 @@ void CheckValidateAllTypes(WebGLElementArrayCache& c, size_t firstByte, size_t c } template -void CheckSanity() +void +CheckSanity() { const size_t numElems = 64; // should be significantly larger than tree leaf size to // ensure we exercise some nontrivial tree-walking @@ -142,7 +145,8 @@ void CheckSanity() } template -void CheckUintOverflow() +void +CheckUintOverflow() { // This test is only for integer types smaller than uint32_t static_assert(sizeof(T) < sizeof(uint32_t), "This test is only for integer types \ @@ -169,7 +173,8 @@ void CheckUintOverflow() CheckValidate(false, c, type, 0, 0, numElems); } -int main(int argc, char *argv[]) +int +main(int argc, char* argv[]) { srand(0); // do not want a random seed here. diff --git a/dom/canvas/compiledtest/moz.build b/dom/canvas/compiledtest/moz.build index c8a6c0fbc343..e0728e373d00 100644 --- a/dom/canvas/compiledtest/moz.build +++ b/dom/canvas/compiledtest/moz.build @@ -4,6 +4,9 @@ # License, v. 2.0. If a copy of the MPL was not distributed with this # file, You can obtain one at http://mozilla.org/MPL/2.0/. +# http://support.microsoft.com/kb/143208 +DEFINES['NOMINMAX'] = True + GeckoCppUnitTests([ 'TestWebGLElementArrayCache', ]) diff --git a/dom/canvas/moz.build b/dom/canvas/moz.build index 9313c774c19d..5cb8f181e7e0 100644 --- a/dom/canvas/moz.build +++ b/dom/canvas/moz.build @@ -25,6 +25,9 @@ EXPORTS.mozilla.dom += [ 'TextMetrics.h', ] +# http://support.microsoft.com/kb/143208 +DEFINES['NOMINMAX'] = True + # Canvas 2D and common sources UNIFIED_SOURCES += [ 'CanvasImageCache.cpp', From 7b7c876367574d8e38ae8d7ed0836137f5fdece1 Mon Sep 17 00:00:00 2001 From: Gijs Kruitbosch Date: Wed, 26 Nov 2014 23:52:50 +0000 Subject: [PATCH 54/64] Bug 1101624 - use dummy page instead of about:blank to avoid a race, r=mconley --HG-- extra : rebase_source : c4857c425e10096c30dfe01af7ea99f2a8c69c8e --- browser/base/content/test/general/browser_alltabslistener.js | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/browser/base/content/test/general/browser_alltabslistener.js b/browser/base/content/test/general/browser_alltabslistener.js index 87e1da08809a..52f1d00633f0 100644 --- a/browser/base/content/test/general/browser_alltabslistener.js +++ b/browser/base/content/test/general/browser_alltabslistener.js @@ -81,13 +81,14 @@ var gAllProgressListener = { var gFrontNotifications, gAllNotifications, gFrontNotificationsPos, gAllNotificationsPos; var gBackgroundTab, gForegroundTab, gBackgroundBrowser, gForegroundBrowser, gTestBrowser; var gTestPage = "/browser/browser/base/content/test/general/alltabslistener.html"; +const kBasePage = "http://example.org/browser/browser/base/content/test/general/dummy_page.html"; var gNextTest; function test() { waitForExplicitFinish(); - gBackgroundTab = gBrowser.addTab("about:blank"); - gForegroundTab = gBrowser.addTab("about:blank"); + gBackgroundTab = gBrowser.addTab(kBasePage); + gForegroundTab = gBrowser.addTab(kBasePage); gBackgroundBrowser = gBrowser.getBrowserForTab(gBackgroundTab); gForegroundBrowser = gBrowser.getBrowserForTab(gForegroundTab); gBrowser.selectedTab = gForegroundTab; From b877692a44fd620978e172da67d2727103ceeee3 Mon Sep 17 00:00:00 2001 From: Gijs Kruitbosch Date: Mon, 17 Nov 2014 16:52:24 +0000 Subject: [PATCH 55/64] Bug 1100419 - add --timeout switch to mochitets, r=ted --HG-- extra : rebase_source : 21285fe8cbab61365f4c987b2119b7feb8d64c08 --- testing/mochitest/mach_commands.py | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/testing/mochitest/mach_commands.py b/testing/mochitest/mach_commands.py index 581323a03b67..210b2341acc4 100644 --- a/testing/mochitest/mach_commands.py +++ b/testing/mochitest/mach_commands.py @@ -194,7 +194,7 @@ class MochitestRunner(MozbuildObject): e10s=False, content_sandbox='off', dmd=False, dump_output_directory=None, dump_about_memory_after_test=False, dump_dmd_after_test=False, install_extension=None, quiet=False, environment=[], app_override=None, bisectChunk=None, runByDir=False, - useTestMediaDevices=False, **kwargs): + useTestMediaDevices=False, timeout=None, **kwargs): """Runs a mochitest. test_paths are path to tests. They can be a relative path from the @@ -325,6 +325,8 @@ class MochitestRunner(MozbuildObject): options.bisectChunk = bisectChunk options.runByDir = runByDir options.useTestMediaDevices = useTestMediaDevices + if timeout: + options.timeout = int(timeout) options.failureFile = failure_file_path if install_extension != None: @@ -569,6 +571,10 @@ def MochitestCommand(func): "run tests against the distribution bundle's binary."); func = app_override(func) + timeout = CommandArgument('--timeout', default=None, + help='The per-test timeout time in seconds (default: 60 seconds)'); + func = timeout(func) + return func def B2GCommand(func): From c0127916ec7e15062af6da88db02f31daeb41581 Mon Sep 17 00:00:00 2001 From: Phil Ringnalda Date: Wed, 26 Nov 2014 17:42:04 -0800 Subject: [PATCH 56/64] Back out 01093b5a774b (bug 948194) for not fixing enough races --HG-- extra : rebase_source : 7e2d451639be57ef03818d84ba2e4e7fd72fa63d --- image/test/browser/browser.ini | 1 + image/test/browser/browser_bug666317.js | 139 +++++++++--------------- 2 files changed, 53 insertions(+), 87 deletions(-) diff --git a/image/test/browser/browser.ini b/image/test/browser/browser.ini index 10bb14ea7ff4..46f56acdb242 100644 --- a/image/test/browser/browser.ini +++ b/image/test/browser/browser.ini @@ -8,5 +8,6 @@ support-files = imageX2.html [browser_bug666317.js] +skip-if = e10s # Bug 948194 - Decoded Images seem to not be discarded on memory-pressure notification with e10s enabled [browser_image.js] skip-if = e10s || !debug # Test is only to run on debug builds diff --git a/image/test/browser/browser_bug666317.js b/image/test/browser/browser_bug666317.js index 7f592c387d8e..15064760890e 100644 --- a/image/test/browser/browser_bug666317.js +++ b/image/test/browser/browser_bug666317.js @@ -1,9 +1,7 @@ -"use strict"; - waitForExplicitFinish(); let pageSource = - '' + + '' + '' + ''; @@ -12,67 +10,47 @@ let prefBranch = Cc["@mozilla.org/preferences-service;1"] .getService(Ci.nsIPrefService) .getBranch('image.mem.'); -function imgDiscardingFrameScript() { - const Cc = Components.classes; - const Ci = Components.interfaces; - - function ImageDiscardObserver(result) { - this.discard = function onDiscard(request) { - result.wasDiscarded = true; - } +function ImageDiscardObserver(result) { + this.discard = function onDiscard(request) + { + result.wasDiscarded = true; + this.synchronous = false; } - function currentRequest() { - let img = content.document.getElementById('testImg'); - img.QueryInterface(Ci.nsIImageLoadingContent); - return img.getRequest(Ci.nsIImageLoadingContent.CURRENT_REQUEST); - } + this.synchronous = true; +} - function attachDiscardObserver(result) { - // Create the discard observer. - let observer = new ImageDiscardObserver(result); - let scriptedObserver = Cc["@mozilla.org/image/tools;1"] - .getService(Ci.imgITools) - .createScriptedObserver(observer); +function currentRequest() { + let img = gBrowser.getBrowserForTab(newTab).contentWindow + .document.getElementById('testImg'); + img.QueryInterface(Ci.nsIImageLoadingContent); + return img.getRequest(Ci.nsIImageLoadingContent.CURRENT_REQUEST); +} - // Clone the current imgIRequest with our new observer. - let request = currentRequest(); - return [ request.clone(scriptedObserver), scriptedObserver ]; - } +function attachDiscardObserver(result) { + // Create the discard observer. + let observer = new ImageDiscardObserver(result); + let scriptedObserver = Cc["@mozilla.org/image/tools;1"] + .getService(Ci.imgITools) + .createScriptedObserver(observer); - // Attach a discard listener and create a place to hold the result. - var result = { wasDiscarded: false }; - var scriptedObserver; - var clonedRequest; + // Clone the current imgIRequest with our new observer. + let request = currentRequest(); + return request.clone(scriptedObserver); +} - addMessageListener("test666317:testPart1", function(message) { - // Ensure that the image is decoded by drawing it to a canvas. - let doc = content.document; - let img = doc.getElementById('testImg'); - let canvas = doc.createElement('canvas'); - let ctx = canvas.getContext('2d'); - ctx.drawImage(img, 0, 0); +function isImgDecoded() { + let request = currentRequest(); + return request.imageStatus & Ci.imgIRequest.STATUS_FRAME_COMPLETE ? true : false; +} - // Verify that we decoded the image. - // Note: We grab a reference to the scripted observer because the image - // holds a weak ref to it. If we don't hold a strong reference, we might - // end up using a deleted pointer. - [ clonedRequest, scriptedObserver ] = attachDiscardObserver(result) - let decoded = clonedRequest.imageStatus & Ci.imgIRequest.STATUS_FRAME_COMPLETE ? true : false; - - message.target.sendAsyncMessage("test666317:testPart1:Answer", - { decoded }); - }); - - addMessageListener("test666317:wasImgDiscarded", function(message) { - let discarded = result.wasDiscarded; - - // NOTE: We know that this is the last test. - clonedRequest.cancelAndForgetObserver(0); - scriptedObserver = null; - message.target.sendAsyncMessage("test666317:wasImgDiscarded:Answer", - { discarded }); - }); +// Ensure that the image is decoded by drawing it to a canvas. +function forceDecodeImg() { + let doc = gBrowser.getBrowserForTab(newTab).contentWindow.document; + let img = doc.getElementById('testImg'); + let canvas = doc.createElement('canvas'); + let ctx = canvas.getContext('2d'); + ctx.drawImage(img, 0, 0); } function test() { @@ -91,38 +69,25 @@ function test() { } function step2() { - let mm = gBrowser.getBrowserForTab(newTab).QueryInterface(Ci.nsIFrameLoaderOwner) - .frameLoader.messageManager; - mm.loadFrameScript("data:,(" + escape(imgDiscardingFrameScript.toString()) + ")();", false); + // Attach a discard listener and create a place to hold the result. + var result = { wasDiscarded: false }; + var clonedRequest = attachDiscardObserver(result); // Check that the image is decoded. - mm.addMessageListener("test666317:testPart1:Answer", function(message) { - let decoded = message.data.decoded; - ok(decoded, 'Image should initially be decoded.'); + forceDecodeImg(); + ok(isImgDecoded(), 'Image should initially be decoded.'); - // Focus the old tab, then fire a memory-pressure notification. This should - // cause the decoded image in the new tab to be discarded. - gBrowser.selectedTab = oldTab; - waitForFocus(() => { - var os = Cc["@mozilla.org/observer-service;1"] - .getService(Ci.nsIObserverService); + // Focus the old tab, then fire a memory-pressure notification. This should + // cause the decoded image in the new tab to be discarded. + gBrowser.selectedTab = oldTab; + var os = Cc["@mozilla.org/observer-service;1"] + .getService(Ci.nsIObserverService); + os.notifyObservers(null, 'memory-pressure', 'heap-minimize'); + ok(result.wasDiscarded, 'Image should be discarded.'); - os.notifyObservers(null, 'memory-pressure', 'heap-minimize'); - - // Now ask if it was. - mm.sendAsyncMessage("test666317:wasImgDiscarded"); - }, oldTab.contentWindow); - }); - - mm.addMessageListener("test666317:wasImgDiscarded:Answer", function(message) { - let discarded = message.data.discarded; - ok(discarded, 'Image should be discarded.'); - - // And we're done. - gBrowser.removeTab(newTab); - prefBranch.setBoolPref('discardable', oldDiscardingPref); - finish(); - }); - - mm.sendAsyncMessage("test666317:testPart1"); + // And we're done. + gBrowser.removeTab(newTab); + prefBranch.setBoolPref('discardable', oldDiscardingPref); + clonedRequest.cancelAndForgetObserver(0); + finish(); } From 102bd529836f41142b3912eb3ceb2d96aaa29caf Mon Sep 17 00:00:00 2001 From: Seth Fowler Date: Wed, 26 Nov 2014 18:00:15 -0800 Subject: [PATCH 57/64] Bug 1065818 - Clean up memory reports and use of decoded size for image cache entries. r=tn,njn --- image/src/DynamicImage.cpp | 32 +- image/src/DynamicImage.h | 9 +- image/src/FrameBlender.cpp | 13 +- image/src/FrameBlender.h | 4 +- image/src/Image.cpp | 15 - image/src/Image.h | 24 +- image/src/ImageWrapper.cpp | 29 +- image/src/ImageWrapper.h | 11 +- image/src/RasterImage.cpp | 30 +- image/src/RasterImage.h | 11 +- image/src/SurfaceCache.cpp | 5 +- image/src/VectorImage.cpp | 76 ++--- image/src/VectorImage.h | 9 +- image/src/imgFrame.cpp | 13 +- image/src/imgFrame.h | 5 +- image/src/imgLoader.cpp | 589 +++++++++++++++++----------------- image/src/imgRequest.cpp | 6 +- image/src/imgRequest.h | 6 +- image/src/imgRequestProxy.cpp | 10 - 19 files changed, 369 insertions(+), 528 deletions(-) diff --git a/image/src/DynamicImage.cpp b/image/src/DynamicImage.cpp index 3f2b63699cee..1851abd6c3d9 100644 --- a/image/src/DynamicImage.cpp +++ b/image/src/DynamicImage.cpp @@ -43,41 +43,17 @@ DynamicImage::FrameRect(uint32_t aWhichFrame) return nsIntRect(0, 0, size.width, size.height); } -uint32_t -DynamicImage::SizeOfData() -{ - // We don't know the answer to this (and the same goes for the other - // memory-related methods) since gfxDrawable doesn't expose a way to check. - return 0; -} - size_t -DynamicImage::HeapSizeOfSourceWithComputedFallback(mozilla::MallocSizeOf aMallocSizeOf) const +DynamicImage::SizeOfSourceWithComputedFallback(MallocSizeOf aMallocSizeOf) const { return 0; } size_t -DynamicImage::HeapSizeOfDecodedWithComputedFallback(mozilla::MallocSizeOf aMallocSizeOf) const -{ - return 0; -} - -size_t -DynamicImage::NonHeapSizeOfDecoded() const -{ - return 0; -} - -size_t -DynamicImage::OutOfProcessSizeOfDecoded() const -{ - return 0; -} - -size_t -DynamicImage::HeapSizeOfVectorImageDocument(nsACString* aDocURL) const +DynamicImage::SizeOfDecoded(gfxMemoryLocation aLocation, + MallocSizeOf aMallocSizeOf) const { + // We don't know the answer since gfxDrawable doesn't expose this information. return 0; } diff --git a/image/src/DynamicImage.h b/image/src/DynamicImage.h index ea17e1e133c4..66880194d316 100644 --- a/image/src/DynamicImage.h +++ b/image/src/DynamicImage.h @@ -37,12 +37,9 @@ public: virtual already_AddRefed GetProgressTracker() MOZ_OVERRIDE; virtual nsIntRect FrameRect(uint32_t aWhichFrame) MOZ_OVERRIDE; - virtual uint32_t SizeOfData() MOZ_OVERRIDE; - virtual size_t HeapSizeOfSourceWithComputedFallback(mozilla::MallocSizeOf aMallocSizeOf) const MOZ_OVERRIDE; - virtual size_t HeapSizeOfDecodedWithComputedFallback(mozilla::MallocSizeOf aMallocSizeOf) const MOZ_OVERRIDE; - virtual size_t NonHeapSizeOfDecoded() const MOZ_OVERRIDE; - virtual size_t OutOfProcessSizeOfDecoded() const MOZ_OVERRIDE; - virtual size_t HeapSizeOfVectorImageDocument(nsACString* aDocURL = nullptr) const MOZ_OVERRIDE; + virtual size_t SizeOfSourceWithComputedFallback(MallocSizeOf aMallocSizeOf) const MOZ_OVERRIDE; + virtual size_t SizeOfDecoded(gfxMemoryLocation aLocation, + MallocSizeOf aMallocSizeOf) const MOZ_OVERRIDE; virtual void IncrementAnimationConsumers() MOZ_OVERRIDE; virtual void DecrementAnimationConsumers() MOZ_OVERRIDE; diff --git a/image/src/FrameBlender.cpp b/image/src/FrameBlender.cpp index 9f47601816e8..7aa219dc45ca 100644 --- a/image/src/FrameBlender.cpp +++ b/image/src/FrameBlender.cpp @@ -563,26 +563,23 @@ FrameBlender::Discard() } size_t -FrameBlender::SizeOfDecodedWithComputedFallbackIfHeap(gfxMemoryLocation aLocation, - MallocSizeOf aMallocSizeOf) const +FrameBlender::SizeOfDecoded(gfxMemoryLocation aLocation, + MallocSizeOf aMallocSizeOf) const { size_t n = 0; for (uint32_t i = 0; i < mFrames.Length(); ++i) { - n += mFrames[i]->SizeOfExcludingThisWithComputedFallbackIfHeap(aLocation, - aMallocSizeOf); + n += mFrames[i]->SizeOfExcludingThis(aLocation, aMallocSizeOf); } if (mAnim) { if (mAnim->compositingFrame) { n += mAnim->compositingFrame - ->SizeOfExcludingThisWithComputedFallbackIfHeap(aLocation, - aMallocSizeOf); + ->SizeOfExcludingThis(aLocation, aMallocSizeOf); } if (mAnim->compositingPrevFrame) { n += mAnim->compositingPrevFrame - ->SizeOfExcludingThisWithComputedFallbackIfHeap(aLocation, - aMallocSizeOf); + ->SizeOfExcludingThis(aLocation, aMallocSizeOf); } } diff --git a/image/src/FrameBlender.h b/image/src/FrameBlender.h index f70774420c16..e0e7e7b9fc7b 100644 --- a/image/src/FrameBlender.h +++ b/image/src/FrameBlender.h @@ -72,8 +72,8 @@ public: void SetSize(nsIntSize aSize) { mSize = aSize; } - size_t SizeOfDecodedWithComputedFallbackIfHeap(gfxMemoryLocation aLocation, - MallocSizeOf aMallocSizeOf) const; + size_t SizeOfDecoded(gfxMemoryLocation aLocation, + MallocSizeOf aMallocSizeOf) const; void ResetAnimation(); diff --git a/image/src/Image.cpp b/image/src/Image.cpp index dd9430521a82..b6f66300457d 100644 --- a/image/src/Image.cpp +++ b/image/src/Image.cpp @@ -24,21 +24,6 @@ ImageResource::ImageResource(ImageURL* aURI) : { } -uint32_t -ImageResource::SizeOfData() -{ - if (mError) - return 0; - - // This is not used by memory reporters, but for sizing the cache, which is - // why it uses |moz_malloc_size_of| rather than a - // |MOZ_DEFINE_MALLOC_SIZE_OF|. - return uint32_t(HeapSizeOfSourceWithComputedFallback(moz_malloc_size_of) + - HeapSizeOfDecodedWithComputedFallback(moz_malloc_size_of) + - NonHeapSizeOfDecoded() + - OutOfProcessSizeOfDecoded()); -} - // Translates a mimetype into a concrete decoder Image::eDecoderType Image::GetDecoderType(const char *aMimeType) diff --git a/image/src/Image.h b/image/src/Image.h index aec050b97226..c8abedfcbb8f 100644 --- a/image/src/Image.h +++ b/image/src/Image.h @@ -7,6 +7,7 @@ #define MOZILLA_IMAGELIB_IMAGE_H_ #include "mozilla/MemoryReporting.h" +#include "gfx2DGlue.h" // for gfxMemoryLocation #include "imgIContainer.h" #include "ProgressTracker.h" #include "ImageURL.h" @@ -72,25 +73,17 @@ public: virtual nsIntRect FrameRect(uint32_t aWhichFrame) = 0; /** - * The size, in bytes, occupied by the significant data portions of the image. - * This includes both compressed source data and decoded frames. + * The size, in bytes, occupied by the compressed source data of the image. + * If MallocSizeOf does not work on this platform, uses a fallback approach to + * ensure that something reasonable is always returned. */ - virtual uint32_t SizeOfData() = 0; + virtual size_t SizeOfSourceWithComputedFallback(MallocSizeOf aMallocSizeOf) const = 0; /** - * The components that make up SizeOfData(). + * The size, in bytes, occupied by the image's decoded data. */ - virtual size_t HeapSizeOfSourceWithComputedFallback(MallocSizeOf aMallocSizeOf) const = 0; - virtual size_t HeapSizeOfDecodedWithComputedFallback(MallocSizeOf aMallocSizeOf) const = 0; - virtual size_t NonHeapSizeOfDecoded() const = 0; - virtual size_t OutOfProcessSizeOfDecoded() const = 0; - - /** - * Gets the size of the memory taken up for the parsed vector image's - * document (e.g. SVGDocument), and returns the document's URL via the - * aDocURL outparam. - */ - virtual size_t HeapSizeOfVectorImageDocument(nsACString* aDocURL = nullptr) const = 0; + virtual size_t SizeOfDecoded(gfxMemoryLocation aLocation, + MallocSizeOf aMallocSizeOf) const = 0; virtual void IncrementAnimationConsumers() = 0; virtual void DecrementAnimationConsumers() = 0; @@ -156,7 +149,6 @@ public: MOZ_ASSERT(!mProgressTracker); mProgressTracker = aProgressTracker; } - virtual uint32_t SizeOfData() MOZ_OVERRIDE; virtual void IncrementAnimationConsumers() MOZ_OVERRIDE; virtual void DecrementAnimationConsumers() MOZ_OVERRIDE; diff --git a/image/src/ImageWrapper.cpp b/image/src/ImageWrapper.cpp index ed28788e12ad..d313581648ce 100644 --- a/image/src/ImageWrapper.cpp +++ b/image/src/ImageWrapper.cpp @@ -39,34 +39,17 @@ ImageWrapper::FrameRect(uint32_t aWhichFrame) return mInnerImage->FrameRect(aWhichFrame); } -uint32_t -ImageWrapper::SizeOfData() +size_t +ImageWrapper::SizeOfSourceWithComputedFallback(MallocSizeOf aMallocSizeOf) const { - return mInnerImage->SizeOfData(); + return mInnerImage->SizeOfSourceWithComputedFallback(aMallocSizeOf); } size_t -ImageWrapper::HeapSizeOfSourceWithComputedFallback(MallocSizeOf aMallocSizeOf) const +ImageWrapper::SizeOfDecoded(gfxMemoryLocation aLocation, + MallocSizeOf aMallocSizeOf) const { - return mInnerImage->HeapSizeOfSourceWithComputedFallback(aMallocSizeOf); -} - -size_t -ImageWrapper::HeapSizeOfDecodedWithComputedFallback(MallocSizeOf aMallocSizeOf) const -{ - return mInnerImage->HeapSizeOfDecodedWithComputedFallback(aMallocSizeOf); -} - -size_t -ImageWrapper::NonHeapSizeOfDecoded() const -{ - return mInnerImage->NonHeapSizeOfDecoded(); -} - -size_t -ImageWrapper::OutOfProcessSizeOfDecoded() const -{ - return mInnerImage->OutOfProcessSizeOfDecoded(); + return mInnerImage->SizeOfDecoded(aLocation, aMallocSizeOf); } void diff --git a/image/src/ImageWrapper.h b/image/src/ImageWrapper.h index 9e24dd045d51..44e7b7ca02c0 100644 --- a/image/src/ImageWrapper.h +++ b/image/src/ImageWrapper.h @@ -27,15 +27,8 @@ public: virtual already_AddRefed GetProgressTracker() MOZ_OVERRIDE; virtual nsIntRect FrameRect(uint32_t aWhichFrame) MOZ_OVERRIDE; - virtual uint32_t SizeOfData() MOZ_OVERRIDE; - virtual size_t HeapSizeOfSourceWithComputedFallback(MallocSizeOf aMallocSizeOf) const MOZ_OVERRIDE; - virtual size_t HeapSizeOfDecodedWithComputedFallback(MallocSizeOf aMallocSizeOf) const MOZ_OVERRIDE; - virtual size_t NonHeapSizeOfDecoded() const MOZ_OVERRIDE; - virtual size_t OutOfProcessSizeOfDecoded() const MOZ_OVERRIDE; - - virtual size_t HeapSizeOfVectorImageDocument(nsACString* aDocURL = nullptr) const MOZ_OVERRIDE { - return mInnerImage->HeapSizeOfVectorImageDocument(aDocURL); - } + virtual size_t SizeOfSourceWithComputedFallback(MallocSizeOf aMallocSizeOf) const MOZ_OVERRIDE; + virtual size_t SizeOfDecoded(gfxMemoryLocation aLocation, MallocSizeOf aMallocSizeOf) const MOZ_OVERRIDE; virtual void IncrementAnimationConsumers() MOZ_OVERRIDE; virtual void DecrementAnimationConsumers() MOZ_OVERRIDE; diff --git a/image/src/RasterImage.cpp b/image/src/RasterImage.cpp index b468537987af..f23ac141318e 100644 --- a/image/src/RasterImage.cpp +++ b/image/src/RasterImage.cpp @@ -964,7 +964,7 @@ RasterImage::UpdateImageContainer() } size_t -RasterImage::HeapSizeOfSourceWithComputedFallback(MallocSizeOf aMallocSizeOf) const +RasterImage::SizeOfSourceWithComputedFallback(MallocSizeOf aMallocSizeOf) const { // n == 0 is possible for two reasons. // - This is a zero-length image. @@ -978,39 +978,17 @@ RasterImage::HeapSizeOfSourceWithComputedFallback(MallocSizeOf aMallocSizeOf) co } size_t -RasterImage::SizeOfDecodedWithComputedFallbackIfHeap(gfxMemoryLocation aLocation, - MallocSizeOf aMallocSizeOf) const +RasterImage::SizeOfDecoded(gfxMemoryLocation aLocation, + MallocSizeOf aMallocSizeOf) const { size_t n = 0; n += SurfaceCache::SizeOfSurfaces(ImageKey(this), aLocation, aMallocSizeOf); if (mFrameBlender) { - n += mFrameBlender->SizeOfDecodedWithComputedFallbackIfHeap(aLocation, - aMallocSizeOf); + n += mFrameBlender->SizeOfDecoded(aLocation, aMallocSizeOf); } return n; } -size_t -RasterImage::HeapSizeOfDecodedWithComputedFallback(MallocSizeOf aMallocSizeOf) const -{ - return SizeOfDecodedWithComputedFallbackIfHeap(gfxMemoryLocation::IN_PROCESS_HEAP, - aMallocSizeOf); -} - -size_t -RasterImage::NonHeapSizeOfDecoded() const -{ - return SizeOfDecodedWithComputedFallbackIfHeap(gfxMemoryLocation::IN_PROCESS_NONHEAP, - nullptr); -} - -size_t -RasterImage::OutOfProcessSizeOfDecoded() const -{ - return SizeOfDecodedWithComputedFallbackIfHeap(gfxMemoryLocation::OUT_OF_PROCESS, - nullptr); -} - RawAccessFrameRef RasterImage::InternalAddFrame(uint32_t aFrameNum, const nsIntRect& aFrameRect, diff --git a/image/src/RasterImage.h b/image/src/RasterImage.h index f4b017dc88b6..3947c4d509dc 100644 --- a/image/src/RasterImage.h +++ b/image/src/RasterImage.h @@ -171,14 +171,9 @@ public: /* The total number of frames in this image. */ uint32_t GetNumFrames() const; - virtual size_t HeapSizeOfSourceWithComputedFallback(MallocSizeOf aMallocSizeOf) const; - virtual size_t HeapSizeOfDecodedWithComputedFallback(MallocSizeOf aMallocSizeOf) const; - virtual size_t NonHeapSizeOfDecoded() const; - virtual size_t OutOfProcessSizeOfDecoded() const; - - virtual size_t HeapSizeOfVectorImageDocument(nsACString* aDocURL = nullptr) const MOZ_OVERRIDE { - return 0; - } + virtual size_t SizeOfSourceWithComputedFallback(MallocSizeOf aMallocSizeOf) const; + virtual size_t SizeOfDecoded(gfxMemoryLocation aLocation, + MallocSizeOf aMallocSizeOf) const; /* Triggers discarding. */ void Discard(bool aForce = false, bool aNotify = true); diff --git a/image/src/SurfaceCache.cpp b/image/src/SurfaceCache.cpp index ec94dae7e85f..35e59b5f1752 100644 --- a/image/src/SurfaceCache.cpp +++ b/image/src/SurfaceCache.cpp @@ -175,9 +175,8 @@ public: if (!aCachedSurface->mSurface) { return; } - - mSum += aCachedSurface->mSurface-> - SizeOfExcludingThisWithComputedFallbackIfHeap(mLocation, mMallocSizeOf); + mSum += aCachedSurface->mSurface->SizeOfExcludingThis(mLocation, + mMallocSizeOf); } size_t Result() const { return mSum; } diff --git a/image/src/VectorImage.cpp b/image/src/VectorImage.cpp index 2eeda34ee551..2cabd7adf4d2 100644 --- a/image/src/VectorImage.cpp +++ b/image/src/VectorImage.cpp @@ -366,71 +366,35 @@ VectorImage::FrameRect(uint32_t aWhichFrame) } size_t -VectorImage::HeapSizeOfSourceWithComputedFallback(MallocSizeOf aMallocSizeOf) const -{ - // We're not storing the source data -- we just feed that directly to - // our helper SVG document as we receive it, for it to parse. - // So 0 is an appropriate return value here. - // If implementing this, we'll need to restructure our callers to make sure - // any amount we return is attributed to the vector images measure (i.e. - // "explicit/images/{content,chrome}/vector/{used,unused}/...") - return 0; -} - -size_t -VectorImage::HeapSizeOfDecodedWithComputedFallback(MallocSizeOf aMallocSizeOf) const -{ - // If implementing this, we'll need to restructure our callers to make sure - // any amount we return is attributed to the vector images measure (i.e. - // "explicit/images/{content,chrome}/vector/{used,unused}/...") - // XXX(seth): Same goes for the other *SizeOfDecoded() methods. We'll do this - // in bug 921300 or one of its blockers. For now it seems worthwhile to get - // this memory accounted for, even if it gets listed under 'raster'. It does - // make some perverse sense, since we are after all reporting on raster data - // here - it just happens to be computed from a vector document. - return SurfaceCache::SizeOfSurfaces(ImageKey(this), - gfxMemoryLocation::IN_PROCESS_HEAP, - aMallocSizeOf); -} - -size_t -VectorImage::NonHeapSizeOfDecoded() const -{ - return SurfaceCache::SizeOfSurfaces(ImageKey(this), - gfxMemoryLocation::IN_PROCESS_NONHEAP, - nullptr); -} - -size_t -VectorImage::OutOfProcessSizeOfDecoded() const -{ - return SurfaceCache::SizeOfSurfaces(ImageKey(this), - gfxMemoryLocation::OUT_OF_PROCESS, - nullptr); -} - -MOZ_DEFINE_MALLOC_SIZE_OF(WindowsMallocSizeOf); - -size_t -VectorImage::HeapSizeOfVectorImageDocument(nsACString* aDocURL) const +VectorImage::SizeOfSourceWithComputedFallback(MallocSizeOf aMallocSizeOf) const { nsIDocument* doc = mSVGDocumentWrapper->GetDocument(); if (!doc) { - if (aDocURL) { - mURI->GetSpec(*aDocURL); - } - return 0; // No document, so no memory used for the document + return 0; // No document, so no memory used for the document. } - if (aDocURL) { - doc->GetDocumentURI()->GetSpec(*aDocURL); - } - - nsWindowSizes windowSizes(WindowsMallocSizeOf); + nsWindowSizes windowSizes(aMallocSizeOf); doc->DocAddSizeOfIncludingThis(&windowSizes); + + if (windowSizes.getTotalSize() == 0) { + // MallocSizeOf fails on this platform. Because we also use this method for + // determining the size of cache entries, we need to return something + // reasonable here. Unfortunately, there's no way to estimate the document's + // size accurately, so we just use a constant value of 100KB, which will + // generally underestimate the true size. + return 100 * 1024; + } + return windowSizes.getTotalSize(); } +size_t +VectorImage::SizeOfDecoded(gfxMemoryLocation aLocation, + MallocSizeOf aMallocSizeOf) const +{ + return SurfaceCache::SizeOfSurfaces(ImageKey(this), aLocation, aMallocSizeOf); +} + nsresult VectorImage::OnImageDataComplete(nsIRequest* aRequest, nsISupports* aContext, diff --git a/image/src/VectorImage.h b/image/src/VectorImage.h index b6cb161eeb0b..894446d65ceb 100644 --- a/image/src/VectorImage.h +++ b/image/src/VectorImage.h @@ -42,12 +42,9 @@ public: uint32_t aFlags); virtual nsIntRect FrameRect(uint32_t aWhichFrame) MOZ_OVERRIDE; - virtual size_t HeapSizeOfSourceWithComputedFallback(MallocSizeOf aMallocSizeOf) const; - virtual size_t HeapSizeOfDecodedWithComputedFallback(MallocSizeOf aMallocSizeOf) const; - virtual size_t NonHeapSizeOfDecoded() const; - virtual size_t OutOfProcessSizeOfDecoded() const; - - virtual size_t HeapSizeOfVectorImageDocument(nsACString* aDocURL = nullptr) const MOZ_OVERRIDE; + virtual size_t SizeOfSourceWithComputedFallback(MallocSizeOf aMallocSizeOf) const MOZ_OVERRIDE; + virtual size_t SizeOfDecoded(gfxMemoryLocation aLocation, + MallocSizeOf aMallocSizeOf) const MOZ_OVERRIDE; virtual nsresult OnImageDataAvailable(nsIRequest* aRequest, nsISupports* aContext, diff --git a/image/src/imgFrame.cpp b/image/src/imgFrame.cpp index 094f698a974a..dac25f4cf95e 100644 --- a/image/src/imgFrame.cpp +++ b/image/src/imgFrame.cpp @@ -905,11 +905,9 @@ void imgFrame::SetCompositingFailed(bool val) mCompositingFailed = val; } -// If |aLocation| indicates this is heap memory, we try to measure things with -// |aMallocSizeOf|. If that fails (because the platform doesn't support it) or -// it's non-heap memory, we fall back to computing the size analytically. size_t -imgFrame::SizeOfExcludingThisWithComputedFallbackIfHeap(gfxMemoryLocation aLocation, MallocSizeOf aMallocSizeOf) const +imgFrame::SizeOfExcludingThis(gfxMemoryLocation aLocation, + MallocSizeOf aMallocSizeOf) const { // aMallocSizeOf is only used if aLocation==gfxMemoryLocation::IN_PROCESS_HEAP. It // should be nullptr otherwise. @@ -921,13 +919,8 @@ imgFrame::SizeOfExcludingThisWithComputedFallbackIfHeap(gfxMemoryLocation aLocat size_t n = 0; if (mPalettedImageData && aLocation == gfxMemoryLocation::IN_PROCESS_HEAP) { - size_t n2 = aMallocSizeOf(mPalettedImageData); - if (n2 == 0) { - n2 = GetImageDataLength() + PaletteDataLength(); - } - n += n2; + n += aMallocSizeOf(mPalettedImageData); } - if (mImageSurface && aLocation == gfxMemoryLocation::IN_PROCESS_HEAP) { n += aMallocSizeOf(mImageSurface); } diff --git a/image/src/imgFrame.h b/image/src/imgFrame.h index 8c61039ff001..597116ed40fe 100644 --- a/image/src/imgFrame.h +++ b/image/src/imgFrame.h @@ -131,9 +131,8 @@ public: TemporaryRef CachedSurface(); - size_t SizeOfExcludingThisWithComputedFallbackIfHeap( - gfxMemoryLocation aLocation, - MallocSizeOf aMallocSizeOf) const; + size_t SizeOfExcludingThis(gfxMemoryLocation aLocation, + MallocSizeOf aMallocSizeOf) const; uint8_t GetPaletteDepth() const { return mPaletteDepth; } uint32_t PaletteDataLength() const { diff --git a/image/src/imgLoader.cpp b/image/src/imgLoader.cpp index f6813c799017..8471870a4fae 100644 --- a/image/src/imgLoader.cpp +++ b/image/src/imgLoader.cpp @@ -54,75 +54,39 @@ MOZ_DEFINE_MALLOC_SIZE_OF(ImagesMallocSizeOf) class imgMemoryReporter MOZ_FINAL : public nsIMemoryReporter { - ~imgMemoryReporter() {} + ~imgMemoryReporter() { } public: NS_DECL_ISUPPORTS - NS_IMETHOD CollectReports(nsIMemoryReporterCallback *aHandleReport, - nsISupports *aData, bool aAnonymize) + NS_IMETHOD CollectReports(nsIHandleReportCallback* aHandleReport, + nsISupports* aData, bool aAnonymize) { nsresult rv; - ImageSizes chrome; - ImageSizes content; - ImageSizes uncached; + nsTArray chrome; + nsTArray content; + nsTArray uncached; for (uint32_t i = 0; i < mKnownLoaders.Length(); i++) { - mKnownLoaders[i]->mChromeCache.EnumerateRead(EntryImageSizes, &chrome); - mKnownLoaders[i]->mCache.EnumerateRead(EntryImageSizes, &content); + mKnownLoaders[i]->mChromeCache.EnumerateRead(DoRecordCounter, &chrome); + mKnownLoaders[i]->mCache.EnumerateRead(DoRecordCounter, &content); MutexAutoLock lock(mKnownLoaders[i]->mUncachedImagesMutex); - mKnownLoaders[i]->mUncachedImages.EnumerateEntries(EntryUncachedImageSizes, &uncached); + mKnownLoaders[i]-> + mUncachedImages.EnumerateEntries(DoRecordCounterUncached, &uncached); } // Note that we only need to anonymize content image URIs. - rv = ReportInfoArray(aHandleReport, aData, chrome.mRasterUsedImageInfo, - "images/chrome/raster/used"); + rv = ReportCounterArray(aHandleReport, aData, chrome, "images/chrome"); NS_ENSURE_SUCCESS(rv, rv); - rv = ReportInfoArray(aHandleReport, aData, chrome.mRasterUnusedImageInfo, - "images/chrome/raster/unused"); + rv = ReportCounterArray(aHandleReport, aData, content, + "images/content", aAnonymize); NS_ENSURE_SUCCESS(rv, rv); - rv = ReportInfoArray(aHandleReport, aData, chrome.mVectorUsedImageDocInfo, - "images/chrome/vector/used/documents"); - NS_ENSURE_SUCCESS(rv, rv); - - rv = ReportInfoArray(aHandleReport, aData, chrome.mVectorUnusedImageDocInfo, - "images/chrome/vector/unused/documents"); - NS_ENSURE_SUCCESS(rv, rv); - - rv = ReportInfoArray(aHandleReport, aData, content.mRasterUsedImageInfo, - "images/content/raster/used", aAnonymize); - NS_ENSURE_SUCCESS(rv, rv); - - rv = ReportInfoArray(aHandleReport, aData, content.mRasterUnusedImageInfo, - "images/content/raster/unused", aAnonymize); - NS_ENSURE_SUCCESS(rv, rv); - - rv = ReportInfoArray(aHandleReport, aData, content.mVectorUsedImageDocInfo, - "images/content/vector/used/documents", aAnonymize); - NS_ENSURE_SUCCESS(rv, rv); - - rv = ReportInfoArray(aHandleReport, aData, content.mVectorUnusedImageDocInfo, - "images/content/vector/unused/documents", aAnonymize); - NS_ENSURE_SUCCESS(rv, rv); - - // The uncached images can contain both content and chrome images, so anonymize it. - rv = ReportInfoArray(aHandleReport, aData, uncached.mRasterUsedImageInfo, - "images/uncached/raster/used", aAnonymize); - NS_ENSURE_SUCCESS(rv, rv); - - rv = ReportInfoArray(aHandleReport, aData, uncached.mRasterUnusedImageInfo, - "images/uncached/raster/unused", aAnonymize); - NS_ENSURE_SUCCESS(rv, rv); - - rv = ReportInfoArray(aHandleReport, aData, uncached.mVectorUsedImageDocInfo, - "images/uncached/vector/used/documents", aAnonymize); - NS_ENSURE_SUCCESS(rv, rv); - - rv = ReportInfoArray(aHandleReport, aData, uncached.mVectorUnusedImageDocInfo, - "images/uncached/vector/unused/documents", aAnonymize); + // Uncached images may be content or chrome, so anonymize them. + rv = ReportCounterArray(aHandleReport, aData, uncached, + "images/uncached", aAnonymize); NS_ENSURE_SUCCESS(rv, rv); return NS_OK; @@ -132,7 +96,8 @@ public: { size_t n = 0; for (uint32_t i = 0; i < imgLoader::sMemReporter->mKnownLoaders.Length(); i++) { - imgLoader::sMemReporter->mKnownLoaders[i]->mCache.EnumerateRead(EntryUsedUncompressedSize, &n); + imgLoader::sMemReporter->mKnownLoaders[i]-> + mCache.EnumerateRead(DoRecordCounterUsedDecoded, &n); } return n; } @@ -150,306 +115,342 @@ public: private: nsTArray mKnownLoaders; - struct RasterSizes + struct MemoryCounter { - size_t mRaw; - size_t mUncompressedHeap; - size_t mUncompressedNonheap; + MemoryCounter() + : mSource(0) + , mDecodedHeap(0) + , mDecodedNonHeap(0) + { } - RasterSizes() - : mRaw(0) - , mUncompressedHeap(0) - , mUncompressedNonheap(0) - {} + void SetSource(size_t aCount) { mSource = aCount; } + size_t Source() const { return mSource; } + void SetDecodedHeap(size_t aCount) { mDecodedHeap = aCount; } + size_t DecodedHeap() const { return mDecodedHeap; } + void SetDecodedNonHeap(size_t aCount) { mDecodedNonHeap = aCount; } + size_t DecodedNonHeap() const { return mDecodedNonHeap; } - void add(const RasterSizes &aOther) + MemoryCounter& operator+=(const MemoryCounter& aOther) { - mRaw += aOther.mRaw; - mUncompressedHeap += aOther.mUncompressedHeap; - mUncompressedNonheap += aOther.mUncompressedNonheap; + mSource += aOther.mSource; + mDecodedHeap += aOther.mDecodedHeap; + mDecodedNonHeap += aOther.mDecodedNonHeap; + return *this; } - bool isNotable() const - { - const size_t NotableThreshold = 16 * 1024; - size_t total = mRaw + mUncompressedHeap + mUncompressedNonheap; - return total >= NotableThreshold; - } + private: + size_t mSource; + size_t mDecodedHeap; + size_t mDecodedNonHeap; }; - struct VectorDocSizes + struct ImageMemoryCounter { - size_t mSize; - - VectorDocSizes() - : mSize(0) - {} - - void add(const VectorDocSizes &aOther) + ImageMemoryCounter(uint16_t aType, const nsACString& aURI, bool aIsUsed) + : mURI(aURI) + , mType(aType) + , mIsUsed(aIsUsed) { - mSize += aOther.mSize; + MOZ_ASSERT(!mURI.IsEmpty(), "Should have a URI for all images"); } - bool isNotable() const + nsCString& URI() { return mURI; } + const nsCString& URI() const { return mURI; } + uint16_t Type() const { return mType; } + MemoryCounter& Values() { return mValues; } + const MemoryCounter& Values() const { return mValues; } + bool IsUsed() const { return mIsUsed; } + + bool IsNotable() const { const size_t NotableThreshold = 16 * 1024; - size_t total = mSize; + size_t total = mValues.Source() + mValues.DecodedHeap() + + mValues.DecodedNonHeap(); return total >= NotableThreshold; } - }; - template - struct ImageInfo - { - ImageSizes mSizes; + private: nsCString mURI; + uint16_t mType; + MemoryCounter mValues; + bool mIsUsed; }; - struct ImageSizes + struct MemoryTotal { - nsTArray > mRasterUsedImageInfo; - nsTArray > mRasterUnusedImageInfo; - nsTArray > mVectorUsedImageDocInfo; - nsTArray > mVectorUnusedImageDocInfo; - }; - - // Definitions specialized for raster and vector images are below. - template - nsresult ReportSizes(nsIMemoryReporterCallback *aHandleReport, - nsISupports *aData, - const nsACString &aPathPrefix, - const nsACString &aLocation, - Sizes aSizes); - - // This is used to report all images of a single kind, e.g. all - // "chrome/raster/used" images. - template - nsresult ReportInfoArray(nsIMemoryReporterCallback *aHandleReport, - nsISupports *aData, - const nsTArray > &aInfoArray, - const char *aPathPartStr, bool aAnonymize = false) - { - nsresult rv; - Sizes totalSizes; - Sizes nonNotableSizes; - - nsCString pathPart(aPathPartStr); - nsCString explicitPathPrefix(aPathPartStr); - explicitPathPrefix.Insert("explicit/", 0); - - // Report notable images, and compute total and non-notable aggregate sizes. - for (uint32_t i = 0; i < aInfoArray.Length(); i++) { - ImageInfo info = aInfoArray[i]; - - if (aAnonymize) { - info.mURI.Truncate(); - info.mURI.AppendPrintf("", i); - } else { - // info.mURI can be a data: URI, and thus extremely long. Truncate if - // necessary. - static const size_t max = 256; - if (info.mURI.Length() > max) { - info.mURI.Truncate(max); - info.mURI.AppendLiteral(" (truncated)"); + MemoryTotal& operator+=(const ImageMemoryCounter& aImageCounter) + { + if (aImageCounter.Type() == imgIContainer::TYPE_RASTER) { + if (aImageCounter.IsUsed()) { + mUsedRasterCounter += aImageCounter.Values(); + } else { + mUnusedRasterCounter += aImageCounter.Values(); } - info.mURI.ReplaceChar('/', '\\'); + } else if (aImageCounter.Type() == imgIContainer::TYPE_VECTOR) { + if (aImageCounter.IsUsed()) { + mUsedVectorCounter += aImageCounter.Values(); + } else { + mUnusedVectorCounter += aImageCounter.Values(); + } + } else { + MOZ_CRASH("Unexpected image type"); } - totalSizes.add(info.mSizes); + return *this; + } - if (!info.mSizes.isNotable()) { - nonNotableSizes.add(info.mSizes); + const MemoryCounter& UsedRaster() const { return mUsedRasterCounter; } + const MemoryCounter& UnusedRaster() const { return mUnusedRasterCounter; } + const MemoryCounter& UsedVector() const { return mUsedVectorCounter; } + const MemoryCounter& UnusedVector() const { return mUnusedVectorCounter; } + + private: + MemoryCounter mUsedRasterCounter; + MemoryCounter mUnusedRasterCounter; + MemoryCounter mUsedVectorCounter; + MemoryCounter mUnusedVectorCounter; + }; + + + // Reports all images of a single kind, e.g. all used chrome images. + nsresult ReportCounterArray(nsIHandleReportCallback* aHandleReport, + nsISupports* aData, + const nsTArray& aCounterArray, + const char* aPathPrefix, + bool aAnonymize = false) + { + nsresult rv; + MemoryTotal summaryTotal; + MemoryTotal nonNotableTotal; + + // Report notable images, and compute total and non-notable aggregate sizes. + for (uint32_t i = 0; i < aCounterArray.Length(); i++) { + ImageMemoryCounter counter = aCounterArray[i]; + + if (aAnonymize) { + counter.URI().Truncate(); + counter.URI().AppendPrintf("", i); } else { - // Report the notable image. - rv = ReportSizes(aHandleReport, aData, explicitPathPrefix, - info.mURI, info.mSizes); + // The URI could be an extremely long data: URI. Truncate if needed. + static const size_t max = 256; + if (counter.URI().Length() > max) { + counter.URI().Truncate(max); + counter.URI().AppendLiteral(" (truncated)"); + } + counter.URI().ReplaceChar('/', '\\'); + } + + summaryTotal += counter; + + if (counter.IsNotable()) { + rv = ReportCounter(aHandleReport, aData, aPathPrefix, counter); NS_ENSURE_SUCCESS(rv, rv); + } else { + nonNotableTotal += counter; } } // Report non-notable images in aggregate. - rv = ReportSizes(aHandleReport, aData, explicitPathPrefix, - NS_LITERAL_CSTRING(""), - nonNotableSizes); + rv = ReportTotal(aHandleReport, aData, /* aExplicit = */ true, + aPathPrefix, "/", nonNotableTotal); NS_ENSURE_SUCCESS(rv, rv); - // Report image totals in aggregate, without the "explicit/" prefix. - rv = ReportSizes(aHandleReport, aData, pathPart, EmptyCString(), - totalSizes); + // Report a summary in aggregate, outside of the explicit tree. + rv = ReportTotal(aHandleReport, aData, /* aExplicit = */ false, + aPathPrefix, "", summaryTotal); NS_ENSURE_SUCCESS(rv, rv); return NS_OK; } - static PLDHashOperator EntryImageSizes(const nsACString&, - imgCacheEntry *aEntry, - void *aUserArg) + static nsresult ReportCounter(nsIHandleReportCallback* aHandleReport, + nsISupports* aData, + const char* aPathPrefix, + const ImageMemoryCounter& aCounter) { - nsRefPtr req = aEntry->GetRequest(); - Image *image = static_cast(req->mImage.get()); - if (image) { - ImageSizes *sizes = static_cast(aUserArg); + nsAutoCString pathPrefix(NS_LITERAL_CSTRING("explicit/")); + pathPrefix.Append(aPathPrefix); + pathPrefix.Append(aCounter.Type() == imgIContainer::TYPE_RASTER + ? "/raster/" + : "/vector/"); + pathPrefix.Append(aCounter.IsUsed() ? "used/" : "unused/"); + pathPrefix.Append("image("); + if (aCounter.URI().IsEmpty()) { + pathPrefix.Append(""); + } else { + pathPrefix.Append(aCounter.URI()); + } + pathPrefix.Append(")/"); - nsRefPtr imageURL(image->GetURI()); - nsAutoCString spec; - imageURL->GetSpec(spec); - ImageInfo rasterInfo; - rasterInfo.mSizes.mRaw = - image->HeapSizeOfSourceWithComputedFallback(ImagesMallocSizeOf); - rasterInfo.mSizes.mUncompressedHeap = - image->HeapSizeOfDecodedWithComputedFallback(ImagesMallocSizeOf); - rasterInfo.mSizes.mUncompressedNonheap = image->NonHeapSizeOfDecoded(); - rasterInfo.mURI = spec.get(); - if (!aEntry->HasNoProxies()) { - sizes->mRasterUsedImageInfo.AppendElement(rasterInfo); - } else { - sizes->mRasterUnusedImageInfo.AppendElement(rasterInfo); - } + return ReportValues(aHandleReport, aData, pathPrefix, aCounter.Values()); + } - ImageInfo vectorInfo; - vectorInfo.mSizes.mSize = - image->HeapSizeOfVectorImageDocument(&vectorInfo.mURI); - if (!vectorInfo.mURI.IsEmpty()) { - if (!aEntry->HasNoProxies()) { - sizes->mVectorUsedImageDocInfo.AppendElement(vectorInfo); - } else { - sizes->mVectorUnusedImageDocInfo.AppendElement(vectorInfo); - } - } + static nsresult ReportTotal(nsIHandleReportCallback* aHandleReport, + nsISupports* aData, + bool aExplicit, + const char* aPathPrefix, + const char* aPathInfix, + const MemoryTotal& aTotal) + { + nsresult rv; + + nsAutoCString pathPrefix; + if (aExplicit) { + pathPrefix.Append("explicit/"); + } + pathPrefix.Append(aPathPrefix); + + nsAutoCString rasterUsedPrefix(pathPrefix); + rasterUsedPrefix.Append("/raster/used/"); + rasterUsedPrefix.Append(aPathInfix); + rv = ReportValues(aHandleReport, aData, rasterUsedPrefix, + aTotal.UsedRaster()); + NS_ENSURE_SUCCESS(rv, rv); + + nsAutoCString rasterUnusedPrefix(pathPrefix); + rasterUnusedPrefix.Append("/raster/unused/"); + rasterUnusedPrefix.Append(aPathInfix); + rv = ReportValues(aHandleReport, aData, rasterUnusedPrefix, + aTotal.UnusedRaster()); + NS_ENSURE_SUCCESS(rv, rv); + + nsAutoCString vectorUsedPrefix(pathPrefix); + vectorUsedPrefix.Append("/vector/used/"); + vectorUsedPrefix.Append(aPathInfix); + rv = ReportValues(aHandleReport, aData, vectorUsedPrefix, + aTotal.UsedVector()); + NS_ENSURE_SUCCESS(rv, rv); + + nsAutoCString vectorUnusedPrefix(pathPrefix); + vectorUnusedPrefix.Append("/vector/unused/"); + vectorUnusedPrefix.Append(aPathInfix); + rv = ReportValues(aHandleReport, aData, vectorUnusedPrefix, + aTotal.UnusedVector()); + NS_ENSURE_SUCCESS(rv, rv); + + return NS_OK; + } + + static nsresult ReportValues(nsIHandleReportCallback* aHandleReport, + nsISupports* aData, + const nsACString& aPathPrefix, + const MemoryCounter& aCounter) + { + nsresult rv; + + rv = ReportValue(aHandleReport, aData, KIND_HEAP, aPathPrefix, + "source", + "Raster image source data and vector image documents.", + aCounter.Source()); + NS_ENSURE_SUCCESS(rv, rv); + + rv = ReportValue(aHandleReport, aData, KIND_HEAP, aPathPrefix, + "decoded-heap", + "Decoded image data which is stored on the heap.", + aCounter.DecodedHeap()); + NS_ENSURE_SUCCESS(rv, rv); + + rv = ReportValue(aHandleReport, aData, KIND_NONHEAP, aPathPrefix, + "decoded-nonheap", + "Decoded image data which isn't stored on the heap.", + aCounter.DecodedNonHeap()); + NS_ENSURE_SUCCESS(rv, rv); + + return NS_OK; + } + + static nsresult ReportValue(nsIHandleReportCallback* aHandleReport, + nsISupports* aData, + int32_t aKind, + const nsACString& aPathPrefix, + const char* aPathSuffix, + const char* aDescription, + size_t aValue) + { + if (aValue == 0) { + return NS_OK; } + nsAutoCString desc(aDescription); + nsAutoCString path(aPathPrefix); + path.Append(aPathSuffix); + + return aHandleReport->Callback(EmptyCString(), path, aKind, UNITS_BYTES, + aValue, desc, aData); + } + + static PLDHashOperator DoRecordCounter(const nsACString&, + imgCacheEntry* aEntry, + void* aUserArg) + { + nsRefPtr req = aEntry->GetRequest(); + RecordCounterForRequest(req, + static_cast*>(aUserArg), + !aEntry->HasNoProxies()); return PL_DHASH_NEXT; } - static PLDHashOperator EntryUncachedImageSizes(nsPtrHashKey* aEntry, + static PLDHashOperator DoRecordCounterUncached(nsPtrHashKey* aEntry, void* aUserArg) { nsRefPtr req = aEntry->GetKey(); - Image *image = static_cast(req->mImage.get()); - if (image) { - ImageSizes *sizes = static_cast(aUserArg); - - nsRefPtr imageURL(image->GetURI()); - nsAutoCString spec; - imageURL->GetSpec(spec); - ImageInfo rasterInfo; - rasterInfo.mSizes.mRaw = - image->HeapSizeOfSourceWithComputedFallback(ImagesMallocSizeOf); - rasterInfo.mSizes.mUncompressedHeap = - image->HeapSizeOfDecodedWithComputedFallback(ImagesMallocSizeOf); - rasterInfo.mSizes.mUncompressedNonheap = image->NonHeapSizeOfDecoded(); - rasterInfo.mURI = spec.get(); - if (req->HasConsumers()) { - sizes->mRasterUsedImageInfo.AppendElement(rasterInfo); - } else { - sizes->mRasterUnusedImageInfo.AppendElement(rasterInfo); - } - - ImageInfo vectorInfo; - vectorInfo.mSizes.mSize = - image->HeapSizeOfVectorImageDocument(&vectorInfo.mURI); - if (!vectorInfo.mURI.IsEmpty()) { - if (req->HasConsumers()) { - sizes->mVectorUsedImageDocInfo.AppendElement(vectorInfo); - } else { - sizes->mVectorUnusedImageDocInfo.AppendElement(vectorInfo); - } - } - } - + RecordCounterForRequest(req, + static_cast*>(aUserArg), + req->HasConsumers()); return PL_DHASH_NEXT; } - static PLDHashOperator EntryUsedUncompressedSize(const nsACString&, - imgCacheEntry *aEntry, - void *aUserArg) + static void RecordCounterForRequest(imgRequest* aRequest, + nsTArray* aArray, + bool aIsUsed) { - if (!aEntry->HasNoProxies()) { - size_t *n = static_cast(aUserArg); - nsRefPtr req = aEntry->GetRequest(); - Image *image = static_cast(req->mImage.get()); - if (image) { - // Both this and EntryImageSizes measure - // images/content/raster/used/uncompressed memory. This function's - // measurement is secondary -- the result doesn't go in the "explicit" - // tree -- so we use moz_malloc_size_of instead of ImagesMallocSizeOf - // to prevent DMD from seeing it reported twice. - *n += image->HeapSizeOfDecodedWithComputedFallback(moz_malloc_size_of); - *n += image->NonHeapSizeOfDecoded(); - } + auto image = static_cast(aRequest->mImage.get()); + if (!image) { + return; } + nsRefPtr imageURL(image->GetURI()); + nsAutoCString spec; + imageURL->GetSpec(spec); + + ImageMemoryCounter counter(image->GetType(), spec, aIsUsed); + + counter.Values().SetSource(image-> + SizeOfSourceWithComputedFallback(ImagesMallocSizeOf)); + counter.Values().SetDecodedHeap(image-> + SizeOfDecoded(gfxMemoryLocation::IN_PROCESS_HEAP, ImagesMallocSizeOf)); + counter.Values().SetDecodedNonHeap(image-> + SizeOfDecoded(gfxMemoryLocation::IN_PROCESS_NONHEAP, nullptr)); + + aArray->AppendElement(counter); + } + + static PLDHashOperator DoRecordCounterUsedDecoded(const nsACString&, + imgCacheEntry* aEntry, + void* aUserArg) + { + if (aEntry->HasNoProxies()) { + return PL_DHASH_NEXT; + } + + nsRefPtr req = aEntry->GetRequest(); + auto image = static_cast(req->mImage.get()); + if (!image) { + return PL_DHASH_NEXT; + } + + // Both this and EntryImageSizes measure images/content/raster/used/decoded + // memory. This function's measurement is secondary -- the result doesn't + // go in the "explicit" tree -- so we use moz_malloc_size_of instead of + // ImagesMallocSizeOf to prevent DMD from seeing it reported twice. + auto n = static_cast(aUserArg); + *n += image->SizeOfDecoded(gfxMemoryLocation::IN_PROCESS_HEAP, + moz_malloc_size_of); + *n += image->SizeOfDecoded(gfxMemoryLocation::IN_PROCESS_NONHEAP, nullptr); return PL_DHASH_NEXT; } }; -// Specialisation of this method for raster images. -template<> -nsresult imgMemoryReporter::ReportSizes( - nsIMemoryReporterCallback *aHandleReport, nsISupports *aData, - const nsACString &aPathPrefix, const nsACString &aLocation, - RasterSizes aSizes) -{ -#define REPORT(_pathPrefix, _pathSuffix, _location, _kind, _amount, _desc) \ - do { \ - if (_amount > 0) { \ - nsCString path(_pathPrefix); \ - path.Append("/"); \ - if (!_location.IsEmpty()) { \ - path.Append("image("); \ - path.Append(_location); \ - path.Append(")/"); \ - } \ - path.Append(_pathSuffix); \ - nsresult rv; \ - rv = aHandleReport->Callback(EmptyCString(), path, _kind, UNITS_BYTES, \ - _amount, NS_LITERAL_CSTRING(_desc), aData);\ - NS_ENSURE_SUCCESS(rv, rv); \ - } \ - } while (0) - - REPORT(aPathPrefix, "raw", aLocation, KIND_HEAP, - aSizes.mRaw, "Compressed image data."); - - REPORT(aPathPrefix, "uncompressed-heap", aLocation, KIND_HEAP, - aSizes.mUncompressedHeap, "Uncompressed image data."); - - REPORT(aPathPrefix, "uncompressed-nonheap", aLocation, KIND_NONHEAP, - aSizes.mUncompressedNonheap, "Uncompressed image data."); -#undef REPORT - return NS_OK; -} - -// Specialisation of this method for vector images. -template<> -nsresult imgMemoryReporter::ReportSizes( - nsIMemoryReporterCallback *aHandleReport, nsISupports *aData, - const nsACString &aPathPrefix, const nsACString &aLocation, - VectorDocSizes aSizes) -{ -#define REPORT(_pathPrefix, _location, _amount, _desc) \ - do { \ - if (_amount > 0) { \ - nsCString path(_pathPrefix); \ - if (!_location.IsEmpty()) { \ - path.Append("/document("); \ - path.Append(_location); \ - path.Append(")"); \ - } \ - nsresult rv; \ - rv = aHandleReport->Callback(EmptyCString(), path, KIND_HEAP, \ - UNITS_BYTES, _amount, \ - NS_LITERAL_CSTRING(_desc), aData); \ - NS_ENSURE_SUCCESS(rv, rv); \ - } \ - } while (0) - - REPORT(aPathPrefix, aLocation, aSizes.mSize, - "Parsed vector image documents."); -#undef REPORT - return NS_OK; -} - NS_IMPL_ISUPPORTS(imgMemoryReporter, nsIMemoryReporter) NS_IMPL_ISUPPORTS(nsProgressNotificationProxy, diff --git a/image/src/imgRequest.cpp b/image/src/imgRequest.cpp index e1e03fb21425..5495f529ee5a 100644 --- a/image/src/imgRequest.cpp +++ b/image/src/imgRequest.cpp @@ -455,8 +455,10 @@ void imgRequest::SetIsInCache(bool incache) void imgRequest::UpdateCacheEntrySize() { - if (mCacheEntry) - mCacheEntry->SetDataSize(mImage->SizeOfData()); + if (mCacheEntry) { + size_t size = mImage->SizeOfSourceWithComputedFallback(moz_malloc_size_of); + mCacheEntry->SetDataSize(size); + } } void imgRequest::SetCacheValidation(imgCacheEntry* aCacheEntry, nsIRequest* aRequest) diff --git a/image/src/imgRequest.h b/image/src/imgRequest.h index 1a4edf98a9d4..aa74b0246e76 100644 --- a/image/src/imgRequest.h +++ b/image/src/imgRequest.h @@ -141,9 +141,6 @@ public: // Resize the cache entry to 0 if it exists void ResetCacheEntry(); - // Update the cache entry size based on the image container - void UpdateCacheEntrySize(); - // OK to use on any thread. nsresult GetURI(ImageURL **aURI); nsresult GetCurrentURI(nsIURI **aURI); @@ -183,6 +180,9 @@ private: // Returns whether we've got a reference to the cache entry. bool HasCacheEntry() const; + // Update the cache entry size based on the image container. + void UpdateCacheEntrySize(); + // Return the priority of the underlying network request, or return // PRIORITY_NORMAL if it doesn't support nsISupportsPriority. int32_t Priority() const; diff --git a/image/src/imgRequestProxy.cpp b/image/src/imgRequestProxy.cpp index 9c8f340d7a48..7ea28dfdce33 100644 --- a/image/src/imgRequestProxy.cpp +++ b/image/src/imgRequestProxy.cpp @@ -776,12 +776,6 @@ void imgRequestProxy::OnDecodeComplete() nsCOMPtr kungFuDeathGrip(mListener); mListener->Notify(this, imgINotificationObserver::DECODE_COMPLETE, nullptr); } - - if (GetOwner()) { - // We finished the decode, and thus have the decoded frames. Update the cache - // entry size to take this into account. - GetOwner()->UpdateCacheEntrySize(); - } } void imgRequestProxy::OnDiscard() @@ -793,10 +787,6 @@ void imgRequestProxy::OnDiscard() nsCOMPtr kungFuDeathGrip(mListener); mListener->Notify(this, imgINotificationObserver::DISCARD, nullptr); } - if (GetOwner()) { - // Update the cache entry size, since we just got rid of frame data. - GetOwner()->UpdateCacheEntrySize(); - } } void imgRequestProxy::OnUnlockedDraw() From 7376e9423b2e57fa5c514b7b328d0ffb9e1ea884 Mon Sep 17 00:00:00 2001 From: Anthony Jones Date: Thu, 27 Nov 2014 16:16:38 +1300 Subject: [PATCH 58/64] Bug 1103733 - Enable EME on non-release builds; r=cpearce --- browser/app/profile/firefox.js | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/browser/app/profile/firefox.js b/browser/app/profile/firefox.js index 33cff33219cc..4cc36157ec35 100644 --- a/browser/app/profile/firefox.js +++ b/browser/app/profile/firefox.js @@ -1742,7 +1742,11 @@ pref("ui.key.menuAccessKeyFocuses", true); #endif // Encrypted media extensions. +#ifdef RELEASE_BUILD pref("media.eme.enabled", false); +#else +pref("media.eme.enabled", true); +#endif // GMPInstallManager prefs From ab6aa22d12e4412f4884211f9fa552d521331c0d Mon Sep 17 00:00:00 2001 From: Anthony Jones Date: Thu, 27 Nov 2014 16:16:40 +1300 Subject: [PATCH 59/64] Bug 1103733 - Fix openh264 test failures; r=unfocused --- .../extensions/test/xpcshell/test_openh264.js | 38 +++++++++---------- 1 file changed, 19 insertions(+), 19 deletions(-) diff --git a/toolkit/mozapps/extensions/test/xpcshell/test_openh264.js b/toolkit/mozapps/extensions/test/xpcshell/test_openh264.js index ba23df71fade..4ff8d913c963 100644 --- a/toolkit/mozapps/extensions/test/xpcshell/test_openh264.js +++ b/toolkit/mozapps/extensions/test/xpcshell/test_openh264.js @@ -183,13 +183,13 @@ add_task(function* test_pluginRegistration() { file.append(OPENH264_PLUGIN_ID); file.append(TEST_VERSION); - let addedPath = null - let removedPath = null; - let clearPaths = () => addedPath = removedPath = null; + let addedPaths = []; + let removedPaths = []; + let clearPaths = () => { addedPaths = []; removedPaths = []; } let MockGMPService = { - addPluginDirectory: path => addedPath = path, - removePluginDirectory: path => removedPath = path, + addPluginDirectory: path => addedPaths.push(path), + removePluginDirectory: path => removedPaths.push(path), }; let OpenH264Scope = Cu.import("resource://gre/modules/addons/OpenH264Provider.jsm"); @@ -200,20 +200,20 @@ add_task(function* test_pluginRegistration() { Services.prefs.setCharPref(OPENH264_PREF_VERSION, TEST_VERSION); clearPaths(); yield promiseRestartManager(); - Assert.equal(addedPath, file.path); - Assert.equal(removedPath, null); + Assert.notEqual(addedPaths.indexOf(file.path), -1); + Assert.deepEqual(removedPaths, []); // Check that clearing the version doesn't trigger registration. clearPaths(); Services.prefs.clearUserPref(OPENH264_PREF_VERSION); - Assert.equal(addedPath, null); - Assert.equal(removedPath, file.path); + Assert.deepEqual(addedPaths, []); + Assert.deepEqual(removedPaths, [file.path]); // Restarting with no version set should not trigger registration. clearPaths(); yield promiseRestartManager(); - Assert.equal(addedPath, null); - Assert.equal(removedPath, null); + Assert.equal(addedPaths.indexOf(file.path), -1); + Assert.equal(removedPaths.indexOf(file.path), -1); // Changing the pref mid-session should cause unregistration and registration. Services.prefs.setCharPref(OPENH264_PREF_VERSION, TEST_VERSION); @@ -223,27 +223,27 @@ add_task(function* test_pluginRegistration() { file2.append(OPENH264_PLUGIN_ID); file2.append(TEST_VERSION_2); Services.prefs.setCharPref(OPENH264_PREF_VERSION, TEST_VERSION_2); - Assert.equal(addedPath, file2.path); - Assert.equal(removedPath, file.path); + Assert.deepEqual(addedPaths, [file2.path]); + Assert.deepEqual(removedPaths, [file.path]); // Disabling OpenH264 should cause unregistration. Services.prefs.setCharPref(OPENH264_PREF_VERSION, TEST_VERSION); clearPaths(); Services.prefs.setBoolPref(OPENH264_PREF_ENABLED, false); - Assert.equal(addedPath, null); - Assert.equal(removedPath, file.path); + Assert.deepEqual(addedPaths, []); + Assert.deepEqual(removedPaths, [file.path]); // Restarting with OpenH264 disabled should not cause registration. clearPaths(); yield promiseRestartManager(); - Assert.equal(addedPath, null); - Assert.equal(removedPath, null); + Assert.equal(addedPaths.indexOf(file.path), -1); + Assert.equal(removedPaths.indexOf(file.path), -1); // Re-enabling OpenH264 should cause registration. clearPaths(); Services.prefs.setBoolPref(OPENH264_PREF_ENABLED, true); - Assert.equal(addedPath, file.path); - Assert.equal(removedPath, null); + Assert.deepEqual(addedPaths, [file.path]); + Assert.deepEqual(removedPaths, []); }); add_task(function* test_periodicUpdate() { From 6212abd6114f7639f1154235d725294695531c36 Mon Sep 17 00:00:00 2001 From: David Major Date: Thu, 27 Nov 2014 16:18:25 +1300 Subject: [PATCH 60/64] Bug 1095103: Remove Windows PGO build hacks that are no longer necessary. r=glandium --HG-- extra : rebase_source : b790c97d1fa3e12597d4cd5f4c7fd6dc7ba133cf --- configure.in | 13 ++----------- js/src/configure.in | 13 ++----------- 2 files changed, 4 insertions(+), 22 deletions(-) diff --git a/configure.in b/configure.in index 4f5126533b48..53e545002a69 100644 --- a/configure.in +++ b/configure.in @@ -2279,17 +2279,8 @@ ia64*-hpux*) dnl For profile-guided optimization PROFILE_GEN_CFLAGS="-GL" PROFILE_GEN_LDFLAGS="-LTCG:PGINSTRUMENT" - dnl XXX: PGO builds can fail with warnings treated as errors, - dnl specifically "no profile data available" appears to be - dnl treated as an error sometimes. This might be a consequence - dnl of using WARNINGS_AS_ERRORS in some modules, combined - dnl with the linker doing most of the work in the whole-program - dnl optimization/PGO case. I think it's probably a compiler bug, - dnl but we work around it here. - PROFILE_USE_CFLAGS="-GL -wd4624 -wd4952" - dnl XXX: should be -LTCG:PGOPTIMIZE, but that fails on libxul. - dnl Probably also a compiler bug, but what can you do? - PROFILE_USE_LDFLAGS="-LTCG:PGUPDATE" + PROFILE_USE_CFLAGS="-GL" + PROFILE_USE_LDFLAGS="-LTCG:PGOPTIMIZE" LDFLAGS="$LDFLAGS -DYNAMICBASE" dnl Minimum reqiurement of Gecko is VS2010 or later which supports dnl both SSSE3 and SSE4.1. diff --git a/js/src/configure.in b/js/src/configure.in index c270df1b60b1..473a0b3e0754 100644 --- a/js/src/configure.in +++ b/js/src/configure.in @@ -1820,17 +1820,8 @@ ia64*-hpux*) dnl For profile-guided optimization PROFILE_GEN_CFLAGS="-GL" PROFILE_GEN_LDFLAGS="-LTCG:PGINSTRUMENT" - dnl XXX: PGO builds can fail with warnings treated as errors, - dnl specifically "no profile data available" appears to be - dnl treated as an error sometimes. This might be a consequence - dnl of using WARNINGS_AS_ERRORS in some modules, combined - dnl with the linker doing most of the work in the whole-program - dnl optimization/PGO case. I think it's probably a compiler bug, - dnl but we work around it here. - PROFILE_USE_CFLAGS="-GL -wd4624 -wd4952" - dnl XXX: should be -LTCG:PGOPTIMIZE, but that fails on libxul. - dnl Probably also a compiler bug, but what can you do? - PROFILE_USE_LDFLAGS="-LTCG:PGUPDATE" + PROFILE_USE_CFLAGS="-GL" + PROFILE_USE_LDFLAGS="-LTCG:PGOPTIMIZE" LDFLAGS="$LDFLAGS -DYNAMICBASE" fi AC_DEFINE(HAVE_SNPRINTF) From 0f8922ac4a188c9a1436b5eb09969f85348de70c Mon Sep 17 00:00:00 2001 From: Daniel Holbert Date: Wed, 26 Nov 2014 19:43:36 -0800 Subject: [PATCH 61/64] Bug 1103184 part 1: Honor "object-fit" & "object-position" on element. r=roc --- layout/generic/nsHTMLCanvasFrame.cpp | 51 +++++++++++++++++++++------- 1 file changed, 38 insertions(+), 13 deletions(-) diff --git a/layout/generic/nsHTMLCanvasFrame.cpp b/layout/generic/nsHTMLCanvasFrame.cpp index 494224e5670b..7de51fe745b0 100644 --- a/layout/generic/nsHTMLCanvasFrame.cpp +++ b/layout/generic/nsHTMLCanvasFrame.cpp @@ -12,6 +12,7 @@ #include "mozilla/dom/HTMLCanvasElement.h" #include "nsDisplayList.h" #include "nsLayoutUtils.h" +#include "nsStyleUtil.h" #include "Layers.h" #include "ActiveLayerTracker.h" @@ -75,12 +76,28 @@ public: virtual nsRegion GetOpaqueRegion(nsDisplayListBuilder* aBuilder, bool* aSnap) MOZ_OVERRIDE { *aSnap = false; - nsIFrame* f = Frame(); - HTMLCanvasElement *canvas = + nsHTMLCanvasFrame* f = static_cast(Frame()); + HTMLCanvasElement* canvas = HTMLCanvasElement::FromContent(f->GetContent()); nsRegion result; if (canvas->GetIsOpaque()) { - result = GetBounds(aBuilder, aSnap); + // OK, the entire region painted by the canvas is opaque. But what is + // that region? It's the canvas's "dest rect" (controlled by the + // object-fit/object-position CSS properties), clipped to the container's + // content box (which is what GetBounds() returns). So, we grab those + // rects and intersect them. + nsRect constraintRect = GetBounds(aBuilder, aSnap); + + // Need intrinsic size & ratio, for ComputeObjectDestRect: + nsIntSize canvasSize = f->GetCanvasSize(); + IntrinsicSize intrinsicSize = IntrinsicSizeFromCanvasSize(canvasSize); + nsSize intrinsicRatio = IntrinsicRatioFromCanvasSize(canvasSize); + + const nsRect destRect = + nsLayoutUtils::ComputeObjectDestRect(constraintRect, + intrinsicSize, intrinsicRatio, + f->StylePosition()); + return nsRegion(destRect.Intersect(constraintRect)); } return result; } @@ -306,12 +323,12 @@ nsHTMLCanvasFrame::BuildLayer(nsDisplayListBuilder* aBuilder, { nsRect area = GetContentRectRelativeToSelf() + aItem->ToReferenceFrame(); HTMLCanvasElement* element = static_cast(GetContent()); - nsIntSize canvasSize = GetCanvasSize(); + nsIntSize canvasSizeInPx = GetCanvasSize(); nsPresContext* presContext = PresContext(); element->HandlePrintCallback(presContext->Type()); - if (canvasSize.width <= 0 || canvasSize.height <= 0 || area.IsEmpty()) + if (canvasSizeInPx.width <= 0 || canvasSizeInPx.height <= 0 || area.IsEmpty()) return nullptr; CanvasLayer* oldLayer = static_cast @@ -320,16 +337,20 @@ nsHTMLCanvasFrame::BuildLayer(nsDisplayListBuilder* aBuilder, if (!layer) return nullptr; - gfxRect r = gfxRect(presContext->AppUnitsToGfxUnits(area.x), - presContext->AppUnitsToGfxUnits(area.y), - presContext->AppUnitsToGfxUnits(area.width), - presContext->AppUnitsToGfxUnits(area.height)); + IntrinsicSize intrinsicSize = IntrinsicSizeFromCanvasSize(canvasSizeInPx); + nsSize intrinsicRatio = IntrinsicRatioFromCanvasSize(canvasSizeInPx); + + nsRect dest = + nsLayoutUtils::ComputeObjectDestRect(area, intrinsicSize, intrinsicRatio, + StylePosition()); + + gfxRect destGFXRect = presContext->AppUnitsToGfxUnits(dest); // Transform the canvas into the right place - gfxPoint p = r.TopLeft() + aContainerParameters.mOffset; + gfxPoint p = destGFXRect.TopLeft() + aContainerParameters.mOffset; Matrix transform = Matrix::Translation(p.x, p.y); - transform.PreScale(r.Width() / canvasSize.width, - r.Height() / canvasSize.height); + transform.PreScale(destGFXRect.Width() / canvasSizeInPx.width, + destGFXRect.Height() / canvasSizeInPx.height); layer->SetBaseTransform(gfx::Matrix4x4::From2D(transform)); layer->SetFilter(nsLayoutUtils::GetGraphicsFilterForFrame(this)); @@ -346,8 +367,12 @@ nsHTMLCanvasFrame::BuildDisplayList(nsDisplayListBuilder* aBuilder, DisplayBorderBackgroundOutline(aBuilder, aLists); + uint32_t clipFlags = + nsStyleUtil::ObjectPropsMightCauseOverflow(StylePosition()) ? + 0 : DisplayListClipState::ASSUME_DRAWING_RESTRICTED_TO_CONTENT_RECT; + DisplayListClipState::AutoClipContainingBlockDescendantsToContentBox - clip(aBuilder, this, DisplayListClipState::ASSUME_DRAWING_RESTRICTED_TO_CONTENT_RECT); + clip(aBuilder, this, clipFlags); aLists.Content()->AppendNewToTop( new (aBuilder) nsDisplayCanvas(aBuilder, this)); From d5035d862f59614e654b7484d4ce5c53e7288846 Mon Sep 17 00:00:00 2001 From: Daniel Holbert Date: Wed, 26 Nov 2014 19:43:39 -0800 Subject: [PATCH 62/64] Bug 1103184 part 2: Generate reftests for object-fit & object-position on , as modified copies of existing tests. (no review) --HG-- rename : layout/reftests/w3c-css/submitted/images3/object-fit-contain-png-001o.html => layout/reftests/w3c-css/submitted/images3/object-fit-contain-png-001c.html rename : layout/reftests/w3c-css/submitted/images3/object-fit-contain-png-002o.html => layout/reftests/w3c-css/submitted/images3/object-fit-contain-png-002c.html rename : layout/reftests/w3c-css/submitted/images3/object-fit-cover-png-001o.html => layout/reftests/w3c-css/submitted/images3/object-fit-cover-png-001c.html rename : layout/reftests/w3c-css/submitted/images3/object-fit-cover-png-002o.html => layout/reftests/w3c-css/submitted/images3/object-fit-cover-png-002c.html rename : layout/reftests/w3c-css/submitted/images3/object-fit-fill-png-001o.html => layout/reftests/w3c-css/submitted/images3/object-fit-fill-png-001c.html rename : layout/reftests/w3c-css/submitted/images3/object-fit-fill-png-002o.html => layout/reftests/w3c-css/submitted/images3/object-fit-fill-png-002c.html rename : layout/reftests/w3c-css/submitted/images3/object-fit-none-png-001o.html => layout/reftests/w3c-css/submitted/images3/object-fit-none-png-001c.html rename : layout/reftests/w3c-css/submitted/images3/object-fit-none-png-002o.html => layout/reftests/w3c-css/submitted/images3/object-fit-none-png-002c.html rename : layout/reftests/w3c-css/submitted/images3/object-fit-scale-down-png-001o.html => layout/reftests/w3c-css/submitted/images3/object-fit-scale-down-png-001c.html rename : layout/reftests/w3c-css/submitted/images3/object-fit-scale-down-png-002o.html => layout/reftests/w3c-css/submitted/images3/object-fit-scale-down-png-002c.html rename : layout/reftests/w3c-css/submitted/images3/object-position-png-001o.html => layout/reftests/w3c-css/submitted/images3/object-position-png-001c.html rename : layout/reftests/w3c-css/submitted/images3/object-position-png-002o.html => layout/reftests/w3c-css/submitted/images3/object-position-png-002c.html --- .../images3/object-fit-contain-png-001c.html | 91 +++++++++++++++++++ .../images3/object-fit-contain-png-002c.html | 91 +++++++++++++++++++ .../images3/object-fit-cover-png-001c.html | 91 +++++++++++++++++++ .../images3/object-fit-cover-png-002c.html | 91 +++++++++++++++++++ .../images3/object-fit-fill-png-001c.html | 91 +++++++++++++++++++ .../images3/object-fit-fill-png-002c.html | 91 +++++++++++++++++++ .../images3/object-fit-none-png-001c.html | 91 +++++++++++++++++++ .../images3/object-fit-none-png-002c.html | 91 +++++++++++++++++++ .../object-fit-scale-down-png-001c.html | 91 +++++++++++++++++++ .../object-fit-scale-down-png-002c.html | 91 +++++++++++++++++++ .../images3/object-position-png-001c.html | 58 ++++++++++++ .../images3/object-position-png-002c.html | 58 ++++++++++++ .../w3c-css/submitted/images3/reftest.list | 12 +++ ...te-object-fit-and-position-canvas-tests.sh | 72 +++++++++++++++ 14 files changed, 1110 insertions(+) create mode 100644 layout/reftests/w3c-css/submitted/images3/object-fit-contain-png-001c.html create mode 100644 layout/reftests/w3c-css/submitted/images3/object-fit-contain-png-002c.html create mode 100644 layout/reftests/w3c-css/submitted/images3/object-fit-cover-png-001c.html create mode 100644 layout/reftests/w3c-css/submitted/images3/object-fit-cover-png-002c.html create mode 100644 layout/reftests/w3c-css/submitted/images3/object-fit-fill-png-001c.html create mode 100644 layout/reftests/w3c-css/submitted/images3/object-fit-fill-png-002c.html create mode 100644 layout/reftests/w3c-css/submitted/images3/object-fit-none-png-001c.html create mode 100644 layout/reftests/w3c-css/submitted/images3/object-fit-none-png-002c.html create mode 100644 layout/reftests/w3c-css/submitted/images3/object-fit-scale-down-png-001c.html create mode 100644 layout/reftests/w3c-css/submitted/images3/object-fit-scale-down-png-002c.html create mode 100644 layout/reftests/w3c-css/submitted/images3/object-position-png-001c.html create mode 100644 layout/reftests/w3c-css/submitted/images3/object-position-png-002c.html create mode 100644 layout/reftests/w3c-css/submitted/images3/support/generate-object-fit-and-position-canvas-tests.sh diff --git a/layout/reftests/w3c-css/submitted/images3/object-fit-contain-png-001c.html b/layout/reftests/w3c-css/submitted/images3/object-fit-contain-png-001c.html new file mode 100644 index 000000000000..a6dfd95813cd --- /dev/null +++ b/layout/reftests/w3c-css/submitted/images3/object-fit-contain-png-001c.html @@ -0,0 +1,91 @@ + + + + + + CSS Test: 'object-fit: contain' on canvas element, with a PNG image and with various 'object-position' values + + + + + + + + + + + + + + + + + +
+ + + + + + + + +
+ + + + + + + + +
+ + diff --git a/layout/reftests/w3c-css/submitted/images3/object-fit-contain-png-002c.html b/layout/reftests/w3c-css/submitted/images3/object-fit-contain-png-002c.html new file mode 100644 index 000000000000..4e49d0fbf7a0 --- /dev/null +++ b/layout/reftests/w3c-css/submitted/images3/object-fit-contain-png-002c.html @@ -0,0 +1,91 @@ + + + + + + CSS Test: 'object-fit: contain' on canvas element, with a PNG image and with various 'object-position' values + + + + + + + + + + + + + + + + + +
+ + + + + + + + +
+ + + + + + + + +
+ + diff --git a/layout/reftests/w3c-css/submitted/images3/object-fit-cover-png-001c.html b/layout/reftests/w3c-css/submitted/images3/object-fit-cover-png-001c.html new file mode 100644 index 000000000000..f2a26a67c76a --- /dev/null +++ b/layout/reftests/w3c-css/submitted/images3/object-fit-cover-png-001c.html @@ -0,0 +1,91 @@ + + + + + + CSS Test: 'object-fit: cover' on canvas element, with a PNG image and with various 'object-position' values + + + + + + + + + + + + + + + + + +
+ + + + + + + + +
+ + + + + + + + +
+ + diff --git a/layout/reftests/w3c-css/submitted/images3/object-fit-cover-png-002c.html b/layout/reftests/w3c-css/submitted/images3/object-fit-cover-png-002c.html new file mode 100644 index 000000000000..ac0f1da7400c --- /dev/null +++ b/layout/reftests/w3c-css/submitted/images3/object-fit-cover-png-002c.html @@ -0,0 +1,91 @@ + + + + + + CSS Test: 'object-fit: cover' on canvas element, with a PNG image and with various 'object-position' values + + + + + + + + + + + + + + + + + +
+ + + + + + + + +
+ + + + + + + + +
+ + diff --git a/layout/reftests/w3c-css/submitted/images3/object-fit-fill-png-001c.html b/layout/reftests/w3c-css/submitted/images3/object-fit-fill-png-001c.html new file mode 100644 index 000000000000..bdf547e19057 --- /dev/null +++ b/layout/reftests/w3c-css/submitted/images3/object-fit-fill-png-001c.html @@ -0,0 +1,91 @@ + + + + + + CSS Test: 'object-fit: fill' on canvas element, with a PNG image and with various 'object-position' values + + + + + + + + + + + + + + + + + +
+ + + + + + + + +
+ + + + + + + + +
+ + diff --git a/layout/reftests/w3c-css/submitted/images3/object-fit-fill-png-002c.html b/layout/reftests/w3c-css/submitted/images3/object-fit-fill-png-002c.html new file mode 100644 index 000000000000..1a851bd6d396 --- /dev/null +++ b/layout/reftests/w3c-css/submitted/images3/object-fit-fill-png-002c.html @@ -0,0 +1,91 @@ + + + + + + CSS Test: 'object-fit: fill' on canvas element, with a PNG image and with various 'object-position' values + + + + + + + + + + + + + + + + + +
+ + + + + + + + +
+ + + + + + + + +
+ + diff --git a/layout/reftests/w3c-css/submitted/images3/object-fit-none-png-001c.html b/layout/reftests/w3c-css/submitted/images3/object-fit-none-png-001c.html new file mode 100644 index 000000000000..c984fefb7efa --- /dev/null +++ b/layout/reftests/w3c-css/submitted/images3/object-fit-none-png-001c.html @@ -0,0 +1,91 @@ + + + + + + CSS Test: 'object-fit: none' on canvas element, with a PNG image and with various 'object-position' values + + + + + + + + + + + + + + + + + +
+ + + + + + + + +
+ + + + + + + + +
+ + diff --git a/layout/reftests/w3c-css/submitted/images3/object-fit-none-png-002c.html b/layout/reftests/w3c-css/submitted/images3/object-fit-none-png-002c.html new file mode 100644 index 000000000000..df58f407dfcd --- /dev/null +++ b/layout/reftests/w3c-css/submitted/images3/object-fit-none-png-002c.html @@ -0,0 +1,91 @@ + + + + + + CSS Test: 'object-fit: none' on canvas element, with a PNG image and with various 'object-position' values + + + + + + + + + + + + + + + + + +
+ + + + + + + + +
+ + + + + + + + +
+ + diff --git a/layout/reftests/w3c-css/submitted/images3/object-fit-scale-down-png-001c.html b/layout/reftests/w3c-css/submitted/images3/object-fit-scale-down-png-001c.html new file mode 100644 index 000000000000..d3f7e4289b05 --- /dev/null +++ b/layout/reftests/w3c-css/submitted/images3/object-fit-scale-down-png-001c.html @@ -0,0 +1,91 @@ + + + + + + CSS Test: 'object-fit: scale-down' on canvas element, with a PNG image and with various 'object-position' values + + + + + + + + + + + + + + + + + +
+ + + + + + + + +
+ + + + + + + + +
+ + diff --git a/layout/reftests/w3c-css/submitted/images3/object-fit-scale-down-png-002c.html b/layout/reftests/w3c-css/submitted/images3/object-fit-scale-down-png-002c.html new file mode 100644 index 000000000000..ece408d09857 --- /dev/null +++ b/layout/reftests/w3c-css/submitted/images3/object-fit-scale-down-png-002c.html @@ -0,0 +1,91 @@ + + + + + + CSS Test: 'object-fit: scale-down' on canvas element, with a PNG image and with various 'object-position' values + + + + + + + + + + + + + + + + + +
+ + + + + + + + +
+ + + + + + + + +
+ + diff --git a/layout/reftests/w3c-css/submitted/images3/object-position-png-001c.html b/layout/reftests/w3c-css/submitted/images3/object-position-png-001c.html new file mode 100644 index 000000000000..20ff1cb935c0 --- /dev/null +++ b/layout/reftests/w3c-css/submitted/images3/object-position-png-001c.html @@ -0,0 +1,58 @@ + + + + + + CSS Test: various 'object-position' values on a fixed-size canvas element, with a PNG image and 'object-fit:contain'. + + + + + + + + + + + + + + + + + + diff --git a/layout/reftests/w3c-css/submitted/images3/object-position-png-002c.html b/layout/reftests/w3c-css/submitted/images3/object-position-png-002c.html new file mode 100644 index 000000000000..5ad030ffb601 --- /dev/null +++ b/layout/reftests/w3c-css/submitted/images3/object-position-png-002c.html @@ -0,0 +1,58 @@ + + + + + + CSS Test: various 'object-position' values on a fixed-size canvas element, with a PNG image and 'object-fit:contain'. + + + + + + + + + + + + + + + + + + diff --git a/layout/reftests/w3c-css/submitted/images3/reftest.list b/layout/reftests/w3c-css/submitted/images3/reftest.list index 44fe371b31dc..3834b0713fdd 100644 --- a/layout/reftests/w3c-css/submitted/images3/reftest.list +++ b/layout/reftests/w3c-css/submitted/images3/reftest.list @@ -1,41 +1,51 @@ default-preferences test-pref(layout.css.object-fit-and-position.enabled,true) # Tests for 'object-fit' / 'object-position' with a PNG image +== object-fit-fill-png-001c.html object-fit-fill-png-001-ref.html == object-fit-fill-png-001e.html object-fit-fill-png-001-ref.html == object-fit-fill-png-001i.html object-fit-fill-png-001-ref.html == object-fit-fill-png-001o.html object-fit-fill-png-001-ref.html == object-fit-fill-png-001p.html object-fit-fill-png-001-ref.html +== object-fit-fill-png-002c.html object-fit-fill-png-002-ref.html == object-fit-fill-png-002e.html object-fit-fill-png-002-ref.html == object-fit-fill-png-002i.html object-fit-fill-png-002-ref.html == object-fit-fill-png-002o.html object-fit-fill-png-002-ref.html == object-fit-fill-png-002p.html object-fit-fill-png-002-ref.html +== object-fit-contain-png-001c.html object-fit-contain-png-001-ref.html == object-fit-contain-png-001e.html object-fit-contain-png-001-ref.html == object-fit-contain-png-001i.html object-fit-contain-png-001-ref.html == object-fit-contain-png-001o.html object-fit-contain-png-001-ref.html == object-fit-contain-png-001p.html object-fit-contain-png-001-ref.html +== object-fit-contain-png-002c.html object-fit-contain-png-002-ref.html == object-fit-contain-png-002e.html object-fit-contain-png-002-ref.html == object-fit-contain-png-002i.html object-fit-contain-png-002-ref.html == object-fit-contain-png-002o.html object-fit-contain-png-002-ref.html == object-fit-contain-png-002p.html object-fit-contain-png-002-ref.html +== object-fit-cover-png-001c.html object-fit-cover-png-001-ref.html == object-fit-cover-png-001e.html object-fit-cover-png-001-ref.html == object-fit-cover-png-001i.html object-fit-cover-png-001-ref.html == object-fit-cover-png-001o.html object-fit-cover-png-001-ref.html == object-fit-cover-png-001p.html object-fit-cover-png-001-ref.html +== object-fit-cover-png-002c.html object-fit-cover-png-002-ref.html == object-fit-cover-png-002e.html object-fit-cover-png-002-ref.html == object-fit-cover-png-002i.html object-fit-cover-png-002-ref.html == object-fit-cover-png-002o.html object-fit-cover-png-002-ref.html == object-fit-cover-png-002p.html object-fit-cover-png-002-ref.html +== object-fit-none-png-001c.html object-fit-none-png-001-ref.html == object-fit-none-png-001e.html object-fit-none-png-001-ref.html == object-fit-none-png-001i.html object-fit-none-png-001-ref.html == object-fit-none-png-001o.html object-fit-none-png-001-ref.html == object-fit-none-png-001p.html object-fit-none-png-001-ref.html +== object-fit-none-png-002c.html object-fit-none-png-002-ref.html == object-fit-none-png-002e.html object-fit-none-png-002-ref.html == object-fit-none-png-002i.html object-fit-none-png-002-ref.html == object-fit-none-png-002o.html object-fit-none-png-002-ref.html == object-fit-none-png-002p.html object-fit-none-png-002-ref.html +== object-fit-scale-down-png-001c.html object-fit-scale-down-png-001-ref.html == object-fit-scale-down-png-001e.html object-fit-scale-down-png-001-ref.html == object-fit-scale-down-png-001i.html object-fit-scale-down-png-001-ref.html == object-fit-scale-down-png-001o.html object-fit-scale-down-png-001-ref.html == object-fit-scale-down-png-001p.html object-fit-scale-down-png-001-ref.html +== object-fit-scale-down-png-002c.html object-fit-scale-down-png-002-ref.html == object-fit-scale-down-png-002e.html object-fit-scale-down-png-002-ref.html == object-fit-scale-down-png-002i.html object-fit-scale-down-png-002-ref.html == object-fit-scale-down-png-002o.html object-fit-scale-down-png-002-ref.html @@ -162,10 +172,12 @@ fails == object-fit-fill-svg-006p.html object-fit-fill-svg-006-ref.html # bug 10 == object-fit-scale-down-svg-006i.html object-fit-scale-down-svg-006-ref.html == object-fit-scale-down-svg-006o.html object-fit-scale-down-svg-006-ref.html == object-fit-scale-down-svg-006p.html object-fit-scale-down-svg-006-ref.html +fails == object-position-png-001c.html object-position-png-001-ref.html # bug 1105150 == object-position-png-001e.html object-position-png-001-ref.html == object-position-png-001i.html object-position-png-001-ref.html == object-position-png-001o.html object-position-png-001-ref.html == object-position-png-001p.html object-position-png-001-ref.html +fails == object-position-png-002c.html object-position-png-002-ref.html # bug 1105150 == object-position-png-002e.html object-position-png-002-ref.html == object-position-png-002i.html object-position-png-002-ref.html == object-position-png-002o.html object-position-png-002-ref.html diff --git a/layout/reftests/w3c-css/submitted/images3/support/generate-object-fit-and-position-canvas-tests.sh b/layout/reftests/w3c-css/submitted/images3/support/generate-object-fit-and-position-canvas-tests.sh new file mode 100644 index 000000000000..b66ea4726951 --- /dev/null +++ b/layout/reftests/w3c-css/submitted/images3/support/generate-object-fit-and-position-canvas-tests.sh @@ -0,0 +1,72 @@ +#!/bin/bash +# +# Any copyright is dedicated to the Public Domain. +# http://creativecommons.org/publicdomain/zero/1.0/ +# +# Script to generate reftest files for "object-fit" and +# "object-position", from corresponding reftest files that use . +# +# This script expects to be run from this working directory: +# mozilla-central/layout/reftests/w3c-css/submitted/images3 + +# Array of image files that we'll use +imageFileArr=("support/colors-16x8.png" "support/colors-8x16.png") +canvasAttributeArr=('width="16" height="8"' 'width="8" height="16"') +numImageFiles=${#imageFileArr[@]} + + +for ((i = 0; i < $numImageFiles; i++)); do + + imageFile=${imageFileArr[$i]} + canvasAttrs=${canvasAttributeArr[$i]} + + # Loop across tests: + # (We assume that tests that end with "001" use the first PNG image in + # $imageFileArr, and tests that end with "002" use the second PNG image.) + let testNum=$i+1 + for origTestName in object-*-png-*00${testNum}o.html; do + # Find the corresponding reference case: + origReferenceName=$(echo $origTestName | + sed "s/o.html/-ref.html/") + + # Replace "o" suffix in filename with "c" (for "canvas") + canvasTestName=$(echo $origTestName | + sed "s/o.html/c.html/") + + # Generate testcase + # (converting to + echo "Generating $canvasTestName from $origTestName." + hg cp $origTestName $canvasTestName + + # Do string-replacements in testcase to convert it to test canvas: + # Adjust html & body nodes: + sed -i "s|||" $canvasTestName + sed -i "s|||" $canvasTestName + # Adjust : + sed -i "s|object element|canvas element|g" $canvasTestName + # Tweak the actual tags (open & close tags, and CSS rule): + sed -i "s|object {|canvas {|" $canvasTestName + sed -i "s|<object|<canvas|" $canvasTestName + sed -i "s|</object>|</canvas>|" $canvasTestName + # Drop "data" attr (pointing to image URI) and replace with + # width/height attrs to establish the canvas's intrinsic size: + sed -i "s|data=\"$imageFile\"|$canvasAttrs|" $canvasTestName + + # Add a <script> block to draw an image into each canvas: + sed -i "/<\/style>/a \\ + <script>\n\ + function drawImageToCanvases(imageURI) {\n\ + var image = new Image();\n\ + image.onload = function() {\n\ + var canvasElems = document.getElementsByTagName(\"canvas\");\n\ + for (var i = 0; i < canvasElems.length; i++) {\n\ + var ctx = canvasElems[i].getContext(\"2d\");\n\ + ctx.drawImage(image, 0, 0);\n\ + }\n\ + document.documentElement.removeAttribute(\"class\");\n\ + }\n\ + image.src = imageURI;\n\ + }\n\ + <\/script>" $canvasTestName + done +done From 77f18d8038a47c1d08f76bf1d4ecbac4442ab820 Mon Sep 17 00:00:00 2001 From: Brian Hackett <bhackett1024@gmail.com> Date: Wed, 26 Nov 2014 22:45:11 -0700 Subject: [PATCH 63/64] Bug 1100173, bug 1102510 - Add baseline caches for typed object scalar element accesses and scalar/reference property accesses, r=jandem. --- js/src/builtin/TypedObject.h | 8 + js/src/jit/BaselineIC.cpp | 598 +++++++++++++++++++++++++++----- js/src/jit/BaselineIC.h | 215 +++++++++++- js/src/jscompartment.cpp | 1 + js/src/jscompartment.h | 3 + js/src/vm/ArrayBufferObject.cpp | 1 + 6 files changed, 744 insertions(+), 82 deletions(-) diff --git a/js/src/builtin/TypedObject.h b/js/src/builtin/TypedObject.h index a91e7e929c5e..b6a4583781ed 100644 --- a/js/src/builtin/TypedObject.h +++ b/js/src/builtin/TypedObject.h @@ -154,6 +154,10 @@ class TypedProto : public NativeObject } inline type::Kind kind() const; + + static int32_t offsetOfTypeDescr() { + return getFixedSlotOffset(JS_TYPROTO_SLOT_DESCR); + } }; class TypeDescr : public NativeObject @@ -432,6 +436,10 @@ class ArrayTypeDescr : public ComplexTypeDescr int32_t length() const { return getReservedSlot(JS_DESCR_SLOT_ARRAY_LENGTH).toInt32(); } + + static int32_t offsetOfLength() { + return getFixedSlotOffset(JS_DESCR_SLOT_ARRAY_LENGTH); + } }; /* diff --git a/js/src/jit/BaselineIC.cpp b/js/src/jit/BaselineIC.cpp index 402660f9e04a..77b033a2da98 100644 --- a/js/src/jit/BaselineIC.cpp +++ b/js/src/jit/BaselineIC.cpp @@ -366,6 +366,11 @@ ICStub::trace(JSTracer *trc) } break; } + case ICStub::GetProp_TypedObject: { + ICGetProp_TypedObject *propStub = toGetProp_TypedObject(); + MarkShape(trc, &propStub->shape(), "baseline-getprop-typedobject-stub-shape"); + break; + } case ICStub::GetProp_CallDOMProxyNative: case ICStub::GetProp_CallDOMProxyWithGenerationNative: { ICGetPropCallDOMProxyNativeStub *propStub; @@ -435,6 +440,12 @@ ICStub::trace(JSTracer *trc) } break; } + case ICStub::SetProp_TypedObject: { + ICSetProp_TypedObject *propStub = toSetProp_TypedObject(); + MarkShape(trc, &propStub->shape(), "baseline-setprop-typedobject-stub-shape"); + MarkTypeObject(trc, &propStub->type(), "baseline-setprop-typedobject-stub-type"); + break; + } case ICStub::SetProp_CallScripted: { ICSetProp_CallScripted *callStub = toSetProp_CallScripted(); MarkShape(trc, &callStub->shape(), "baseline-setpropcallscripted-stub-shape"); @@ -1545,6 +1556,25 @@ DoTypeUpdateFallback(JSContext *cx, BaselineFrame *frame, ICUpdatedStub *stub, H types::AddTypePropertyId(cx, obj, id, value); break; } + case ICStub::SetProp_TypedObject: { + MOZ_ASSERT(obj->is<TypedObject>()); + jsbytecode *pc = stub->getChainFallback()->icEntry()->pc(script); + id = NameToId(script->getName(pc)); + if (stub->toSetProp_TypedObject()->isObjectReference()) { + // Ignore all values being written except plain objects. Null + // is included implicitly in type information for this property, + // and non-object non-null values will cause the stub to fail to + // match shortly and we will end up doing the assignment in the VM. + if (value.isObject()) + types::AddTypePropertyId(cx, obj, id, value); + } else { + // Ignore undefined values, which are included implicitly in type + // information for this property. + if (!value.isUndefined()) + types::AddTypePropertyId(cx, obj, id, value); + } + break; + } default: MOZ_CRASH("Invalid stub"); } @@ -3893,9 +3923,35 @@ static bool TryAttachNativeGetElemStub(JSContext *cx, HandleScript script, jsbyt } static bool -TypedArrayRequiresFloatingPoint(HandleObject obj) +IsPrimitiveArrayTypedObject(JSObject *obj) { - uint32_t type = AnyTypedArrayType(obj); + if (!obj->is<TypedObject>()) + return false; + TypeDescr &descr = obj->as<TypedObject>().typeDescr(); + return descr.is<ArrayTypeDescr>() && + descr.as<ArrayTypeDescr>().elementType().is<ScalarTypeDescr>(); +} + +static Scalar::Type +PrimitiveArrayTypedObjectType(JSObject *obj) +{ + MOZ_ASSERT(IsPrimitiveArrayTypedObject(obj)); + TypeDescr &descr = obj->as<TypedObject>().typeDescr(); + return descr.as<ArrayTypeDescr>().elementType().as<ScalarTypeDescr>().type(); +} + +static Scalar::Type +TypedThingElementType(JSObject *obj) +{ + return IsAnyTypedArray(obj) + ? AnyTypedArrayType(obj) + : PrimitiveArrayTypedObjectType(obj); +} + +static bool +TypedThingRequiresFloatingPoint(JSObject *obj) +{ + Scalar::Type type = TypedThingElementType(obj); return type == Scalar::Uint32 || type == Scalar::Float32 || type == Scalar::Float64; @@ -3987,8 +4043,10 @@ TryAttachGetElemStub(JSContext *cx, JSScript *script, jsbytecode *pc, ICGetElem_ } } - // Check for TypedArray[int] => Number accesses. - if (IsAnyTypedArray(obj.get()) && rhs.isNumber() && res.isNumber() && + // Check for TypedArray[int] => Number and TypedObject[int] => Number accesses. + if ((IsAnyTypedArray(obj.get()) || IsPrimitiveArrayTypedObject(obj)) && + rhs.isNumber() && + res.isNumber() && !TypedArrayGetElemStubExists(stub, obj)) { // Don't attach CALLELEM stubs for accesses on typed array expected to yield numbers. @@ -3998,15 +4056,19 @@ TryAttachGetElemStub(JSContext *cx, JSScript *script, jsbytecode *pc, ICGetElem_ #endif if (!cx->runtime()->jitSupportsFloatingPoint && - (TypedArrayRequiresFloatingPoint(obj) || rhs.isDouble())) + (TypedThingRequiresFloatingPoint(obj) || rhs.isDouble())) { return true; } + // Don't attach typed object stubs if they might be neutered, as the + // stub will always bail out. + if (IsPrimitiveArrayTypedObject(obj) && cx->compartment()->neuteredTypedObjects) + return true; + JitSpew(JitSpew_BaselineIC, " Generating GetElem(TypedArray[Int32]) stub"); - ICGetElem_TypedArray::Compiler compiler(cx, - AnyTypedArrayShape(obj.get()), - AnyTypedArrayType(obj.get())); + ICGetElem_TypedArray::Compiler compiler(cx, obj->lastProperty(), + TypedThingElementType(obj)); ICStub *typedArrayStub = compiler.getStub(compiler.getStubSpace(script)); if (!typedArrayStub) return false; @@ -4614,10 +4676,60 @@ ICGetElem_Dense::Compiler::generateStubCode(MacroAssembler &masm) // GetElem_TypedArray // +static void +LoadTypedThingLength(MacroAssembler &masm, TypedThingLayout layout, Register obj, Register result) +{ + switch (layout) { + case Layout_TypedArray: + masm.unboxInt32(Address(obj, TypedArrayLayout::lengthOffset()), result); + break; + case Layout_OutlineTypedObject: + case Layout_InlineTypedObject: + masm.loadObjProto(obj, result); + masm.unboxObject(Address(result, TypedProto::offsetOfTypeDescr()), result); + masm.unboxInt32(Address(result, ArrayTypeDescr::offsetOfLength()), result); + break; + default: + MOZ_CRASH(); + } +} + +static void +LoadTypedThingData(MacroAssembler &masm, TypedThingLayout layout, Register obj, Register result) +{ + switch (layout) { + case Layout_TypedArray: + masm.loadPtr(Address(obj, TypedArrayLayout::dataOffset()), result); + break; + case Layout_OutlineTypedObject: + masm.loadPtr(Address(obj, OutlineTypedObject::offsetOfData()), result); + break; + case Layout_InlineTypedObject: + masm.computeEffectiveAddress(Address(obj, InlineTypedObject::offsetOfDataStart()), result); + break; + default: + MOZ_CRASH(); + } +} + +static void +CheckForNeuteredTypedObject(JSContext *cx, MacroAssembler &masm, Label *failure) +{ + // All stubs which manipulate typed objects need to check the compartment + // wide flag indicating whether the objects are neutered, and bail out in + // this case. + int32_t *address = &cx->compartment()->neuteredTypedObjects; + masm.branch32(Assembler::NotEqual, AbsoluteAddress(address), Imm32(0), failure); +} + bool ICGetElem_TypedArray::Compiler::generateStubCode(MacroAssembler &masm) { Label failure; + + if (layout_ != Layout_TypedArray) + CheckForNeuteredTypedObject(cx, masm, &failure); + masm.branchTestObject(Assembler::NotEqual, R0, &failure); GeneralRegisterSet regs(availableGeneralRegs(2)); @@ -4650,11 +4762,11 @@ ICGetElem_TypedArray::Compiler::generateStubCode(MacroAssembler &masm) Register key = masm.extractInt32(R1, ExtractTemp1); // Bounds check. - masm.unboxInt32(Address(obj, TypedArrayLayout::lengthOffset()), scratchReg); + LoadTypedThingLength(masm, layout_, obj, scratchReg); masm.branch32(Assembler::BelowOrEqual, scratchReg, key, &failure); // Load the elements vector. - masm.loadPtr(Address(obj, TypedArrayLayout::dataOffset()), scratchReg); + LoadTypedThingData(masm, layout_, obj, scratchReg); // Load the value. BaseIndex source(scratchReg, key, ScaleFromElemWidth(Scalar::byteSize(type_))); @@ -5113,31 +5225,45 @@ DoSetElemFallback(JSContext *cx, BaselineFrame *frame, ICSetElem_Fallback *stub_ return true; } - if (IsAnyTypedArray(obj.get()) && index.isNumber() && rhs.isNumber()) { + if ((IsAnyTypedArray(obj.get()) || IsPrimitiveArrayTypedObject(obj)) && + index.isNumber() && + rhs.isNumber()) + { if (!cx->runtime()->jitSupportsFloatingPoint && - (TypedArrayRequiresFloatingPoint(obj) || index.isDouble())) + (TypedThingRequiresFloatingPoint(obj) || index.isDouble())) { return true; } - uint32_t len = AnyTypedArrayLength(obj.get()); + bool expectOutOfBounds; double idx = index.toNumber(); - bool expectOutOfBounds = (idx < 0 || idx >= double(len)); + if (IsAnyTypedArray(obj)) { + expectOutOfBounds = (idx < 0 || idx >= double(AnyTypedArrayLength(obj))); + } else { + // Typed objects throw on out of bounds accesses. Don't attach + // a stub in this case. + if (idx < 0 || idx >= double(obj->as<TypedObject>().length())) + return true; + expectOutOfBounds = false; + + // Don't attach stubs if typed objects in the compartment might be + // neutered, as the stub will always bail out. + if (cx->compartment()->neuteredTypedObjects) + return true; + } if (!TypedArraySetElemStubExists(stub, obj, expectOutOfBounds)) { // Remove any existing TypedArraySetElemStub that doesn't handle out-of-bounds if (expectOutOfBounds) RemoveExistingTypedArraySetElemStub(cx, stub, obj); + Shape *shape = obj->lastProperty(); + Scalar::Type type = TypedThingElementType(obj); + JitSpew(JitSpew_BaselineIC, " Generating SetElem_TypedArray stub (shape=%p, type=%u, oob=%s)", - AnyTypedArrayShape(obj.get()), - AnyTypedArrayType(obj.get()), - expectOutOfBounds ? "yes" : "no"); - ICSetElem_TypedArray::Compiler compiler(cx, - AnyTypedArrayShape(obj.get()), - AnyTypedArrayType(obj.get()), - expectOutOfBounds); + shape, type, expectOutOfBounds ? "yes" : "no"); + ICSetElem_TypedArray::Compiler compiler(cx, shape, type, expectOutOfBounds); ICStub *typedArrayStub = compiler.getStub(compiler.getStubSpace(script)); if (!typedArrayStub) return false; @@ -5521,10 +5647,80 @@ ICSetElemDenseAddCompiler::generateStubCode(MacroAssembler &masm) // SetElem_TypedArray // +// Write an arbitrary value to a typed array or typed object address at dest. +// If the value could not be converted to the appropriate format, jump to +// failure or failureModifiedScratch. +template <typename T> +static void +StoreToTypedArray(JSContext *cx, MacroAssembler &masm, Scalar::Type type, Address value, T dest, + Register scratch, Label *failure, Label *failureModifiedScratch) +{ + Label done; + + if (type == Scalar::Float32 || type == Scalar::Float64) { + masm.ensureDouble(value, FloatReg0, failure); + if (type == Scalar::Float32) { + masm.convertDoubleToFloat32(FloatReg0, ScratchFloat32Reg); + masm.storeToTypedFloatArray(type, ScratchFloat32Reg, dest); + } else { + masm.storeToTypedFloatArray(type, FloatReg0, dest); + } + } else if (type == Scalar::Uint8Clamped) { + Label notInt32; + masm.branchTestInt32(Assembler::NotEqual, value, ¬Int32); + masm.unboxInt32(value, scratch); + masm.clampIntToUint8(scratch); + + Label clamped; + masm.bind(&clamped); + masm.storeToTypedIntArray(type, scratch, dest); + masm.jump(&done); + + // If the value is a double, clamp to uint8 and jump back. + // Else, jump to failure. + masm.bind(¬Int32); + if (cx->runtime()->jitSupportsFloatingPoint) { + masm.branchTestDouble(Assembler::NotEqual, value, failure); + masm.unboxDouble(value, FloatReg0); + masm.clampDoubleToUint8(FloatReg0, scratch); + masm.jump(&clamped); + } else { + masm.jump(failure); + } + } else { + Label notInt32; + masm.branchTestInt32(Assembler::NotEqual, value, ¬Int32); + masm.unboxInt32(value, scratch); + + Label isInt32; + masm.bind(&isInt32); + masm.storeToTypedIntArray(type, scratch, dest); + masm.jump(&done); + + // If the value is a double, truncate and jump back. + // Else, jump to failure. + masm.bind(¬Int32); + if (cx->runtime()->jitSupportsFloatingPoint) { + masm.branchTestDouble(Assembler::NotEqual, value, failure); + masm.unboxDouble(value, FloatReg0); + masm.branchTruncateDouble(FloatReg0, scratch, failureModifiedScratch); + masm.jump(&isInt32); + } else { + masm.jump(failure); + } + } + + masm.bind(&done); +} + bool ICSetElem_TypedArray::Compiler::generateStubCode(MacroAssembler &masm) { Label failure; + + if (layout_ != Layout_TypedArray) + CheckForNeuteredTypedObject(cx, masm, &failure); + masm.branchTestObject(Assembler::NotEqual, R0, &failure); GeneralRegisterSet regs(availableGeneralRegs(2)); @@ -5558,12 +5754,12 @@ ICSetElem_TypedArray::Compiler::generateStubCode(MacroAssembler &masm) // Bounds check. Label oobWrite; - masm.unboxInt32(Address(obj, TypedArrayLayout::lengthOffset()), scratchReg); + LoadTypedThingLength(masm, layout_, obj, scratchReg); masm.branch32(Assembler::BelowOrEqual, scratchReg, key, expectOutOfBounds_ ? &oobWrite : &failure); // Load the elements vector. - masm.loadPtr(Address(obj, TypedArrayLayout::dataOffset()), scratchReg); + LoadTypedThingData(masm, layout_, obj, scratchReg); BaseIndex dest(scratchReg, key, ScaleFromElemWidth(Scalar::byteSize(type_))); Address value(BaselineStackReg, ICStackValueOffset); @@ -5576,64 +5772,15 @@ ICSetElem_TypedArray::Compiler::generateStubCode(MacroAssembler &masm) regs.take(scratchReg); Register secondScratch = regs.takeAny(); - if (type_ == Scalar::Float32 || type_ == Scalar::Float64) { - masm.ensureDouble(value, FloatReg0, &failure); - if (type_ == Scalar::Float32) - { - masm.convertDoubleToFloat32(FloatReg0, ScratchFloat32Reg); - masm.storeToTypedFloatArray(type_, ScratchFloat32Reg, dest); - } else { - masm.storeToTypedFloatArray(type_, FloatReg0, dest); - } - EmitReturnFromIC(masm); - } else if (type_ == Scalar::Uint8Clamped) { - Label notInt32; - masm.branchTestInt32(Assembler::NotEqual, value, ¬Int32); - masm.unboxInt32(value, secondScratch); - masm.clampIntToUint8(secondScratch); - - Label clamped; - masm.bind(&clamped); - masm.storeToTypedIntArray(type_, secondScratch, dest); - EmitReturnFromIC(masm); - - // If the value is a double, clamp to uint8 and jump back. - // Else, jump to failure. - masm.bind(¬Int32); - if (cx->runtime()->jitSupportsFloatingPoint) { - masm.branchTestDouble(Assembler::NotEqual, value, &failure); - masm.unboxDouble(value, FloatReg0); - masm.clampDoubleToUint8(FloatReg0, secondScratch); - masm.jump(&clamped); - } else { - masm.jump(&failure); - } - } else { - Label notInt32; - masm.branchTestInt32(Assembler::NotEqual, value, ¬Int32); - masm.unboxInt32(value, secondScratch); - - Label isInt32; - masm.bind(&isInt32); - masm.storeToTypedIntArray(type_, secondScratch, dest); - EmitReturnFromIC(masm); - - // If the value is a double, truncate and jump back. - // Else, jump to failure. - Label failureRestoreRegs; - masm.bind(¬Int32); - if (cx->runtime()->jitSupportsFloatingPoint) { - masm.branchTestDouble(Assembler::NotEqual, value, &failure); - masm.unboxDouble(value, FloatReg0); - masm.branchTruncateDouble(FloatReg0, secondScratch, &failureRestoreRegs); - masm.jump(&isInt32); - } else { - masm.jump(&failure); - } + Label failureModifiedSecondScratch; + StoreToTypedArray(cx, masm, type_, value, dest, + secondScratch, &failure, &failureModifiedSecondScratch); + EmitReturnFromIC(masm); + if (failureModifiedSecondScratch.used()) { // Writing to secondScratch may have clobbered R0 or R1, restore them // first. - masm.bind(&failureRestoreRegs); + masm.bind(&failureModifiedSecondScratch); masm.tagValue(JSVAL_TYPE_OBJECT, obj, R0); masm.tagValue(JSVAL_TYPE_INT32, key, R1); } @@ -5643,6 +5790,7 @@ ICSetElem_TypedArray::Compiler::generateStubCode(MacroAssembler &masm) EmitStubGuardFailure(masm); if (expectOutOfBounds_) { + MOZ_ASSERT(layout_ == Layout_TypedArray); masm.bind(&oobWrite); EmitReturnFromIC(masm); } @@ -6604,6 +6752,46 @@ TryAttachNativeGetPropStub(JSContext *cx, HandleScript script, jsbytecode *pc, return true; } +static bool +TryAttachTypedObjectGetPropStub(JSContext *cx, HandleScript script, + ICGetProp_Fallback *stub, HandlePropertyName name, HandleValue val, + bool *attached) +{ + MOZ_ASSERT(!*attached); + + if (!cx->runtime()->jitSupportsFloatingPoint) + return true; + + if (!val.isObject() || !val.toObject().is<TypedObject>()) + return true; + Rooted<TypedObject *> obj(cx, &val.toObject().as<TypedObject>()); + + if (!obj->typeDescr().is<StructTypeDescr>()) + return true; + Rooted<StructTypeDescr *> structDescr(cx, &obj->typeDescr().as<StructTypeDescr>()); + + size_t fieldIndex; + if (!structDescr->fieldIndex(NameToId(name), &fieldIndex)) + return true; + + Rooted<TypeDescr *> fieldDescr(cx, &structDescr->fieldDescr(fieldIndex)); + if (!fieldDescr->is<SimpleTypeDescr>()) + return true; + + uint32_t fieldOffset = structDescr->fieldOffset(fieldIndex); + ICStub *monitorStub = stub->fallbackMonitorStub()->firstMonitorStub(); + + ICGetProp_TypedObject::Compiler compiler(cx, monitorStub, obj->lastProperty(), + fieldOffset, &fieldDescr->as<SimpleTypeDescr>()); + ICStub *newStub = compiler.getStub(compiler.getStubSpace(script)); + if (!newStub) + return false; + stub->addNewStub(newStub); + + *attached = true; + return true; +} + static bool TryAttachPrimitiveGetPropStub(JSContext *cx, HandleScript script, jsbytecode *pc, ICGetProp_Fallback *stub, HandlePropertyName name, HandleValue val, @@ -6811,6 +6999,11 @@ DoGetPropFallback(JSContext *cx, BaselineFrame *frame, ICGetProp_Fallback *stub_ if (attached) return true; + if (!TryAttachTypedObjectGetPropStub(cx, script, stub, name, val, &attached)) + return false; + if (attached) + return true; + if (val.isString() || val.isNumber() || val.isBoolean()) { if (!TryAttachPrimitiveGetPropStub(cx, script, pc, stub, name, val, res, &attached)) return false; @@ -7706,6 +7899,82 @@ ICGetProp_Generic::Compiler::generateStubCode(MacroAssembler &masm) return true; } +bool +ICGetProp_TypedObject::Compiler::generateStubCode(MacroAssembler &masm) +{ + Label failure; + + CheckForNeuteredTypedObject(cx, masm, &failure); + + GeneralRegisterSet regs(availableGeneralRegs(1)); + + Register scratch1 = regs.takeAnyExcluding(BaselineTailCallReg); + Register scratch2 = regs.takeAnyExcluding(BaselineTailCallReg); + + // Object and shape guard. + masm.branchTestObject(Assembler::NotEqual, R0, &failure); + Register object = masm.extractObject(R0, ExtractTemp0); + masm.loadPtr(Address(BaselineStubReg, ICGetProp_TypedObject::offsetOfShape()), scratch1); + masm.branchTestObjShape(Assembler::NotEqual, object, scratch1, &failure); + + // Get the object's data pointer. + LoadTypedThingData(masm, layout_, object, scratch1); + + // Get the address being written to. + masm.load32(Address(BaselineStubReg, ICGetProp_TypedObject::offsetOfFieldOffset()), scratch2); + masm.addPtr(scratch2, scratch1); + + // Only monitor the result if the type produced by this stub might vary. + bool monitorLoad; + + if (fieldDescr_->is<ScalarTypeDescr>()) { + Scalar::Type type = fieldDescr_->as<ScalarTypeDescr>().type(); + monitorLoad = type == Scalar::Uint32; + + masm.loadFromTypedArray(type, Address(scratch1, 0), R0, /* allowDouble = */ true, + scratch2, nullptr); + } else { + ReferenceTypeDescr::Type type = fieldDescr_->as<ReferenceTypeDescr>().type(); + monitorLoad = type != ReferenceTypeDescr::TYPE_STRING; + + switch (type) { + case ReferenceTypeDescr::TYPE_ANY: + masm.loadValue(Address(scratch1, 0), R0); + break; + + case ReferenceTypeDescr::TYPE_OBJECT: { + Label notNull, done; + masm.loadPtr(Address(scratch1, 0), scratch1); + masm.branchTestPtr(Assembler::NonZero, scratch1, scratch1, ¬Null); + masm.moveValue(NullValue(), R0); + masm.jump(&done); + masm.bind(¬Null); + masm.tagValue(JSVAL_TYPE_OBJECT, scratch1, R0); + masm.bind(&done); + break; + } + + case ReferenceTypeDescr::TYPE_STRING: + masm.loadPtr(Address(scratch1, 0), scratch1); + masm.tagValue(JSVAL_TYPE_STRING, scratch1, R0); + break; + + default: + MOZ_CRASH(); + } + } + + if (monitorLoad) + EmitEnterTypeMonitorIC(masm); + else + EmitReturnFromIC(masm); + + masm.bind(&failure); + EmitStubGuardFailure(masm); + + return true; +} + void BaselineScript::noteAccessedGetter(uint32_t pcOffset) { @@ -7884,6 +8153,48 @@ TryAttachSetAccessorPropStub(JSContext *cx, HandleScript script, jsbytecode *pc, return true; } +static bool +TryAttachTypedObjectSetPropStub(JSContext *cx, HandleScript script, + ICSetProp_Fallback *stub, HandleId id, + HandleObject obj, HandleValue rhs, bool *attached) +{ + MOZ_ASSERT(!*attached); + + if (!cx->runtime()->jitSupportsFloatingPoint) + return true; + + if (!obj->is<TypedObject>()) + return true; + + if (!obj->as<TypedObject>().typeDescr().is<StructTypeDescr>()) + return true; + Rooted<StructTypeDescr *> structDescr(cx); + structDescr = &obj->as<TypedObject>().typeDescr().as<StructTypeDescr>(); + + size_t fieldIndex; + if (!structDescr->fieldIndex(id, &fieldIndex)) + return true; + + Rooted<TypeDescr *> fieldDescr(cx, &structDescr->fieldDescr(fieldIndex)); + if (!fieldDescr->is<SimpleTypeDescr>()) + return true; + + uint32_t fieldOffset = structDescr->fieldOffset(fieldIndex); + + ICSetProp_TypedObject::Compiler compiler(cx, obj->lastProperty(), obj->type(), fieldOffset, + &fieldDescr->as<SimpleTypeDescr>()); + ICUpdatedStub *newStub = compiler.getStub(compiler.getStubSpace(script)); + if (!newStub) + return false; + if (compiler.needsUpdateStubs() && !newStub->addUpdateStubForValue(cx, script, obj, id, rhs)) + return false; + + stub->addNewStub(newStub); + + *attached = true; + return true; +} + static bool DoSetPropFallback(JSContext *cx, BaselineFrame *frame, ICSetProp_Fallback *stub_, HandleValue lhs, HandleValue rhs, MutableHandleValue res) @@ -7985,6 +8296,15 @@ DoSetPropFallback(JSContext *cx, BaselineFrame *frame, ICSetProp_Fallback *stub_ if (attached) return true; + if (!attached && + lhs.isObject() && + !TryAttachTypedObjectSetPropStub(cx, script, stub, id, obj, rhs, &attached)) + { + return false; + } + if (attached) + return true; + MOZ_ASSERT(!attached); if (!isTemporarilyUnoptimizable) stub->noteUnoptimizableAccess(); @@ -8264,6 +8584,128 @@ ICSetPropNativeAddCompiler::generateStubCode(MacroAssembler &masm) return true; } +bool +ICSetProp_TypedObject::Compiler::generateStubCode(MacroAssembler &masm) +{ + Label failure; + + CheckForNeuteredTypedObject(cx, masm, &failure); + + // Guard input is an object. + masm.branchTestObject(Assembler::NotEqual, R0, &failure); + + GeneralRegisterSet regs(availableGeneralRegs(2)); + Register scratch = regs.takeAny(); + + // Unbox and shape guard. + Register object = masm.extractObject(R0, ExtractTemp0); + masm.loadPtr(Address(BaselineStubReg, ICSetProp_TypedObject::offsetOfShape()), scratch); + masm.branchTestObjShape(Assembler::NotEqual, object, scratch, &failure); + + // Guard that the type object matches. + masm.loadPtr(Address(BaselineStubReg, ICSetProp_TypedObject::offsetOfType()), scratch); + masm.branchPtr(Assembler::NotEqual, Address(object, JSObject::offsetOfType()), scratch, + &failure); + + if (needsUpdateStubs()) { + // Stow both R0 and R1 (object and value). + masm.push(object); + masm.push(BaselineStubReg); + EmitStowICValues(masm, 2); + + // Move RHS into R0 for TypeUpdate check. + masm.moveValue(R1, R0); + + // Call the type update stub. + if (!callTypeUpdateIC(masm, sizeof(Value))) + return false; + + // Unstow R0 and R1 (object and key) + EmitUnstowICValues(masm, 2); + masm.pop(BaselineStubReg); + masm.pop(object); + + // Trigger post barriers here on the values being written. Descriptors + // which can write objects also need update stubs. + GeneralRegisterSet saveRegs; + saveRegs.add(R0); + saveRegs.add(R1); + saveRegs.addUnchecked(object); + saveRegs.add(BaselineStubReg); + emitPostWriteBarrierSlot(masm, object, R1, scratch, saveRegs); + } + + // Save the rhs on the stack so we can get a second scratch register. + Label failurePopRHS; + masm.pushValue(R1); + regs = availableGeneralRegs(1); + regs.takeUnchecked(object); + regs.take(scratch); + Register secondScratch = regs.takeAny(); + + // Get the object's data pointer. + LoadTypedThingData(masm, layout_, object, scratch); + + // Compute the address being written to. + masm.load32(Address(BaselineStubReg, ICSetProp_TypedObject::offsetOfFieldOffset()), secondScratch); + masm.addPtr(secondScratch, scratch); + + Address dest(scratch, 0); + Address value(BaselineStackReg, 0); + + if (fieldDescr_->is<ScalarTypeDescr>()) { + Scalar::Type type = fieldDescr_->as<ScalarTypeDescr>().type(); + StoreToTypedArray(cx, masm, type, value, dest, + secondScratch, &failurePopRHS, &failurePopRHS); + masm.popValue(R1); + EmitReturnFromIC(masm); + } else { + ReferenceTypeDescr::Type type = fieldDescr_->as<ReferenceTypeDescr>().type(); + + masm.popValue(R1); + + switch (type) { + case ReferenceTypeDescr::TYPE_ANY: + EmitPreBarrier(masm, dest, MIRType_Value); + masm.storeValue(R1, dest); + break; + + case ReferenceTypeDescr::TYPE_OBJECT: { + EmitPreBarrier(masm, dest, MIRType_Object); + Label notObject; + masm.branchTestObject(Assembler::NotEqual, R1, ¬Object); + Register rhsObject = masm.extractObject(R1, ExtractTemp0); + masm.storePtr(rhsObject, dest); + EmitReturnFromIC(masm); + masm.bind(¬Object); + masm.branchTestNull(Assembler::NotEqual, R1, &failure); + masm.storePtr(ImmWord(0), dest); + break; + } + + case ReferenceTypeDescr::TYPE_STRING: { + EmitPreBarrier(masm, dest, MIRType_String); + masm.branchTestString(Assembler::NotEqual, R1, &failure); + Register rhsString = masm.extractString(R1, ExtractTemp0); + masm.storePtr(rhsString, dest); + break; + } + + default: + MOZ_CRASH(); + } + + EmitReturnFromIC(masm); + } + + masm.bind(&failurePopRHS); + masm.popValue(R1); + + masm.bind(&failure); + EmitStubGuardFailure(masm); + return true; +} + bool ICSetProp_CallScripted::Compiler::generateStubCode(MacroAssembler &masm) { diff --git a/js/src/jit/BaselineIC.h b/js/src/jit/BaselineIC.h index 6e2de5c545c8..172bc280b936 100644 --- a/js/src/jit/BaselineIC.h +++ b/js/src/jit/BaselineIC.h @@ -14,9 +14,11 @@ #include "jsgc.h" #include "jsopcode.h" +#include "builtin/TypedObject.h" #include "jit/BaselineJIT.h" #include "jit/BaselineRegisters.h" #include "vm/ArrayObject.h" +#include "vm/TypedArrayCommon.h" namespace js { @@ -424,6 +426,7 @@ class ICEntry _(GetProp_Native) \ _(GetProp_NativeDoesNotExist) \ _(GetProp_NativePrototype) \ + _(GetProp_TypedObject) \ _(GetProp_CallScripted) \ _(GetProp_CallNative) \ _(GetProp_CallNativePrototype)\ @@ -437,6 +440,7 @@ class ICEntry _(SetProp_Fallback) \ _(SetProp_Native) \ _(SetProp_NativeAdd) \ + _(SetProp_TypedObject) \ _(SetProp_CallScripted) \ _(SetProp_CallNative) \ \ @@ -3409,6 +3413,26 @@ class ICGetElem_Dense : public ICMonitoredStub }; }; +// Enum for stubs handling a combination of typed arrays and typed objects. +enum TypedThingLayout { + Layout_TypedArray, + Layout_OutlineTypedObject, + Layout_InlineTypedObject +}; + +static inline TypedThingLayout +GetTypedThingLayout(const Class *clasp) +{ + if (IsAnyTypedArrayClass(clasp)) + return Layout_TypedArray; + if (IsOutlineTypedObjectClass(clasp)) + return Layout_OutlineTypedObject; + if (IsInlineTypedObjectClass(clasp)) + return Layout_InlineTypedObject; + MOZ_CRASH("Bad object class"); +} + +// Accesses scalar elements of a typed array or typed object. class ICGetElem_TypedArray : public ICStub { friend class ICStubSpace; @@ -3438,19 +3462,23 @@ class ICGetElem_TypedArray : public ICStub class Compiler : public ICStubCompiler { RootedShape shape_; Scalar::Type type_; + TypedThingLayout layout_; protected: bool generateStubCode(MacroAssembler &masm); virtual int32_t getKey() const { - return static_cast<int32_t>(kind) | (static_cast<int32_t>(type_) << 16); + return static_cast<int32_t>(kind) | + (static_cast<int32_t>(type_) << 16) | + (static_cast<int32_t>(layout_) << 24); } public: Compiler(JSContext *cx, Shape *shape, Scalar::Type type) : ICStubCompiler(cx, ICStub::GetElem_TypedArray), shape_(cx, shape), - type_(type) + type_(type), + layout_(GetTypedThingLayout(shape->getObjectClass())) {} ICStub *getStub(ICStubSpace *space) { @@ -3724,6 +3752,7 @@ class ICSetElemDenseAddCompiler : public ICStubCompiler { ICUpdatedStub *getStub(ICStubSpace *space); }; +// Accesses scalar elements of a typed array or typed object. class ICSetElem_TypedArray : public ICStub { friend class ICStubSpace; @@ -3763,14 +3792,17 @@ class ICSetElem_TypedArray : public ICStub class Compiler : public ICStubCompiler { RootedShape shape_; Scalar::Type type_; + TypedThingLayout layout_; bool expectOutOfBounds_; protected: bool generateStubCode(MacroAssembler &masm); virtual int32_t getKey() const { - return static_cast<int32_t>(kind) | (static_cast<int32_t>(type_) << 16) | - (static_cast<int32_t>(expectOutOfBounds_) << 24); + return static_cast<int32_t>(kind) | + (static_cast<int32_t>(type_) << 16) | + (static_cast<int32_t>(layout_) << 24) | + (static_cast<int32_t>(expectOutOfBounds_) << 28); } public: @@ -3778,6 +3810,7 @@ class ICSetElem_TypedArray : public ICStub : ICStubCompiler(cx, ICStub::SetElem_TypedArray), shape_(cx, shape), type_(type), + layout_(GetTypedThingLayout(shape->getObjectClass())), expectOutOfBounds_(expectOutOfBounds) {} @@ -4574,6 +4607,84 @@ class ICGetPropNativeDoesNotExistCompiler : public ICStubCompiler ICStub *getStub(ICStubSpace *space); }; +static uint32_t +SimpleTypeDescrKey(SimpleTypeDescr *descr) +{ + if (descr->is<ScalarTypeDescr>()) + return uint32_t(descr->as<ScalarTypeDescr>().type()) << 1; + return (uint32_t(descr->as<ReferenceTypeDescr>().type()) << 1) | 1; +} + +class ICGetProp_TypedObject : public ICMonitoredStub +{ + friend class ICStubSpace; + + HeapPtrShape shape_; + uint32_t fieldOffset_; + + ICGetProp_TypedObject(JitCode *stubCode, ICStub *firstMonitorStub, HandleShape shape, + uint32_t fieldOffset) + : ICMonitoredStub(ICStub::GetProp_TypedObject, stubCode, firstMonitorStub), + shape_(shape), fieldOffset_(fieldOffset) + { + (void) fieldOffset_; // Silence clang warning + } + + public: + static inline ICGetProp_TypedObject *New(ICStubSpace *space, JitCode *code, + ICStub *firstMonitorStub, HandleShape shape, + uint32_t fieldOffset) + { + if (!code) + return nullptr; + return space->allocate<ICGetProp_TypedObject>(code, firstMonitorStub, shape, fieldOffset); + } + + HeapPtrShape &shape() { + return shape_; + } + + static size_t offsetOfShape() { + return offsetof(ICGetProp_TypedObject, shape_); + } + static size_t offsetOfFieldOffset() { + return offsetof(ICGetProp_TypedObject, fieldOffset_); + } + + class Compiler : public ICStubCompiler { + protected: + ICStub *firstMonitorStub_; + RootedShape shape_; + uint32_t fieldOffset_; + TypedThingLayout layout_; + Rooted<SimpleTypeDescr *> fieldDescr_; + + bool generateStubCode(MacroAssembler &masm); + + virtual int32_t getKey() const { + return static_cast<int32_t>(kind) | + (static_cast<int32_t>(SimpleTypeDescrKey(fieldDescr_)) << 16) | + (static_cast<int32_t>(layout_) << 24); + } + + public: + Compiler(JSContext *cx, ICStub *firstMonitorStub, + Shape *shape, uint32_t fieldOffset, SimpleTypeDescr *fieldDescr) + : ICStubCompiler(cx, ICStub::GetProp_TypedObject), + firstMonitorStub_(firstMonitorStub), + shape_(cx, shape), + fieldOffset_(fieldOffset), + layout_(GetTypedThingLayout(shape->getObjectClass())), + fieldDescr_(cx, fieldDescr) + {} + + ICStub *getStub(ICStubSpace *space) { + return ICGetProp_TypedObject::New(space, getStubCode(), firstMonitorStub_, + shape_, fieldOffset_); + } + }; +}; + class ICGetPropCallGetter : public ICMonitoredStub { friend class ICStubSpace; @@ -5416,6 +5527,102 @@ class ICSetPropNativeAddCompiler : public ICStubCompiler ICUpdatedStub *getStub(ICStubSpace *space); }; +class ICSetProp_TypedObject : public ICUpdatedStub +{ + friend class ICStubSpace; + + HeapPtrShape shape_; + HeapPtrTypeObject type_; + uint32_t fieldOffset_; + bool isObjectReference_; + + ICSetProp_TypedObject(JitCode *stubCode, HandleShape shape, HandleTypeObject type, + uint32_t fieldOffset, bool isObjectReference) + : ICUpdatedStub(ICStub::SetProp_TypedObject, stubCode), + shape_(shape), + type_(type), + fieldOffset_(fieldOffset), + isObjectReference_(isObjectReference) + { + (void) fieldOffset_; // Silence clang warning + } + + public: + static inline ICSetProp_TypedObject *New(ICStubSpace *space, JitCode *code, + HandleShape shape, HandleTypeObject type, + uint32_t fieldOffset, bool isObjectReference) + { + if (!code) + return nullptr; + return space->allocate<ICSetProp_TypedObject>(code, shape, type, + fieldOffset, isObjectReference); + } + + HeapPtrShape &shape() { + return shape_; + } + HeapPtrTypeObject &type() { + return type_; + } + bool isObjectReference() { + return isObjectReference_; + } + + static size_t offsetOfShape() { + return offsetof(ICSetProp_TypedObject, shape_); + } + static size_t offsetOfType() { + return offsetof(ICSetProp_TypedObject, type_); + } + static size_t offsetOfFieldOffset() { + return offsetof(ICSetProp_TypedObject, fieldOffset_); + } + + class Compiler : public ICStubCompiler { + protected: + RootedShape shape_; + RootedTypeObject type_; + uint32_t fieldOffset_; + TypedThingLayout layout_; + Rooted<SimpleTypeDescr *> fieldDescr_; + + bool generateStubCode(MacroAssembler &masm); + + virtual int32_t getKey() const { + return static_cast<int32_t>(kind) | + (static_cast<int32_t>(SimpleTypeDescrKey(fieldDescr_)) << 16) | + (static_cast<int32_t>(layout_) << 24); + } + + public: + Compiler(JSContext *cx, Shape *shape, types::TypeObject *type, uint32_t fieldOffset, + SimpleTypeDescr *fieldDescr) + : ICStubCompiler(cx, ICStub::SetProp_TypedObject), + shape_(cx, shape), + type_(cx, type), + fieldOffset_(fieldOffset), + layout_(GetTypedThingLayout(shape->getObjectClass())), + fieldDescr_(cx, fieldDescr) + {} + + ICUpdatedStub *getStub(ICStubSpace *space) { + bool isObjectReference = + fieldDescr_->is<ReferenceTypeDescr>() && + fieldDescr_->as<ReferenceTypeDescr>().type() == ReferenceTypeDescr::TYPE_OBJECT; + ICUpdatedStub *stub = ICSetProp_TypedObject::New(space, getStubCode(), shape_, type_, + fieldOffset_, isObjectReference); + if (!stub || !stub->initUpdatingChain(cx, space)) + return nullptr; + return stub; + } + + bool needsUpdateStubs() { + return fieldDescr_->is<ReferenceTypeDescr>() && + fieldDescr_->as<ReferenceTypeDescr>().type() != ReferenceTypeDescr::TYPE_STRING; + } + }; +}; + // Base stub for calling a setters on a native object. class ICSetPropCallSetter : public ICStub { diff --git a/js/src/jscompartment.cpp b/js/src/jscompartment.cpp index 762f555e2640..6dbdcc67b126 100644 --- a/js/src/jscompartment.cpp +++ b/js/src/jscompartment.cpp @@ -56,6 +56,7 @@ JSCompartment::JSCompartment(Zone *zone, const JS::CompartmentOptions &options = lastAnimationTime(0), regExps(runtime_), globalWriteBarriered(false), + neuteredTypedObjects(0), propertyTree(thisForCtor()), selfHostingScriptSource(nullptr), lazyArrayBuffers(nullptr), diff --git a/js/src/jscompartment.h b/js/src/jscompartment.h index df76c4543b63..e13b0f4c644a 100644 --- a/js/src/jscompartment.h +++ b/js/src/jscompartment.h @@ -241,6 +241,9 @@ struct JSCompartment */ bool globalWriteBarriered; + // Non-zero if any typed objects in this compartment might be neutered. + int32_t neuteredTypedObjects; + public: void addSizeOfIncludingThis(mozilla::MallocSizeOf mallocSizeOf, size_t *tiAllocationSiteTables, diff --git a/js/src/vm/ArrayBufferObject.cpp b/js/src/vm/ArrayBufferObject.cpp index 52b42196f4ed..8d918575ccda 100644 --- a/js/src/vm/ArrayBufferObject.cpp +++ b/js/src/vm/ArrayBufferObject.cpp @@ -529,6 +529,7 @@ ArrayBufferObject::neuter(JSContext *cx, Handle<ArrayBufferObject*> buffer, if (!cx->global()->getType(cx)) CrashAtUnhandlableOOM("ArrayBufferObject::neuter"); types::MarkTypeObjectFlags(cx, cx->global(), types::OBJECT_FLAG_TYPED_OBJECT_NEUTERED); + cx->compartment()->neuteredTypedObjects = 1; } // Neuter all views on the buffer, clear out the list of views and the From d40cbb7a3dd06c2748699d92f605ea25335cccdb Mon Sep 17 00:00:00 2001 From: "Patrick Wang (Chih-Kai Wang)" <kk1fff@patrickz.net> Date: Thu, 27 Nov 2014 13:52:56 +0800 Subject: [PATCH 64/64] Bug 1105215: fix build break when MOZ_CALLSTACK_DISABLED is not defined. r=njn --- xpcom/glue/BlockingResourceBase.cpp | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/xpcom/glue/BlockingResourceBase.cpp b/xpcom/glue/BlockingResourceBase.cpp index 1723583b5417..a9170a0b07a7 100644 --- a/xpcom/glue/BlockingResourceBase.cpp +++ b/xpcom/glue/BlockingResourceBase.cpp @@ -187,9 +187,11 @@ BlockingResourceBase::Print(nsACString& aOut) const for (uint32_t i = 0; i < state.Length(); i++) { const size_t kMaxLength = 1024; char buffer[kMaxLength]; - addressService.GetLocation(state[i], buffer, kMaxLength); + addressService.GetLocation(i + 1, state[i], buffer, kMaxLength); const char* fmt = " %s\n"; - aOut += nsPrintfCString(fmt, buffer); + aOut.AppendLiteral(" "); + aOut.Append(buffer); + aOut.AppendLiteral("\n"); fprintf(stderr, fmt, buffer); }