Merge inbound to m-c
authorWes Kocher <wkocher@mozilla.com>
Mon, 28 Apr 2014 15:54:30 -0700
changeset 180982 b771e5a414418f7aa9228c10587c4d3e8a2cf338
parent 180981 e350a1923f0e014cdafe6b501c447ca6281f126f (current diff)
parent 180978 fe7f450a5435aa55ca7931a2c2570edfe625f0dc (diff)
child 180983 6810499bd649f44e866e7df16fcc96605611a007
push id272
push userpvanderbeken@mozilla.com
push dateMon, 05 May 2014 16:31:18 +0000
milestone32.0a1
Merge inbound to m-c
js/src/jsanalyze.cpp
js/src/jsanalyze.h
--- a/addon-sdk/source/lib/sdk/content/sandbox.js
+++ b/addon-sdk/source/lib/sdk/content/sandbox.js
@@ -138,17 +138,17 @@ const WorkerSandbox = Class({
     apiSandbox.console = console;
 
     // Create the sandbox and bind it to window in order for content scripts to
     // have access to all standard globals (window, document, ...)
     let content = sandbox(principals, {
       sandboxPrototype: proto,
       wantXrays: true,
       wantGlobalProperties: wantGlobalProperties,
-      wantExportHelpers: !waiveSecurityMembrane,
+      wantExportHelpers: true,
       sameZoneAs: window,
       metadata: {
         SDKContentScript: true,
         'inner-window-id': getInnerId(window)
       }
     });
     model.sandbox = content;
 
--- a/content/base/src/FragmentOrElement.cpp
+++ b/content/base/src/FragmentOrElement.cpp
@@ -949,23 +949,26 @@ FragmentOrElement::SetXBLBinding(nsXBLBi
   // constructor twice (if aBinding inherits from it) or firing its constructor
   // after aContent has been deleted (if aBinding is null and the content node
   // dies before we process mAttachedStack).
   nsRefPtr<nsXBLBinding> oldBinding = GetXBLBinding();
   if (oldBinding) {
     bindingManager->RemoveFromAttachedQueue(oldBinding);
   }
 
-  nsDOMSlots *slots = DOMSlots();
   if (aBinding) {
     SetFlags(NODE_MAY_BE_IN_BINDING_MNGR);
+    nsDOMSlots *slots = DOMSlots();
     slots->mXBLBinding = aBinding;
     bindingManager->AddBoundContent(this);
   } else {
-    slots->mXBLBinding = nullptr;
+    nsDOMSlots *slots = GetExistingDOMSlots();
+    if (slots) {
+      slots->mXBLBinding = nullptr;
+    }
     bindingManager->RemoveBoundContent(this);
     if (oldBinding) {
       oldBinding->SetBoundElement(nullptr);
     }
   }
 }
 
 nsIContent*
@@ -1006,21 +1009,26 @@ FragmentOrElement::SetShadowRoot(ShadowR
 {
   nsDOMSlots *slots = DOMSlots();
   slots->mShadowRoot = aShadowRoot;
 }
 
 void
 FragmentOrElement::SetXBLInsertionParent(nsIContent* aContent)
 {
-  nsDOMSlots *slots = DOMSlots();
   if (aContent) {
+    nsDOMSlots *slots = DOMSlots();
     SetFlags(NODE_MAY_BE_IN_BINDING_MNGR);
+    slots->mXBLInsertionParent = aContent;
+  } else {
+    nsDOMSlots *slots = GetExistingDOMSlots();
+    if (slots) {
+      slots->mXBLInsertionParent = nullptr;
+    }
   }
-  slots->mXBLInsertionParent = aContent;
 }
 
 CustomElementData*
 FragmentOrElement::GetCustomElementData() const
 {
   nsDOMSlots *slots = GetExistingDOMSlots();
   if (slots) {
     return slots->mCustomElementData;
--- a/content/base/src/nsFrameMessageManager.cpp
+++ b/content/base/src/nsFrameMessageManager.cpp
@@ -1769,28 +1769,35 @@ class nsAsyncMessageToSameProcessParent 
 {
 public:
   nsAsyncMessageToSameProcessParent(JSContext* aCx,
                                     const nsAString& aMessage,
                                     const StructuredCloneData& aData,
                                     JS::Handle<JSObject *> aCpows,
                                     nsIPrincipal* aPrincipal)
     : nsSameProcessAsyncMessageBase(aCx, aMessage, aData, aCpows, aPrincipal)
+    , mDelivered(false)
   {
   }
 
   NS_IMETHOD Run()
   {
     if (nsFrameMessageManager::sPendingSameProcessAsyncMessages) {
       nsFrameMessageManager::sPendingSameProcessAsyncMessages->RemoveElement(this);
     }
-    nsFrameMessageManager* ppm = nsFrameMessageManager::sSameProcessParentManager;
-    ReceiveMessage(static_cast<nsIContentFrameMessageManager*>(ppm), ppm);
+    if (!mDelivered) {
+      mDelivered = true;
+      nsFrameMessageManager* ppm = nsFrameMessageManager::sSameProcessParentManager;
+      ReceiveMessage(static_cast<nsIContentFrameMessageManager*>(ppm), ppm);
+    }
     return NS_OK;
   }
+
+private:
+  bool mDelivered;
 };
 
 /**
  * Send messages to the imaginary parent process in a single-process scenario.
  */
 class SameChildProcessMessageManagerCallback : public MessageManagerCallback
 {
 public:
--- a/content/base/src/nsGenericDOMDataNode.cpp
+++ b/content/base/src/nsGenericDOMDataNode.cpp
@@ -97,18 +97,16 @@ NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(
   if (!nsINode::Traverse(tmp, cb)) {
     return NS_SUCCESS_INTERRUPTED_TRAVERSE;
   }
 
   nsDataSlots *slots = tmp->GetExistingDataSlots();
   if (slots) {
     slots->Traverse(cb);
   }
-
-  tmp->OwnerDoc()->BindingManager()->Traverse(tmp, cb);
 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
 
 NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(nsGenericDOMDataNode)
   nsINode::Unlink(tmp);
 
   nsDataSlots *slots = tmp->GetExistingDataSlots();
   if (slots) {
     slots->Unlink();
@@ -710,21 +708,26 @@ nsGenericDOMDataNode::GetXBLInsertionPar
   }
 
   return nullptr;
 }
 
 void
 nsGenericDOMDataNode::SetXBLInsertionParent(nsIContent* aContent)
 {
-  nsDataSlots *slots = DataSlots();
   if (aContent) {
+    nsDataSlots *slots = DataSlots();
     SetFlags(NODE_MAY_BE_IN_BINDING_MNGR);
+    slots->mXBLInsertionParent = aContent;
+  } else {
+    nsDataSlots *slots = GetExistingDataSlots();
+    if (slots) {
+      slots->mXBLInsertionParent = nullptr;
+    }
   }
-  slots->mXBLInsertionParent = aContent;
 }
 
 CustomElementData *
 nsGenericDOMDataNode::GetCustomElementData() const
 {
   return nullptr;
 }
 
--- a/content/html/content/src/HTMLMediaElement.cpp
+++ b/content/html/content/src/HTMLMediaElement.cpp
@@ -3843,16 +3843,21 @@ void HTMLMediaElement::UpdateAudioChanne
       } else {
         mAudioChannelAgent->InitWithWeakCallback(OwnerDoc()->GetWindow(),
                                                  static_cast<int32_t>(mAudioChannel),
                                                  this);
       }
       mAudioChannelAgent->SetVisibilityState(!OwnerDoc()->Hidden());
     }
 
+    // This is needed to pass nsContentUtils::IsCallerChrome().
+    // AudioChannel API should not called from content but it can happen that
+    // this method has some content JS in its stack.
+    AutoNoJSAPI nojsapi;
+
     if (mPlayingThroughTheAudioChannel) {
       int32_t canPlay;
       mAudioChannelAgent->StartPlaying(&canPlay);
       CanPlayChanged(canPlay);
     } else {
       mAudioChannelAgent->StopPlaying();
       mAudioChannelAgent = nullptr;
     }
--- a/dom/datastore/DataStoreCursorImpl.jsm
+++ b/dom/datastore/DataStoreCursorImpl.jsm
@@ -146,17 +146,17 @@ this.DataStoreCursor.prototype = {
     }
 
     let self = this;
     let request = aRevisionStore.openCursor(null, 'prev');
     request.onsuccess = function(aEvent) {
       self._revision = aEvent.target.result.value;
       self._objectId = 0;
       self._state = STATE_SEND_ALL;
-      aResolve(Cu.cloneInto({ operation: 'clear' }, self._window));
+      aResolve(self.createTask('clear', null, '', null));
     }
   },
 
   stateMachineRevisionInit: function(aStore, aRevisionStore, aResolve, aReject) {
     debug('StateMachineRevisionInit');
 
     let self = this;
     let request = this._dataStore._db.getInternalRevisionId(
@@ -286,32 +286,31 @@ this.DataStoreCursor.prototype = {
     debug('StateMachineSendAll');
 
     let self = this;
     let request = aRevisionStore.openCursor(null, 'prev');
     request.onsuccess = function(aEvent) {
       if (self._revision.revisionId != aEvent.target.result.value.revisionId) {
         self._revision = aEvent.target.result.value;
         self._objectId = 0;
-        aResolve(Cu.cloneInto({ operation: 'clear' }, self._window));
+        aResolve(self.createTask('clear', null, '', null));
         return;
       }
 
       let request = aStore.openCursor(self._window.IDBKeyRange.lowerBound(self._objectId, true));
       request.onsuccess = function(aEvent) {
         let cursor = aEvent.target.result;
         if (!cursor) {
           self._state = STATE_REVISION_CHECK;
           self.stateMachine(aStore, aRevisionStore, aResolve, aReject);
           return;
         }
 
         self._objectId = cursor.key;
-        aResolve(Cu.cloneInto({ operation: 'add', id: self._objectId,
-                                data: cursor.value }, self._window));
+        aResolve(self.createTask('add', self._objectId, '', cursor.value));
       };
     };
   },
 
   stateMachineRevisionSend: function(aStore, aRevisionStore, aResolve, aReject) {
     debug('StateMachineRevisionSend');
 
     if (!this._revisionsList.length) {
@@ -319,31 +318,30 @@ this.DataStoreCursor.prototype = {
       this.stateMachine(aStore, aRevisionStore, aResolve, aReject);
       return;
     }
 
     this._revision = this._revisionsList.shift();
 
     switch (this._revision.operation) {
       case REVISION_REMOVED:
-        aResolve(Cu.cloneInto({ operation: 'remove', id: this._revision.objectId },
-                              this._window));
+        aResolve(this.createTask('remove', this._revision.objectId, '', null));
         break;
 
       case REVISION_ADDED: {
         let request = aStore.get(this._revision.objectId);
         let self = this;
         request.onsuccess = function(aEvent) {
           if (aEvent.target.result == undefined) {
             self.stateMachine(aStore, aRevisionStore, aResolve, aReject);
             return;
           }
 
-          aResolve(Cu.cloneInto({ operation: 'add', id: self._revision.objectId,
-                                  data: aEvent.target.result }, self._window));
+          aResolve(self.createTask('add', self._revision.objectId, '',
+                                   aEvent.target.result));
         }
         break;
       }
 
       case REVISION_UPDATED: {
         let request = aStore.get(this._revision.objectId);
         let self = this;
         request.onsuccess = function(aEvent) {
@@ -352,18 +350,18 @@ this.DataStoreCursor.prototype = {
             return;
           }
 
           if (aEvent.target.result.revisionId >  self._revision.internalRevisionId) {
             self.stateMachine(aStore, aRevisionStore, aResolve, aReject);
             return;
           }
 
-          aResolve(Cu.cloneInto({ operation: 'update', id: self._revision.objectId,
-                                  data: aEvent.target.result }, self._window));
+          aResolve(self.createTask('update', self._revision.objectId, '',
+                                   aEvent.target.result));
         }
         break;
       }
 
       case REVISION_VOID:
         // Internal error!
         dump('Internal error: Revision "' + REVISION_VOID + '" should not be found!!!\n');
         break;
@@ -372,18 +370,17 @@ this.DataStoreCursor.prototype = {
         // This revision contains data that has already been sent by another one.
         this.stateMachine(aStore, aRevisionStore, aResolve, aReject);
         break;
     }
   },
 
   stateMachineDone: function(aStore, aRevisionStore, aResolve, aReject) {
     this.close();
-    aResolve(Cu.cloneInto({ revisionId: this._revision.revisionId,
-                            operation: 'done' }, this._window));
+    aResolve(this.createTask('done', null, this._revision.revisionId, null));
   },
 
   // public interface
 
   get store() {
     return this._dataStore.exposedObject;
   },
 
@@ -400,10 +397,15 @@ this.DataStoreCursor.prototype = {
           aReject(createDOMError(self._window, aEvent));
         }
       );
     });
   },
 
   close: function() {
     this._dataStore.syncTerminated(this);
+  },
+
+  createTask: function(aOperation, aId, aRevisionId, aData) {
+    return Cu.cloneInto({ operation: aOperation, id: aId,
+                          revisionId: aRevisionId, data: aData }, this._window);
   }
 };
--- a/dom/datastore/DataStoreImpl.jsm
+++ b/dom/datastore/DataStoreImpl.jsm
@@ -270,17 +270,17 @@ this.DataStore.prototype = {
     let self = this;
     let request = aStore.clear();
     request.onsuccess = function() {
       debug("ClearInternal success");
       self._db.clearRevisions(aRevisionStore,
         function() {
           debug("Revisions cleared");
 
-          self.addRevision(aRevisionStore, 0, REVISION_VOID,
+          self.addRevision(aRevisionStore, null, REVISION_VOID,
             function() {
               debug("ClearInternal - revisionId increased");
               aResolve();
             }
           );
         }
       );
     };
--- a/dom/datastore/tests/file_changes.html
+++ b/dom/datastore/tests/file_changes.html
@@ -61,21 +61,20 @@
     }, cbError);
   }
 
   function testStoreClear() {
     gStore.clear().catch(cbError);
   }
 
   function eventListener(evt) {
+    ok(evt instanceof DataStoreChangeEvent, "DataStoreChangeEvent has been received");
     ok(evt, "OnChangeListener is called with data");
     is(/[0-9a-zA-Z]{8}-[0-9a-zA-Z]{4}-[0-9a-zA-Z]{4}-[0-9a-zA-Z]{4}-[0-9a-zA-Z]{12}/.test(evt.revisionId), true, "event.revisionId returns something");
-    if (gChangeId) {
-      is(evt.id, gChangeId, "OnChangeListener is called with the right ID: " + evt.id);
-    }
+    is(evt.id, gChangeId, "OnChangeListener is called with the right ID: " + evt.id);
     is(evt.operation, gChangeOperation, "OnChangeListener is called with the right operation:" + evt.operation + " " + gChangeOperation);
     runTest();
   }
 
   var tests = [
     // Test for GetDataStore
     testGetDataStores,
 
@@ -94,17 +93,17 @@
     function() { gChangeId = 1; gChangeOperation = 'updated';
                  testStorePut({ number: 43 }, 1); },
 
     // Remove
     function() { gChangeId = 1; gChangeOperation = 'removed';
                  testStoreRemove(1, true); },
 
     // Clear
-    function() { gChangeId = 0; gChangeOperation = 'cleared';
+    function() { gChangeId = null; gChangeOperation = 'cleared';
                  testStoreClear(); },
 
     // Remove onchange function and replace it with addEventListener
     function() {
       gStore.onchange = null;
       gStore.addEventListener('change', eventListener);
       runTest();
     },
@@ -117,17 +116,17 @@
     function() { gChangeId = 2; gChangeOperation = 'updated';
                  testStorePut({ number: 43 }, 2); },
 
     // Remove
     function() { gChangeId = 2; gChangeOperation = 'removed';
                  testStoreRemove(2, true); },
 
     // Clear
-    function() { gChangeId = 0; gChangeOperation = 'cleared';
+    function() { gChangeId = null; gChangeOperation = 'cleared';
                  testStoreClear(); },
 
     // Remove event listener
     function() {
       gStore.removeEventListener('change', eventListener);
       runTest();
     },
   ];
--- a/dom/datastore/tests/file_sync.html
+++ b/dom/datastore/tests/file_sync.html
@@ -66,19 +66,24 @@
 
     var step = steps.shift();
     cursor.next().then(function(data) {
       ok(!!data, "Cursor.next returns data");
       is(data.operation, step.operation, "Waiting for operation: '" + step.operation + "' received '" + data.operation + "'");
 
 
       switch (data.operation) {
+        case 'clear':
+          is (data.id, null, "'clear' operation wants a null id");
+          break;
+
         case 'done':
           is(/[0-9a-zA-Z]{8}-[0-9a-zA-Z]{4}-[0-9a-zA-Z]{4}-[0-9a-zA-Z]{4}-[0-9a-zA-Z]{12}/.test(data.revisionId), true, "done has a valid revisionId");
           is (data.revisionId, gRevisions[gRevisions.length-1], "Last revision matches");
+          is (data.id, null, "'done' operation wants a null id");
           break;
 
         case 'add':
         case 'update':
           if ('id' in step) {
             is(data.id, step.id, "next() add: id matches: " + data.id + " " + step.id);
           }
 
--- a/dom/ipc/TabChild.cpp
+++ b/dom/ipc/TabChild.cpp
@@ -142,22 +142,16 @@ TabChildBase::InitializeRootMetrics()
   mLastRootMetrics.mCumulativeResolution =
     mLastRootMetrics.GetZoom() / mLastRootMetrics.mDevPixelsPerCSSPixel * ScreenToLayerScale(1);
   // This is the root layer, so the cumulative resolution is the same
   // as the resolution.
   mLastRootMetrics.mResolution = mLastRootMetrics.mCumulativeResolution / LayoutDeviceToParentLayerScale(1);
   mLastRootMetrics.SetScrollOffset(CSSPoint(0, 0));
 }
 
-bool
-TabChildBase::HasValidInnerSize()
-{
-  return (mInnerSize.width != 0) && (mInnerSize.height != 0);
-}
-
 void
 TabChildBase::SetCSSViewport(const CSSSize& aSize)
 {
   mOldViewportWidth = aSize.width;
 
   if (mContentDocumentIsDisplayed) {
     nsCOMPtr<nsIDOMWindowUtils> utils(GetDOMWindowUtils());
     utils->SetCSSViewport(aSize.width, aSize.height);
@@ -691,16 +685,17 @@ TabChild::TabChild(ContentChild* aManage
   , mNotified(false)
   , mTriedBrowserInit(false)
   , mOrientation(eScreenOrientation_PortraitPrimary)
   , mUpdateHitRegion(false)
   , mContextMenuHandled(false)
   , mWaitingTouchListeners(false)
   , mIgnoreKeyPressEvent(false)
   , mActiveElementManager(new ActiveElementManager())
+  , mHasValidInnerSize(false)
 {
   if (!sActiveDurationMsSet) {
     Preferences::AddIntVarCache(&sActiveDurationMs,
                                 "ui.touch_activation.duration_ms",
                                 sActiveDurationMs);
     sActiveDurationMsSet = true;
   }
 }
@@ -1283,16 +1278,22 @@ TabChild::BrowserFrameProvideWindow(nsID
   // pretty bogus; see bug 763602.
   newChild->DoFakeShow();
 
   nsCOMPtr<nsIDOMWindow> win = do_GetInterface(newChild->WebNavigation());
   win.forget(aReturn);
   return NS_OK;
 }
 
+bool
+TabChild::HasValidInnerSize()
+{
+  return mHasValidInnerSize;
+}
+
 #ifdef DEBUG
 PContentPermissionRequestChild*
 TabChild:: SendPContentPermissionRequestConstructor(PContentPermissionRequestChild* aActor,
                                                     const InfallibleTArray<PermissionRequest>& aRequests,
                                                     const IPC::Principal& aPrincipal)
 {
   PCOMContentPermissionRequestChild* child = static_cast<PCOMContentPermissionRequestChild*>(aActor);
   PContentPermissionRequestChild* request = PBrowserChild::SendPContentPermissionRequestConstructor(aActor, aRequests, aPrincipal);
@@ -1609,16 +1610,19 @@ TabChild::RecvUpdateDimensions(const nsR
 
     mOuterRect.x = rect.x;
     mOuterRect.y = rect.y;
     mOuterRect.width = rect.width;
     mOuterRect.height = rect.height;
 
     bool initialSizing = !HasValidInnerSize()
                       && (size.width != 0 && size.height != 0);
+    if (initialSizing) {
+      mHasValidInnerSize = true;
+    }
 
     mOrientation = orientation;
     mInnerSize = ScreenIntSize::FromUnknownSize(
       gfx::IntSize(size.width, size.height));
     mWidget->Resize(0, 0, size.width, size.height,
                     true);
 
     nsCOMPtr<nsIBaseWindow> baseWin = do_QueryInterface(WebNavigation());
--- a/dom/ipc/TabChild.h
+++ b/dom/ipc/TabChild.h
@@ -200,17 +200,16 @@ protected:
     //
     // XXX/bug 780335: Do the work the browser chrome script does in C++ instead
     // so we don't need things like this.
     void DispatchMessageManagerMessage(const nsAString& aMessageName,
                                        const nsAString& aJSONData);
 
     nsEventStatus DispatchWidgetEvent(WidgetGUIEvent& event);
 
-    bool HasValidInnerSize();
     void InitializeRootMetrics();
 
     mozilla::layers::FrameMetrics ProcessUpdateFrame(const mozilla::layers::FrameMetrics& aFrameMetrics);
 
     bool UpdateFrameHandler(const mozilla::layers::FrameMetrics& aFrameMetrics);
 
 protected:
     float mOldViewportWidth;
@@ -517,16 +516,18 @@ private:
     nsresult
     BrowserFrameProvideWindow(nsIDOMWindow* aOpener,
                               nsIURI* aURI,
                               const nsAString& aName,
                               const nsACString& aFeatures,
                               bool* aWindowIsNew,
                               nsIDOMWindow** aReturn);
 
+    bool HasValidInnerSize();
+
     class CachedFileDescriptorInfo;
     class CachedFileDescriptorCallbackRunnable;
 
     TextureFactoryIdentifier mTextureFactoryIdentifier;
     nsCOMPtr<nsIWebNavigation> mWebNav;
     nsCOMPtr<nsIWidget> mWidget;
     nsCOMPtr<nsIURI> mLastURI;
     RenderFrameChild* mRemoteFrame;
@@ -555,16 +556,17 @@ private:
     ScreenOrientation mOrientation;
     bool mUpdateHitRegion;
     bool mContextMenuHandled;
     bool mWaitingTouchListeners;
     void FireSingleTapEvent(LayoutDevicePoint aPoint);
 
     bool mIgnoreKeyPressEvent;
     nsRefPtr<ActiveElementManager> mActiveElementManager;
+    bool mHasValidInnerSize;
 
     DISALLOW_EVIL_CONSTRUCTORS(TabChild);
 };
 
 }
 }
 
 #endif // mozilla_dom_TabChild_h
--- a/dom/webidl/DataStore.webidl
+++ b/dom/webidl/DataStore.webidl
@@ -98,11 +98,13 @@ enum DataStoreOperation {
   "clear",
   "done"
 };
 
 dictionary DataStoreTask {
   DOMString revisionId;
 
   DataStoreOperation operation;
-  DataStoreKey id;
+
+  // When |operation| is "clear" or "done", this must return null.
+  DataStoreKey? id;
   any data;
 };
--- a/dom/webidl/DataStoreChangeEvent.webidl
+++ b/dom/webidl/DataStoreChangeEvent.webidl
@@ -1,21 +1,24 @@
 /* -*- Mode: IDL; 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/.
  */
 
 dictionary DataStoreChangeEventInit : EventInit {
   DOMString revisionId = "";
-  DataStoreKey id = 0;
+
+  // When |operation| is "clear" or "done", this must return null.
+  DataStoreKey? id = null;
+
   DOMString operation = "";
   DOMString owner = "";
 };
 
 [Func="Navigator::HasDataStoreSupport",
  Constructor(DOMString type, optional DataStoreChangeEventInit eventInitDict)]
 interface DataStoreChangeEvent : Event {
   readonly attribute DOMString revisionId;
-  readonly attribute DataStoreKey id;
+  readonly attribute DataStoreKey? id;
   readonly attribute DOMString operation;
   readonly attribute DOMString owner;
 };
--- a/extensions/spellcheck/locales/en-US/hunspell/dictionary-sources/upstream-hunspell.diff
+++ b/extensions/spellcheck/locales/en-US/hunspell/dictionary-sources/upstream-hunspell.diff
@@ -9231,425 +9231,427 @@ 20196,20197c26013,26014
 < dialogue/SM
 ---
 > dialog/SMGD
 > dialogue/SMRGD
 20220a26038
 > diatomaceous
 20481a26300
 > disclose/DSG
-20830c26649
+20633a26453
+> dissentious
+20830c26650
 < dogie/M
 ---
 > dogie/SM
-20895a26715
+20895a26716
 > donator/MS
-21820a27641
+21820a27642
 > elicitor/MS
-22071a27893
+22071a27894
 > encyclopaedia
-22196a28019
+22196a28020
 > enqueue/DSG
-22556a28380
+22556a28381
 > estoppel
-22638c28462
+22638c28463
 < euthanize
 ---
 > euthanize/DSG
-22719a28544
+22719a28545
 > exabyte/MS
-22947a28773
+22947a28774
 > experimentalism
-23207,23208d29032
+23207,23208d29033
 < faecal
 < faeces/M
-23215c29039
+23215c29040
 < faggoting's
 ---
 > faggot/SMG
-23701a29526
+23701a29527
 > filesystem/MS
-24155c29980
+24155c29981
 < fluidized
 ---
 > fluidize/DSG
-24216a30042
+24216a30043
 > foci
-24736d30561
+24736d30562
 < frier/M
-24855,24856c30680,30681
+24855,24856c30681,30682
 < fucker/M!
 < fuckhead/S!
 ---
 > fucker/SM!
 > fuckhead/SM!
-24953d30777
+24953d30778
 < furore/MS
-25125c30949
+25125c30950
 < gaolbird/S
 ---
 > gaolbirds
-25180d31003
+25180d31004
 < gasolene/M
-25190a31014
+25190a31015
 > gastroenterologist/M
-25262c31086
+25262c31087
 < geezer/M
 ---
 > geezer/MS
-25327c31151
+25327c31152
 < genomic
 ---
 > genomic/S
-25462a31287
+25462a31288
 > gigabit/MS
-25464a31290,31292
+25464a31291,31293
 > gigajoule/MS
 > gigapixel/MS
 > gigawatt/MS
-25560d31387
+25560d31388
 < glamourize/DSG
-25674c31501
+25674c31502
 < glycerine's
 ---
 > glycerine/M
-25905c31732
+25905c31733
 < gram/MS
 ---
 > gram/KMS
-25909d31735
+25909d31736
 < gramme/SM
-26063c31889,31890
+26063c31890,31891
 < greybeard
 ---
 > grey/MDRTGSP
 > greybeard/SM
-26066c31893
+26066c31894
 < greyness
 ---
 > greyness/M
-26246,26247d32072
+26246,26247d32073
 < guerilla's
 < guerillas
-26432,26436d32256
+26432,26436d32257
 < haemoglobin's
 < haemophilia/M
 < haemorrhage/DSMG
 < haemorrhoid/S
 < haemorrhoids/M
-27167c32987
+27167c32988
 < hexane
 ---
 > hexane/SM
-27273a33094
+27273a33095
 > hippopotami
-27875d33695
+27875d33696
 < hyaena/SM
-28017c33837
+28017c33838
 < iPod/M
 ---
 > iPod/MS
-28105a33926
+28105a33927
 > idolator/SM
-28513c34334
+28513c34335
 < inbound
 ---
 > inbound/s
-28590,28591c34411
+28590,28591c34412
 < incorrigibility/M
 < incorrigible
 ---
 > incorrigibleness
-28593d34412
+28593d34413
 < incorruptibly
-28650a34470
+28650a34471
 > indices
-28812d34631
+28812d34632
 < inflexion/SM
-29216a35036
+29216a35037
 > intern/GDL
-29266a35087
+29266a35088
 > interruptible/U
-29272a35094,35097
+29272a35095,35098
 > intersex
 > intersexual/MS
 > intersexualism
 > intersexuality
-29724c35549
+29724c35550
 < jewellery's
 ---
 > jewellery/M
-29870a35696
+29870a35697
 > judgement/MS
-30066c35892
+30066c35893
 < kiddie/M
 ---
 > kiddie/SM
-30262,30263c36088
+30262,30263c36089
 < kraut's
 < kraut/S!
 ---
 > kraut/MS!
-30665a36491
+30665a36492
 > lector/MS
-31031c36857
+31031c36858
 < linguini's
 ---
 > linguini/M
-31034c36860
+31034c36861
 < linguistically
 ---
 > linguistical/Y
-31151,31152c36977
+31151,31152c36978
 < liver's
 < liver/S
 ---
 > liver/MS
-32230c38055
+32230c38056
 < meanie/M
 ---
 > meanie/MS
-32317,32318c38142
+32317,32318c38143
 < megadeath/M
 < megadeaths
 ---
 > megadeath/SM
-32320c38144
+32320c38145
 < megajoules
 ---
 > megajoule/SM
-32329c38153
+32329c38154
 < megapixel/S
 ---
 > megapixel/MS
-32708a38533
+32708a38534
 > might've
-32717a38543
+32717a38544
 > migrator/SM
-32760a38587
+32760a38588
 > millennia
-32777d38603
+32777d38604
 < millionnaire/M
-32934a38761
+32934a38762
 > miscommunication/S
-32991a38819
+32991a38820
 > misjudgement/MS
-33784a39613
+33784a39614
 > must've
-33963c39792
+33963c39793
 < native/MS
 ---
 > native/MSY
-34169,34171c39998,39999
+34169,34171c39999,40000
 < neurone/S
 < neurophysiology
 < neuroscience
 ---
 > neurophysiology/M
 > neuroscience/MS
-34275c40103
+34275c40104
 < nightie/M
 ---
 > nightie/SM
-35104a40933
+35104a40934
 > octopi
-35219d41047
+35219d41048
 < oleomargarin/M
-35226a41055
+35226a41056
 > oligo
-35913c41742
+35913c41743
 < oversize/D
 ---
 > oversize
-36056,36059d41884
+36056,36059d41885
 < paederast/S
 < paediatrician's
 < paediatricians
 < paediatrics/M
-36291a42117
+36291a42118
 > paralyses
-36403d42228
+36403d42229
 < parrakeet/MS
-36449d42273
+36449d42274
 < partizan/SM
-37093a42918
+37093a42919
 > petabyte/MS
-37102c42927
+37102c42928
 < petitioner/M
 ---
 > petitioner/MS
-37264a43090
+37264a43091
 > phosphorylate/DSGN
-37316d43141
+37316d43142
 < phrenetic
-37630a43456
+37630a43457
 > plaintext
-37796a43623
+37796a43624
 > plugin/MS
-37987c43814
+37987c43815
 < polypeptide/S
 ---
 > polypeptide/MS
-38291d44117
+38291d44118
 < practise's
-38451a44278
+38451a44279
 > prejudgement/MS
-38805a44633
+38805a44634
 > profiler/SM
-38835a44664
+38835a44665
 > programmatically
-38891a44721,44722
+38891a44722,44723
 > pronate/DSGN
 > pronator/MS
-38951c44782
+38951c44783
 < proprietorship/M
 ---
 > proprietorship/MS
-39039a44871
+39039a44872
 > provender/M
-39095a44928
+39095a44929
 > pseudorandom/Y
-39564a45398
+39564a45399
 > quinoa
-39873a45708,45709
+39873a45709,45710
 > rasterization/M
 > rasterize/SGDR
-40036a45873
+40036a45874
 > recency
-40140a45978
+40140a45979
 > recurse/DGSV
-40141a45980
+40141a45981
 > recuse/DGS
-40208a46048
+40208a46049
 > refactor/SMDG
-40244d46083
+40244d46084
 < reflexion/SM
-40659d46497
+40659d46498
 < resizing
-40829c46667
+40829c46668
 < reverie/M
 ---
 > reverie/MS
-41415a47254
+41415a47255
 > sabre/MS
-41914c47753
+41914c47754
 < schnaps's
 ---
 > schnaps/M
-41949c47788
+41949c47789
 < schrod's
 ---
 > schrod/SM
-41998a47838
+41998a47839
 > scot-free
-42883,42885c48723
+42883,42885c48724
 < shit's
 < shit/S!
 < shite/S!
 ---
 > shit/MS!
-42887,42888c48725,48726
+42887,42888c48726,48727
 < shithead/S!
 < shitload/!
 ---
 > shithead/MS!
 > shitload/MS!
-42891c48729
+42891c48730
 < shitty/RT!
 ---
 > shitty/TR!
-42976a48815
+42976a48816
 > should've
-43008c48847
+43008c48848
 < showtime
 ---
 > showtime/MS
-43328c49167
+43328c49168
 < size/MGBDRS
 ---
 > size/AMGBDRS
-43724,43726c49563
+43724,43726c49564
 < smoulder's
 < smouldered
 < smoulders
 ---
 > smoulder/GSMD
-43766a49604,49605
+43766a49605,49606
 > snarkily
 > snarky/TR
-44062c49901
+44062c49902
 < sonofabitch
 ---
 > sonofabitch/!
-44346a50186
+44346a50187
 > spelled
-44348a50189
+44348a50190
 > spelt
-44371a50213
+44371a50214
 > spick/S!
-44383c50225
+44383c50226
 < spik/S
 ---
 > spik/S!
-46106a51949
+46106a51950
 > syllabi
-46160c52003
+46160c52004
 < synch/GMD
 ---
 > synch/GMDS
-46167d52009
+46167d52010
 < synchs
-46203,46204c52045,52046
+46203,46204c52046,52047
 < sysadmin/S
 < sysop/S
 ---
 > sysadmin/MS
 > sysop/MS
-46752a52595
+46752a52596
 > terabit/MS
-46753a52597,52598
+46753a52598,52599
 > terahertz/M
 > terapixel/MS
-46817a52663
+46817a52664
 > testcase/MS
-46831a52678
+46831a52679
 > testsuite/MS
-46925a52773
+46925a52774
 > theremin/MS
-47455c53303
+47455c53304
 < toolbar
 ---
 > toolbar/MS
-47755a53604
+47755a53605
 > transfect/DSMG
-47774a53624,53625
+47774a53625,53626
 > transgenderism
 > transgene/MS
-47951c53802
+47951c53803
 < triage/M
 ---
 > triage/MG
-48869a54721
+48869a54722
 > unlikeable
-49211c55063
+49211c55064
 < vagina/M
 ---
 > vagina/MS
-49368,49369c55220
+49368,49369c55221
 < velour's
 < velours's
 ---
 > velour/MS
-49478a55330
+49478a55331
 > vertices
-50148a56001
+50148a56002
 > weaponize/DSG
-50260,50261d56112
+50260,50261d56113
 < werwolf/M
 < werwolves
-50728c56579
+50728c56580
 < women
 ---
 > women/M
-50794c56645
+50794c56646
 < wop/S!
 ---
 > wop/MS!
--- a/extensions/spellcheck/locales/en-US/hunspell/en-US.dic
+++ b/extensions/spellcheck/locales/en-US/hunspell/en-US.dic
@@ -1,9 +1,9 @@
-57467
+57468
 0/nm
 0th/pt
 1/n1
 1st/p
 1th/tc
 2/nm
 2nd/p
 2th/tc
@@ -26719,16 +26719,17 @@ dissect/SDG
 dissemblance/M
 dissemble/ZGDRS
 dissembler/M
 disseminate/DSGN
 dissemination/M
 dissension/MS
 dissent/SMDRZG
 dissenter/M
+dissentious
 dissertation/MS
 dissidence/M
 dissident/MS
 dissimilar
 dissimilitude/S
 dissipate/GNVDS
 dissipated/U
 dissipation/M
--- a/gfx/gl/GLBlitTextureImageHelper.cpp
+++ b/gfx/gl/GLBlitTextureImageHelper.cpp
@@ -47,17 +47,17 @@ GLBlitTextureImageHelper::BlitTextureIma
     ScopedGLState scopedScissorTestState(mGL, LOCAL_GL_SCISSOR_TEST, false);
     ScopedGLState scopedBlendState(mGL, LOCAL_GL_BLEND, false);
 
     // 2.0 means scale up by two
     float blitScaleX = float(aDstRect.width) / float(aSrcRect.width);
     float blitScaleY = float(aDstRect.height) / float(aSrcRect.height);
 
     // We start iterating over all destination tiles
-    aDst->BeginTileIteration();
+    aDst->BeginBigImageIteration();
     do {
         // calculate portion of the tile that is going to be painted to
         nsIntRect dstSubRect;
         nsIntRect dstTextureRect = ThebesIntRect(aDst->GetTileRect());
         dstSubRect.IntersectRect(aDstRect, dstTextureRect);
 
         // this tile is not part of the destination rectangle aDstRect
         if (dstSubRect.IsEmpty())
@@ -68,17 +68,17 @@ GLBlitTextureImageHelper::BlitTextureIma
         dstInSrcRect.MoveBy(-aDstRect.TopLeft());
         // ...which might be of different size, hence scale accordingly
         dstInSrcRect.ScaleRoundOut(1.0f / blitScaleX, 1.0f / blitScaleY);
         dstInSrcRect.MoveBy(aSrcRect.TopLeft());
 
         SetBlitFramebufferForDestTexture(aDst->GetTextureID());
         UseBlitProgram();
 
-        aSrc->BeginTileIteration();
+        aSrc->BeginBigImageIteration();
         // now iterate over all tiles in the source Image...
         do {
             // calculate portion of the source tile that is in the source rect
             nsIntRect srcSubRect;
             nsIntRect srcTextureRect = ThebesIntRect(aSrc->GetTileRect());
             srcSubRect.IntersectRect(aSrcRect, srcTextureRect);
 
             // this tile is not part of the source rect
--- a/gfx/gl/GLTextureImage.cpp
+++ b/gfx/gl/GLTextureImage.cpp
@@ -357,17 +357,17 @@ TiledTextureImage::DirectUpdate(gfx::Dat
         nsIntRect bounds = nsIntRect(0, 0, mSize.width, mSize.height);
         region = nsIntRegion(bounds);
     } else {
         region = aRegion;
     }
 
     bool result = true;
     int oldCurrentImage = mCurrentImage;
-    BeginTileIteration();
+    BeginBigImageIteration();
     do {
         nsIntRect tileRect = ThebesIntRect(GetSrcTileRect());
         int xPos = tileRect.x;
         int yPos = tileRect.y;
 
         nsIntRegion tileRegion;
         tileRegion.And(region, tileRect); // intersect with tile
 
@@ -542,17 +542,17 @@ TiledTextureImage::EndUpdate()
     }
 
     mUpdateDrawTarget = nullptr;
     mInUpdate = false;
     mTextureFormat = mImages[0]->GetTextureFormat();
     mTextureState = Valid;
 }
 
-void TiledTextureImage::BeginTileIteration()
+void TiledTextureImage::BeginBigImageIteration()
 {
     mCurrentImage = 0;
 }
 
 bool TiledTextureImage::NextTile()
 {
     bool continueIteration = true;
 
@@ -562,17 +562,17 @@ bool TiledTextureImage::NextTile()
 
     if (mCurrentImage + 1 < mImages.Length()) {
         mCurrentImage++;
         return continueIteration;
     }
     return false;
 }
 
-void TiledTextureImage::SetIterationCallback(TileIterationCallback aCallback,
+void TiledTextureImage::SetIterationCallback(BigImageIterationCallback aCallback,
                                              void* aCallbackData)
 {
     mIterationCallback = aCallback;
     mIterationCallbackData = aCallbackData;
 }
 
 gfx::IntRect TiledTextureImage::GetTileRect()
 {
--- a/gfx/gl/GLTextureImage.h
+++ b/gfx/gl/GLTextureImage.h
@@ -118,32 +118,32 @@ public:
      * EndUpdate().
      */
     virtual void EndUpdate() = 0;
 
     /**
      * The Image may contain several textures for different regions (tiles).
      * These functions iterate over each sub texture image tile.
      */
-    virtual void BeginTileIteration() {
+    virtual void BeginBigImageIteration() {
     }
 
     virtual bool NextTile() {
         return false;
     }
 
     // Function prototype for a tile iteration callback. Returning false will
     // cause iteration to be interrupted (i.e. the corresponding NextTile call
     // will return false).
-    typedef bool (* TileIterationCallback)(TextureImage* aImage,
+    typedef bool (* BigImageIterationCallback)(TextureImage* aImage,
                                            int aTileNumber,
                                            void* aCallbackData);
 
     // Sets a callback to be called every time NextTile is called.
-    virtual void SetIterationCallback(TileIterationCallback aCallback,
+    virtual void SetIterationCallback(BigImageIterationCallback aCallback,
                                       void* aCallbackData) {
     }
 
     virtual gfx::IntRect GetTileRect();
 
     virtual GLuint GetTextureID() = 0;
 
     virtual uint32_t GetTileCount() {
@@ -330,33 +330,33 @@ public:
                       TextureImage::ImageFormat aImageFormat = gfxImageFormat::Unknown);
     ~TiledTextureImage();
     void DumpDiv();
     virtual gfx::DrawTarget* BeginUpdate(nsIntRegion& aRegion);
     virtual void GetUpdateRegion(nsIntRegion& aForRegion);
     virtual void EndUpdate();
     virtual void Resize(const gfx::IntSize& aSize);
     virtual uint32_t GetTileCount();
-    virtual void BeginTileIteration();
+    virtual void BeginBigImageIteration();
     virtual bool NextTile();
-    virtual void SetIterationCallback(TileIterationCallback aCallback,
+    virtual void SetIterationCallback(BigImageIterationCallback aCallback,
                                       void* aCallbackData);
     virtual gfx::IntRect GetTileRect();
     virtual GLuint GetTextureID() {
         return mImages[mCurrentImage]->GetTextureID();
     }
     virtual bool DirectUpdate(gfx::DataSourceSurface* aSurf, const nsIntRegion& aRegion, const gfx::IntPoint& aFrom = gfx::IntPoint(0,0));
     virtual bool InUpdate() const { return mInUpdate; }
     virtual void BindTexture(GLenum);
 
 protected:
     virtual gfx::IntRect GetSrcTileRect();
 
     unsigned int mCurrentImage;
-    TileIterationCallback mIterationCallback;
+    BigImageIterationCallback mIterationCallback;
     void* mIterationCallbackData;
     nsTArray< nsRefPtr<TextureImage> > mImages;
     bool mInUpdate;
     gfx::IntSize mSize;
     unsigned int mTileSize;
     unsigned int mRows, mColumns;
     GLContext* mGL;
     // A temporary draw target to faciliate cross-tile updates.
--- a/gfx/gl/SharedSurfaceGralloc.cpp
+++ b/gfx/gl/SharedSurfaceGralloc.cpp
@@ -70,17 +70,17 @@ SharedSurface_Gralloc::Create(GLContext*
     gfxImageFormat format
       = gfxPlatform::GetPlatform()->OptimalFormatForContent(type);
 
     RefPtr<GrallocTextureClientOGL> grallocTC =
       new GrallocTextureClientOGL(
           allocator,
           gfx::ImageFormatToSurfaceFormat(format),
           gfx::BackendType::NONE, // we don't need to use it with a DrawTarget
-          TEXTURE_FLAGS_DEFAULT);
+          layers::TextureFlags::DEFAULT);
 
     if (!grallocTC->AllocateForGLRendering(size)) {
       return nullptr;
     }
 
     sp<GraphicBuffer> buffer = grallocTC->GetGraphicBuffer();
 
     EGLDisplay display = egl->Display();
--- a/gfx/ipc/GfxMessageUtils.h
+++ b/gfx/ipc/GfxMessageUtils.h
@@ -318,16 +318,45 @@ struct ParamTraits<mozilla::gfx::Primiti
 template <>
 struct ParamTraits<mozilla::gfx::ColorSpace>
   : public ContiguousTypedEnumSerializer<
              mozilla::gfx::ColorSpace,
              mozilla::gfx::ColorSpace::SRGB,
              mozilla::gfx::ColorSpace::Max>
 {};
 
+template <>
+struct ParamTraits<mozilla::layers::TextureFlags>
+  : public BitFlagsTypedEnumSerializer<
+            mozilla::layers::TextureFlags,
+            mozilla::layers::TextureFlags::ALL_BITS>
+{};
+
+template <>
+struct ParamTraits<mozilla::layers::TextureIdentifier>
+  : public ContiguousTypedEnumSerializer<
+             mozilla::layers::TextureIdentifier,
+             mozilla::layers::TextureIdentifier::Front,
+             mozilla::layers::TextureIdentifier::HighBound>
+{};
+
+template <>
+struct ParamTraits<mozilla::layers::DeprecatedTextureHostFlags>
+  : public BitFlagsTypedEnumSerializer<
+             mozilla::layers::DeprecatedTextureHostFlags,
+             mozilla::layers::DeprecatedTextureHostFlags::ALL_BITS>
+{};
+
+template <>
+struct ParamTraits<mozilla::layers::DiagnosticTypes>
+  : public BitFlagsTypedEnumSerializer<
+             mozilla::layers::DiagnosticTypes,
+             mozilla::layers::DiagnosticTypes::ALL_BITS>
+{};
+
 /*
 template <>
 struct ParamTraits<mozilla::PixelFormat>
   : public EnumSerializer<mozilla::PixelFormat,
                           gfxImageFormat::ARGB32,
                           gfxImageFormat::Unknown>
 {};
 */
@@ -804,20 +833,20 @@ struct ParamTraits<mozilla::layers::Text
     return ReadParam(aMsg, aIter, &aResult->mCompositableType) &&
            ReadParam(aMsg, aIter, &aResult->mDeprecatedTextureHostFlags) &&
            ReadParam(aMsg, aIter, &aResult->mTextureFlags);
   }
 };
 
 template <>
 struct ParamTraits<mozilla::layers::CompositableType>
-  : public ContiguousEnumSerializer<
+  : public ContiguousTypedEnumSerializer<
              mozilla::layers::CompositableType,
-             mozilla::layers::BUFFER_UNKNOWN,
-             mozilla::layers::BUFFER_COUNT>
+             mozilla::layers::CompositableType::BUFFER_UNKNOWN,
+             mozilla::layers::CompositableType::BUFFER_COUNT>
 {};
 
 template <>
 struct ParamTraits<mozilla::gfx::SurfaceFormat>
   : public ContiguousTypedEnumSerializer<
              mozilla::gfx::SurfaceFormat,
              mozilla::gfx::SurfaceFormat::B8G8R8A8,
              mozilla::gfx::SurfaceFormat::UNKNOWN>
--- a/gfx/layers/Compositor.cpp
+++ b/gfx/layers/Compositor.cpp
@@ -46,24 +46,24 @@ Compositor::AssertOnCompositorThread()
   MOZ_ASSERT(CompositorParent::CompositorLoop() ==
              MessageLoop::current(),
              "Can only call this from the compositor thread!");
 }
 
 bool
 Compositor::ShouldDrawDiagnostics(DiagnosticFlags aFlags)
 {
-  if ((aFlags & DIAGNOSTIC_TILE) && !(mDiagnosticTypes & DIAGNOSTIC_TILE_BORDERS)) {
+  if ((aFlags & DiagnosticFlags::TILE) && !(mDiagnosticTypes & DiagnosticTypes::TILE_BORDERS)) {
     return false;
   }
-  if ((aFlags & DIAGNOSTIC_BIGIMAGE) &&
-      !(mDiagnosticTypes & DIAGNOSTIC_BIGIMAGE_BORDERS)) {
+  if ((aFlags & DiagnosticFlags::BIGIMAGE) &&
+      !(mDiagnosticTypes & DiagnosticTypes::BIGIMAGE_BORDERS)) {
     return false;
   }
-  if (!mDiagnosticTypes) {
+  if (mDiagnosticTypes == DiagnosticTypes::NO_DIAGNOSTIC) {
     return false;
   }
   return true;
 }
 
 void
 Compositor::DrawDiagnostics(DiagnosticFlags aFlags,
                             const nsIntRegion& aVisibleRegion,
@@ -75,17 +75,17 @@ Compositor::DrawDiagnostics(DiagnosticFl
     return;
   }
 
   if (aVisibleRegion.GetNumRects() > 1) {
     nsIntRegionRectIterator screenIter(aVisibleRegion);
 
     while (const nsIntRect* rect = screenIter.Next())
     {
-      DrawDiagnostics(aFlags | DIAGNOSTIC_REGION_RECT,
+      DrawDiagnostics(aFlags | DiagnosticFlags::REGION_RECT,
                       ToRect(*rect), aClipRect, aTransform, aFlashCounter);
     }
   }
 
   DrawDiagnostics(aFlags, ToRect(aVisibleRegion.GetBounds()),
                   aClipRect, aTransform, aFlashCounter);
 }
 
@@ -148,41 +148,41 @@ Compositor::DrawDiagnosticsInternal(Diag
 #elif defined(ANDROID)
   int lWidth = 10;
 #else
   int lWidth = 2;
 #endif
   float opacity = 0.7f;
 
   gfx::Color color;
-  if (aFlags & DIAGNOSTIC_CONTENT) {
+  if (aFlags & DiagnosticFlags::CONTENT) {
     color = gfx::Color(0.0f, 1.0f, 0.0f, 1.0f); // green
-    if (aFlags & DIAGNOSTIC_COMPONENT_ALPHA) {
+    if (aFlags & DiagnosticFlags::COMPONENT_ALPHA) {
       color = gfx::Color(0.0f, 1.0f, 1.0f, 1.0f); // greenish blue
     }
-  } else if (aFlags & DIAGNOSTIC_IMAGE) {
+  } else if (aFlags & DiagnosticFlags::IMAGE) {
     color = gfx::Color(1.0f, 0.0f, 0.0f, 1.0f); // red
-  } else if (aFlags & DIAGNOSTIC_COLOR) {
+  } else if (aFlags & DiagnosticFlags::COLOR) {
     color = gfx::Color(0.0f, 0.0f, 1.0f, 1.0f); // blue
-  } else if (aFlags & DIAGNOSTIC_CONTAINER) {
+  } else if (aFlags & DiagnosticFlags::CONTAINER) {
     color = gfx::Color(0.8f, 0.0f, 0.8f, 1.0f); // purple
   }
 
   // make tile borders a bit more transparent to keep layer borders readable.
-  if (aFlags & DIAGNOSTIC_TILE ||
-      aFlags & DIAGNOSTIC_BIGIMAGE ||
-      aFlags & DIAGNOSTIC_REGION_RECT) {
+  if (aFlags & DiagnosticFlags::TILE ||
+      aFlags & DiagnosticFlags::BIGIMAGE ||
+      aFlags & DiagnosticFlags::REGION_RECT) {
     lWidth = 1;
     opacity = 0.5f;
     color.r *= 0.7f;
     color.g *= 0.7f;
     color.b *= 0.7f;
   }
 
-  if (mDiagnosticTypes & DIAGNOSTIC_FLASH_BORDERS) {
+  if (mDiagnosticTypes & DiagnosticTypes::FLASH_BORDERS) {
     float flash = (float)aFlashCounter / (float)DIAGNOSTIC_FLASH_COUNTER_MAX;
     color.r *= flash;
     color.g *= flash;
     color.b *= flash;
   }
 
   EffectChain effects;
 
--- a/gfx/layers/Compositor.h
+++ b/gfx/layers/Compositor.h
@@ -194,23 +194,23 @@ class Compositor
 protected:
   virtual ~Compositor() {}
 
 public:
   NS_INLINE_DECL_REFCOUNTING(Compositor)
 
   Compositor(PCompositorParent* aParent = nullptr)
     : mCompositorID(0)
-    , mDiagnosticTypes(DIAGNOSTIC_NONE)
+    , mDiagnosticTypes(DiagnosticTypes::NO_DIAGNOSTIC)
     , mParent(aParent)
     , mScreenRotation(ROTATION_0)
   {
   }
 
-  virtual TemporaryRef<DataTextureSource> CreateDataTextureSource(TextureFlags aFlags = 0) = 0;
+  virtual TemporaryRef<DataTextureSource> CreateDataTextureSource(TextureFlags aFlags = TextureFlags::NO_FLAGS) = 0;
   virtual bool Initialize() = 0;
   virtual void Destroy() = 0;
 
   /**
    * Return true if the effect type is supported.
    *
    * By default Compositor implementations should support all effects but in
    * some rare cases it is not possible to support an effect efficiently.
--- a/gfx/layers/CompositorTypes.h
+++ b/gfx/layers/CompositorTypes.h
@@ -6,175 +6,186 @@
 #ifndef MOZILLA_LAYERS_COMPOSITORTYPES_H
 #define MOZILLA_LAYERS_COMPOSITORTYPES_H
 
 #include <stdint.h>                     // for uint32_t
 #include <sys/types.h>                  // for int32_t
 #include "LayersTypes.h"                // for LayersBackend, etc
 #include "nsXULAppAPI.h"                // for GeckoProcessType, etc
 
+#include "mozilla/TypedEnum.h"
+#include "mozilla/TypedEnumBits.h"
+
 namespace mozilla {
 namespace layers {
 
 typedef int32_t SurfaceDescriptorType;
 const SurfaceDescriptorType SURFACEDESCRIPTOR_UNKNOWN = 0;
 
 /**
  * Flags used by texture clients and texture hosts. These are passed from client
  * side to host side when textures and compositables are created. Usually set
  * by the compositableCient, they may be modified by either the compositable or
  * texture clients.
  *
  * XXX - switch to all caps constant names which seems to be the standard in gecko
  */
-typedef uint32_t TextureFlags;
-// Use nearest-neighbour texture filtering (as opposed to linear filtering).
-const TextureFlags TEXTURE_USE_NEAREST_FILTER = 1 << 0;
-// The texture should be flipped around the y-axis when composited.
-const TextureFlags TEXTURE_NEEDS_Y_FLIP       = 1 << 1;
-// Force the texture to be represented using a single tile (note that this means
-// tiled textures, not tiled layers).
-const TextureFlags TEXTURE_DISALLOW_BIGIMAGE  = 1 << 2;
-// Allow using 'repeat' mode for wrapping.
-const TextureFlags TEXTURE_ALLOW_REPEAT       = 1 << 3;
-// The texture represents a tile which is newly created.
-const TextureFlags TEXTURE_NEW_TILE           = 1 << 4;
-// The texture is part of a component-alpha pair
-const TextureFlags TEXTURE_COMPONENT_ALPHA    = 1 << 5;
-// The buffer will be treated as if the RB bytes are swapped.
-// This is useful for rendering using Cairo/Thebes, because there is no
-// BGRX Android pixel format, and so we have to do byte swapping.
-//
-// For example, if the GraphicBuffer has an Android pixel format of
-// PIXEL_FORMAT_RGBA_8888 and isRBSwapped is true, when it is sampled
-// (for example, with GL), a BGRA shader should be used.
-const TextureFlags TEXTURE_RB_SWAPPED         = 1 << 6;
+MOZ_BEGIN_ENUM_CLASS(TextureFlags, uint32_t)
+  NO_FLAGS           = 0,
+  // Use nearest-neighbour texture filtering (as opposed to linear filtering).
+  USE_NEAREST_FILTER = 1 << 0,
+  // The texture should be flipped around the y-axis when composited.
+  NEEDS_Y_FLIP       = 1 << 1,
+  // Force the texture to be represented using a single tile (note that this means
+  // tiled textures, not tiled layers).
+  DISALLOW_BIGIMAGE  = 1 << 2,
+  // Allow using 'repeat' mode for wrapping.
+  ALLOW_REPEAT       = 1 << 3,
+  // The texture represents a tile which is newly created.
+  NEW_TILE           = 1 << 4,
+  // The texture is part of a component-alpha pair
+  COMPONENT_ALPHA    = 1 << 5,
+  // The buffer will be treated as if the RB bytes are swapped.
+  // This is useful for rendering using Cairo/Thebes, because there is no
+  // BGRX Android pixel format, and so we have to do byte swapping.
+  //
+  // For example, if the GraphicBuffer has an Android pixel format of
+  // PIXEL_FORMAT_RGBA_8888 and isRBSwapped is true, when it is sampled
+  // (for example, with GL), a BGRA shader should be used.
+  RB_SWAPPED         = 1 << 6,
 
-const TextureFlags TEXTURE_FRONT              = 1 << 12;
-// A texture host on white for component alpha
-const TextureFlags TEXTURE_ON_WHITE           = 1 << 13;
- // A texture host on black for component alpha
-const TextureFlags TEXTURE_ON_BLACK           = 1 << 14;
-// A texture host that supports tiling
-const TextureFlags TEXTURE_TILE               = 1 << 15;
-// A texture should be recycled when no longer in used
-const TextureFlags TEXTURE_RECYCLE            = 1 << 16;
-// Texture contents should be initialized
-// from the previous texture.
-const TextureFlags TEXTURE_COPY_PREVIOUS      = 1 << 24;
-// Who is responsible for deallocating the shared data.
-// if TEXTURE_DEALLOCATE_CLIENT is set, the shared data is deallocated on the
-// client side and requires some extra synchronizaion to ensure race-free
-// deallocation.
-// The default behaviour is to deallocate on the host side.
-const TextureFlags TEXTURE_DEALLOCATE_CLIENT  = 1 << 25;
-// After being shared ith the compositor side, an immutable texture is never
-// modified, it can only be read. It is safe to not Lock/Unlock immutable
-// textures.
-const TextureFlags TEXTURE_IMMUTABLE          = 1 << 27;
-// The contents of the texture must be uploaded or copied immediately
-// during the transaction, because the producer may want to write
-// to it again.
-const TextureFlags TEXTURE_IMMEDIATE_UPLOAD   = 1 << 28;
-// The texture is going to be used as part of a double
-// buffered pair, and so we can guarantee that the producer/consumer
-// won't be racing to access its contents.
-const TextureFlags TEXTURE_DOUBLE_BUFFERED    = 1 << 29;
-// We've previously tried a texture and it didn't work for some reason. If there
-// is a fallback available, try that.
-const TextureFlags TEXTURE_ALLOC_FALLBACK     = 1 << 31;
-
-// the default flags
-const TextureFlags TEXTURE_FLAGS_DEFAULT = TEXTURE_FRONT;
+  FRONT              = 1 << 7,
+  // A texture host on white for component alpha
+  ON_WHITE           = 1 << 8,
+  // A texture host on black for component alpha
+  ON_BLACK           = 1 << 9,
+  // A texture host that supports tiling
+  TILE               = 1 << 10,
+  // A texture should be recycled when no longer in used
+  RECYCLE            = 1 << 11,
+  // Texture contents should be initialized
+  // from the previous texture.
+  COPY_PREVIOUS      = 1 << 12,
+  // Who is responsible for deallocating the shared data.
+  // if DEALLOCATE_CLIENT is set, the shared data is deallocated on the
+  // client side and requires some extra synchronizaion to ensure race-free
+  // deallocation.
+  // The default behaviour is to deallocate on the host side.
+  DEALLOCATE_CLIENT  = 1 << 13,
+  // After being shared ith the compositor side, an immutable texture is never
+  // modified, it can only be read. It is safe to not Lock/Unlock immutable
+  // textures.
+  IMMUTABLE          = 1 << 14,
+  // The contents of the texture must be uploaded or copied immediately
+  // during the transaction, because the producer may want to write
+  // to it again.
+  IMMEDIATE_UPLOAD   = 1 << 15,
+  // The texture is going to be used as part of a double
+  // buffered pair, and so we can guarantee that the producer/consumer
+  // won't be racing to access its contents.
+  DOUBLE_BUFFERED    = 1 << 16,
+  // We've previously tried a texture and it didn't work for some reason. If there
+  // is a fallback available, try that.
+  ALLOC_FALLBACK     = 1 << 17,
+  // OR union of all valid bits
+  ALL_BITS           = (1 << 18) - 1,
+  // the default flags
+  DEFAULT = FRONT
+MOZ_END_ENUM_CLASS(TextureFlags)
+MOZ_MAKE_ENUM_CLASS_BITWISE_OPERATORS(TextureFlags)
 
 static inline bool
 TextureRequiresLocking(TextureFlags aFlags)
 {
   // If we're not double buffered, or uploading
   // within a transaction, then we need to support
   // locking correctly.
-  return !(aFlags & (TEXTURE_IMMEDIATE_UPLOAD |
-                     TEXTURE_DOUBLE_BUFFERED |
-                     TEXTURE_IMMUTABLE));
+  return !(aFlags & (TextureFlags::IMMEDIATE_UPLOAD |
+                     TextureFlags::DOUBLE_BUFFERED |
+                     TextureFlags::IMMUTABLE));
 }
 
 /**
  * The type of debug diagnostic to enable.
  */
-typedef uint32_t DiagnosticTypes;
-const DiagnosticTypes DIAGNOSTIC_NONE             = 0;
-const DiagnosticTypes DIAGNOSTIC_TILE_BORDERS     = 1 << 0;
-const DiagnosticTypes DIAGNOSTIC_LAYER_BORDERS    = 1 << 1;
-const DiagnosticTypes DIAGNOSTIC_BIGIMAGE_BORDERS = 1 << 2;
-const DiagnosticTypes DIAGNOSTIC_FLASH_BORDERS    = 1 << 3;
+MOZ_BEGIN_ENUM_CLASS(DiagnosticTypes, uint8_t)
+  NO_DIAGNOSTIC    = 0,
+  TILE_BORDERS     = 1 << 0,
+  LAYER_BORDERS    = 1 << 1,
+  BIGIMAGE_BORDERS = 1 << 2,
+  FLASH_BORDERS    = 1 << 3,
+  ALL_BITS         = (1 << 4) - 1
+MOZ_END_ENUM_CLASS(DiagnosticTypes)
+MOZ_MAKE_ENUM_CLASS_BITWISE_OPERATORS(DiagnosticTypes)
 
 #define DIAGNOSTIC_FLASH_COUNTER_MAX 100
 
 /**
  * Information about the object that is being diagnosed.
  */
-typedef uint32_t DiagnosticFlags;
-const DiagnosticFlags DIAGNOSTIC_IMAGE      = 1 << 0;
-const DiagnosticFlags DIAGNOSTIC_CONTENT    = 1 << 1;
-const DiagnosticFlags DIAGNOSTIC_CANVAS     = 1 << 2;
-const DiagnosticFlags DIAGNOSTIC_COLOR      = 1 << 3;
-const DiagnosticFlags DIAGNOSTIC_CONTAINER  = 1 << 4;
-const DiagnosticFlags DIAGNOSTIC_TILE       = 1 << 5;
-const DiagnosticFlags DIAGNOSTIC_BIGIMAGE   = 1 << 6;
-const DiagnosticFlags DIAGNOSTIC_COMPONENT_ALPHA = 1 << 7;
-const DiagnosticFlags DIAGNOSTIC_REGION_RECT = 1 << 8;
+MOZ_BEGIN_ENUM_CLASS(DiagnosticFlags, uint16_t)
+  NO_DIAGNOSTIC   = 0,
+  IMAGE           = 1 << 0,
+  CONTENT         = 1 << 1,
+  CANVAS          = 1 << 2,
+  COLOR           = 1 << 3,
+  CONTAINER       = 1 << 4,
+  TILE            = 1 << 5,
+  BIGIMAGE        = 1 << 6,
+  COMPONENT_ALPHA = 1 << 7,
+  REGION_RECT     = 1 << 8
+MOZ_END_ENUM_CLASS(DiagnosticFlags)
+MOZ_MAKE_ENUM_CLASS_BITWISE_OPERATORS(DiagnosticFlags)
 
 /**
  * See gfx/layers/Effects.h
  */
-enum EffectTypes
-{
-  EFFECT_MASK,
-  EFFECT_MAX_SECONDARY, // sentinel for the count of secondary effect types
-  EFFECT_RGB,
-  EFFECT_YCBCR,
-  EFFECT_COMPONENT_ALPHA,
-  EFFECT_SOLID_COLOR,
-  EFFECT_RENDER_TARGET,
-  EFFECT_MAX  //sentinel for the count of all effect types
-};
+MOZ_BEGIN_ENUM_CLASS(EffectTypes, uint8_t)
+  MASK,
+  MAX_SECONDARY, // sentinel for the count of secondary effect types
+  RGB,
+  YCBCR,
+  COMPONENT_ALPHA,
+  SOLID_COLOR,
+  RENDER_TARGET,
+  MAX  //sentinel for the count of all effect types
+MOZ_END_ENUM_CLASS(EffectTypes)
 
 /**
  * How the Compositable should manage textures.
  */
-enum CompositableType
-{
+MOZ_BEGIN_ENUM_CLASS(CompositableType, uint8_t)
   BUFFER_UNKNOWN,
   // the deprecated compositable types
   BUFFER_IMAGE_SINGLE,    // image/canvas with a single texture, single buffered
   BUFFER_IMAGE_BUFFERED,  // canvas, double buffered
   BUFFER_BRIDGE,          // image bridge protocol
   BUFFER_CONTENT_INC,     // thebes layer interface, only sends incremental
                           // updates to a texture on the compositor side.
   // somewhere in the middle
   BUFFER_TILED,           // tiled thebes layer
   BUFFER_SIMPLE_TILED,
   // the new compositable types
-  COMPOSITABLE_IMAGE,     // image with single buffering
-  COMPOSITABLE_CONTENT_SINGLE,  // thebes layer interface, single buffering
-  COMPOSITABLE_CONTENT_DOUBLE,  // thebes layer interface, double buffering
+  IMAGE,     // image with single buffering
+  CONTENT_SINGLE,  // thebes layer interface, single buffering
+  CONTENT_DOUBLE,  // thebes layer interface, double buffering
   BUFFER_COUNT
-};
+MOZ_END_ENUM_CLASS(CompositableType)
 
 /**
  * How the texture host is used for composition,
  */
-enum DeprecatedTextureHostFlags
-{
-  TEXTURE_HOST_DEFAULT = 0,       // The default texture host for the given
-                                  // SurfaceDescriptor
-  TEXTURE_HOST_TILED = 1 << 0,    // A texture host that supports tiling
-  TEXTURE_HOST_COPY_PREVIOUS = 1 << 1 // Texture contents should be initialized
+MOZ_BEGIN_ENUM_CLASS(DeprecatedTextureHostFlags, uint8_t)
+  DEFAULT = 0,       // The default texture host for the given SurfaceDescriptor
+  TILED = 1 << 0,    // A texture host that supports tiling
+  COPY_PREVIOUS = 1 << 1, // Texture contents should be initialized
                                       // from the previous texture.
-};
+  ALL_BITS = (1 << 2) - 1
+MOZ_END_ENUM_CLASS(DeprecatedTextureHostFlags)
+MOZ_MAKE_ENUM_CLASS_BITWISE_OPERATORS(DeprecatedTextureHostFlags)
 
 /**
  * Sent from the compositor to the content-side LayerManager, includes properties
  * of the compositor and should (in the future) include information about what
  * kinds of buffer and texture clients to create.
  */
 struct TextureFactoryIdentifier
 {
@@ -198,72 +209,77 @@ struct TextureFactoryIdentifier
 };
 
 /**
  * Identify a texture to a compositable. Many textures can have the same id, but
  * the id is unique for any texture owned by a particular compositable.
  * XXX - This is now redundant with TextureFlags. it ill be removed along with
  * deprecated texture classes.
  */
-typedef uint32_t TextureIdentifier;
-const TextureIdentifier TextureFront = 1;
-const TextureIdentifier TextureBack = 2;
-const TextureIdentifier TextureOnWhiteFront = 3;
-const TextureIdentifier TextureOnWhiteBack = 4;
+MOZ_BEGIN_ENUM_CLASS(TextureIdentifier, uint8_t)
+  Front = 1,
+  Back = 2,
+  OnWhiteFront = 3,
+  OnWhiteBack = 4,
+  HighBound
+MOZ_END_ENUM_CLASS(TextureIdentifier)
 
 /**
  * Information required by the compositor from the content-side for creating or
  * using compositables and textures.
  * XXX - TextureInfo is a bad name: this information is useful for the compositable,
  * not the Texture. And ith new Textures, only the compositable type is really
  * useful. This may (should) be removed in the near future.
  */
 struct TextureInfo
 {
   CompositableType mCompositableType;
-  uint32_t mDeprecatedTextureHostFlags;
-  uint32_t mTextureFlags;
+  DeprecatedTextureHostFlags mDeprecatedTextureHostFlags;
+  TextureFlags mTextureFlags;
 
   TextureInfo()
-    : mCompositableType(BUFFER_UNKNOWN)
-    , mDeprecatedTextureHostFlags(0)
-    , mTextureFlags(0)
+    : mCompositableType(CompositableType::BUFFER_UNKNOWN)
+    , mDeprecatedTextureHostFlags(DeprecatedTextureHostFlags::DEFAULT)
+    , mTextureFlags(TextureFlags::NO_FLAGS)
   {}
 
   TextureInfo(CompositableType aType)
     : mCompositableType(aType)
-    , mDeprecatedTextureHostFlags(0)
-    , mTextureFlags(0)
+    , mDeprecatedTextureHostFlags(DeprecatedTextureHostFlags::DEFAULT)
+    , mTextureFlags(TextureFlags::NO_FLAGS)
   {}
 
   bool operator==(const TextureInfo& aOther) const
   {
     return mCompositableType == aOther.mCompositableType &&
            mDeprecatedTextureHostFlags == aOther.mDeprecatedTextureHostFlags &&
            mTextureFlags == aOther.mTextureFlags;
   }
 };
 
 /**
  * How a SurfaceDescriptor will be opened.
  *
  * See ShadowLayerForwarder::OpenDescriptor for example.
  */
-typedef uint32_t OpenMode;
-const OpenMode OPEN_READ        = 0x1;
-const OpenMode OPEN_WRITE       = 0x2;
-const OpenMode OPEN_READ_WRITE  = OPEN_READ|OPEN_WRITE;
-const OpenMode OPEN_READ_ONLY   = OPEN_READ;
-const OpenMode OPEN_WRITE_ONLY  = OPEN_WRITE;
+MOZ_BEGIN_ENUM_CLASS(OpenMode, uint8_t)
+  OPEN_NONE        = 0,
+  OPEN_READ        = 0x1,
+  OPEN_WRITE       = 0x2,
+  OPEN_READ_WRITE  = OPEN_READ|OPEN_WRITE,
+  OPEN_READ_ONLY   = OPEN_READ,
+  OPEN_WRITE_ONLY  = OPEN_WRITE
+MOZ_END_ENUM_CLASS(OpenMode)
+MOZ_MAKE_ENUM_CLASS_BITWISE_OPERATORS(OpenMode)
 
 // The kinds of mask texture a shader can support
 // We rely on the items in this enum being sequential
-enum MaskType {
+MOZ_BEGIN_ENUM_CLASS(MaskType, uint8_t)
   MaskNone = 0,   // no mask layer
   Mask2d,         // mask layer for layers with 2D transforms
   Mask3d,         // mask layer for layers with 3D transforms
   NumMaskTypes
-};
+MOZ_END_ENUM_CLASS(MaskType)
 
 } // namespace layers
 } // namespace mozilla
 
 #endif
--- a/gfx/layers/D3D9SurfaceImage.cpp
+++ b/gfx/layers/D3D9SurfaceImage.cpp
@@ -126,17 +126,17 @@ D3D9SurfaceImage::GetSize()
 }
 
 TextureClient*
 D3D9SurfaceImage::GetTextureClient(CompositableClient* aClient)
 {
   EnsureSynchronized();
   if (!mTextureClient) {
     RefPtr<SharedTextureClientD3D9> textureClient =
-      new SharedTextureClientD3D9(gfx::SurfaceFormat::B8G8R8X8, TEXTURE_FLAGS_DEFAULT);
+      new SharedTextureClientD3D9(gfx::SurfaceFormat::B8G8R8X8, TextureFlags::DEFAULT);
     textureClient->InitWith(mTexture, mShareHandle, mDesc);
     mTextureClient = textureClient;
   }
   return mTextureClient;
 }
 
 TemporaryRef<gfx::SourceSurface>
 D3D9SurfaceImage::GetAsSourceSurface()
--- a/gfx/layers/Effects.h
+++ b/gfx/layers/Effects.h
@@ -12,16 +12,17 @@
 #include "mozilla/gfx/Point.h"          // for IntSize
 #include "mozilla/gfx/Rect.h"           // for Rect
 #include "mozilla/gfx/Types.h"          // for Filter, etc
 #include "mozilla/layers/CompositorTypes.h"  // for EffectTypes, etc
 #include "mozilla/layers/LayersTypes.h"
 #include "mozilla/layers/TextureHost.h"  // for CompositingRenderTarget, etc
 #include "mozilla/mozalloc.h"           // for operator delete, etc
 #include "nscore.h"                     // for nsACString
+#include "mozilla/EnumeratedArray.h"
 
 namespace mozilla {
 namespace layers {
 
 /**
  * Effects and effect chains are used by the compositor API (see Compositor.h).
  * An effect chain represents a rendering method, for example some shader and
  * the data required for that shader to run. An effect is some component of the
@@ -75,17 +76,17 @@ struct TexturedEffect : public Effect
 };
 
 // Support an alpha mask.
 struct EffectMask : public Effect
 {
   EffectMask(TextureSource *aMaskTexture,
              gfx::IntSize aSize,
              const gfx::Matrix4x4 &aMaskTransform)
-    : Effect(EFFECT_MASK)
+    : Effect(EffectTypes::MASK)
     , mMaskTexture(aMaskTexture)
     , mIs3D(false)
     , mSize(aSize)
     , mMaskTransform(aMaskTransform)
   {}
 
   virtual void PrintInfo(nsACString& aTo, const char* aPrefix);
 
@@ -94,82 +95,83 @@ struct EffectMask : public Effect
   gfx::IntSize mSize;
   gfx::Matrix4x4 mMaskTransform;
 };
 
 // Render to a render target rather than the screen.
 struct EffectRenderTarget : public TexturedEffect
 {
   EffectRenderTarget(CompositingRenderTarget *aRenderTarget)
-    : TexturedEffect(EFFECT_RENDER_TARGET, aRenderTarget, true, gfx::Filter::LINEAR)
+    : TexturedEffect(EffectTypes::RENDER_TARGET, aRenderTarget, true, gfx::Filter::LINEAR)
     , mRenderTarget(aRenderTarget)
   {}
 
   virtual const char* Name() { return "EffectRenderTarget"; }
   virtual void PrintInfo(nsACString& aTo, const char* aPrefix);
 
   RefPtr<CompositingRenderTarget> mRenderTarget;
 };
 
 struct EffectRGB : public TexturedEffect
 {
   EffectRGB(TextureSource *aTexture,
             bool aPremultiplied,
             gfx::Filter aFilter,
             bool aFlipped = false)
-    : TexturedEffect(EFFECT_RGB, aTexture, aPremultiplied, aFilter)
+    : TexturedEffect(EffectTypes::RGB, aTexture, aPremultiplied, aFilter)
   {}
 
   virtual const char* Name() { return "EffectRGB"; }
 };
 
 struct EffectYCbCr : public TexturedEffect
 {
   EffectYCbCr(TextureSource *aSource, gfx::Filter aFilter)
-    : TexturedEffect(EFFECT_YCBCR, aSource, false, aFilter)
+    : TexturedEffect(EffectTypes::YCBCR, aSource, false, aFilter)
   {}
 
   virtual const char* Name() { return "EffectYCbCr"; }
 };
 
 struct EffectComponentAlpha : public TexturedEffect
 {
   EffectComponentAlpha(TextureSource *aOnBlack,
                        TextureSource *aOnWhite,
                        gfx::Filter aFilter)
-    : TexturedEffect(EFFECT_COMPONENT_ALPHA, nullptr, false, aFilter)
+    : TexturedEffect(EffectTypes::COMPONENT_ALPHA, nullptr, false, aFilter)
     , mOnBlack(aOnBlack)
     , mOnWhite(aOnWhite)
   {}
 
   virtual const char* Name() { return "EffectComponentAlpha"; }
 
   TextureSource* mOnBlack;
   TextureSource* mOnWhite;
 };
 
 struct EffectSolidColor : public Effect
 {
   EffectSolidColor(const gfx::Color &aColor)
-    : Effect(EFFECT_SOLID_COLOR)
+    : Effect(EffectTypes::SOLID_COLOR)
     , mColor(aColor)
   {}
 
   virtual void PrintInfo(nsACString& aTo, const char* aPrefix);
 
   gfx::Color mColor;
 };
 
 struct EffectChain
 {
   EffectChain() : mLayerRef(nullptr) {}
   explicit EffectChain(void* aLayerRef) : mLayerRef(aLayerRef) {}
 
   RefPtr<Effect> mPrimaryEffect;
-  RefPtr<Effect> mSecondaryEffects[EFFECT_MAX_SECONDARY];
+  EnumeratedArray<EffectTypes, EffectTypes::MAX_SECONDARY, RefPtr<Effect>>
+    mSecondaryEffects;
   void* mLayerRef; //!< For LayerScope logging
 };
 
 /**
  * Create a Textured effect corresponding to aFormat and using
  * aSource as the (first) texture source.
  *
  * Note that aFormat can be different form aSource->GetFormat if, we are
--- a/gfx/layers/ImageContainer.cpp
+++ b/gfx/layers/ImageContainer.cpp
@@ -126,17 +126,17 @@ ImageContainer::ImageContainer(int flag)
   mRemoteData(nullptr),
   mRemoteDataMutex(nullptr),
   mCompositionNotifySink(nullptr),
   mImageClient(nullptr)
 {
   if (flag == ENABLE_ASYNC && ImageBridgeChild::IsCreated()) {
     // the refcount of this ImageClient is 1. we don't use a RefPtr here because the refcount
     // of this class must be done on the ImageBridge thread.
-    mImageClient = ImageBridgeChild::GetSingleton()->CreateImageClient(BUFFER_IMAGE_SINGLE).drop();
+    mImageClient = ImageBridgeChild::GetSingleton()->CreateImageClient(CompositableType::BUFFER_IMAGE_SINGLE).drop();
     MOZ_ASSERT(mImageClient);
   }
 }
 
 ImageContainer::~ImageContainer()
 {
   if (IsAsync()) {
     ImageBridgeChild::DispatchReleaseImageClient(mImageClient);
@@ -619,22 +619,22 @@ CairoImage::GetTextureClient(Compositabl
     return textureClient;
   }
 
   RefPtr<SourceSurface> surface = GetAsSourceSurface();
   MOZ_ASSERT(surface);
 
   // gfx::BackendType::NONE means default to content backend
   textureClient = aClient->CreateTextureClientForDrawing(surface->GetFormat(),
-                                                         TEXTURE_FLAGS_DEFAULT,
+                                                         TextureFlags::DEFAULT,
                                                          gfx::BackendType::NONE,
                                                          surface->GetSize());
   MOZ_ASSERT(textureClient->CanExposeDrawTarget());
   if (!textureClient->AllocateForSurface(surface->GetSize()) ||
-      !textureClient->Lock(OPEN_WRITE_ONLY)) {
+      !textureClient->Lock(OpenMode::OPEN_WRITE_ONLY)) {
     return nullptr;
   }
 
   {
     // We must not keep a reference to the DrawTarget after it has been unlocked.
     RefPtr<DrawTarget> dt = textureClient->GetAsDrawTarget();
     dt->CopySurface(surface, IntRect(IntPoint(), surface->GetSize()), IntPoint());
   }
--- a/gfx/layers/LayerScope.cpp
+++ b/gfx/layers/LayerScope.cpp
@@ -773,47 +773,47 @@ LayerScope::SendEffectChain(GLContext* a
                             const EffectChain& aEffectChain,
                             int aWidth, int aHeight)
 {
     if (!CheckSender())
         return;
 
     const Effect* primaryEffect = aEffectChain.mPrimaryEffect;
     switch (primaryEffect->mType) {
-    case EFFECT_RGB:
+    case EffectTypes::RGB:
     {
         const TexturedEffect* texturedEffect =
             static_cast<const TexturedEffect*>(primaryEffect);
         SendTexturedEffect(aGLContext, aEffectChain.mLayerRef, texturedEffect);
     }
     break;
-    case EFFECT_YCBCR:
+    case EffectTypes::YCBCR:
     {
         const EffectYCbCr* yCbCrEffect =
             static_cast<const EffectYCbCr*>(primaryEffect);
         SendYCbCrEffect(aGLContext, aEffectChain.mLayerRef, yCbCrEffect);
     }
-    case EFFECT_SOLID_COLOR:
+    case EffectTypes::SOLID_COLOR:
     {
         const EffectSolidColor* solidColorEffect =
             static_cast<const EffectSolidColor*>(primaryEffect);
         gfxRGBA color(solidColorEffect->mColor.r,
                       solidColorEffect->mColor.g,
                       solidColorEffect->mColor.b,
                       solidColorEffect->mColor.a);
         SendColor(aEffectChain.mLayerRef, color, aWidth, aHeight);
     }
     break;
-    case EFFECT_COMPONENT_ALPHA:
-    case EFFECT_RENDER_TARGET:
+    case EffectTypes::COMPONENT_ALPHA:
+    case EffectTypes::RENDER_TARGET:
     default:
         break;
     }
 
-    //const Effect* secondaryEffect = aEffectChain.mSecondaryEffects[EFFECT_MASK];
+    //const Effect* secondaryEffect = aEffectChain.mSecondaryEffects[EffectTypes::MASK];
     // TODO:
 }
 
 LayerScopeWebSocketManager::LayerScopeWebSocketManager()
 {
     NS_NewThread(getter_AddRefs(mDebugSenderThread));
 
     mServerSocket = do_CreateInstance(NS_SERVERSOCKET_CONTRACTID);
--- a/gfx/layers/LayersLogging.cpp
+++ b/gfx/layers/LayersLogging.cpp
@@ -175,36 +175,36 @@ AppendToString(nsACString& s, const Filt
   return s += sfx;
 }
 
 nsACString&
 AppendToString(nsACString& s, TextureFlags flags,
                const char* pfx, const char* sfx)
 {
   s += pfx;
-  if (!flags) {
+  if (flags == TextureFlags::NO_FLAGS) {
     s += "NoFlags";
   } else {
 
 #define AppendFlag(test) \
 { \
-  if (flags & test) { \
+  if (!!(flags & test)) { \
     if (previous) { \
       s += "|"; \
     } \
     s += #test; \
     previous = true; \
   } \
 }
     bool previous = false;
-    AppendFlag(TEXTURE_USE_NEAREST_FILTER);
-    AppendFlag(TEXTURE_NEEDS_Y_FLIP);
-    AppendFlag(TEXTURE_DISALLOW_BIGIMAGE);
-    AppendFlag(TEXTURE_ALLOW_REPEAT);
-    AppendFlag(TEXTURE_NEW_TILE);
+    AppendFlag(TextureFlags::USE_NEAREST_FILTER);
+    AppendFlag(TextureFlags::NEEDS_Y_FLIP);
+    AppendFlag(TextureFlags::DISALLOW_BIGIMAGE);
+    AppendFlag(TextureFlags::ALLOW_REPEAT);
+    AppendFlag(TextureFlags::NEW_TILE);
 
 #undef AppendFlag
   }
   return s += sfx;
 }
 
 nsACString&
 AppendToString(nsACString& s, mozilla::gfx::SurfaceFormat format,
--- a/gfx/layers/LayersTypes.h
+++ b/gfx/layers/LayersTypes.h
@@ -6,16 +6,17 @@
 #ifndef GFX_LAYERSTYPES_H
 #define GFX_LAYERSTYPES_H
 
 #include <stdint.h>                     // for uint32_t
 #include "nsPoint.h"                    // for nsIntPoint
 #include "nsRegion.h"
 
 #include "mozilla/TypedEnum.h"
+#include "mozilla/TypedEnumBits.h"
 
 #ifdef MOZ_WIDGET_GONK
 #include <ui/GraphicBuffer.h>
 #endif
 #if defined(DEBUG) || defined(PR_LOGGING)
 #  include <stdio.h>            // FILE
 #  include "prlog.h"            // for PR_LOG
 #  ifndef MOZ_LAYERS_HAVE_LOG
@@ -35,18 +36,16 @@ namespace android {
 class GraphicBuffer;
 }
 
 namespace mozilla {
 namespace layers {
 
 class TextureHost;
 
-typedef uint32_t TextureFlags;
-
 #undef NONE
 #undef OPAQUE
 
 MOZ_BEGIN_ENUM_CLASS(LayersBackend, int8_t)
   LAYERS_NONE = 0,
   LAYERS_BASIC,
   LAYERS_OPENGL,
   LAYERS_D3D9,
@@ -72,73 +71,78 @@ MOZ_BEGIN_ENUM_CLASS(SurfaceMode, int8_t
   SURFACE_OPAQUE,
   SURFACE_SINGLE_CHANNEL_ALPHA,
   SURFACE_COMPONENT_ALPHA
 MOZ_END_ENUM_CLASS(SurfaceMode)
 
 // LayerRenderState for Composer2D
 // We currently only support Composer2D using gralloc. If we want to be backed
 // by other surfaces we will need a more generic LayerRenderState.
-enum LayerRenderStateFlags {
-  LAYER_RENDER_STATE_Y_FLIPPED = 1 << 0,
-  LAYER_RENDER_STATE_BUFFER_ROTATION = 1 << 1,
+MOZ_BEGIN_ENUM_CLASS(LayerRenderStateFlags, int8_t)
+  LAYER_RENDER_STATE_DEFAULT = 0,
+  Y_FLIPPED = 1 << 0,
+  BUFFER_ROTATION = 1 << 1,
   // Notify Composer2D to swap the RB pixels of gralloc buffer
-  LAYER_RENDER_STATE_FORMAT_RB_SWAP = 1 << 2
-};
+  FORMAT_RB_SWAP = 1 << 2
+MOZ_END_ENUM_CLASS(LayerRenderStateFlags)
+MOZ_MAKE_ENUM_CLASS_BITWISE_OPERATORS(LayerRenderStateFlags)
 
 // The 'ifdef MOZ_WIDGET_GONK' sadness here is because we don't want to include
 // android::sp unless we have to.
 struct LayerRenderState {
   LayerRenderState()
 #ifdef MOZ_WIDGET_GONK
-    : mSurface(nullptr), mTexture(nullptr), mFlags(0), mHasOwnOffset(false)
+    : mFlags(LayerRenderStateFlags::LAYER_RENDER_STATE_DEFAULT)
+    , mHasOwnOffset(false)
+    , mSurface(nullptr)
+    , mTexture(nullptr)
 #endif
   {}
 
 #ifdef MOZ_WIDGET_GONK
   LayerRenderState(android::GraphicBuffer* aSurface,
                    const nsIntSize& aSize,
-                   uint32_t aFlags,
+                   LayerRenderStateFlags aFlags,
                    TextureHost* aTexture)
-    : mSurface(aSurface)
+    : mFlags(aFlags)
+    , mHasOwnOffset(false)
+    , mSurface(aSurface)
     , mSize(aSize)
     , mTexture(aTexture)
-    , mFlags(aFlags)
-    , mHasOwnOffset(false)
   {}
 
   bool YFlipped() const
-  { return mFlags & LAYER_RENDER_STATE_Y_FLIPPED; }
+  { return bool(mFlags & LayerRenderStateFlags::Y_FLIPPED); }
 
   bool BufferRotated() const
-  { return mFlags & LAYER_RENDER_STATE_BUFFER_ROTATION; }
+  { return bool(mFlags & LayerRenderStateFlags::BUFFER_ROTATION); }
 
   bool FormatRBSwapped() const
-  { return mFlags & LAYER_RENDER_STATE_FORMAT_RB_SWAP; }
+  { return bool(mFlags & LayerRenderStateFlags::FORMAT_RB_SWAP); }
 #endif
 
   void SetOffset(const nsIntPoint& aOffset)
   {
     mOffset = aOffset;
     mHasOwnOffset = true;
   }
 
+  // see LayerRenderStateFlags
+  LayerRenderStateFlags mFlags;
+  // true if mOffset is applicable
+  bool mHasOwnOffset;
+  // the location of the layer's origin on mSurface
+  nsIntPoint mOffset;
 #ifdef MOZ_WIDGET_GONK
   // surface to render
   android::sp<android::GraphicBuffer> mSurface;
   // size of mSurface 
   nsIntSize mSize;
   TextureHost* mTexture;
 #endif
-  // see LayerRenderStateFlags
-  uint32_t mFlags;
-  // the location of the layer's origin on mSurface
-  nsIntPoint mOffset;
-  // true if mOffset is applicable
-  bool mHasOwnOffset;
 };
 
 MOZ_BEGIN_ENUM_CLASS(ScaleMode, int8_t)
   SCALE_NONE,
   STRETCH,
   SENTINEL
 // Unimplemented - PRESERVE_ASPECT_RATIO_CONTAIN
 MOZ_END_ENUM_CLASS(ScaleMode)
--- a/gfx/layers/MacIOSurfaceImage.cpp
+++ b/gfx/layers/MacIOSurfaceImage.cpp
@@ -9,17 +9,17 @@
 using namespace mozilla;
 using namespace mozilla::layers;
 
 TextureClient*
 MacIOSurfaceImage::GetTextureClient(CompositableClient* aClient)
 {
   if (!mTextureClient) {
     RefPtr<MacIOSurfaceTextureClientOGL> buffer =
-      new MacIOSurfaceTextureClientOGL(TEXTURE_FLAGS_DEFAULT);
+      new MacIOSurfaceTextureClientOGL(TextureFlags::DEFAULT);
     buffer->InitWith(mSurface);
     mTextureClient = buffer;
   }
   return mTextureClient;
 }
 
 TemporaryRef<gfx::SourceSurface>
 MacIOSurfaceImage::GetAsSourceSurface()
--- a/gfx/layers/apz/src/AsyncPanZoomController.cpp
+++ b/gfx/layers/apz/src/AsyncPanZoomController.cpp
@@ -1597,36 +1597,44 @@ bool AsyncPanZoomController::SampleConte
                                                             ViewTransform* aNewTransform,
                                                             ScreenPoint& aScrollOffset) {
   // The eventual return value of this function. The compositor needs to know
   // whether or not to advance by a frame as soon as it can. For example, if a
   // fling is happening, it has to keep compositing so that the animation is
   // smooth. If an animation frame is requested, it is the compositor's
   // responsibility to schedule a composite.
   bool requestAnimationFrame = false;
+  Vector<Task*> deferredTasks;
 
   {
     ReentrantMonitorAutoEnter lock(mMonitor);
 
     requestAnimationFrame = UpdateAnimation(aSampleTime);
 
     aScrollOffset = mFrameMetrics.GetScrollOffset() * mFrameMetrics.GetZoom();
     *aNewTransform = GetCurrentAsyncTransform();
 
     LogRendertraceRect(GetGuid(), "viewport", "red",
       CSSRect(mFrameMetrics.GetScrollOffset(),
               ParentLayerSize(mFrameMetrics.mCompositionBounds.Size()) / mFrameMetrics.GetZoomToParent()));
 
     mCurrentAsyncScrollOffset = mFrameMetrics.GetScrollOffset();
+
+    // Get any deferred tasks queued up by mAnimation's Sample() (called by
+    // UpdateAnimation()). This needs to be done here since mAnimation can
+    // be destroyed by another thread when we release the monitor, but
+    // the tasks need to be executed after we release the monitor since they
+    // are allowed to call APZCTreeManager methods which can grab the tree lock. 
+    if (mAnimation) {
+      deferredTasks = mAnimation->TakeDeferredTasks();
+    }
   }
 
-  // Execute tasks queued up by mAnimation's Sample() (called by
-  // UpdateAnimation()) for execution after mMonitor has been released.
-  if (mAnimation) {
-    mAnimation->ExecuteDeferredTasks();
+  for (uint32_t i = 0; i < deferredTasks.length(); ++i) {
+    deferredTasks[i]->Run();
   }
 
   // Cancel the mAsyncScrollTimeoutTask because we will fire a
   // mozbrowserasyncscroll event or renew the mAsyncScrollTimeoutTask again.
   if (mAsyncScrollTimeoutTask) {
     mAsyncScrollTimeoutTask->Cancel();
     mAsyncScrollTimeoutTask = nullptr;
   }
--- a/gfx/layers/apz/src/AsyncPanZoomController.h
+++ b/gfx/layers/apz/src/AsyncPanZoomController.h
@@ -943,24 +943,24 @@ public:
                         TimeDuration::Forever())
     : mRepaintInterval(aRepaintInterval)
   { }
 
   virtual bool Sample(FrameMetrics& aFrameMetrics,
                       const TimeDuration& aDelta) = 0;
 
   /**
-   * Execute the tasks in |mDeferredTasks| in order. See |mDeferredTasks|
+   * Get the deferred tasks in |mDeferredTasks|. See |mDeferredTasks|
    * for more information.
+   * Clears |mDeferredTasks|.
    */
-  void ExecuteDeferredTasks() {
-    for (uint32_t i = 0; i < mDeferredTasks.length(); ++i) {
-      mDeferredTasks[i]->Run();
-    }
-    mDeferredTasks.clear();
+  Vector<Task*> TakeDeferredTasks() {
+    Vector<Task*> result;
+    mDeferredTasks.swap(result);
+    return result;
   }
 
   /**
    * Specifies how frequently (at most) we want to do repaints during the
    * animation sequence. TimeDuration::Forever() will cause it to only repaint
    * at the end of the animation.
    */
   TimeDuration mRepaintInterval;
--- a/gfx/layers/basic/BasicCompositor.cpp
+++ b/gfx/layers/basic/BasicCompositor.cpp
@@ -121,17 +121,17 @@ BasicCompositor::CreateDataTextureSource
 {
   RefPtr<DataTextureSource> result = new DataTextureSourceBasic();
   return result.forget();
 }
 
 bool
 BasicCompositor::SupportsEffect(EffectTypes aEffect)
 {
-  return static_cast<EffectTypes>(aEffect) != EFFECT_YCBCR;
+  return static_cast<EffectTypes>(aEffect) != EffectTypes::YCBCR;
 }
 
 static void
 DrawSurfaceWithTextureCoords(DrawTarget *aDest,
                              const gfx::Rect& aDestRect,
                              SourceSurface *aSource,
                              const gfx::Rect& aTextureCoords,
                              gfx::Filter aFilter,
@@ -286,65 +286,65 @@ BasicCompositor::DrawQuad(const gfx::Rec
     transformBounds.MoveTo(0, 0);
   }
 
   newTransform.Translate(-offset.x, -offset.y);
   buffer->SetTransform(newTransform);
 
   RefPtr<SourceSurface> sourceMask;
   Matrix maskTransform;
-  if (aEffectChain.mSecondaryEffects[EFFECT_MASK]) {
-    EffectMask *effectMask = static_cast<EffectMask*>(aEffectChain.mSecondaryEffects[EFFECT_MASK].get());
+  if (aEffectChain.mSecondaryEffects[EffectTypes::MASK]) {
+    EffectMask *effectMask = static_cast<EffectMask*>(aEffectChain.mSecondaryEffects[EffectTypes::MASK].get());
     sourceMask = effectMask->mMaskTexture->AsSourceBasic()->GetSurface();
     MOZ_ASSERT(effectMask->mMaskTransform.Is2D(), "How did we end up with a 3D transform here?!");
     MOZ_ASSERT(!effectMask->mIs3D);
     maskTransform = effectMask->mMaskTransform.As2D();
     maskTransform.Translate(-offset.x, -offset.y);
   }
 
   switch (aEffectChain.mPrimaryEffect->mType) {
-    case EFFECT_SOLID_COLOR: {
+    case EffectTypes::SOLID_COLOR: {
       EffectSolidColor* effectSolidColor =
         static_cast<EffectSolidColor*>(aEffectChain.mPrimaryEffect.get());
 
       FillRectWithMask(dest, aRect, effectSolidColor->mColor,
                        DrawOptions(aOpacity), sourceMask, &maskTransform);
       break;
     }
-    case EFFECT_RGB: {
+    case EffectTypes::RGB: {
       TexturedEffect* texturedEffect =
           static_cast<TexturedEffect*>(aEffectChain.mPrimaryEffect.get());
       TextureSourceBasic* source = texturedEffect->mTexture->AsSourceBasic();
 
       DrawSurfaceWithTextureCoords(dest, aRect,
                                    source->GetSurface(),
                                    texturedEffect->mTextureCoords,
                                    texturedEffect->mFilter,
                                    aOpacity, sourceMask, &maskTransform);
       break;
     }
-    case EFFECT_YCBCR: {
+    case EffectTypes::YCBCR: {
       NS_RUNTIMEABORT("Can't (easily) support component alpha with BasicCompositor!");
       break;
     }
-    case EFFECT_RENDER_TARGET: {
+    case EffectTypes::RENDER_TARGET: {
       EffectRenderTarget* effectRenderTarget =
         static_cast<EffectRenderTarget*>(aEffectChain.mPrimaryEffect.get());
       RefPtr<BasicCompositingRenderTarget> surface
         = static_cast<BasicCompositingRenderTarget*>(effectRenderTarget->mRenderTarget.get());
       RefPtr<SourceSurface> sourceSurf = surface->mDrawTarget->Snapshot();
 
       DrawSurfaceWithTextureCoords(dest, aRect,
                                    sourceSurf,
                                    effectRenderTarget->mTextureCoords,
                                    effectRenderTarget->mFilter,
                                    aOpacity, sourceMask, &maskTransform);
       break;
     }
-    case EFFECT_COMPONENT_ALPHA: {
+    case EffectTypes::COMPONENT_ALPHA: {
       NS_RUNTIMEABORT("Can't (easily) support component alpha with BasicCompositor!");
       break;
     }
     default: {
       NS_RUNTIMEABORT("Invalid effect type!");
       break;
     }
   }
--- a/gfx/layers/basic/BasicCompositor.h
+++ b/gfx/layers/basic/BasicCompositor.h
@@ -60,17 +60,17 @@ public:
   CreateRenderTarget(const gfx::IntRect &aRect, SurfaceInitMode aInit) MOZ_OVERRIDE;
 
   virtual TemporaryRef<CompositingRenderTarget>
   CreateRenderTargetFromSource(const gfx::IntRect &aRect,
                                const CompositingRenderTarget *aSource,
                                const gfx::IntPoint &aSourcePoint) MOZ_OVERRIDE;
 
   virtual TemporaryRef<DataTextureSource>
-  CreateDataTextureSource(TextureFlags aFlags = 0) MOZ_OVERRIDE;
+  CreateDataTextureSource(TextureFlags aFlags = TextureFlags::NO_FLAGS) MOZ_OVERRIDE;
 
   virtual bool SupportsEffect(EffectTypes aEffect) MOZ_OVERRIDE;
 
   virtual void SetRenderTarget(CompositingRenderTarget *aSource) MOZ_OVERRIDE
   {
     mRenderTarget = static_cast<BasicCompositingRenderTarget*>(aSource);
   }
   virtual CompositingRenderTarget* GetCurrentRenderTarget() const MOZ_OVERRIDE
--- a/gfx/layers/basic/TextureClientX11.cpp
+++ b/gfx/layers/basic/TextureClientX11.cpp
@@ -66,17 +66,17 @@ TextureClientX11::ToSurfaceDescriptor(Su
 
   aOutDescriptor = SurfaceDescriptorX11(mSurface);
   return true;
 }
 
 TextureClientData*
 TextureClientX11::DropTextureData()
 {
-  MOZ_ASSERT(!(mFlags & TEXTURE_DEALLOCATE_CLIENT));
+  MOZ_ASSERT(!(mFlags & TextureFlags::DEALLOCATE_CLIENT));
   return nullptr;
 }
 
 bool
 TextureClientX11::AllocateForSurface(IntSize aSize, TextureAllocationFlags aTextureFlags)
 {
   MOZ_ASSERT(IsValid());
   //MOZ_ASSERT(mFormat != gfx::FORMAT_YUV, "This TextureClient cannot use YCbCr data");
--- a/gfx/layers/basic/TextureClientX11.h
+++ b/gfx/layers/basic/TextureClientX11.h
@@ -14,17 +14,17 @@ namespace mozilla {
 namespace layers {
 
 /**
  * A TextureClient implementation based on Xlib.
  */
 class TextureClientX11 : public TextureClient
 {
  public:
-  TextureClientX11(gfx::SurfaceFormat format, TextureFlags aFlags = TEXTURE_FLAGS_DEFAULT);
+  TextureClientX11(gfx::SurfaceFormat format, TextureFlags aFlags = TextureFlags::DEFAULT);
 
   ~TextureClientX11();
 
   // TextureClient
 
   virtual bool IsAllocated() const MOZ_OVERRIDE;
 
   virtual bool ToSurfaceDescriptor(SurfaceDescriptor& aOutDescriptor) MOZ_OVERRIDE;
--- a/gfx/layers/client/CanvasClient.cpp
+++ b/gfx/layers/client/CanvasClient.cpp
@@ -38,17 +38,17 @@ CanvasClient::CreateCanvasClient(CanvasC
 #ifndef MOZ_WIDGET_GONK
   if (XRE_GetProcessType() != GeckoProcessType_Default) {
     NS_WARNING("Most platforms still need an optimized way to share GL cross process.");
     return new CanvasClient2D(aForwarder, aFlags);
   }
 #endif
   if (aType == CanvasClientGLContext &&
       aForwarder->GetCompositorBackendType() == LayersBackend::LAYERS_OPENGL) {
-    aFlags |= TEXTURE_DEALLOCATE_CLIENT;
+    aFlags |= TextureFlags::DEALLOCATE_CLIENT;
     return new CanvasClientSurfaceStream(aForwarder, aFlags);
   }
   return new CanvasClient2D(aForwarder, aFlags);
 }
 
 void
 CanvasClient2D::Update(gfx::IntSize aSize, ClientCanvasLayer* aLayer)
 {
@@ -61,30 +61,30 @@ CanvasClient2D::Update(gfx::IntSize aSiz
   bool bufferCreated = false;
   if (!mBuffer) {
     bool isOpaque = (aLayer->GetContentFlags() & Layer::CONTENT_OPAQUE);
     gfxContentType contentType = isOpaque
                                                 ? gfxContentType::COLOR
                                                 : gfxContentType::COLOR_ALPHA;
     gfxImageFormat format
       = gfxPlatform::GetPlatform()->OptimalFormatForContent(contentType);
-    uint32_t flags = TEXTURE_FLAGS_DEFAULT;
-    if (mTextureFlags & TEXTURE_NEEDS_Y_FLIP) {
-      flags |= TEXTURE_NEEDS_Y_FLIP;
+    TextureFlags flags = TextureFlags::DEFAULT;
+    if (mTextureFlags & TextureFlags::NEEDS_Y_FLIP) {
+      flags |= TextureFlags::NEEDS_Y_FLIP;
     }
     mBuffer = CreateBufferTextureClient(gfx::ImageFormatToSurfaceFormat(format),
                                         flags,
                                         gfxPlatform::GetPlatform()->GetPreferredCanvasBackend());
     MOZ_ASSERT(mBuffer->CanExposeDrawTarget());
     mBuffer->AllocateForSurface(aSize);
 
     bufferCreated = true;
   }
 
-  if (!mBuffer->Lock(OPEN_WRITE_ONLY)) {
+  if (!mBuffer->Lock(OpenMode::OPEN_WRITE_ONLY)) {
     mBuffer = nullptr;
     return;
   }
 
   bool updated = false;
   {
     // Restrict drawTarget to a scope so that terminates before Unlock.
     RefPtr<DrawTarget> target =
--- a/gfx/layers/client/CanvasClient.h
+++ b/gfx/layers/client/CanvasClient.h
@@ -74,17 +74,17 @@ public:
   CanvasClient2D(CompositableForwarder* aLayerForwarder,
                  TextureFlags aFlags)
     : CanvasClient(aLayerForwarder, aFlags)
   {
   }
 
   TextureInfo GetTextureInfo() const
   {
-    return TextureInfo(COMPOSITABLE_IMAGE);
+    return TextureInfo(CompositableType::IMAGE);
   }
 
   virtual void Clear() MOZ_OVERRIDE
   {
     mBuffer = nullptr;
   }
 
   virtual void Update(gfx::IntSize aSize, ClientCanvasLayer* aLayer) MOZ_OVERRIDE;
@@ -108,17 +108,17 @@ private:
 // GL backend.
 class CanvasClientSurfaceStream : public CanvasClient
 {
 public:
   CanvasClientSurfaceStream(CompositableForwarder* aLayerForwarder, TextureFlags aFlags);
 
   TextureInfo GetTextureInfo() const
   {
-    return TextureInfo(COMPOSITABLE_IMAGE);
+    return TextureInfo(CompositableType::IMAGE);
   }
 
   virtual void Clear() MOZ_OVERRIDE
   {
     mBuffer = nullptr;
   }
 
   virtual void Update(gfx::IntSize aSize, ClientCanvasLayer* aLayer) MOZ_OVERRIDE;
--- a/gfx/layers/client/ClientCanvasLayer.cpp
+++ b/gfx/layers/client/ClientCanvasLayer.cpp
@@ -128,28 +128,28 @@ ClientCanvasLayer::RenderLayer()
     return;
   }
 
   if (GetMaskLayer()) {
     ToClientLayer(GetMaskLayer())->RenderLayer();
   }
   
   if (!mCanvasClient) {
-    TextureFlags flags = TEXTURE_IMMEDIATE_UPLOAD;
+    TextureFlags flags = TextureFlags::IMMEDIATE_UPLOAD;
     if (mNeedsYFlip) {
-      flags |= TEXTURE_NEEDS_Y_FLIP;
+      flags |= TextureFlags::NEEDS_Y_FLIP;
     }
 
     if (!mGLContext) {
       // We don't support locking for buffer surfaces currently
-      flags |= TEXTURE_IMMEDIATE_UPLOAD;
+      flags |= TextureFlags::IMMEDIATE_UPLOAD;
     } else {
       // GLContext's SurfaceStream handles ownership itself,
       // and doesn't require layers to do any deallocation.
-      flags |= TEXTURE_DEALLOCATE_CLIENT;
+      flags |= TextureFlags::DEALLOCATE_CLIENT;
     }
     mCanvasClient = CanvasClient::CreateCanvasClient(GetCanvasClientType(),
                                                      ClientManager()->AsShadowForwarder(), flags);
     if (!mCanvasClient) {
       return;
     }
     if (HasShadow()) {
       mCanvasClient->Connect();
--- a/gfx/layers/client/ClientImageLayer.cpp
+++ b/gfx/layers/client/ClientImageLayer.cpp
@@ -24,30 +24,30 @@ namespace mozilla {
 namespace layers {
 
 class ClientImageLayer : public ImageLayer, 
                          public ClientLayer {
 public:
   ClientImageLayer(ClientLayerManager* aLayerManager)
     : ImageLayer(aLayerManager,
                  static_cast<ClientLayer*>(MOZ_THIS_IN_INITIALIZER_LIST()))
-    , mImageClientTypeContainer(BUFFER_UNKNOWN)
+    , mImageClientTypeContainer(CompositableType::BUFFER_UNKNOWN)
   {
     MOZ_COUNT_CTOR(ClientImageLayer);
   }
   virtual ~ClientImageLayer()
   {
     DestroyBackBuffer();
     MOZ_COUNT_DTOR(ClientImageLayer);
   }
   
   virtual void SetContainer(ImageContainer* aContainer) MOZ_OVERRIDE
   {
     ImageLayer::SetContainer(aContainer);
-    mImageClientTypeContainer = BUFFER_UNKNOWN;
+    mImageClientTypeContainer = CompositableType::BUFFER_UNKNOWN;
   }
 
   virtual void SetVisibleRegion(const nsIntRegion& aRegion)
   {
     NS_ASSERTION(ClientManager()->InConstruction(),
                  "Can only set properties in construction phase");
     ImageLayer::SetVisibleRegion(aRegion);
   }
@@ -89,36 +89,36 @@ public:
 protected:
   ClientLayerManager* ClientManager()
   {
     return static_cast<ClientLayerManager*>(mManager);
   }
 
   CompositableType GetImageClientType()
   {
-    if (mImageClientTypeContainer != BUFFER_UNKNOWN) {
+    if (mImageClientTypeContainer != CompositableType::BUFFER_UNKNOWN) {
       return mImageClientTypeContainer;
     }
 
     if (mContainer->IsAsync()) {
-      mImageClientTypeContainer = BUFFER_BRIDGE;
+      mImageClientTypeContainer = CompositableType::BUFFER_BRIDGE;
       return mImageClientTypeContainer;
     }
 
     RefPtr<gfx::SourceSurface> surface;
     AutoLockImage autoLock(mContainer, &surface);
 
 #ifdef MOZ_WIDGET_GONK
-    // gralloc buffer needs BUFFER_IMAGE_BUFFERED to prevent
+    // gralloc buffer needs CompositableType::BUFFER_IMAGE_BUFFERED to prevent
     // the buffer's usage conflict.
     mImageClientTypeContainer = autoLock.GetImage() ?
-                                  BUFFER_IMAGE_BUFFERED : BUFFER_UNKNOWN;
+                                  CompositableType::BUFFER_IMAGE_BUFFERED : CompositableType::BUFFER_UNKNOWN;
 #else
     mImageClientTypeContainer = autoLock.GetImage() ?
-                                  BUFFER_IMAGE_SINGLE : BUFFER_UNKNOWN;
+                                  CompositableType::BUFFER_IMAGE_SINGLE : CompositableType::BUFFER_UNKNOWN;
 #endif
     return mImageClientTypeContainer;
   }
 
   RefPtr<ImageClient> mImageClient;
   CompositableType mImageClientTypeContainer;
 };
 
@@ -135,27 +135,27 @@ ClientImageLayer::RenderLayer()
 
   if (mImageClient) {
     mImageClient->OnTransaction();
   }
 
   if (!mImageClient ||
       !mImageClient->UpdateImage(mContainer, GetContentFlags())) {
     CompositableType type = GetImageClientType();
-    if (type == BUFFER_UNKNOWN) {
+    if (type == CompositableType::BUFFER_UNKNOWN) {
       return;
     }
-    TextureFlags flags = TEXTURE_FRONT;
+    TextureFlags flags = TextureFlags::FRONT;
     if (mDisallowBigImage) {
-      flags |= TEXTURE_DISALLOW_BIGIMAGE;
+      flags |= TextureFlags::DISALLOW_BIGIMAGE;
     }
     mImageClient = ImageClient::CreateImageClient(type,
                                                   ClientManager()->AsShadowForwarder(),
                                                   flags);
-    if (type == BUFFER_BRIDGE) {
+    if (type == CompositableType::BUFFER_BRIDGE) {
       static_cast<ImageClientBridge*>(mImageClient.get())->SetLayer(this);
     }
 
     if (!mImageClient) {
       return;
     }
     if (HasShadow() && !mContainer->IsAsync()) {
       mImageClient->Connect();
--- a/gfx/layers/client/CompositableClient.cpp
+++ b/gfx/layers/client/CompositableClient.cpp
@@ -5,16 +5,17 @@
 
 #include "mozilla/layers/CompositableClient.h"
 #include <stdint.h>                     // for uint64_t, uint32_t
 #include "gfxPlatform.h"                // for gfxPlatform
 #include "mozilla/layers/CompositableForwarder.h"
 #include "mozilla/layers/TextureClient.h"  // for TextureClient, etc
 #include "mozilla/layers/TextureClientOGL.h"
 #include "mozilla/mozalloc.h"           // for operator delete, etc
+#include "mozilla/layers/PCompositableChild.h"
 #ifdef XP_WIN
 #include "gfxWindowsPlatform.h"         // for gfxWindowsPlatform
 #include "mozilla/layers/TextureD3D11.h"
 #include "mozilla/layers/TextureD3D9.h"
 #endif
 
 using namespace mozilla::gfx;
 
--- a/gfx/layers/client/CompositableClient.h
+++ b/gfx/layers/client/CompositableClient.h
@@ -9,31 +9,30 @@
 #include <stdint.h>                     // for uint64_t
 #include <vector>                       // for vector
 #include <map>                          // for map
 #include "mozilla/Assertions.h"         // for MOZ_CRASH
 #include "mozilla/RefPtr.h"             // for TemporaryRef, RefCounted
 #include "mozilla/gfx/Types.h"          // for SurfaceFormat
 #include "mozilla/layers/CompositorTypes.h"
 #include "mozilla/layers/LayersTypes.h"  // for LayersBackend
-#include "mozilla/layers/PCompositableChild.h"  // for PCompositableChild
 #include "nsISupportsImpl.h"            // for MOZ_COUNT_CTOR, etc
 
 namespace mozilla {
 namespace layers {
 
 class CompositableClient;
 class TextureClient;
 class BufferTextureClient;
 class ImageBridgeChild;
 class CompositableForwarder;
 class CompositableChild;
 class SurfaceDescriptor;
 class TextureClientData;
-
+class PCompositableChild;
 /**
  * CompositableClient manages the texture-specific logic for composite layers,
  * independently of the layer. It is the content side of a CompositableClient/
  * CompositableHost pair.
  *
  * CompositableClient's purpose is to send texture data to the compositor side
  * along with any extra information about how the texture is to be composited.
  * Things like opacity or transformation belong to layer and not compositable.
@@ -70,25 +69,25 @@ class TextureClientData;
 class CompositableClient
 {
 protected:
   virtual ~CompositableClient();
 
 public:
   NS_INLINE_DECL_THREADSAFE_REFCOUNTING(CompositableClient)
 
-  CompositableClient(CompositableForwarder* aForwarder, TextureFlags aFlags = 0);
+  CompositableClient(CompositableForwarder* aForwarder, TextureFlags aFlags = TextureFlags::NO_FLAGS);
 
   virtual TextureInfo GetTextureInfo() const = 0;
 
   LayersBackend GetCompositorBackendType() const;
 
   TemporaryRef<BufferTextureClient>
   CreateBufferTextureClient(gfx::SurfaceFormat aFormat,
-                            TextureFlags aFlags = TEXTURE_FLAGS_DEFAULT,
+                            TextureFlags aFlags = TextureFlags::DEFAULT,
                             gfx::BackendType aMoz2dBackend = gfx::BackendType::NONE);
 
   TemporaryRef<TextureClient>
   CreateTextureClientForDrawing(gfx::SurfaceFormat aFormat,
                                 TextureFlags aTextureFlags,
                                 gfx::BackendType aMoz2dBackend,
                                 const gfx::IntSize& aSizeHint);
 
--- a/gfx/layers/client/ContentClient.cpp
+++ b/gfx/layers/client/ContentClient.cpp
@@ -35,30 +35,29 @@
 namespace mozilla {
 
 using namespace gfx;
 
 namespace layers {
 
 static TextureFlags TextureFlagsForRotatedContentBufferFlags(uint32_t aBufferFlags)
 {
-  TextureFlags result = 0;
+  TextureFlags result = TextureFlags::NO_FLAGS;
 
   if (aBufferFlags & RotatedContentBuffer::BUFFER_COMPONENT_ALPHA) {
-    result |= TEXTURE_COMPONENT_ALPHA;
+    result |= TextureFlags::COMPONENT_ALPHA;
   }
 
   if (aBufferFlags & RotatedContentBuffer::ALLOW_REPEAT) {
-    result |= TEXTURE_ALLOW_REPEAT;
+    result |= TextureFlags::ALLOW_REPEAT;
   }
 
   return result;
 }
 
-
 /* static */ TemporaryRef<ContentClient>
 ContentClient::CreateContentClient(CompositableForwarder* aForwarder)
 {
   LayersBackend backend = aForwarder->GetCompositorBackendType();
   if (backend != LayersBackend::LAYERS_OPENGL &&
       backend != LayersBackend::LAYERS_D3D9 &&
       backend != LayersBackend::LAYERS_D3D11 &&
       backend != LayersBackend::LAYERS_BASIC) {
@@ -192,17 +191,17 @@ ContentClientRemoteBuffer::CreateAndAllo
                                           gfx::BackendType::NONE,
                                           mSize);
   if (!aClient) {
     return false;
   }
 
   if (!aClient->AllocateForSurface(mSize, ALLOC_CLEAR_BUFFER)) {
     aClient = CreateTextureClientForDrawing(mSurfaceFormat,
-                mTextureInfo.mTextureFlags | TEXTURE_ALLOC_FALLBACK | aFlags,
+                mTextureInfo.mTextureFlags | TextureFlags::ALLOC_FALLBACK | aFlags,
                 gfx::BackendType::NONE,
                 mSize);
     if (!aClient) {
       return false;
     }
     if (!aClient->AllocateForSurface(mSize, ALLOC_CLEAR_BUFFER)) {
       NS_WARNING("Could not allocate texture client");
       aClient = nullptr;
@@ -231,29 +230,29 @@ ContentClientRemoteBuffer::BuildTextureC
   mIsNewBuffer = true;
 
   DestroyBuffers();
 
   mSurfaceFormat = aFormat;
   mSize = gfx::IntSize(aRect.width, aRect.height);
   mTextureInfo.mTextureFlags = TextureFlagsForRotatedContentBufferFlags(aFlags);
 
-  if (!CreateAndAllocateTextureClient(mTextureClient, TEXTURE_ON_BLACK) ||
+  if (!CreateAndAllocateTextureClient(mTextureClient, TextureFlags::ON_BLACK) ||
       !AddTextureClient(mTextureClient)) {
     AbortTextureClientCreation();
     return;
   }
 
   if (aFlags & BUFFER_COMPONENT_ALPHA) {
-    if (!CreateAndAllocateTextureClient(mTextureClientOnWhite, TEXTURE_ON_WHITE) ||
+    if (!CreateAndAllocateTextureClient(mTextureClientOnWhite, TextureFlags::ON_WHITE) ||
         !AddTextureClient(mTextureClientOnWhite)) {
       AbortTextureClientCreation();
       return;
     }
-    mTextureInfo.mTextureFlags |= TEXTURE_COMPONENT_ALPHA;
+    mTextureInfo.mTextureFlags |= TextureFlags::COMPONENT_ALPHA;
   }
 
   CreateFrontBuffer(aRect);
 }
 
 void
 ContentClientRemoteBuffer::CreateBuffer(ContentType aType,
                                         const nsIntRect& aRect,
@@ -263,22 +262,22 @@ ContentClientRemoteBuffer::CreateBuffer(
 {
   BuildTextureClients(gfxPlatform::GetPlatform()->Optimal2DFormatForContent(aType), aRect, aFlags);
   if (!mTextureClient) {
     return;
   }
 
   // We just created the textures and we are about to get their draw targets
   // so we have to lock them here.
-  DebugOnly<bool> locked = mTextureClient->Lock(OPEN_READ_WRITE);
+  DebugOnly<bool> locked = mTextureClient->Lock(OpenMode::OPEN_READ_WRITE);
   MOZ_ASSERT(locked, "Could not lock the TextureClient");
 
   *aBlackDT = mTextureClient->GetAsDrawTarget();
   if (aFlags & BUFFER_COMPONENT_ALPHA) {
-    locked = mTextureClientOnWhite->Lock(OPEN_READ_WRITE);
+    locked = mTextureClientOnWhite->Lock(OpenMode::OPEN_READ_WRITE);
     MOZ_ASSERT(locked, "Could not lock the second TextureClient for component alpha");
 
     *aWhiteDT = mTextureClientOnWhite->GetAsDrawTarget();
   }
 }
 
 nsIntRegion
 ContentClientRemoteBuffer::GetUpdatedRegion(const nsIntRegion& aRegionToDraw,
@@ -334,23 +333,23 @@ ContentClientRemoteBuffer::SwapBuffers(c
 {
   MOZ_ASSERT(mTextureClient);
   mFrontAndBackBufferDiffer = true;
 }
 
 void
 ContentClientDoubleBuffered::CreateFrontBuffer(const nsIntRect& aBufferRect)
 {
-  if (!CreateAndAllocateTextureClient(mFrontClient, TEXTURE_ON_BLACK) ||
+  if (!CreateAndAllocateTextureClient(mFrontClient, TextureFlags::ON_BLACK) ||
       !AddTextureClient(mFrontClient)) {
     AbortTextureClientCreation();
     return;
   }
-  if (mTextureInfo.mTextureFlags & TEXTURE_COMPONENT_ALPHA) {
-    if (!CreateAndAllocateTextureClient(mFrontClientOnWhite, TEXTURE_ON_WHITE) ||
+  if (mTextureInfo.mTextureFlags & TextureFlags::COMPONENT_ALPHA) {
+    if (!CreateAndAllocateTextureClient(mFrontClientOnWhite, TextureFlags::ON_WHITE) ||
         !AddTextureClient(mFrontClientOnWhite)) {
       AbortTextureClientCreation();
       return;
     }
   }
 
   mFrontBufferRect = aBufferRect;
   mFrontBufferRotation = nsIntPoint();
@@ -422,21 +421,21 @@ ContentClientDoubleBuffered::BeginPaint(
 // Sync front/back buffers content
 // After executing, the new back buffer has the same (interesting) pixels as
 // the new front buffer, and mValidRegion et al. are correct wrt the new
 // back buffer (i.e. as they were for the old back buffer)
 void
 ContentClientDoubleBuffered::FinalizeFrame(const nsIntRegion& aRegionToDraw)
 {
   if (mTextureClient) {
-    DebugOnly<bool> locked = mTextureClient->Lock(OPEN_READ_WRITE);
+    DebugOnly<bool> locked = mTextureClient->Lock(OpenMode::OPEN_READ_WRITE);
     MOZ_ASSERT(locked);
   }
   if (mTextureClientOnWhite) {
-    DebugOnly<bool> locked = mTextureClientOnWhite->Lock(OPEN_READ_WRITE);
+    DebugOnly<bool> locked = mTextureClientOnWhite->Lock(OpenMode::OPEN_READ_WRITE);
     MOZ_ASSERT(locked);
   }
 
   if (!mFrontAndBackBufferDiffer) {
     MOZ_ASSERT(!mDidSelfCopy, "If we have to copy the world, then our buffers are different, right?");
     return;
   }
   MOZ_ASSERT(mFrontClient);
@@ -460,21 +459,21 @@ ContentClientDoubleBuffered::FinalizeFra
   // nothing to sync at all, there is nothing to do and we can go home early.
   updateRegion.Sub(updateRegion, aRegionToDraw);
   if (updateRegion.IsEmpty()) {
     return;
   }
 
   // We need to ensure that we lock these two buffers in the same
   // order as the compositor to prevent deadlocks.
-  if (!mFrontClient->Lock(OPEN_READ_ONLY)) {
+  if (!mFrontClient->Lock(OpenMode::OPEN_READ_ONLY)) {
     return;
   }
   if (mFrontClientOnWhite &&
-      !mFrontClientOnWhite->Lock(OPEN_READ_ONLY)) {
+      !mFrontClientOnWhite->Lock(OpenMode::OPEN_READ_ONLY)) {
     mFrontClient->Unlock();
     return;
   }
   {
     // Restrict the DrawTargets and frontBuffer to a scope to make
     // sure there is no more external references to the DrawTargets
     // when we Unlock the TextureClients.
     RefPtr<DrawTarget> dt = mFrontClient->GetAsDrawTarget();
@@ -535,21 +534,21 @@ ContentClientDoubleBuffered::UpdateDesti
     }
   }
 }
 
 void
 ContentClientSingleBuffered::FinalizeFrame(const nsIntRegion& aRegionToDraw)
 {
   if (mTextureClient) {
-    DebugOnly<bool> locked = mTextureClient->Lock(OPEN_READ_WRITE);
+    DebugOnly<bool> locked = mTextureClient->Lock(OpenMode::OPEN_READ_WRITE);
     MOZ_ASSERT(locked);
   }
   if (mTextureClientOnWhite) {
-    DebugOnly<bool> locked = mTextureClientOnWhite->Lock(OPEN_READ_WRITE);
+    DebugOnly<bool> locked = mTextureClientOnWhite->Lock(OpenMode::OPEN_READ_WRITE);
     MOZ_ASSERT(locked);
   }
 }
 
 static void
 WrapRotationAxis(int32_t* aRotationPoint, int32_t aSize)
 {
   if (*aRotationPoint < 0) {
@@ -567,21 +566,33 @@ FillSurface(DrawTarget* aDT, const nsInt
   const nsIntRect* r;
   while ((r = iter.Next()) != nullptr) {
     aDT->FillRect(Rect(r->x - aOffset.x, r->y - aOffset.y,
                        r->width, r->height),
                   ColorPattern(ToColor(aColor)));
   }
 }
 
+void
+ContentClientIncremental::NotifyBufferCreated(ContentType aType, TextureFlags aFlags)
+{
+  mTextureInfo.mTextureFlags = aFlags;
+  mContentType = aType;
+
+  mForwarder->CreatedIncrementalBuffer(this,
+                                        mTextureInfo,
+                                        mBufferRect);
+
+}
+
 RotatedContentBuffer::PaintState
 ContentClientIncremental::BeginPaintBuffer(ThebesLayer* aLayer,
                                            uint32_t aFlags)
 {
-  mTextureInfo.mDeprecatedTextureHostFlags = 0;
+  mTextureInfo.mDeprecatedTextureHostFlags = DeprecatedTextureHostFlags::DEFAULT;
   PaintState result;
   // We need to disable rotation if we're going to be resampled when
   // drawing, because we might sample across the rotation boundary.
   bool canHaveRotation =  !(aFlags & RotatedContentBuffer::PAINT_WILL_RESAMPLE);
 
   nsIntRegion validRegion = aLayer->GetValidRegion();
 
   bool canUseOpaqueSurface = aLayer->CanUseOpaqueSurface();
@@ -596,17 +607,17 @@ ContentClientIncremental::BeginPaintBuff
 
   while (true) {
     mode = aLayer->GetSurfaceMode();
     neededRegion = aLayer->GetVisibleRegion();
     // If we're going to resample, we need a buffer that's in clamp mode.
     canReuseBuffer = neededRegion.GetBounds().Size() <= mBufferRect.Size() &&
       mHasBuffer &&
       (!(aFlags & RotatedContentBuffer::PAINT_WILL_RESAMPLE) ||
-       !(mTextureInfo.mTextureFlags & TEXTURE_ALLOW_REPEAT));
+       !(mTextureInfo.mTextureFlags & TextureFlags::ALLOW_REPEAT));
 
     if (canReuseBuffer) {
       if (mBufferRect.Contains(neededRegion.GetBounds())) {
         // We don't need to adjust mBufferRect.
         destBufferRect = mBufferRect;
       } else {
         // The buffer's big enough but doesn't contain everything that's
         // going to be visible. We'll move it.
@@ -680,19 +691,22 @@ ContentClientIncremental::BeginPaintBuff
     mBufferRect.SetRect(0, 0, 0, 0);
     mBufferRotation.MoveTo(0, 0);
     canReuseBuffer = false;
   }
 
   nsIntRect drawBounds = result.mRegionToDraw.GetBounds();
   bool createdBuffer = false;
 
-  uint32_t bufferFlags = canHaveRotation ? TEXTURE_ALLOW_REPEAT : 0;
+  TextureFlags bufferFlags = TextureFlags::NO_FLAGS;
+  if (canHaveRotation) {
+    bufferFlags |= TextureFlags::ALLOW_REPEAT;
+  }
   if (mode == SurfaceMode::SURFACE_COMPONENT_ALPHA) {
-    bufferFlags |= TEXTURE_COMPONENT_ALPHA;
+    bufferFlags |= TextureFlags::COMPONENT_ALPHA;
   }
   if (canReuseBuffer) {
     nsIntRect keepArea;
     if (keepArea.IntersectRect(destBufferRect, mBufferRect)) {
       // Set mBufferRotation so that the pixels currently in mBuffer
       // will still be rendered in the right place when mBufferRect
       // changes to destBufferRect.
       nsIntPoint newRotation = mBufferRotation +
@@ -735,17 +749,17 @@ ContentClientIncremental::BeginPaintBuff
 
   if (!createdBuffer && !mHasBuffer) {
     return result;
   }
 
   if (createdBuffer) {
     if (mHasBuffer &&
         (mode != SurfaceMode::SURFACE_COMPONENT_ALPHA || mHasBufferOnWhite)) {
-      mTextureInfo.mDeprecatedTextureHostFlags = TEXTURE_HOST_COPY_PREVIOUS;
+      mTextureInfo.mDeprecatedTextureHostFlags = DeprecatedTextureHostFlags::COPY_PREVIOUS;
     }
 
     mHasBuffer = true;
     if (mode == SurfaceMode::SURFACE_COMPONENT_ALPHA) {
       mHasBufferOnWhite = true;
     }
     mBufferRect = destBufferRect;
     mBufferRotation = nsIntPoint(0,0);
@@ -832,26 +846,26 @@ ContentClientIncremental::BorrowDrawTarg
 
 void
 ContentClientIncremental::Updated(const nsIntRegion& aRegionToDraw,
                                   const nsIntRegion& aVisibleRegion,
                                   bool aDidSelfCopy)
 {
   if (IsSurfaceDescriptorValid(mUpdateDescriptor)) {
     mForwarder->UpdateTextureIncremental(this,
-                                         TextureFront,
+                                         TextureIdentifier::Front,
                                          mUpdateDescriptor,
                                          aRegionToDraw,
                                          mBufferRect,
                                          mBufferRotation);
     mUpdateDescriptor = SurfaceDescriptor();
   }
   if (IsSurfaceDescriptorValid(mUpdateDescriptorOnWhite)) {
     mForwarder->UpdateTextureIncremental(this,
-                                         TextureOnWhiteFront,
+                                         TextureIdentifier::OnWhiteFront,
                                          mUpdateDescriptorOnWhite,
                                          aRegionToDraw,
                                          mBufferRect,
                                          mBufferRotation);
     mUpdateDescriptorOnWhite = SurfaceDescriptor();
   }
 
 }
--- a/gfx/layers/client/ContentClient.h
+++ b/gfx/layers/client/ContentClient.h
@@ -269,17 +269,17 @@ protected:
                            uint32_t aFlags);
 
   // Create the front buffer for the ContentClient/Host pair if necessary
   // and notify the compositor that we have created the buffer(s).
   virtual void CreateFrontBuffer(const nsIntRect& aBufferRect) = 0;
   virtual void DestroyFrontBuffer() {}
 
   bool CreateAndAllocateTextureClient(RefPtr<TextureClient>& aClient,
-                                      TextureFlags aFlags = 0);
+                                      TextureFlags aFlags = TextureFlags::NO_FLAGS);
 
   virtual void AbortTextureClientCreation()
   {
     mTextureClient = nullptr;
     mTextureClientOnWhite = nullptr;
     mIsNewBuffer = false;
   }
 
@@ -309,17 +309,17 @@ protected:
  * (in SwapBuffers).
  */
 class ContentClientDoubleBuffered : public ContentClientRemoteBuffer
 {
 public:
   ContentClientDoubleBuffered(CompositableForwarder* aFwd)
     : ContentClientRemoteBuffer(aFwd)
   {
-    mTextureInfo.mCompositableType = COMPOSITABLE_CONTENT_DOUBLE;
+    mTextureInfo.mCompositableType = CompositableType::CONTENT_DOUBLE;
   }
   virtual ~ContentClientDoubleBuffered() {}
 
   virtual void Clear() MOZ_OVERRIDE
   {
     ContentClientRemoteBuffer::Clear();
     mFrontClient = nullptr;
     mFrontClientOnWhite = nullptr;
@@ -363,17 +363,17 @@ private:
  * the compositor.
  */
 class ContentClientSingleBuffered : public ContentClientRemoteBuffer
 {
 public:
   ContentClientSingleBuffered(CompositableForwarder* aFwd)
     : ContentClientRemoteBuffer(aFwd)
   {
-    mTextureInfo.mCompositableType = COMPOSITABLE_CONTENT_SINGLE;
+    mTextureInfo.mCompositableType = CompositableType::CONTENT_SINGLE;
   }
   virtual ~ContentClientSingleBuffered() {}
 
   virtual void FinalizeFrame(const nsIntRegion& aRegionToDraw) MOZ_OVERRIDE;
 
 protected:
   virtual void CreateFrontBuffer(const nsIntRect& aBufferRect) MOZ_OVERRIDE {}
 };
@@ -389,17 +389,17 @@ class ContentClientIncremental : public 
 {
 public:
   ContentClientIncremental(CompositableForwarder* aFwd)
     : ContentClientRemote(aFwd)
     , mContentType(gfxContentType::COLOR_ALPHA)
     , mHasBuffer(false)
     , mHasBufferOnWhite(false)
   {
-    mTextureInfo.mCompositableType = BUFFER_CONTENT_INC;
+    mTextureInfo.mCompositableType = CompositableType::BUFFER_CONTENT_INC;
   }
 
   typedef RotatedContentBuffer::PaintState PaintState;
   typedef RotatedContentBuffer::ContentType ContentType;
 
   virtual TextureInfo GetTextureInfo() const
   {
     return mTextureInfo;
@@ -438,26 +438,17 @@ public:
 
 private:
 
   enum BufferType{
     BUFFER_BLACK,
     BUFFER_WHITE
   };
 
-  void NotifyBufferCreated(ContentType aType, uint32_t aFlags)
-  {
-    mTextureInfo.mTextureFlags = aFlags & ~TEXTURE_DEALLOCATE_CLIENT;
-    mContentType = aType;
-
-    mForwarder->CreatedIncrementalBuffer(this,
-                                         mTextureInfo,
-                                         mBufferRect);
-
-  }
+  void NotifyBufferCreated(ContentType aType, TextureFlags aFlags);
 
   TemporaryRef<gfx::DrawTarget> GetUpdateSurface(BufferType aType,
                                                  const nsIntRegion& aUpdateRegion);
 
   TextureInfo mTextureInfo;
   nsIntRect mBufferRect;
   nsIntPoint mBufferRotation;
 
--- a/gfx/layers/client/ImageClient.cpp
+++ b/gfx/layers/client/ImageClient.cpp
@@ -43,27 +43,27 @@ namespace layers {
 
 /* static */ TemporaryRef<ImageClient>
 ImageClient::CreateImageClient(CompositableType aCompositableHostType,
                                CompositableForwarder* aForwarder,
                                TextureFlags aFlags)
 {
   RefPtr<ImageClient> result = nullptr;
   switch (aCompositableHostType) {
-  case COMPOSITABLE_IMAGE:
-  case BUFFER_IMAGE_SINGLE:
-    result = new ImageClientSingle(aForwarder, aFlags, COMPOSITABLE_IMAGE);
+  case CompositableType::IMAGE:
+  case CompositableType::BUFFER_IMAGE_SINGLE:
+    result = new ImageClientSingle(aForwarder, aFlags, CompositableType::IMAGE);
     break;
-  case BUFFER_IMAGE_BUFFERED:
-    result = new ImageClientBuffered(aForwarder, aFlags, COMPOSITABLE_IMAGE);
+  case CompositableType::BUFFER_IMAGE_BUFFERED:
+    result = new ImageClientBuffered(aForwarder, aFlags, CompositableType::IMAGE);
     break;
-  case BUFFER_BRIDGE:
+  case CompositableType::BUFFER_BRIDGE:
     result = new ImageClientBridge(aForwarder, aFlags);
     break;
-  case BUFFER_UNKNOWN:
+  case CompositableType::BUFFER_UNKNOWN:
     result = nullptr;
     break;
   default:
     MOZ_CRASH("unhandled program type");
   }
 
   NS_ASSERTION(result, "Failed to create ImageClient");
 
@@ -81,17 +81,17 @@ ImageClientBuffered::ImageClientBuffered
                                          TextureFlags aFlags,
                                          CompositableType aType)
   : ImageClientSingle(aFwd, aFlags, aType)
 {
 }
 
 TextureInfo ImageClientSingle::GetTextureInfo() const
 {
-  return TextureInfo(COMPOSITABLE_IMAGE);
+  return TextureInfo(CompositableType::IMAGE);
 }
 
 void
 ImageClientSingle::FlushAllImages(bool aExceptFront)
 {
   if (!aExceptFront && mFrontBuffer) {
     GetForwarder()->RemoveTextureFromCompositable(this, mFrontBuffer);
     mFrontBuffer = nullptr;
@@ -159,27 +159,27 @@ ImageClientSingle::UpdateImageInternal(I
 
     if (mFrontBuffer && mFrontBuffer->IsImmutable()) {
       GetForwarder()->RemoveTextureFromCompositable(this, mFrontBuffer);
       mFrontBuffer = nullptr;
     }
 
     bool bufferCreated = false;
     if (!mFrontBuffer) {
-      mFrontBuffer = CreateBufferTextureClient(gfx::SurfaceFormat::YUV, TEXTURE_FLAGS_DEFAULT);
+      mFrontBuffer = CreateBufferTextureClient(gfx::SurfaceFormat::YUV, TextureFlags::DEFAULT);
       gfx::IntSize ySize(data->mYSize.width, data->mYSize.height);
       gfx::IntSize cbCrSize(data->mCbCrSize.width, data->mCbCrSize.height);
       if (!mFrontBuffer->AsTextureClientYCbCr()->AllocateForYCbCr(ySize, cbCrSize, data->mStereoMode)) {
         mFrontBuffer = nullptr;
         return false;
       }
       bufferCreated = true;
     }
 
-    if (!mFrontBuffer->Lock(OPEN_WRITE_ONLY)) {
+    if (!mFrontBuffer->Lock(OpenMode::OPEN_WRITE_ONLY)) {
       mFrontBuffer = nullptr;
       return false;
     }
     bool status = mFrontBuffer->AsTextureClientYCbCr()->UpdateYCbCr(*data);
     mFrontBuffer->Unlock();
 
     if (bufferCreated) {
       if (!AddTextureClient(mFrontBuffer)) {
@@ -237,17 +237,17 @@ ImageClientSingle::UpdateImageInternal(I
       if (!mFrontBuffer->AllocateForSurface(size)) {
         mFrontBuffer = nullptr;
         return false;
       }
 
       bufferCreated = true;
     }
 
-    if (!mFrontBuffer->Lock(OPEN_WRITE_ONLY)) {
+    if (!mFrontBuffer->Lock(OpenMode::OPEN_WRITE_ONLY)) {
       mFrontBuffer = nullptr;
       return false;
     }
 
     {
       // We must not keep a reference to the DrawTarget after it has been unlocked.
       RefPtr<DrawTarget> dt = mFrontBuffer->GetAsDrawTarget();
       MOZ_ASSERT(surface.get());
@@ -330,17 +330,17 @@ ImageClient::UpdatePictureRect(nsIntRect
   }
   mPictureRect = aRect;
   MOZ_ASSERT(mForwarder);
   GetForwarder()->UpdatePictureRect(this, aRect);
 }
 
 ImageClientBridge::ImageClientBridge(CompositableForwarder* aFwd,
                                      TextureFlags aFlags)
-: ImageClient(aFwd, aFlags, BUFFER_BRIDGE)
+: ImageClient(aFwd, aFlags, CompositableType::BUFFER_BRIDGE)
 , mAsyncContainerID(0)
 , mLayer(nullptr)
 {
 }
 
 bool
 ImageClientBridge::UpdateImage(ImageContainer* aContainer, uint32_t aContentFlags)
 {
--- a/gfx/layers/client/SimpleTextureClientPool.cpp
+++ b/gfx/layers/client/SimpleTextureClientPool.cpp
@@ -67,20 +67,20 @@ SimpleTextureClientPool::GetTextureClien
     textureClient->WaitReleaseFence();
     mAvailableTextureClients.pop();
     RECYCLE_LOG("%s Skip allocate (%i left), returning %p\n", (mFormat == SurfaceFormat::B8G8R8A8?"poolA":"poolX"), mAvailableTextureClients.size(), textureClient.get());
 
   } else {
     // No unused clients in the pool, create one
     if (gfxPrefs::ForceShmemTiles()) {
       textureClient = TextureClient::CreateBufferTextureClient(mSurfaceAllocator,
-        mFormat, TEXTURE_IMMEDIATE_UPLOAD | TEXTURE_RECYCLE, gfx::BackendType::NONE);
+        mFormat, TextureFlags::IMMEDIATE_UPLOAD | TextureFlags::RECYCLE, gfx::BackendType::NONE);
     } else {
       textureClient = TextureClient::CreateTextureClientForDrawing(mSurfaceAllocator,
-        mFormat, TEXTURE_FLAGS_DEFAULT | TEXTURE_RECYCLE, gfx::BackendType::NONE, mSize);
+        mFormat, TextureFlags::DEFAULT | TextureFlags::RECYCLE, gfx::BackendType::NONE, mSize);
     }
     if (!textureClient->AllocateForSurface(mSize, ALLOC_DEFAULT)) {
       NS_WARNING("TextureClient::AllocateForSurface failed!");
     }
     RECYCLE_LOG("%s Must allocate (0 left), returning %p\n", (mFormat == SurfaceFormat::B8G8R8A8?"poolA":"poolX"), textureClient.get());
   }
 
   if (aAutoRecycle) {
--- a/gfx/layers/client/SimpleTiledContentClient.cpp
+++ b/gfx/layers/client/SimpleTiledContentClient.cpp
@@ -85,17 +85,17 @@ SimpleTiledLayerBuffer::ValidateTile(Sim
 
   RefPtr<TextureClient> textureClient = mManager->GetSimpleTileTexturePool(tileFormat)->GetTextureClientWithAutoRecycle();
 
   if (!textureClient) {
     NS_WARNING("TextureClient allocation failed");
     return SimpleTiledLayerTile();
   }
 
-  if (!textureClient->Lock(OPEN_READ_WRITE)) {
+  if (!textureClient->Lock(OpenMode::OPEN_READ_WRITE)) {
     NS_WARNING("TextureClient lock failed");
     return SimpleTiledLayerTile();
   }
 
   if (!textureClient->CanExposeDrawTarget()) {
     doBufferedDrawing = false;
   }
 
--- a/gfx/layers/client/SimpleTiledContentClient.h
+++ b/gfx/layers/client/SimpleTiledContentClient.h
@@ -139,17 +139,17 @@ class SimpleTiledContentClient : public 
 public:
   SimpleTiledContentClient(SimpleClientTiledThebesLayer* aThebesLayer,
                            ClientLayerManager* aManager);
 
   ~SimpleTiledContentClient();
 
   virtual TextureInfo GetTextureInfo() const MOZ_OVERRIDE
   {
-    return TextureInfo(BUFFER_SIMPLE_TILED);
+    return TextureInfo(CompositableType::BUFFER_SIMPLE_TILED);
   }
 
   void UseTiledLayerBuffer();
 
 private:
   SimpleTiledLayerBuffer mTiledBuffer;
 };
 
--- a/gfx/layers/client/TextureClient.cpp
+++ b/gfx/layers/client/TextureClient.cpp
@@ -20,16 +20,17 @@
 #include "mozilla/layers/ShadowLayers.h"  // for ShadowLayerForwarder
 #include "mozilla/layers/SharedPlanarYCbCrImage.h"
 #include "mozilla/layers/YCbCrImageDataSerializer.h"
 #include "nsDebug.h"                    // for NS_ASSERTION, NS_WARNING, etc
 #include "nsISupportsImpl.h"            // for MOZ_COUNT_CTOR, etc
 #include "ImageContainer.h"             // for PlanarYCbCrImage, etc
 #include "mozilla/gfx/2D.h"
 #include "mozilla/layers/TextureClientOGL.h"
+#include "mozilla/layers/PTextureChild.h"
 
 #ifdef XP_WIN
 #include "mozilla/layers/TextureD3D9.h"
 #include "mozilla/layers/TextureD3D11.h"
 #include "gfxWindowsPlatform.h"
 #include "gfx2DGlue.h"
 #endif
 #ifdef MOZ_X11
@@ -284,49 +285,49 @@ TextureClient::CreateTextureClientForDra
 #ifdef XP_WIN
   LayersBackend parentBackend = aAllocator->GetCompositorBackendType();
   if (parentBackend == LayersBackend::LAYERS_D3D11 &&
       (aMoz2DBackend == gfx::BackendType::DIRECT2D ||
         aMoz2DBackend == gfx::BackendType::DIRECT2D1_1) &&
       gfxWindowsPlatform::GetPlatform()->GetD2DDevice() &&
       aSizeHint.width <= maxTextureSize &&
       aSizeHint.height <= maxTextureSize &&
-      !(aTextureFlags & TEXTURE_ALLOC_FALLBACK)) {
+      !(aTextureFlags & TextureFlags::ALLOC_FALLBACK)) {
     result = new TextureClientD3D11(aFormat, aTextureFlags);
   }
   if (parentBackend == LayersBackend::LAYERS_D3D9 &&
       aMoz2DBackend == gfx::BackendType::CAIRO &&
       aAllocator->IsSameProcess() &&
       aSizeHint.width <= maxTextureSize &&
       aSizeHint.height <= maxTextureSize &&
-      !(aTextureFlags & TEXTURE_ALLOC_FALLBACK)) {
+      !(aTextureFlags & TextureFlags::ALLOC_FALLBACK)) {
     if (!gfxWindowsPlatform::GetPlatform()->GetD3D9Device()) {
       result = new DIBTextureClientD3D9(aFormat, aTextureFlags);
     } else {
       result = new CairoTextureClientD3D9(aFormat, aTextureFlags);
     }
   }
 #endif
 
 #ifdef MOZ_X11
   LayersBackend parentBackend = aAllocator->GetCompositorBackendType();
   gfxSurfaceType type =
     gfxPlatform::GetPlatform()->ScreenReferenceSurface()->GetType();
 
   if (parentBackend == LayersBackend::LAYERS_BASIC &&
       aMoz2DBackend == gfx::BackendType::CAIRO &&
       type == gfxSurfaceType::Xlib &&
-      !(aTextureFlags & TEXTURE_ALLOC_FALLBACK))
+      !(aTextureFlags & TextureFlags::ALLOC_FALLBACK))
   {
     result = new TextureClientX11(aFormat, aTextureFlags);
   }
 #ifdef GL_PROVIDER_GLX
   if (parentBackend == LayersBackend::LAYERS_OPENGL &&
       type == gfxSurfaceType::Xlib &&
-      !(aTextureFlags & TEXTURE_ALLOC_FALLBACK) &&
+      !(aTextureFlags & TextureFlags::ALLOC_FALLBACK) &&
       aFormat != SurfaceFormat::A8 &&
       gl::sGLXLibrary.UseTextureFromPixmap())
   {
     result = new TextureClientX11(aFormat, aTextureFlags);
   }
 #endif
 #endif
 
@@ -453,17 +454,17 @@ TextureClient::~TextureClient()
 {
   // All the destruction code that may lead to virtual method calls must
   // be in Finalize() which is called just before the destructor.
 }
 
 void TextureClient::ForceRemove()
 {
   if (mValid && mActor) {
-    if (GetFlags() & TEXTURE_DEALLOCATE_CLIENT) {
+    if (GetFlags() & TextureFlags::DEALLOCATE_CLIENT) {
       mActor->SetTextureData(DropTextureData());
       if (mActor->IPCOpen()) {
         mActor->SendRemoveTextureSync();
       }
       mActor->DeleteTextureData();
     } else {
       if (mActor->IPCOpen()) {
         mActor->SendRemoveTexture();
@@ -641,17 +642,17 @@ MemoryTextureClient::~MemoryTextureClien
 BufferTextureClient::BufferTextureClient(ISurfaceAllocator* aAllocator,
                                          gfx::SurfaceFormat aFormat,
                                          gfx::BackendType aMoz2DBackend,
                                          TextureFlags aFlags)
   : TextureClient(aFlags)
   , mAllocator(aAllocator)
   , mFormat(aFormat)
   , mBackend(aMoz2DBackend)
-  , mOpenMode(0)
+  , mOpenMode(OpenMode::OPEN_NONE)
   , mUsingFallbackDrawTarget(false)
   , mLocked(false)
 {}
 
 BufferTextureClient::~BufferTextureClient()
 {}
 
 ISurfaceAllocator*
@@ -708,17 +709,17 @@ BufferTextureClient::GetAsDrawTarget()
   // DrawTarget around raw memory. This is going to be slow :(
   mDrawTarget = gfx::Factory::CreateDrawTarget(mBackend, serializer.GetSize(),
                                                serializer.GetFormat());
   if (!mDrawTarget) {
     return nullptr;
   }
 
   mUsingFallbackDrawTarget = true;
-  if (mOpenMode & OPEN_READ) {
+  if (mOpenMode & OpenMode::OPEN_READ) {
     RefPtr<DataSourceSurface> surface = serializer.GetAsSurface();
     IntRect rect(0, 0, surface->GetSize().width, surface->GetSize().height);
     mDrawTarget->CopySurface(surface, rect, IntPoint(0,0));
   }
   return mDrawTarget;
 }
 
 bool
@@ -742,17 +743,17 @@ BufferTextureClient::Unlock()
 
   // see the comment on TextureClient::GetAsDrawTarget.
   // This DrawTarget is internal to the TextureClient and is only exposed to the
   // outside world between Lock() and Unlock(). This assertion checks that no outside
   // reference remains by the time Unlock() is called.
   MOZ_ASSERT(mDrawTarget->refCount() == 1);
 
   mDrawTarget->Flush();
-  if (mUsingFallbackDrawTarget && (mOpenMode & OPEN_WRITE)) {
+  if (mUsingFallbackDrawTarget && (mOpenMode & OpenMode::OPEN_WRITE)) {
     // When we are using a fallback DrawTarget, it means we could not create
     // a DrawTarget wrapping the TextureClient's shared memory. In this scenario
     // we need to put the content of the fallback draw target back into our shared
     // memory.
     RefPtr<SourceSurface> snapshot = mDrawTarget->Snapshot();
     RefPtr<DataSourceSurface> surface = snapshot->GetDataSurface();
     ImageDataSerializer serializer(GetBuffer(), GetBufferSize());
     if (!serializer.IsValid() || serializer.GetSize() != surface->GetSize()) {
--- a/gfx/layers/client/TextureClient.h
+++ b/gfx/layers/client/TextureClient.h
@@ -17,17 +17,16 @@
 #include "mozilla/gfx/2D.h"             // for DrawTarget
 #include "mozilla/gfx/Point.h"          // for IntSize
 #include "mozilla/gfx/Types.h"          // for SurfaceFormat
 #include "mozilla/layers/FenceUtils.h"  // for FenceHandle
 #include "mozilla/ipc/Shmem.h"          // for Shmem
 #include "mozilla/layers/AtomicRefCountedWithFinalize.h"
 #include "mozilla/layers/CompositorTypes.h"  // for TextureFlags, etc
 #include "mozilla/layers/LayersSurfaces.h"  // for SurfaceDescriptor
-#include "mozilla/layers/PTextureChild.h" // for PTextureChild
 #include "mozilla/mozalloc.h"           // for operator delete
 #include "nsAutoPtr.h"                  // for nsRefPtr
 #include "nsCOMPtr.h"                   // for already_AddRefed
 #include "nsISupportsImpl.h"            // for TextureImage::AddRef, etc
 
 class gfxReusableSurfaceWrapper;
 class gfxImageSurface;
 
@@ -125,17 +124,17 @@ public:
  * responsibility of the compositable (which would use two Texture pairs).
  * In order to send several different buffers to the compositor side, use
  * several TextureClients.
  */
 class TextureClient
   : public AtomicRefCountedWithFinalize<TextureClient>
 {
 public:
-  TextureClient(TextureFlags aFlags = TEXTURE_FLAGS_DEFAULT);
+  TextureClient(TextureFlags aFlags = TextureFlags::DEFAULT);
   virtual ~TextureClient();
 
   static TemporaryRef<BufferTextureClient>
   CreateBufferTextureClient(ISurfaceAllocator* aAllocator,
                             gfx::SurfaceFormat aFormat,
                             TextureFlags aTextureFlags,
                             gfx::BackendType aMoz2dBackend);
 
@@ -170,17 +169,17 @@ public:
    * return the same DrawTarget.
    * The DrawTarget is automatically flushed by the TextureClient when the latter
    * is unlocked, and the DrawTarget that will be returned within the next
    * lock/unlock pair may or may not be the same object.
    * Do not keep references to the DrawTarget outside of the lock/unlock pair.
    *
    * This is typically used as follows:
    *
-   * if (!texture->Lock(OPEN_READ_WRITE)) {
+   * if (!texture->Lock(OpenMode::OPEN_READ_WRITE)) {
    *   return false;
    * }
    * {
    *   // Restrict this code's scope to ensure all references to dt are gone
    *   // when Unlock is called.
    *   RefPtr<DrawTarget> dt = texture->GetAsDrawTarget();
    *   // use the draw target ...
    * }
@@ -257,32 +256,32 @@ public:
    * TextureFlags contain important information about various aspects
    * of the texture, like how its liferime is managed, and how it
    * should be displayed.
    * See TextureFlags in CompositorTypes.h.
    */
   TextureFlags GetFlags() const { return mFlags; }
 
   /**
-   * valid only for TEXTURE_RECYCLE TextureClient.
+   * valid only for TextureFlags::RECYCLE TextureClient.
    * When called this texture client will grab a strong reference and release
    * it once the compositor notifies that it is done with the texture.
    * NOTE: In this stage the texture client can no longer be used by the
    * client in a transaction.
    */
   void WaitForCompositorRecycle();
 
   /**
    * After being shared with the compositor side, an immutable texture is never
    * modified, it can only be read. It is safe to not Lock/Unlock immutable
    * textures.
    */
-  bool IsImmutable() const { return mFlags & TEXTURE_IMMUTABLE; }
+  bool IsImmutable() const { return !!(mFlags & TextureFlags::IMMUTABLE); }
 
-  void MarkImmutable() { AddFlags(TEXTURE_IMMUTABLE); }
+  void MarkImmutable() { AddFlags(TextureFlags::IMMUTABLE); }
 
   bool IsSharedWithCompositor() const { return mShared; }
 
   bool ShouldDeallocateInDestructor() const;
 
   /**
    * If this method returns false users of TextureClient are not allowed
    * to access the shared data.
@@ -302,17 +301,17 @@ public:
    * This is to be used with IPDL messages only. Do not store the returned
    * pointer.
    */
   PTextureChild* GetIPDLActor();
 
   /**
    * Triggers the destruction of the shared data and the corresponding TextureHost.
    *
-   * If the texture flags contain TEXTURE_DEALLOCATE_CLIENT, the destruction
+   * If the texture flags contain TextureFlags::DEALLOCATE_CLIENT, the destruction
    * will be synchronously coordinated with the compositor side, otherwise it
    * will be done asynchronously.
    */
   void ForceRemove();
 
   virtual void SetReleaseFenceHandle(FenceHandle aReleaseFenceHandle) {}
 
   const FenceHandle& GetReleaseFenceHandle() const
--- a/gfx/layers/client/TextureClientPool.cpp
+++ b/gfx/layers/client/TextureClientPool.cpp
@@ -52,20 +52,20 @@ TextureClientPool::GetTextureClient()
   // We're increasing the number of outstanding TextureClients without reusing a
   // client, we may need to free a deferred-return TextureClient.
   ShrinkToMaximumSize();
 
   // No unused clients in the pool, create one
   if (gfxPrefs::ForceShmemTiles()) {
     // gfx::BackendType::NONE means use the content backend
     textureClient = TextureClient::CreateBufferTextureClient(mSurfaceAllocator,
-      mFormat, TEXTURE_IMMEDIATE_UPLOAD, gfx::BackendType::NONE);
+      mFormat, TextureFlags::IMMEDIATE_UPLOAD, gfx::BackendType::NONE);
   } else {
     textureClient = TextureClient::CreateTextureClientForDrawing(mSurfaceAllocator,
-      mFormat, TEXTURE_IMMEDIATE_UPLOAD, gfx::BackendType::NONE, mSize);
+      mFormat, TextureFlags::IMMEDIATE_UPLOAD, gfx::BackendType::NONE, mSize);
   }
   textureClient->AllocateForSurface(mSize, ALLOC_DEFAULT);
 
   return textureClient;
 }
 
 void
 TextureClientPool::ReturnTextureClient(TextureClient *aClient)
--- a/gfx/layers/client/TiledContentClient.cpp
+++ b/gfx/layers/client/TiledContentClient.cpp
@@ -438,23 +438,23 @@ TileClient::ValidateBackBufferFromFront(
 
       if (regionToCopy.IsEmpty() ||
           (aCanRerasterizeValidRegion &&
            regionToCopy.Area() < tileSize.width * tileSize.height * MINIMUM_TILE_COPY_AREA)) {
         // Just redraw it all.
         return;
       }
 
-      if (!mFrontBuffer->Lock(OPEN_READ)) {
+      if (!mFrontBuffer->Lock(OpenMode::OPEN_READ)) {
         NS_WARNING("Failed to lock the tile's front buffer");
         return;
       }
       TextureClientAutoUnlock autoFront(mFrontBuffer);
 
-      if (!mBackBuffer->Lock(OPEN_WRITE)) {
+      if (!mBackBuffer->Lock(OpenMode::OPEN_WRITE)) {
         NS_WARNING("Failed to lock the tile's back buffer");
         return;
       }
       TextureClientAutoUnlock autoBack(mBackBuffer);
 
       // Copy the bounding rect of regionToCopy. As tiles are quite small, it
       // is unlikely that we'd save much by copying each individual rect of the
       // region, but we can reevaluate this if it becomes an issue.
@@ -744,17 +744,17 @@ ClientTiledLayerBuffer::ValidateTile(Til
   offsetScaledDirtyRegion.ScaleRoundOut(mResolution, mResolution);
 
   bool usingSinglePaintBuffer = !!mSinglePaintDrawTarget;
   RefPtr<TextureClient> backBuffer =
     aTile.GetBackBuffer(offsetScaledDirtyRegion,
                         mManager->GetTexturePool(gfxPlatform::GetPlatform()->Optimal2DFormatForContent(GetContentType())),
                         &createdTextureClient, !usingSinglePaintBuffer);
 
-  if (!backBuffer->Lock(OPEN_READ_WRITE)) {
+  if (!backBuffer->Lock(OpenMode::OPEN_READ_WRITE)) {
     NS_WARNING("Failed to lock tile TextureClient for updating.");
     aTile.DiscardFrontBuffer();
     return aTile;
   }
 
   // We must not keep a reference to the DrawTarget after it has been unlocked,
   // make sure these are null'd before unlocking as destruction of the context
   // may cause the target to be flushed.
--- a/gfx/layers/client/TiledContentClient.h
+++ b/gfx/layers/client/TiledContentClient.h
@@ -478,17 +478,17 @@ public:
     MOZ_COUNT_DTOR(TiledContentClient);
 
     mTiledBuffer.Release();
     mLowPrecisionTiledBuffer.Release();
   }
 
   virtual TextureInfo GetTextureInfo() const MOZ_OVERRIDE
   {
-    return TextureInfo(BUFFER_TILED);
+    return TextureInfo(CompositableType::BUFFER_TILED);
   }
 
   virtual void ClearCachedResources() MOZ_OVERRIDE;
 
   enum TiledBufferType {
     TILED_BUFFER,
     LOW_PRECISION_TILED_BUFFER
   };
--- a/gfx/layers/composite/CanvasLayerComposite.cpp
+++ b/gfx/layers/composite/CanvasLayerComposite.cpp
@@ -39,19 +39,19 @@ CanvasLayerComposite::~CanvasLayerCompos
 
   CleanupResources();
 }
 
 bool
 CanvasLayerComposite::SetCompositableHost(CompositableHost* aHost)
 {
   switch (aHost->GetType()) {
-    case BUFFER_IMAGE_SINGLE:
-    case BUFFER_IMAGE_BUFFERED:
-    case COMPOSITABLE_IMAGE:
+    case CompositableType::BUFFER_IMAGE_SINGLE:
+    case CompositableType::BUFFER_IMAGE_BUFFERED:
+    case CompositableType::IMAGE:
       mImageHost = aHost;
       return true;
     default:
       return false;
   }
 
 }
 
--- a/gfx/layers/composite/ColorLayerComposite.cpp
+++ b/gfx/layers/composite/ColorLayerComposite.cpp
@@ -6,17 +6,17 @@
 #include "ColorLayerComposite.h"
 #include "gfxColor.h"                   // for gfxRGBA
 #include "mozilla/RefPtr.h"             // for RefPtr
 #include "mozilla/gfx/Matrix.h"         // for Matrix4x4
 #include "mozilla/gfx/Point.h"          // for Point
 #include "mozilla/gfx/Rect.h"           // for Rect
 #include "mozilla/gfx/Types.h"          // for Color
 #include "mozilla/layers/Compositor.h"  // for Compositor
-#include "mozilla/layers/CompositorTypes.h"  // for DIAGNOSTIC_COLOR
+#include "mozilla/layers/CompositorTypes.h"  // for DiagnosticFlags::COLOR
 #include "mozilla/layers/Effects.h"     // for Effect, EffectChain, etc
 #include "mozilla/mozalloc.h"           // for operator delete, etc
 #include "nsPoint.h"                    // for nsIntPoint
 #include "nsRect.h"                     // for nsIntRect
 
 namespace mozilla {
 namespace layers {
 
@@ -38,15 +38,15 @@ ColorLayerComposite::RenderLayer(const n
                  boundRect.width, boundRect.height);
   gfx::Rect clipRect(aClipRect.x, aClipRect.y,
                      aClipRect.width, aClipRect.height);
 
   float opacity = GetEffectiveOpacity();
 
   const gfx::Matrix4x4& transform = GetEffectiveTransform();
   mCompositor->DrawQuad(rect, clipRect, effects, opacity, transform);
-  mCompositor->DrawDiagnostics(DIAGNOSTIC_COLOR,
+  mCompositor->DrawDiagnostics(DiagnosticFlags::COLOR,
                                rect, clipRect,
                                transform);
 }
 
 } /* layers */
 } /* mozilla */
--- a/gfx/layers/composite/CompositableHost.cpp
+++ b/gfx/layers/composite/CompositableHost.cpp
@@ -11,16 +11,17 @@
 #include "ImageHost.h"                  // for ImageHostBuffered, etc
 #include "TiledContentHost.h"           // for TiledContentHost
 #include "mozilla/layers/LayersSurfaces.h"  // for SurfaceDescriptor
 #include "mozilla/layers/TextureHost.h"  // for TextureHost, etc
 #include "nsAutoPtr.h"                  // for nsRefPtr
 #include "nsDebug.h"                    // for NS_WARNING
 #include "nsISupportsImpl.h"            // for MOZ_COUNT_CTOR, etc
 #include "gfxPlatform.h"                // for gfxPlatform
+#include "mozilla/layers/PCompositableParent.h"
 
 namespace mozilla {
 namespace layers {
 
 class Compositor;
 
 /**
  * IPDL actor used by CompositableHost to match with its corresponding
@@ -153,17 +154,17 @@ CompositableHost::AddMaskEffect(EffectCh
     NS_WARNING("Using compositable with no texture host as mask layer");
     return false;
   }
 
   RefPtr<EffectMask> effect = new EffectMask(source,
                                              source->GetSize(),
                                              aTransform);
   effect->mIs3D = aIs3D;
-  aEffects.mSecondaryEffects[EFFECT_MASK] = effect;
+  aEffects.mSecondaryEffects[EffectTypes::MASK] = effect;
   return true;
 }
 
 void
 CompositableHost::RemoveMaskEffect()
 {
   RefPtr<TextureHost> host = GetAsTextureHost();
   if (host) {
@@ -174,41 +175,41 @@ CompositableHost::RemoveMaskEffect()
 // implemented in TextureHostOGL.cpp
 TemporaryRef<CompositableBackendSpecificData> CreateCompositableBackendSpecificDataOGL();
 
 /* static */ TemporaryRef<CompositableHost>
 CompositableHost::Create(const TextureInfo& aTextureInfo)
 {
   RefPtr<CompositableHost> result;
   switch (aTextureInfo.mCompositableType) {
-  case BUFFER_BRIDGE:
+  case CompositableType::BUFFER_BRIDGE:
     NS_ERROR("Cannot create an image bridge compositable this way");
     break;
-  case BUFFER_CONTENT_INC:
+  case CompositableType::BUFFER_CONTENT_INC:
     result = new ContentHostIncremental(aTextureInfo);
     break;
-  case BUFFER_TILED:
-  case BUFFER_SIMPLE_TILED:
+  case CompositableType::BUFFER_TILED:
+  case CompositableType::BUFFER_SIMPLE_TILED:
     result = new TiledContentHost(aTextureInfo);
     break;
-  case COMPOSITABLE_IMAGE:
+  case CompositableType::IMAGE:
     result = new ImageHost(aTextureInfo);
     break;
-  case COMPOSITABLE_CONTENT_SINGLE:
+  case CompositableType::CONTENT_SINGLE:
     result = new ContentHostSingleBuffered(aTextureInfo);
     break;
-  case COMPOSITABLE_CONTENT_DOUBLE:
+  case CompositableType::CONTENT_DOUBLE:
     result = new ContentHostDoubleBuffered(aTextureInfo);
     break;
   default:
     NS_ERROR("Unknown CompositableType");
   }
   // We know that Tiled buffers don't use the compositable backend-specific
   // data, so don't bother creating it.
-  if (result && aTextureInfo.mCompositableType != BUFFER_TILED) {
+  if (result && aTextureInfo.mCompositableType != CompositableType::BUFFER_TILED) {
     RefPtr<CompositableBackendSpecificData> data = CreateCompositableBackendSpecificDataOGL();
     result->SetCompositableBackendSpecificData(data);
   }
   return result;
 }
 
 #ifdef MOZ_DUMP_PAINTING
 void
--- a/gfx/layers/composite/CompositableHost.h
+++ b/gfx/layers/composite/CompositableHost.h
@@ -13,17 +13,16 @@
 #include "mozilla/Attributes.h"         // for MOZ_OVERRIDE
 #include "mozilla/RefPtr.h"             // for RefPtr, RefCounted, etc
 #include "mozilla/gfx/Point.h"          // for Point
 #include "mozilla/gfx/Rect.h"           // for Rect
 #include "mozilla/gfx/Types.h"          // for Filter
 #include "mozilla/ipc/ProtocolUtils.h"
 #include "mozilla/layers/CompositorTypes.h"  // for TextureInfo, etc
 #include "mozilla/layers/LayersTypes.h"  // for LayerRenderState, etc
-#include "mozilla/layers/PCompositableParent.h"
 #include "mozilla/layers/TextureHost.h" // for TextureHost
 #include "mozilla/mozalloc.h"           // for operator delete
 #include "nsCOMPtr.h"                   // for already_AddRefed
 #include "nsRegion.h"                   // for nsIntRegion
 #include "nscore.h"                     // for nsACString
 #include "Units.h"                      // for CSSToScreenScale
 
 struct nsIntPoint;
@@ -47,16 +46,17 @@ struct TiledLayerProperties
 
 class Layer;
 class SurfaceDescriptor;
 class Compositor;
 class ISurfaceAllocator;
 class ThebesBufferData;
 class TiledLayerComposer;
 class CompositableParentManager;
+class PCompositableParent;
 struct EffectChain;
 
 /**
  * A base class for doing CompositableHost and platform dependent task on TextureHost.
  */
 class CompositableBackendSpecificData
 {
 protected:
--- a/gfx/layers/composite/ContainerLayerComposite.cpp
+++ b/gfx/layers/composite/ContainerLayerComposite.cpp
@@ -13,17 +13,17 @@
 #include "gfxUtils.h"                   // for gfxUtils, etc
 #include "mozilla/Assertions.h"         // for MOZ_ASSERT, etc
 #include "mozilla/RefPtr.h"             // for RefPtr
 #include "mozilla/gfx/BaseRect.h"       // for BaseRect
 #include "mozilla/gfx/Matrix.h"         // for Matrix4x4
 #include "mozilla/gfx/Point.h"          // for Point, IntPoint
 #include "mozilla/gfx/Rect.h"           // for IntRect, Rect
 #include "mozilla/layers/Compositor.h"  // for Compositor, etc
-#include "mozilla/layers/CompositorTypes.h"  // for DIAGNOSTIC_CONTAINER
+#include "mozilla/layers/CompositorTypes.h"  // for DiagnosticFlags::CONTAINER
 #include "mozilla/layers/Effects.h"     // for Effect, EffectChain, etc
 #include "mozilla/layers/TextureHost.h"  // for CompositingRenderTarget
 #include "mozilla/mozalloc.h"           // for operator delete, etc
 #include "nsAutoPtr.h"                  // for nsRefPtr
 #include "nsDebug.h"                    // for NS_ASSERTION
 #include "nsISupportsImpl.h"            // for MOZ_COUNT_CTOR, etc
 #include "nsISupportsUtils.h"           // for NS_ADDREF, NS_RELEASE
 #include "nsPoint.h"                    // for nsIntPoint
@@ -408,17 +408,17 @@ ContainerRender(ContainerT* aContainer,
                                         aContainer->GetEffectiveTransform());
   }
 
   if (aContainer->GetFrameMetrics().IsScrollable()) {
     const FrameMetrics& frame = aContainer->GetFrameMetrics();
     LayerRect layerBounds = ParentLayerRect(frame.mCompositionBounds) * ParentLayerToLayerScale(1.0);
     gfx::Rect rect(layerBounds.x, layerBounds.y, layerBounds.width, layerBounds.height);
     gfx::Rect clipRect(aClipRect.x, aClipRect.y, aClipRect.width, aClipRect.height);
-    aManager->GetCompositor()->DrawDiagnostics(DIAGNOSTIC_CONTAINER,
+    aManager->GetCompositor()->DrawDiagnostics(DiagnosticFlags::CONTAINER,
                                                rect, clipRect,
                                                aContainer->GetEffectiveTransform());
   }
 }
 
 ContainerLayerComposite::ContainerLayerComposite(LayerManagerComposite *aManager)
   : ContainerLayer(aManager, nullptr)
   , LayerComposite(aManager)
--- a/gfx/layers/composite/ContentHost.cpp
+++ b/gfx/layers/composite/ContentHost.cpp
@@ -124,39 +124,39 @@ ContentHostBase::Composite(EffectChain& 
     nsIntRect regionRect = *iterRect;
     nsIntRect screenRect = regionRect;
     screenRect.MoveBy(origin);
 
     screenRects.Or(screenRects, screenRect);
     regionRects.Or(regionRects, regionRect);
   }
 
-  TileIterator* tileIter = source->AsTileIterator();
-  TileIterator* iterOnWhite = nullptr;
-  if (tileIter) {
-    tileIter->BeginTileIteration();
+  BigImageIterator* bigImgIter = source->AsBigImageIterator();
+  BigImageIterator* iterOnWhite = nullptr;
+  if (bigImgIter) {
+    bigImgIter->BeginBigImageIteration();
   }
 
   if (sourceOnWhite) {
-    iterOnWhite = sourceOnWhite->AsTileIterator();
-    MOZ_ASSERT(!tileIter || tileIter->GetTileCount() == iterOnWhite->GetTileCount(),
+    iterOnWhite = sourceOnWhite->AsBigImageIterator();
+    MOZ_ASSERT(!bigImgIter || bigImgIter->GetTileCount() == iterOnWhite->GetTileCount(),
                "Tile count mismatch on component alpha texture");
     if (iterOnWhite) {
-      iterOnWhite->BeginTileIteration();
+      iterOnWhite->BeginBigImageIteration();
     }
   }
 
-  bool usingTiles = (tileIter && tileIter->GetTileCount() > 1);
+  bool usingTiles = (bigImgIter && bigImgIter->GetTileCount() > 1);
   do {
     if (iterOnWhite) {
-      MOZ_ASSERT(iterOnWhite->GetTileRect() == tileIter->GetTileRect(),
+      MOZ_ASSERT(iterOnWhite->GetTileRect() == bigImgIter->GetTileRect(),
                  "component alpha textures should be the same size.");
     }
 
-    nsIntRect texRect = tileIter ? tileIter->GetTileRect()
+    nsIntRect texRect = bigImgIter ? bigImgIter->GetTileRect()
                                  : nsIntRect(0, 0,
                                              texSize.width,
                                              texSize.height);
 
     // Draw texture. If we're using tiles, we do repeating manually, as texture
     // repeat would cause each individual tile to repeat instead of the
     // compound texture as a whole. This involves drawing at most 4 sections,
     // 2 for each axis that has texture repeat.
@@ -193,39 +193,43 @@ ContentHostBase::Composite(EffectChain& 
                          tileScreenRect.width, tileScreenRect.height);
 
           effect->mTextureCoords = Rect(Float(tileRegionRect.x) / texRect.width,
                                         Float(tileRegionRect.y) / texRect.height,
                                         Float(tileRegionRect.width) / texRect.width,
                                         Float(tileRegionRect.height) / texRect.height);
           GetCompositor()->DrawQuad(rect, aClipRect, aEffectChain, aOpacity, aTransform);
           if (usingTiles) {
-            DiagnosticTypes diagnostics = DIAGNOSTIC_CONTENT | DIAGNOSTIC_BIGIMAGE;
-            diagnostics |= iterOnWhite ? DIAGNOSTIC_COMPONENT_ALPHA : 0;
+            DiagnosticFlags diagnostics = DiagnosticFlags::CONTENT | DiagnosticFlags::BIGIMAGE;
+            if (iterOnWhite) {
+              diagnostics |= DiagnosticFlags::COMPONENT_ALPHA;
+            }
             GetCompositor()->DrawDiagnostics(diagnostics, rect, aClipRect,
                                              aTransform, mFlashCounter);
           }
         }
       }
     }
 
     if (iterOnWhite) {
       iterOnWhite->NextTile();
     }
-  } while (usingTiles && tileIter->NextTile());
+  } while (usingTiles && bigImgIter->NextTile());
 
-  if (tileIter) {
-    tileIter->EndTileIteration();
+  if (bigImgIter) {
+    bigImgIter->EndBigImageIteration();
   }
   if (iterOnWhite) {
-    iterOnWhite->EndTileIteration();
+    iterOnWhite->EndBigImageIteration();
   }
 
-  DiagnosticTypes diagnostics = DIAGNOSTIC_CONTENT;
-  diagnostics |= iterOnWhite ? DIAGNOSTIC_COMPONENT_ALPHA : 0;
+  DiagnosticFlags diagnostics = DiagnosticFlags::CONTENT;
+  if (iterOnWhite) {
+    diagnostics |= DiagnosticFlags::COMPONENT_ALPHA;
+  }
   GetCompositor()->DrawDiagnostics(diagnostics, *aVisibleRegion, aClipRect,
                                    aTransform, mFlashCounter);
 }
 
 
 void
 ContentHostTexture::UseTextureHost(TextureHost* aTexture)
 {
@@ -483,25 +487,25 @@ ContentHostIncremental::TextureCreationR
   RefPtr<DataTextureSource> temp =
     compositor->CreateDataTextureSource(mTextureInfo.mTextureFlags);
   MOZ_ASSERT(temp->AsSourceOGL() &&
              temp->AsSourceOGL()->AsTextureImageTextureSource());
   RefPtr<TextureImageTextureSourceOGL> newSource =
     temp->AsSourceOGL()->AsTextureImageTextureSource();
 
   RefPtr<TextureImageTextureSourceOGL> newSourceOnWhite;
-  if (mTextureInfo.mTextureFlags & TEXTURE_COMPONENT_ALPHA) {
+  if (mTextureInfo.mTextureFlags & TextureFlags::COMPONENT_ALPHA) {
     temp =
       compositor->CreateDataTextureSource(mTextureInfo.mTextureFlags);
     MOZ_ASSERT(temp->AsSourceOGL() &&
                temp->AsSourceOGL()->AsTextureImageTextureSource());
     newSourceOnWhite = temp->AsSourceOGL()->AsTextureImageTextureSource();
   }
 
-  if (mTextureInfo.mDeprecatedTextureHostFlags & TEXTURE_HOST_COPY_PREVIOUS) {
+  if (mTextureInfo.mDeprecatedTextureHostFlags & DeprecatedTextureHostFlags::COPY_PREVIOUS) {
     nsIntRect bufferRect = aHost->mBufferRect;
     nsIntPoint bufferRotation = aHost->mBufferRotation;
     nsIntRect overlap;
 
     // The buffer looks like:
     //  ______
     // |1  |2 |  Where the center point is offset by mBufferRotation from the top-left corner.
     // |___|__|
@@ -641,17 +645,17 @@ ContentHostIncremental::TextureUpdateReq
   NS_ASSERTION(quadrantRect.Contains(drawBounds), "Messed up quadrants");
 
   mUpdated.MoveBy(-nsIntPoint(quadrantRect.x, quadrantRect.y));
 
   IntPoint offset = ToIntPoint(-mUpdated.GetBounds().TopLeft());
 
   RefPtr<DataSourceSurface> surf = GetSurfaceForDescriptor(mDescriptor);
 
-  if (mTextureId == TextureFront) {
+  if (mTextureId == TextureIdentifier::Front) {
     aHost->mSource->Update(surf, &mUpdated, &offset);
   } else {
     aHost->mSourceOnWhite->Update(surf, &mUpdated, &offset);
   }
 }
 
 void
 ContentHostTexture::PrintInfo(nsACString& aTo, const char* aPrefix)
@@ -680,17 +684,17 @@ ContentHostTexture::GetRenderState()
 {
   if (!mTextureHost) {
     return LayerRenderState();
   }
 
   LayerRenderState result = mTextureHost->GetRenderState();
 
   if (mBufferRotation != nsIntPoint()) {
-    result.mFlags |= LAYER_RENDER_STATE_BUFFER_ROTATION;
+    result.mFlags |= LayerRenderStateFlags::BUFFER_ROTATION;
   }
   result.SetOffset(GetOriginOffset());
   return result;
 }
 
 #ifdef MOZ_DUMP_PAINTING
 TemporaryRef<gfx::DataSourceSurface>
 ContentHostTexture::GetAsSurface()
--- a/gfx/layers/composite/ContentHost.h
+++ b/gfx/layers/composite/ContentHost.h
@@ -204,17 +204,17 @@ class ContentHostDoubleBuffered : public
 {
 public:
   ContentHostDoubleBuffered(const TextureInfo& aTextureInfo)
     : ContentHostTexture(aTextureInfo)
   {}
 
   virtual ~ContentHostDoubleBuffered() {}
 
-  virtual CompositableType GetType() { return COMPOSITABLE_CONTENT_DOUBLE; }
+  virtual CompositableType GetType() { return CompositableType::CONTENT_DOUBLE; }
 
   virtual bool UpdateThebes(const ThebesBufferData& aData,
                             const nsIntRegion& aUpdated,
                             const nsIntRegion& aOldValidRegionBack,
                             nsIntRegion* aUpdatedRegionBack);
 
 protected:
   nsIntRegion mValidRegionForNextBackBuffer;
@@ -227,17 +227,17 @@ protected:
 class ContentHostSingleBuffered : public ContentHostTexture
 {
 public:
   ContentHostSingleBuffered(const TextureInfo& aTextureInfo)
     : ContentHostTexture(aTextureInfo)
   {}
   virtual ~ContentHostSingleBuffered() {}
 
-  virtual CompositableType GetType() { return COMPOSITABLE_CONTENT_SINGLE; }
+  virtual CompositableType GetType() { return CompositableType::CONTENT_SINGLE; }
 
   virtual bool UpdateThebes(const ThebesBufferData& aData,
                             const nsIntRegion& aUpdated,
                             const nsIntRegion& aOldValidRegionBack,
                             nsIntRegion* aUpdatedRegionBack);
 };
 
 /**
@@ -251,17 +251,17 @@ public:
  * avoid blocking the main thread.
  */
 class ContentHostIncremental : public ContentHostBase
 {
 public:
   ContentHostIncremental(const TextureInfo& aTextureInfo);
   ~ContentHostIncremental();
 
-  virtual CompositableType GetType() { return BUFFER_CONTENT_INC; }
+  virtual CompositableType GetType() { return CompositableType::BUFFER_CONTENT_INC; }
 
   virtual LayerRenderState GetRenderState() MOZ_OVERRIDE { return LayerRenderState(); }
 
   virtual bool CreatedIncrementalTexture(ISurfaceAllocator* aAllocator,
                                          const TextureInfo& aTextureInfo,
                                          const nsIntRect& aBufferRect) MOZ_OVERRIDE;
 
   virtual void UpdateIncremental(TextureIdentifier aTextureId,
--- a/gfx/layers/composite/ImageHost.cpp
+++ b/gfx/layers/composite/ImageHost.cpp
@@ -104,63 +104,63 @@ ImageHost::Composite(EffectChain& aEffec
                       : gfx::Rect(0, 0, textureSize.width, textureSize.height);
 
   gfx::Rect pictureRect(0, 0,
                         mPictureRect.width,
                         mPictureRect.height);
   //XXX: We might have multiple texture sources here (e.g. 3 YCbCr textures), and we're
   // only iterating over the tiles of the first one. Are we assuming that the tiling
   // will be identical? Can we ensure that somehow?
-  TileIterator* it = source->AsTileIterator();
+  BigImageIterator* it = source->AsBigImageIterator();
   if (it) {
-    it->BeginTileIteration();
+    it->BeginBigImageIteration();
     do {
       nsIntRect tileRect = it->GetTileRect();
       gfx::Rect rect(tileRect.x, tileRect.y, tileRect.width, tileRect.height);
       if (mHasPictureRect) {
         rect = rect.Intersect(pictureRect);
         effect->mTextureCoords = Rect(Float(rect.x - tileRect.x)/ tileRect.width,
                                       Float(rect.y - tileRect.y) / tileRect.height,
                                       Float(rect.width) / tileRect.width,
                                       Float(rect.height) / tileRect.height);
       } else {
         effect->mTextureCoords = Rect(0, 0, 1, 1);
       }
       GetCompositor()->DrawQuad(rect, aClipRect, aEffectChain,
                                 aOpacity, aTransform);
-      GetCompositor()->DrawDiagnostics(DIAGNOSTIC_IMAGE|DIAGNOSTIC_BIGIMAGE,
+      GetCompositor()->DrawDiagnostics(DiagnosticFlags::IMAGE | DiagnosticFlags::BIGIMAGE,
                                        rect, aClipRect, aTransform, mFlashCounter);
     } while (it->NextTile());
-    it->EndTileIteration();
+    it->EndBigImageIteration();
     // layer border
-    GetCompositor()->DrawDiagnostics(DIAGNOSTIC_IMAGE,
+    GetCompositor()->DrawDiagnostics(DiagnosticFlags::IMAGE,
                                      gfxPictureRect, aClipRect,
                                      aTransform, mFlashCounter);
   } else {
     IntSize textureSize = source->GetSize();
     gfx::Rect rect;
     if (mHasPictureRect) {
       effect->mTextureCoords = Rect(Float(mPictureRect.x) / textureSize.width,
                                     Float(mPictureRect.y) / textureSize.height,
                                     Float(mPictureRect.width) / textureSize.width,
                                     Float(mPictureRect.height) / textureSize.height);
       rect = pictureRect;
     } else {
       effect->mTextureCoords = Rect(0, 0, 1, 1);
       rect = gfx::Rect(0, 0, textureSize.width, textureSize.height);
     }
 
-    if (mFrontBuffer->GetFlags() & TEXTURE_NEEDS_Y_FLIP) {
+    if (mFrontBuffer->GetFlags() & TextureFlags::NEEDS_Y_FLIP) {
       effect->mTextureCoords.y = effect->mTextureCoords.YMost();
       effect->mTextureCoords.height = -effect->mTextureCoords.height;
     }
 
     GetCompositor()->DrawQuad(rect, aClipRect, aEffectChain,
                               aOpacity, aTransform);
-    GetCompositor()->DrawDiagnostics(DIAGNOSTIC_IMAGE,
+    GetCompositor()->DrawDiagnostics(DiagnosticFlags::IMAGE,
                                      rect, aClipRect,
                                      aTransform, mFlashCounter);
   }
 }
 
 void
 ImageHost::SetCompositor(Compositor* aCompositor)
 {
--- a/gfx/layers/composite/ImageLayerComposite.cpp
+++ b/gfx/layers/composite/ImageLayerComposite.cpp
@@ -46,19 +46,19 @@ ImageLayerComposite::~ImageLayerComposit
 
   CleanupResources();
 }
 
 bool
 ImageLayerComposite::SetCompositableHost(CompositableHost* aHost)
 {
   switch (aHost->GetType()) {
-    case BUFFER_IMAGE_SINGLE:
-    case BUFFER_IMAGE_BUFFERED:
-    case COMPOSITABLE_IMAGE:
+    case CompositableType::BUFFER_IMAGE_SINGLE:
+    case CompositableType::BUFFER_IMAGE_BUFFERED:
+    case CompositableType::IMAGE:
       mImageHost = aHost;
       return true;
     default:
       return false;
   }
 }
 
 void
--- a/gfx/layers/composite/TextureHost.cpp
+++ b/gfx/layers/composite/TextureHost.cpp
@@ -228,17 +228,17 @@ TextureHost::TextureHost(TextureFlags aF
 {}
 
 TextureHost::~TextureHost()
 {
 }
 
 void TextureHost::Finalize()
 {
-  if (!(GetFlags() & TEXTURE_DEALLOCATE_CLIENT)) {
+  if (!(GetFlags() & TextureFlags::DEALLOCATE_CLIENT)) {
     DeallocateSharedData();
     DeallocateDeviceData();
   }
 }
 
 void
 TextureHost::PrintInfo(nsACString& aTo, const char* aPrefix)
 {
@@ -287,17 +287,17 @@ BufferTextureHost::Updated(const nsIntRe
 {
   ++mUpdateSerial;
   if (aRegion) {
     mPartialUpdate = true;
     mMaybeUpdatedRegion = *aRegion;
   } else {
     mPartialUpdate = false;
   }
-  if (GetFlags() & TEXTURE_IMMEDIATE_UPLOAD) {
+  if (GetFlags() & TextureFlags::IMMEDIATE_UPLOAD) {
     DebugOnly<bool> result = MaybeUpload(mPartialUpdate ? &mMaybeUpdatedRegion : nullptr);
     NS_WARN_IF_FALSE(result, "Failed to upload a texture");
   }
 }
 
 void
 BufferTextureHost::SetCompositor(Compositor* aCompositor)
 {
@@ -350,17 +350,17 @@ BufferTextureHost::GetFormat() const
 {
   // mFormat is the format of the data that we share with the content process.
   // GetFormat, on the other hand, expects the format that we present to the
   // Compositor (it is used to choose the effect type).
   // if the compositor does not support YCbCr effects, we give it a RGBX texture
   // instead (see BufferTextureHost::Upload)
   if (mFormat == gfx::SurfaceFormat::YUV &&
     mCompositor &&
-    !mCompositor->SupportsEffect(EFFECT_YCBCR)) {
+    !mCompositor->SupportsEffect(EffectTypes::YCBCR)) {
     return gfx::SurfaceFormat::R8G8B8X8;
   }
   return mFormat;
 }
 
 bool
 BufferTextureHost::MaybeUpload(nsIntRegion *aRegion)
 {
@@ -392,33 +392,33 @@ BufferTextureHost::Upload(nsIntRegion *a
   }
   if (mFormat == gfx::SurfaceFormat::UNKNOWN) {
     NS_WARNING("BufferTextureHost: unsupported format!");
     return false;
   } else if (mFormat == gfx::SurfaceFormat::YUV) {
     YCbCrImageDataDeserializer yuvDeserializer(GetBuffer(), GetBufferSize());
     MOZ_ASSERT(yuvDeserializer.IsValid());
 
-    if (!mCompositor->SupportsEffect(EFFECT_YCBCR)) {
+    if (!mCompositor->SupportsEffect(EffectTypes::YCBCR)) {
       RefPtr<gfx::DataSourceSurface> surf = yuvDeserializer.ToDataSourceSurface();
       if (!mFirstSource) {
         mFirstSource = mCompositor->CreateDataTextureSource(mFlags);
       }
       mFirstSource->Update(surf, aRegion);
       return true;
     }
 
     RefPtr<DataTextureSource> srcY;
     RefPtr<DataTextureSource> srcU;
     RefPtr<DataTextureSource> srcV;
     if (!mFirstSource) {
       // We don't support BigImages for YCbCr compositing.
-      srcY = mCompositor->CreateDataTextureSource(mFlags|TEXTURE_DISALLOW_BIGIMAGE);
-      srcU = mCompositor->CreateDataTextureSource(mFlags|TEXTURE_DISALLOW_BIGIMAGE);
-      srcV = mCompositor->CreateDataTextureSource(mFlags|TEXTURE_DISALLOW_BIGIMAGE);
+      srcY = mCompositor->CreateDataTextureSource(mFlags|TextureFlags::DISALLOW_BIGIMAGE);
+      srcU = mCompositor->CreateDataTextureSource(mFlags|TextureFlags::DISALLOW_BIGIMAGE);
+      srcV = mCompositor->CreateDataTextureSource(mFlags|TextureFlags::DISALLOW_BIGIMAGE);
       mFirstSource = srcY;
       srcY->SetNextSibling(srcU);
       srcU->SetNextSibling(srcV);
     } else {
       // mFormat never changes so if this was created as a YCbCr host and already
       // contains a source it should already have 3 sources.
       // BufferTextureHost only uses DataTextureSources so it is safe to assume
       // all 3 sources are DataTextureSource.
@@ -564,17 +564,17 @@ MemoryTextureHost::MemoryTextureHost(uin
 , mBuffer(aBuffer)
 {
   MOZ_COUNT_CTOR(MemoryTextureHost);
 }
 
 MemoryTextureHost::~MemoryTextureHost()
 {
   DeallocateDeviceData();
-  NS_ASSERTION(!mBuffer || (mFlags & TEXTURE_DEALLOCATE_CLIENT),
+  NS_ASSERTION(!mBuffer || (mFlags & TextureFlags::DEALLOCATE_CLIENT),
                "Leaking our buffer");
   MOZ_COUNT_DTOR(MemoryTextureHost);
 }
 
 void
 MemoryTextureHost::DeallocateSharedData()
 {
   if (mBuffer) {
@@ -639,17 +639,17 @@ TextureParent::CompositorRecycle()
       // In this case, HWC implicitly handles buffer's fence.
     }
   }
 #endif
   mozilla::unused << SendCompositorRecycle(handle);
 
   // Don't forget to prepare for the next reycle
   // if TextureClient request it.
-  if (mTextureHost->GetFlags() & TEXTURE_RECYCLE) {
+  if (mTextureHost->GetFlags() & TextureFlags::RECYCLE) {
     mWaitForClientRecycle = mTextureHost;
   }
 }
 
 bool
 TextureParent::RecvClientRecycle()
 {
   // This will allow the RecycleCallback to be called once the compositor
@@ -666,17 +666,17 @@ bool
 TextureParent::Init(const SurfaceDescriptor& aSharedData,
                     const TextureFlags& aFlags)
 {
   mTextureHost = TextureHost::Create(aSharedData,
                                      mAllocator,
                                      aFlags);
   if (mTextureHost) {
     mTextureHost->mActor = this;
-    if (aFlags & TEXTURE_RECYCLE) {
+    if (aFlags & TextureFlags::RECYCLE) {
       mWaitForClientRecycle = mTextureHost;
       RECYCLE_LOG("Setup recycling for tile %p\n", this);
     }
   }
 
   return !!mTextureHost;
 }
 
@@ -706,21 +706,21 @@ TextureParent::ActorDestroy(ActorDestroy
   case Deletion:
   case NormalShutdown:
   case AbnormalShutdown:
     break;
   case FailedConstructor:
     NS_RUNTIMEABORT("FailedConstructor isn't possible in PTexture");
   }
 
-  if (mTextureHost->GetFlags() & TEXTURE_RECYCLE) {
+  if (mTextureHost->GetFlags() & TextureFlags::RECYCLE) {
     RECYCLE_LOG("clear recycling for tile %p\n", this);
     mTextureHost->ClearRecycleCallback();
   }
-  if (mTextureHost->GetFlags() & TEXTURE_DEALLOCATE_CLIENT) {
+  if (mTextureHost->GetFlags() & TextureFlags::DEALLOCATE_CLIENT) {
     mTextureHost->ForgetSharedData();
   }
 
   // Clear recycle callback.
   mTextureHost->ClearRecycleCallback();
   mWaitForClientRecycle = nullptr;
 
   mTextureHost->mActor = nullptr;
--- a/gfx/layers/composite/TextureHost.h
+++ b/gfx/layers/composite/TextureHost.h
@@ -55,21 +55,21 @@ class TextureParent;
 /**
  * A view on a TextureHost where the texture is internally represented as tiles
  * (contrast with a tiled buffer, where each texture is a tile). For iteration by
  * the texture's buffer host.
  * This is only useful when the underlying surface is too big to fit in one
  * device texture, which forces us to split it in smaller parts.
  * Tiled Compositable is a different thing.
  */
-class TileIterator
+class BigImageIterator
 {
 public:
-  virtual void BeginTileIteration() = 0;
-  virtual void EndTileIteration() {};
+  virtual void BeginBigImageIteration() = 0;
+  virtual void EndBigImageIteration() {};
   virtual nsIntRect GetTileRect() = 0;
   virtual size_t GetTileCount() = 0;
   virtual bool NextTile() = 0;
 };
 
 /**
  * TextureSource is the interface for texture objects that can be composited
  * by a given compositor backend. Since the drawing APIs are different
@@ -118,17 +118,17 @@ public:
    * TextureSource, that can be split in sub-TextureSources.
    */
   virtual TextureSource* GetSubSource(int index) { return nullptr; }
 
   /**
    * Overload this if the TextureSource supports big textures that don't fit in
    * one device texture and must be tiled internally.
    */
-  virtual TileIterator* AsTileIterator() { return nullptr; }
+  virtual BigImageIterator* AsBigImageIterator() { return nullptr; }
 
   virtual void SetCompositableBackendSpecificData(CompositableBackendSpecificData* aBackendData);
 
 protected:
   RefPtr<CompositableBackendSpecificData> mCompositableBackendData;
 };
 
 /**
--- a/gfx/layers/composite/ThebesLayerComposite.cpp
+++ b/gfx/layers/composite/ThebesLayerComposite.cpp
@@ -49,20 +49,20 @@ ThebesLayerComposite::~ThebesLayerCompos
   MOZ_COUNT_DTOR(ThebesLayerComposite);
   CleanupResources();
 }
 
 bool
 ThebesLayerComposite::SetCompositableHost(CompositableHost* aHost)
 {
   switch (aHost->GetType()) {
-    case BUFFER_CONTENT_INC:
-    case BUFFER_TILED:
-    case COMPOSITABLE_CONTENT_SINGLE:
-    case COMPOSITABLE_CONTENT_DOUBLE:
+    case CompositableType::BUFFER_CONTENT_INC:
+    case CompositableType::BUFFER_TILED:
+    case CompositableType::CONTENT_SINGLE:
+    case CompositableType::CONTENT_DOUBLE:
       mBuffer = static_cast<ContentHost*>(aHost);
       return true;
     default:
       return false;
   }
 }
 
 void
--- a/gfx/layers/composite/TiledContentHost.cpp
+++ b/gfx/layers/composite/TiledContentHost.cpp
@@ -119,17 +119,17 @@ TiledLayerBufferComposite::ReleaseTextur
 }
 
 void
 TiledLayerBufferComposite::Upload()
 {
   if(!IsValid()) {
     return;
   }
-  // The TextureClients were created with the TEXTURE_IMMEDIATE_UPLOAD flag,
+  // The TextureClients were created with the TextureFlags::IMMEDIATE_UPLOAD flag,
   // so calling Update on all the texture hosts will perform the texture upload.
   Update(mValidRegion, mPaintedRegion);
   ClearPaintedRegion();
 }
 
 TileHost
 TiledLayerBufferComposite::ValidateTile(TileHost aTile,
                                         const nsIntPoint& aTileOrigin,
@@ -140,17 +140,17 @@ TiledLayerBufferComposite::ValidateTile(
     return aTile;
   }
 
 #ifdef GFX_TILEDLAYER_PREF_WARNINGS
   printf_stderr("Upload tile %i, %i\n", aTileOrigin.x, aTileOrigin.y);
   long start = PR_IntervalNow();
 #endif
 
-  MOZ_ASSERT(aTile.mTextureHost->GetFlags() & TEXTURE_IMMEDIATE_UPLOAD);
+  MOZ_ASSERT(aTile.mTextureHost->GetFlags() & TextureFlags::IMMEDIATE_UPLOAD);
   // We possibly upload the entire texture contents here. This is a purposeful
   // decision, as sub-image upload can often be slow and/or unreliable, but
   // we may want to reevaluate this in the future.
   // For !HasInternalBuffer() textures, this is likely a no-op.
   aTile.mTextureHost->Updated(nullptr);
 
 #ifdef GFX_TILEDLAYER_PREF_WARNINGS
   if (PR_IntervalNow() - start > 1) {
@@ -375,17 +375,17 @@ TiledContentHost::RenderTile(const TileH
                      rect->width, rect->height);
 
     effect->mTextureCoords = Rect(textureRect.x / aTextureBounds.width,
                                   textureRect.y / aTextureBounds.height,
                                   textureRect.width / aTextureBounds.width,
                                   textureRect.height / aTextureBounds.height);
     mCompositor->DrawQuad(graphicsRect, aClipRect, aEffectChain, aOpacity, aTransform);
   }
-  mCompositor->DrawDiagnostics(DIAGNOSTIC_CONTENT|DIAGNOSTIC_TILE,
+  mCompositor->DrawDiagnostics(DiagnosticFlags::CONTENT | DiagnosticFlags::TILE,
                                aScreenRegion, aClipRect, aTransform, mFlashCounter);
 }
 
 void
 TiledContentHost::RenderLayerBuffer(TiledLayerBufferComposite& aLayerBuffer,
                                     EffectChain& aEffectChain,
                                     float aOpacity,
                                     const gfx::Filter& aFilter,
@@ -466,17 +466,17 @@ TiledContentHost::RenderLayerBuffer(Tile
       tileY++;
       y += h;
     }
     tileX++;
     x += w;
   }
   gfx::Rect rect(visibleRect.x, visibleRect.y,
                  visibleRect.width, visibleRect.height);
-  GetCompositor()->DrawDiagnostics(DIAGNOSTIC_CONTENT,
+  GetCompositor()->DrawDiagnostics(DiagnosticFlags::CONTENT,
                                    rect, aClipRect, aTransform, mFlashCounter);
 }
 
 void
 TiledContentHost::PrintInfo(nsACString& aTo, const char* aPrefix)
 {
   aTo += aPrefix;
   aTo += nsPrintfCString("TiledContentHost (0x%p)", this);
--- a/gfx/layers/composite/TiledContentHost.h
+++ b/gfx/layers/composite/TiledContentHost.h
@@ -214,17 +214,17 @@ public:
   void Composite(EffectChain& aEffectChain,
                  float aOpacity,
                  const gfx::Matrix4x4& aTransform,
                  const gfx::Filter& aFilter,
                  const gfx::Rect& aClipRect,
                  const nsIntRegion* aVisibleRegion = nullptr,
                  TiledLayerProperties* aLayerProperties = nullptr);
 
-  virtual CompositableType GetType() { return BUFFER_TILED; }
+  virtual CompositableType GetType() { return CompositableType::BUFFER_TILED; }
 
   virtual TiledLayerComposer* AsTiledLayerComposer() MOZ_OVERRIDE { return this; }
 
   virtual void Attach(Layer* aLayer,
                       Compositor* aCompositor,
                       AttachFlags aFlags = NO_FLAGS) MOZ_OVERRIDE;
 
 #ifdef MOZ_DUMP_PAINTING
--- a/gfx/layers/composite/X11TextureHost.cpp
+++ b/gfx/layers/composite/X11TextureHost.cpp
@@ -20,17 +20,17 @@ using namespace mozilla::gfx;
 X11TextureHost::X11TextureHost(TextureFlags aFlags,
                                const SurfaceDescriptorX11& aDescriptor)
  : TextureHost(aFlags)
 {
   nsRefPtr<gfxXlibSurface> surface = aDescriptor.OpenForeign();
   mSurface = surface.get();
 
   // The host always frees the pixmap.
-  MOZ_ASSERT(!(aFlags & TEXTURE_DEALLOCATE_CLIENT));
+  MOZ_ASSERT(!(aFlags & TextureFlags::DEALLOCATE_CLIENT));
   mSurface->TakePixmap();
 }
 
 bool
 X11TextureHost::Lock()
 {
   if (!mCompositor) {
     return false;
--- a/gfx/layers/d3d11/CompositorD3D11.cpp
+++ b/gfx/layers/d3d11/CompositorD3D11.cpp
@@ -11,16 +11,18 @@
 #include "gfxWindowsPlatform.h"
 #include "nsIWidget.h"
 #include "mozilla/layers/ImageHost.h"
 #include "mozilla/layers/ContentHost.h"
 #include "mozilla/layers/Effects.h"
 #include "nsWindowsHelpers.h"
 #include "gfxPrefs.h"
 
+#include "mozilla/EnumeratedArray.h"
+
 #ifdef MOZ_METRO
 #include <DXGI1_2.h>
 #endif
 
 namespace mozilla {
 
 using namespace gfx;
 
@@ -37,24 +39,30 @@ static const GUID sDeviceAttachmentsD3D1
 // {88041664-C835-4AA8-ACB8-7EC832357ED8}
 static const GUID sLayerManagerCount =
 { 0x88041664, 0xc835, 0x4aa8, { 0xac, 0xb8, 0x7e, 0xc8, 0x32, 0x35, 0x7e, 0xd8 } };
 
 const FLOAT sBlendFactor[] = { 0, 0, 0, 0 };
 
 struct DeviceAttachmentsD3D11
 {
+  typedef EnumeratedArray<MaskType, MaskType::NumMaskTypes, RefPtr<ID3D11VertexShader>>
+          VertexShaderArray;
+  typedef EnumeratedArray<MaskType, MaskType::NumMaskTypes, RefPtr<ID3D11PixelShader>>
+          PixelShaderArray;
+
   RefPtr<ID3D11InputLayout> mInputLayout;
   RefPtr<ID3D11Buffer> mVertexBuffer;
-  RefPtr<ID3D11VertexShader> mVSQuadShader[3];
-  RefPtr<ID3D11PixelShader> mSolidColorShader[2];
-  RefPtr<ID3D11PixelShader> mRGBAShader[3];
-  RefPtr<ID3D11PixelShader> mRGBShader[2];
-  RefPtr<ID3D11PixelShader> mYCbCrShader[2];
-  RefPtr<ID3D11PixelShader> mComponentAlphaShader[2];
+
+  VertexShaderArray mVSQuadShader;
+  PixelShaderArray mSolidColorShader;
+  PixelShaderArray mRGBAShader;
+  PixelShaderArray mRGBShader;
+  PixelShaderArray mYCbCrShader;
+  PixelShaderArray mComponentAlphaShader;
   RefPtr<ID3D11Buffer> mPSConstantBuffer;
   RefPtr<ID3D11Buffer> mVSConstantBuffer;
   RefPtr<ID3D11RasterizerState> mRasterizerState;
   RefPtr<ID3D11SamplerState> mLinearSamplerState;
   RefPtr<ID3D11SamplerState> mPointSamplerState;
   RefPtr<ID3D11BlendState> mPremulBlendState;
   RefPtr<ID3D11BlendState> mNonPremulBlendState;
   RefPtr<ID3D11BlendState> mComponentBlendState;
@@ -473,31 +481,31 @@ CompositorD3D11::SetRenderTarget(Composi
   mContext->OMSetRenderTargets(1, &view, nullptr);
   PrepareViewport(newRT->GetSize(), gfx::Matrix());
 }
 
 void
 CompositorD3D11::SetPSForEffect(Effect* aEffect, MaskType aMaskType, gfx::SurfaceFormat aFormat)
 {
   switch (aEffect->mType) {
-  case EFFECT_SOLID_COLOR:
+  case EffectTypes::SOLID_COLOR:
     mContext->PSSetShader(mAttachments->mSolidColorShader[aMaskType], nullptr, 0);
     return;
-  case EFFECT_RENDER_TARGET:
+  case EffectTypes::RENDER_TARGET:
     mContext->PSSetShader(mAttachments->mRGBAShader[aMaskType], nullptr, 0);
     return;
-  case EFFECT_RGB:
+  case EffectTypes::RGB:
     mContext->PSSetShader((aFormat == SurfaceFormat::B8G8R8A8 || aFormat == SurfaceFormat::R8G8B8A8)
                           ? mAttachments->mRGBAShader[aMaskType]
                           : mAttachments->mRGBShader[aMaskType], nullptr, 0);
     return;
-  case EFFECT_YCBCR:
+  case EffectTypes::YCBCR:
     mContext->PSSetShader(mAttachments->mYCbCrShader[aMaskType], nullptr, 0);
     return;
-  case EFFECT_COMPONENT_ALPHA:
+  case EffectTypes::COMPONENT_ALPHA:
     mContext->PSSetShader(mAttachments->mComponentAlphaShader[aMaskType], nullptr, 0);
     return;
   default:
     NS_WARNING("No shader to load");
     return;
   }
 }
 
@@ -516,19 +524,19 @@ CompositorD3D11::ClearRect(const gfx::Re
 
   D3D11_RECT scissor;
   scissor.left = aRect.x;
   scissor.right = aRect.XMost();
   scissor.top = aRect.y;
   scissor.bottom = aRect.YMost();
   mContext->RSSetScissorRects(1, &scissor);
   mContext->IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_TRIANGLESTRIP);
-  mContext->VSSetShader(mAttachments->mVSQuadShader[MaskNone], nullptr, 0);
+  mContext->VSSetShader(mAttachments->mVSQuadShader[MaskType::MaskNone], nullptr, 0);
 
-  mContext->PSSetShader(mAttachments->mSolidColorShader[MaskNone], nullptr, 0);
+  mContext->PSSetShader(mAttachments->mSolidColorShader[MaskType::MaskNone], nullptr, 0);
   mPSConstants.layerColor[0] = 0;
   mPSConstants.layerColor[1] = 0;
   mPSConstants.layerColor[2] = 0;
   mPSConstants.layerColor[3] = 0;
 
   UpdateConstantBuffers();
 
   mContext->Draw(4, 0);
@@ -549,28 +557,28 @@ CompositorD3D11::DrawQuad(const gfx::Rec
   mVSConstants.renderTargetOffset[0] = origin.x;
   mVSConstants.renderTargetOffset[1] = origin.y;
   mVSConstants.layerQuad = aRect;
 
   mPSConstants.layerOpacity[0] = aOpacity;
 
   bool restoreBlendMode = false;
 
-  MaskType maskType = MaskNone;
+  MaskType maskType = MaskType::MaskNone;
 
-  if (aEffectChain.mSecondaryEffects[EFFECT_MASK]) {
+  if (aEffectChain.mSecondaryEffects[EffectTypes::MASK]) {
     if (aTransform.Is2D()) {
-      maskType = Mask2d;
+      maskType = MaskType::Mask2d;
     } else {
-      MOZ_ASSERT(aEffectChain.mPrimaryEffect->mType == EFFECT_RGB);
-      maskType = Mask3d;
+      MOZ_ASSERT(aEffectChain.mPrimaryEffect->mType == EffectTypes::RGB);
+      maskType = MaskType::Mask3d;
     }
 
     EffectMask* maskEffect =
-      static_cast<EffectMask*>(aEffectChain.mSecondaryEffects[EFFECT_MASK].get());
+      static_cast<EffectMask*>(aEffectChain.mSecondaryEffects[EffectTypes::MASK].get());
     TextureSourceD3D11* source = maskEffect->mMaskTexture->AsSourceD3D11();
 
     if (!source) {
       NS_WARNING("Missing texture source!");
       return;
     }
 
     RefPtr<ID3D11ShaderResourceView> view;
@@ -593,29 +601,29 @@ CompositorD3D11::DrawQuad(const gfx::Rec
   scissor.top = aClipRect.y;
   scissor.bottom = aClipRect.YMost();
   mContext->RSSetScissorRects(1, &scissor);
   mContext->IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_TRIANGLESTRIP);
   mContext->VSSetShader(mAttachments->mVSQuadShader[maskType], nullptr, 0);
 
 
   switch (aEffectChain.mPrimaryEffect->mType) {
-  case EFFECT_SOLID_COLOR: {
+  case EffectTypes::SOLID_COLOR: {
       SetPSForEffect(aEffectChain.mPrimaryEffect, maskType, SurfaceFormat::UNKNOWN);
 
       Color color =
         static_cast<EffectSolidColor*>(aEffectChain.mPrimaryEffect.get())->mColor;
       mPSConstants.layerColor[0] = color.r * color.a * aOpacity;
       mPSConstants.layerColor[1] = color.g * color.a * aOpacity;
       mPSConstants.layerColor[2] = color.b * color.a * aOpacity;
       mPSConstants.layerColor[3] = color.a * aOpacity;
     }
     break;
-  case EFFECT_RGB:
-  case EFFECT_RENDER_TARGET:
+  case EffectTypes::RGB:
+  case EffectTypes::RENDER_TARGET:
     {
       TexturedEffect* texturedEffect =
         static_cast<TexturedEffect*>(aEffectChain.mPrimaryEffect.get());
 
       mVSConstants.textureCoords = texturedEffect->mTextureCoords;
 
       TextureSourceD3D11* source = texturedEffect->mTexture->AsSourceD3D11();
 
@@ -635,17 +643,17 @@ CompositorD3D11::DrawQuad(const gfx::Rec
       if (!texturedEffect->mPremultiplied) {
         mContext->OMSetBlendState(mAttachments->mNonPremulBlendState, sBlendFactor, 0xFFFFFFFF);
         restoreBlendMode = true;
       }
 
       SetSamplerForFilter(texturedEffect->mFilter);
     }
     break;
-  case EFFECT_YCBCR: {
+  case EffectTypes::YCBCR: {
       EffectYCbCr* ycbcrEffect =
         static_cast<EffectYCbCr*>(aEffectChain.mPrimaryEffect.get());
 
       SetSamplerForFilter(Filter::LINEAR);
 
       mVSConstants.textureCoords = ycbcrEffect->mTextureCoords;
 
       const int Y = 0, Cb = 1, Cr = 2;
@@ -675,17 +683,17 @@ CompositorD3D11::DrawQuad(const gfx::Rec
                                         nullptr, byRef(views[1]));
       mDevice->CreateShaderResourceView(sourceCr->GetD3D11Texture(),
                                         nullptr, byRef(views[2]));
 
       ID3D11ShaderResourceView* srViews[3] = { views[0], views[1], views[2] };
       mContext->PSSetShaderResources(0, 3, srViews);
     }
     break;
-  case EFFECT_COMPONENT_ALPHA:
+  case EffectTypes::COMPONENT_ALPHA:
     {
       MOZ_ASSERT(gfxPrefs::ComponentAlphaEnabled());
       MOZ_ASSERT(mAttachments->mComponentBlendState);
       EffectComponentAlpha* effectComponentAlpha =
         static_cast<EffectComponentAlpha*>(aEffectChain.mPrimaryEffect.get());
 
       TextureSourceD3D11* sourceOnWhite = effectComponentAlpha->mOnWhite->AsSourceD3D11();
       TextureSourceD3D11* sourceOnBlack = effectComponentAlpha->mOnBlack->AsSourceD3D11();
@@ -895,42 +903,42 @@ CompositorD3D11::UpdateRenderTarget()
 bool
 CompositorD3D11::CreateShaders()
 {
   HRESULT hr;
 
   hr = mDevice->CreateVertexShader(LayerQuadVS,
                                    sizeof(LayerQuadVS),
                                    nullptr,
-                                   byRef(mAttachments->mVSQuadShader[MaskNone]));
+                                   byRef(mAttachments->mVSQuadShader[MaskType::MaskNone]));
   if (FAILED(hr)) {
     return false;
   }
 
   hr = mDevice->CreateVertexShader(LayerQuadMaskVS,
                                    sizeof(LayerQuadMaskVS),
                                    nullptr,
-                                   byRef(mAttachments->mVSQuadShader[Mask2d]));
+                                   byRef(mAttachments->mVSQuadShader[MaskType::Mask2d]));
   if (FAILED(hr)) {
     return false;
   }
 
   hr = mDevice->CreateVertexShader(LayerQuadMask3DVS,
                                    sizeof(LayerQuadMask3DVS),
                                    nullptr,
-                                   byRef(mAttachments->mVSQuadShader[Mask3d]));
+                                   byRef(mAttachments->mVSQuadShader[MaskType::Mask3d]));
   if (FAILED(hr)) {
     return false;
   }
 
-#define LOAD_PIXEL_SHADER(x) hr = mDevice->CreatePixelShader(x, sizeof(x), nullptr, byRef(mAttachments->m##x[MaskNone])); \
+#define LOAD_PIXEL_SHADER(x) hr = mDevice->CreatePixelShader(x, sizeof(x), nullptr, byRef(mAttachments->m##x[MaskType::MaskNone])); \
   if (FAILED(hr)) { \
     return false; \
   } \
-  hr = mDevice->CreatePixelShader(x##Mask, sizeof(x##Mask), nullptr, byRef(mAttachments->m##x[Mask2d])); \
+  hr = mDevice->CreatePixelShader(x##Mask, sizeof(x##Mask), nullptr, byRef(mAttachments->m##x[MaskType::Mask2d])); \
   if (FAILED(hr)) { \
     return false; \
   }
 
   LOAD_PIXEL_SHADER(SolidColorShader);
   LOAD_PIXEL_SHADER(RGBShader);
   LOAD_PIXEL_SHADER(RGBAShader);
   LOAD_PIXEL_SHADER(YCbCrShader);
@@ -938,17 +946,17 @@ CompositorD3D11::CreateShaders()
     LOAD_PIXEL_SHADER(ComponentAlphaShader);
   }
 
 #undef LOAD_PIXEL_SHADER
 
   hr = mDevice->CreatePixelShader(RGBAShaderMask3D,
                                   sizeof(RGBAShaderMask3D),
                                   nullptr,
-                                  byRef(mAttachments->mRGBAShader[Mask3d]));
+                                  byRef(mAttachments->mRGBAShader[MaskType::Mask3d]));
   if (FAILED(hr)) {
     return false;
   }
 
   return true;
 }
 
 void
--- a/gfx/layers/d3d11/CompositorD3D11.h
+++ b/gfx/layers/d3d11/CompositorD3D11.h
@@ -45,17 +45,17 @@ public:
 
   virtual bool Initialize() MOZ_OVERRIDE;
   virtual void Destroy() MOZ_OVERRIDE {}
 
   virtual TextureFactoryIdentifier
     GetTextureFactoryIdentifier() MOZ_OVERRIDE;
 
   virtual TemporaryRef<DataTextureSource>
-    CreateDataTextureSource(TextureFlags aFlags = 0) MOZ_OVERRIDE;
+    CreateDataTextureSource(TextureFlags aFlags = TextureFlags::NO_FLAGS) MOZ_OVERRIDE;
 
   virtual bool CanUseCanvasLayerForSize(const gfx::IntSize& aSize) MOZ_OVERRIDE;
   virtual int32_t GetMaxTextureSize() const MOZ_FINAL;
 
   virtual void SetTargetContext(gfx::DrawTarget* aTarget)  MOZ_OVERRIDE
   {
     mTarget = aTarget;
   }
--- a/gfx/layers/d3d11/TextureD3D11.cpp
+++ b/gfx/layers/d3d11/TextureD3D11.cpp
@@ -72,17 +72,17 @@ DataTextureSourceD3D11::DataTextureSourc
   MOZ_COUNT_CTOR(DataTextureSourceD3D11);
 }
 
 DataTextureSourceD3D11::DataTextureSourceD3D11(SurfaceFormat aFormat,
                                                CompositorD3D11* aCompositor,
                                                ID3D11Texture2D* aTexture)
 : mCompositor(aCompositor)
 , mFormat(aFormat)
-, mFlags(0)
+, mFlags(TextureFlags::NO_FLAGS)
 , mCurrentTile(0)
 , mIsTiled(false)
 , mIterating(false)
 {
   MOZ_COUNT_CTOR(DataTextureSourceD3D11);
 
   mTexture = aTexture;
   D3D11_TEXTURE2D_DESC desc;
@@ -356,17 +356,17 @@ DataTextureSourceD3D11::Update(DataSourc
   mFormat = aSurface->GetFormat();
 
   CD3D11_TEXTURE2D_DESC desc(dxgiFormat, mSize.width, mSize.height,
                              1, 1, D3D11_BIND_SHADER_RESOURCE,
                              D3D11_USAGE_IMMUTABLE);
 
   int32_t maxSize = mCompositor->GetMaxTextureSize();
   if ((mSize.width <= maxSize && mSize.height <= maxSize) ||
-      (mFlags & TEXTURE_DISALLOW_BIGIMAGE)) {
+      (mFlags & TextureFlags::DISALLOW_BIGIMAGE)) {
     D3D11_SUBRESOURCE_DATA initData;
     initData.pSysMem = aSurface->GetData();
     initData.SysMemPitch = aSurface->Stride();
 
     mCompositor->GetDevice()->CreateTexture2D(&desc, &initData, byRef(mTexture));
     mIsTiled = false;
     if (!mTexture) {
       Reset();
--- a/gfx/layers/d3d11/TextureD3D11.h
+++ b/gfx/layers/d3d11/TextureD3D11.h
@@ -91,17 +91,17 @@ protected:
 
 /**
  * A TextureSource that implements the DataTextureSource interface.
  * it can be used without a TextureHost and is able to upload texture data
  * from a gfx::DataSourceSurface.
  */
 class DataTextureSourceD3D11 : public DataTextureSource
                              , public TextureSourceD3D11
-                             , public TileIterator
+                             , public BigImageIterator
 {
 public:
   DataTextureSourceD3D11(gfx::SurfaceFormat aFormat, CompositorD3D11* aCompositor,
                          TextureFlags aFlags);
 
   DataTextureSourceD3D11(gfx::SurfaceFormat aFormat, CompositorD3D11* aCompositor,
                          ID3D11Texture2D* aTexture);
 
@@ -125,29 +125,29 @@ public:
   virtual void DeallocateDeviceData() MOZ_OVERRIDE { mTexture = nullptr; }
 
   virtual gfx::IntSize GetSize() const  MOZ_OVERRIDE { return mSize; }
 
   virtual gfx::SurfaceFormat GetFormat() const MOZ_OVERRIDE { return mFormat; }
 
   virtual void SetCompositor(Compositor* aCompositor) MOZ_OVERRIDE;
 
-  // TileIterator
+  // BigImageIterator
 
-  virtual TileIterator* AsTileIterator() MOZ_OVERRIDE { return mIsTiled ? this : nullptr; }
+  virtual BigImageIterator* AsBigImageIterator() MOZ_OVERRIDE { return mIsTiled ? this : nullptr; }
 
   virtual size_t GetTileCount() MOZ_OVERRIDE { return mTileTextures.size(); }
 
   virtual bool NextTile() MOZ_OVERRIDE { return (++mCurrentTile < mTileTextures.size()); }
 
   virtual nsIntRect GetTileRect() MOZ_OVERRIDE;
 
-  virtual void EndTileIteration() MOZ_OVERRIDE { mIterating = false; }
+  virtual void EndBigImageIteration() MOZ_OVERRIDE { mIterating = false; }
 
-  virtual void BeginTileIteration() MOZ_OVERRIDE
+  virtual void BeginBigImageIteration() MOZ_OVERRIDE
   {
     mIterating = true;
     mCurrentTile = 0;
   }
 
 protected:
   gfx::IntRect GetTileRect(uint32_t aIndex) const;
 
--- a/gfx/layers/d3d9/CompositorD3D9.cpp
+++ b/gfx/layers/d3d9/CompositorD3D9.cpp
@@ -190,25 +190,25 @@ CompositorD3D9::SetRenderTarget(Composit
   mCurrentRT->BindRenderTarget(device());
   PrepareViewport(mCurrentRT->GetSize(), Matrix());
 }
 
 static DeviceManagerD3D9::ShaderMode
 ShaderModeForEffectType(EffectTypes aEffectType, gfx::SurfaceFormat aFormat)
 {
   switch (aEffectType) {
-  case EFFECT_SOLID_COLOR:
+  case EffectTypes::SOLID_COLOR:
     return DeviceManagerD3D9::SOLIDCOLORLAYER;
-  case EFFECT_RENDER_TARGET:
+  case EffectTypes::RENDER_TARGET:
     return DeviceManagerD3D9::RGBALAYER;
-  case EFFECT_RGB:
+  case EffectTypes::RGB:
     if (aFormat == SurfaceFormat::B8G8R8A8 || aFormat == SurfaceFormat::R8G8B8A8)
       return DeviceManagerD3D9::RGBALAYER;
     return DeviceManagerD3D9::RGBLAYER;
-  case EFFECT_YCBCR:
+  case EffectTypes::YCBCR:
     return DeviceManagerD3D9::YCBCRLAYER;
   }
 
   MOZ_CRASH("Bad effect type");
 }
 
 void
 CompositorD3D9::ClearRect(const gfx::Rect& aRect)
@@ -248,66 +248,66 @@ CompositorD3D9::DrawQuad(const gfx::Rect
   d3d9Device->SetVertexShaderConstantF(CBvLayerQuad,
                                        ShaderConstantRect(aRect.x,
                                                           aRect.y,
                                                           aRect.width,
                                                           aRect.height),
                                        1);
   bool target = false;
 
-  if (aEffectChain.mPrimaryEffect->mType != EFFECT_SOLID_COLOR) {
+  if (aEffectChain.mPrimaryEffect->mType != EffectTypes::SOLID_COLOR) {
     float opacity[4];
     /*
      * We always upload a 4 component float, but the shader will use only the
      * first component since it's declared as a 'float'.
      */
     opacity[0] = aOpacity;
     d3d9Device->SetPixelShaderConstantF(CBfLayerOpacity, opacity, 1);
   }
 
   bool isPremultiplied = true;
 
-  MaskType maskType = MaskNone;
+  MaskType maskType = MaskType::MaskNone;
 
-  if (aEffectChain.mSecondaryEffects[EFFECT_MASK]) {
+  if (aEffectChain.mSecondaryEffects[EffectTypes::MASK]) {
     if (aTransform.Is2D()) {
-      maskType = Mask2d;
+      maskType = MaskType::Mask2d;
     } else {
-      maskType = Mask3d;
+      maskType = MaskType::Mask3d;
     }
   }
 
   RECT scissor;
   scissor.left = aClipRect.x;
   scissor.right = aClipRect.XMost();
   scissor.top = aClipRect.y;
   scissor.bottom = aClipRect.YMost();
   d3d9Device->SetScissorRect(&scissor);
 
   uint32_t maskTexture = 0;
   switch (aEffectChain.mPrimaryEffect->mType) {
-  case EFFECT_SOLID_COLOR:
+  case EffectTypes::SOLID_COLOR:
     {
       // output color is premultiplied, so we need to adjust all channels.
       Color layerColor =
         static_cast<EffectSolidColor*>(aEffectChain.mPrimaryEffect.get())->mColor;
       float color[4];
       color[0] = layerColor.r * layerColor.a * aOpacity;
       color[1] = layerColor.g * layerColor.a * aOpacity;
       color[2] = layerColor.b * layerColor.a * aOpacity;
       color[3] = layerColor.a * aOpacity;
 
       d3d9Device->SetPixelShaderConstantF(CBvColor, color, 1);
 
       maskTexture = mDeviceManager
         ->SetShaderMode(DeviceManagerD3D9::SOLIDCOLORLAYER, maskType);
     }
     break;
-  case EFFECT_RENDER_TARGET:
-  case EFFECT_RGB:
+  case EffectTypes::RENDER_TARGET:
+  case EffectTypes::RGB:
     {
       TexturedEffect* texturedEffect =
         static_cast<TexturedEffect*>(aEffectChain.mPrimaryEffect.get());
 
       Rect textureCoords = texturedEffect->mTextureCoords;
       d3d9Device->SetVertexShaderConstantF(CBvTextureCoords,
                                            ShaderConstantRect(
                                              textureCoords.x,
@@ -324,17 +324,17 @@ CompositorD3D9::DrawQuad(const gfx::Rect
       maskTexture = mDeviceManager
         ->SetShaderMode(ShaderModeForEffectType(aEffectChain.mPrimaryEffect->mType,
                                                 texturedEffect->mTexture->GetFormat()),
                         maskType);
 
       isPremultiplied = texturedEffect->mPremultiplied;
     }
     break;
-  case EFFECT_YCBCR:
+  case EffectTypes::YCBCR:
     {
       EffectYCbCr* ycbcrEffect =
         static_cast<EffectYCbCr*>(aEffectChain.mPrimaryEffect.get());
 
       SetSamplerForFilter(Filter::LINEAR);
 
       Rect textureCoords = ycbcrEffect->mTextureCoords;
       d3d9Device->SetVertexShaderConstantF(CBvTextureCoords,
@@ -410,17 +410,17 @@ CompositorD3D9::DrawQuad(const gfx::Rect
       // presumably even with point filtering we'll still want chroma upsampling
       // to be linear. In the current approach we can't.
       device()->SetTexture(Y, sourceY->GetD3D9Texture());
       device()->SetTexture(Cb, sourceCb->GetD3D9Texture());
       device()->SetTexture(Cr, sourceCr->GetD3D9Texture());
       maskTexture = mDeviceManager->SetShaderMode(DeviceManagerD3D9::YCBCRLAYER, maskType);
     }
     break;
-  case EFFECT_COMPONENT_ALPHA:
+  case EffectTypes::COMPONENT_ALPHA:
     {
       MOZ_ASSERT(gfxPrefs::ComponentAlphaEnabled());
       EffectComponentAlpha* effectComponentAlpha =
         static_cast<EffectComponentAlpha*>(aEffectChain.mPrimaryEffect.get());
       TextureSourceD3D9* sourceOnWhite = effectComponentAlpha->mOnWhite->AsSourceD3D9();
       TextureSourceD3D9* sourceOnBlack = effectComponentAlpha->mOnBlack->AsSourceD3D9();
 
       Rect textureCoords = effectComponentAlpha->mTextureCoords;
@@ -471,17 +471,17 @@ CompositorD3D9::DrawQuad(const gfx::Rect
     d3d9Device->SetRenderState(D3DRS_SRCBLEND, D3DBLEND_ONE);
   }
 }
 
 void
 CompositorD3D9::SetMask(const EffectChain &aEffectChain, uint32_t aMaskTexture)
 {
   EffectMask *maskEffect =
-    static_cast<EffectMask*>(aEffectChain.mSecondaryEffects[EFFECT_MASK].get());
+    static_cast<EffectMask*>(aEffectChain.mSecondaryEffects[EffectTypes::MASK].get());
   if (!maskEffect) {
     return;
   }
 
   TextureSourceD3D9 *source = maskEffect->mMaskTexture->AsSourceD3D9();
 
   MOZ_ASSERT(aMaskTexture >= 0);
   device()->SetTexture(aMaskTexture, source->GetD3D9Texture());
--- a/gfx/layers/d3d9/CompositorD3D9.h
+++ b/gfx/layers/d3d9/CompositorD3D9.h
@@ -118,17 +118,17 @@ public:
   {
     if (aOffset.x || aOffset.y) {
       NS_RUNTIMEABORT("SetScreenRenderOffset not supported by CompositorD3D9.");
     }
     // If the offset is 0, 0 that's okay.
   }
 
   virtual TemporaryRef<DataTextureSource>
-    CreateDataTextureSource(TextureFlags aFlags = 0) MOZ_OVERRIDE;
+    CreateDataTextureSource(TextureFlags aFlags = TextureFlags::NO_FLAGS) MOZ_OVERRIDE;
 private:
   // ensure mSize is up to date with respect to mWidget
   void EnsureSize();
   void SetSamplerForFilter(gfx::Filter aFilter);
   void PaintToTarget();
   void SetMask(const EffectChain &aEffectChain, uint32_t aMaskTexture);
   /**
    * Ensure we have a swap chain and it is ready for rendering.
--- a/gfx/layers/d3d9/DeviceManagerD3D9.cpp
+++ b/gfx/layers/d3d9/DeviceManagerD3D9.cpp
@@ -564,17 +564,17 @@ LoadMaskTexture(Layer* aMask, IDirect3DD
 
   aDevice->SetTexture(aMaskTexRegister, texture);
   return true;
 }
 
 uint32_t
 DeviceManagerD3D9::SetShaderMode(ShaderMode aMode, MaskType aMaskType)
 {
-  if (aMaskType == MaskNone) {
+  if (aMaskType == MaskType::MaskNone) {
     switch (aMode) {
       case RGBLAYER:
         mDevice->SetVertexShader(mLayerVS);
         mDevice->SetPixelShader(mRGBPS);
         break;
       case RGBALAYER:
         mDevice->SetVertexShader(mLayerVS);
         mDevice->SetPixelShader(mRGBAPS);
@@ -602,17 +602,17 @@ DeviceManagerD3D9::SetShaderMode(ShaderM
   uint32_t maskTexRegister;
   switch (aMode) {
     case RGBLAYER:
       mDevice->SetVertexShader(mLayerVSMask);
       mDevice->SetPixelShader(mRGBPSMask);
       maskTexRegister = 1;
       break;
     case RGBALAYER:
-      if (aMaskType == Mask2d) {
+      if (aMaskType == MaskType::Mask2d) {
         mDevice->SetVertexShader(mLayerVSMask);
         mDevice->SetPixelShader(mRGBAPSMask);
       } else {
         mDevice->SetVertexShader(mLayerVSMask3D);
         mDevice->SetPixelShader(mRGBAPSMask3D);
       }
       maskTexRegister = 1;
       break;
@@ -638,28 +638,28 @@ DeviceManagerD3D9::SetShaderMode(ShaderM
       break;
   }
   return maskTexRegister;
 }
 
 void
 DeviceManagerD3D9::SetShaderMode(ShaderMode aMode, Layer* aMask, bool aIs2D)
 {
-  MaskType maskType = MaskNone;
+  MaskType maskType = MaskType::MaskNone;
   if (aMask) {
-    maskType = aIs2D ? Mask2d : Mask3d;
+    maskType = aIs2D ? MaskType::Mask2d : MaskType::Mask3d;
   }
   uint32_t maskTexRegister = SetShaderMode(aMode, maskType);
   if (aMask) {
     // register allocations are taken from LayerManagerD3D9Shaders.h after
     // the shaders are compiled (genshaders.sh)
     if (!LoadMaskTexture(aMask, mDevice, maskTexRegister)) {
       // if we can't load the mask, fall back to unmasked rendering
       NS_WARNING("Could not load texture for mask layer.");
-      SetShaderMode(aMode, MaskNone);
+      SetShaderMode(aMode, MaskType::MaskNone);
     }
   }
 }
 
 void
 DeviceManagerD3D9::DestroyDevice()
 {
   ++mDeviceResetCount;
--- a/gfx/layers/d3d9/TextureD3D9.cpp
+++ b/gfx/layers/d3d9/TextureD3D9.cpp
@@ -407,17 +407,17 @@ DataTextureSourceD3D9::Update(gfx::DataS
   default:
     NS_WARNING("Bad image format");
     return false;
   }
 
   int32_t maxSize = mCompositor->GetMaxTextureSize();
   DeviceManagerD3D9* deviceManager = gfxWindowsPlatform::GetPlatform()->GetD3D9DeviceManager();
   if ((mSize.width <= maxSize && mSize.height <= maxSize) ||
-      (mFlags & TEXTURE_DISALLOW_BIGIMAGE)) {
+      (mFlags & TextureFlags::DISALLOW_BIGIMAGE)) {
     mTexture = DataToTexture(deviceManager,
                              aSurface->GetData(), aSurface->Stride(),
                              IntSize(mSize), format, bpp);
     if (!mTexture) {
       NS_WARNING("Could not upload texture");
       Reset();
       return false;
     }
@@ -482,17 +482,17 @@ DataTextureSourceD3D9::Update(gfxWindows
   default:
     NS_WARNING("Bad image format");
     return false;
   }
 
   int32_t maxSize = mCompositor->GetMaxTextureSize();
   DeviceManagerD3D9* deviceManager = gfxWindowsPlatform::GetPlatform()->GetD3D9DeviceManager();
   if ((mSize.width <= maxSize && mSize.height <= maxSize) ||
-      (mFlags & TEXTURE_DISALLOW_BIGIMAGE)) {
+      (mFlags & TextureFlags::DISALLOW_BIGIMAGE)) {
     mTexture = SurfaceToTexture(deviceManager, aSurface, mSize, format);
 
     if (!mTexture) {
       NS_WARNING("Could not upload texture");
       Reset();
       return false;
     }
     mIsTiled = false;
--- a/gfx/layers/d3d9/TextureD3D9.h
+++ b/gfx/layers/d3d9/TextureD3D9.h
@@ -96,29 +96,29 @@ protected:
 
 /**
  * A TextureSource that implements the DataTextureSource interface.
  * it can be used without a TextureHost and is able to upload texture data
  * from a gfx::DataSourceSurface.
  */
 class DataTextureSourceD3D9 : public DataTextureSource
                             , public TextureSourceD3D9
-                            , public TileIterator
+                            , public BigImageIterator
 {
 public:
   DataTextureSourceD3D9(gfx::SurfaceFormat aFormat,
                         CompositorD3D9* aCompositor,
-                        TextureFlags aFlags = TEXTURE_FLAGS_DEFAULT,
+                        TextureFlags aFlags = TextureFlags::DEFAULT,
                         StereoMode aStereoMode = StereoMode::MONO);
 
   DataTextureSourceD3D9(gfx::SurfaceFormat aFormat,
                         gfx::IntSize aSize,
                         CompositorD3D9* aCompositor,
                         IDirect3DTexture9* aTexture,
-                        TextureFlags aFlags = TEXTURE_FLAGS_DEFAULT);
+                        TextureFlags aFlags = TextureFlags::DEFAULT);
 
   virtual ~DataTextureSourceD3D9();
 
   // DataTextureSource
 
   virtual bool Update(gfx::DataSourceSurface* aSurface,
                       nsIntRegion* aDestRegion = nullptr,
                       gfx::IntPoint* aSrcOffset = nullptr) MOZ_OVERRIDE;
@@ -134,29 +134,29 @@ public:
   virtual void DeallocateDeviceData() MOZ_OVERRIDE { mTexture = nullptr; }
 
   virtual gfx::IntSize GetSize() const MOZ_OVERRIDE { return mSize; }
 
   virtual gfx::SurfaceFormat GetFormat() const MOZ_OVERRIDE { return mFormat; }
 
   virtual void SetCompositor(Compositor* aCompositor) MOZ_OVERRIDE;
 
-  // TileIterator
+  // BigImageIterator
 
-  virtual TileIterator* AsTileIterator() MOZ_OVERRIDE { return mIsTiled ? this : nullptr; }
+  virtual BigImageIterator* AsBigImageIterator() MOZ_OVERRIDE { return mIsTiled ? this : nullptr; }
 
   virtual size_t GetTileCount() MOZ_OVERRIDE { return mTileTextures.size(); }
 
   virtual bool NextTile() MOZ_OVERRIDE { return (++mCurrentTile < mTileTextures.size()); }
 
   virtual nsIntRect GetTileRect() MOZ_OVERRIDE;
 
-  virtual void EndTileIteration() MOZ_OVERRIDE { mIterating = false; }
+  virtual void EndBigImageIteration() MOZ_OVERRIDE { mIterating = false; }
 
-  virtual void BeginTileIteration() MOZ_OVERRIDE
+  virtual void BeginBigImageIteration() MOZ_OVERRIDE
   {
     mIterating = true;
     mCurrentTile = 0;
   }
 
   /**
    * Copy the content of aTexture using the GPU.
    */
--- a/gfx/layers/ipc/CompositorParent.cpp
+++ b/gfx/layers/ipc/CompositorParent.cpp
@@ -674,17 +674,17 @@ CompositorParent::CompositeToTarget(Draw
   if (executionTime > frameBudget) {
     printf_stderr("Compositor: Composite execution took %4.1f ms\n",
                   executionTime.ToMilliseconds());
   }
 #endif
 
   // 0 -> Full-tilt composite
   if (gfxPrefs::LayersCompositionFrameRate() == 0
-    || mLayerManager->GetCompositor()->GetDiagnosticTypes() & DIAGNOSTIC_FLASH_BORDERS) {
+    || mLayerManager->GetCompositor()->GetDiagnosticTypes() & DiagnosticTypes::FLASH_BORDERS) {
     // Special full-tilt composite mode for performance testing
     ScheduleComposition();
   }
 
   profiler_tracing("Paint", "Composite", TRACING_INTERVAL_END);
 }
 
 void
@@ -733,30 +733,39 @@ SetShadowProperties(Layer* aLayer)
 
   for (Layer* child = aLayer->GetFirstChild();
       child; child = child->GetNextSibling()) {
     SetShadowProperties(child);
   }
 }
 
 void
-CompositorParent::ShadowLayersUpdated(LayerTransactionParent* aLayerTree,
-                                      const TargetConfig& aTargetConfig,
-                                      bool aIsFirstPaint,
-                                      bool aScheduleComposite)
+CompositorParent::ScheduleRotationOnCompositorThread(const TargetConfig& aTargetConfig,
+                                                     bool aIsFirstPaint)
 {
+  MOZ_ASSERT(IsInCompositorThread());
+
   if (!aIsFirstPaint &&
       !mCompositionManager->IsFirstPaint() &&
       mCompositionManager->RequiresReorientation(aTargetConfig.orientation())) {
     if (mForceCompositionTask != nullptr) {
       mForceCompositionTask->Cancel();
     }
     mForceCompositionTask = NewRunnableMethod(this, &CompositorParent::ForceComposition);
     ScheduleTask(mForceCompositionTask, gfxPrefs::OrientationSyncMillis());
   }
+}
+
+void
+CompositorParent::ShadowLayersUpdated(LayerTransactionParent* aLayerTree,
+                                      const TargetConfig& aTargetConfig,
+                                      bool aIsFirstPaint,
+                                      bool aScheduleComposite)
+{
+  ScheduleRotationOnCompositorThread(aTargetConfig, aIsFirstPaint);
 
   // Instruct the LayerManager to update its render bounds now. Since all the orientation
   // change, dimension change would be done at the stage, update the size here is free of
   // race condition.
   mLayerManager->UpdateRenderBounds(aTargetConfig.clientBounds());
   mLayerManager->SetRegionToClear(aTargetConfig.clearRegion());
 
   mCompositionManager->Updated(aIsFirstPaint, aTargetConfig);
@@ -1245,17 +1254,22 @@ CrossProcessCompositorParent::RecvNotify
 void
 CrossProcessCompositorParent::ShadowLayersUpdated(
   LayerTransactionParent* aLayerTree,
   const TargetConfig& aTargetConfig,
   bool aIsFirstPaint,
   bool aScheduleComposite)
 {
   uint64_t id = aLayerTree->GetId();
+
   MOZ_ASSERT(id != 0);
+  MOZ_ASSERT(sIndirectLayerTrees[id].mParent);
+
+  sIndirectLayerTrees[id].mParent->ScheduleRotationOnCompositorThread(aTargetConfig, aIsFirstPaint);
+
   Layer* shadowRoot = aLayerTree->GetRoot();
   if (shadowRoot) {
     SetShadowProperties(shadowRoot);
   }
   UpdateIndirectTree(id, shadowRoot, aTargetConfig);
 
   sIndirectLayerTrees[id].mParent->NotifyShadowTreeTransaction(id, aIsFirstPaint, aScheduleComposite);
 }
--- a/gfx/layers/ipc/CompositorParent.h
+++ b/gfx/layers/ipc/CompositorParent.h
@@ -125,16 +125,22 @@ public:
    * otherwise.
    */
   bool ScheduleResumeOnCompositorThread(int width, int height);
 
   virtual void ScheduleComposition();
   void NotifyShadowTreeTransaction(uint64_t aId, bool aIsFirstPaint, bool aScheduleComposite);
 
   /**
+   * Check rotation info and schedule a rendering task if needed.
+   * Only can be called from compositor thread.
+   */
+  void ScheduleRotationOnCompositorThread(const TargetConfig& aTargetConfig, bool aIsFirstPaint);
+
+  /**
    * Returns the unique layer tree identifier that corresponds to the root
    * tree of this compositor.
    */
   uint64_t RootLayerTreeId();
 
   /**
    * Returns a pointer to the compositor corresponding to the given ID.
    */
--- a/gfx/layers/ipc/ImageBridgeChild.cpp
+++ b/gfx/layers/ipc/ImageBridgeChild.cpp
@@ -168,17 +168,16 @@ static Thread *sImageBridgeChildThread =
 // dispatched function
 static void StopImageBridgeSync(ReentrantMonitor *aBarrier, bool *aDone)
 {
   ReentrantMonitorAutoEnter autoMon(*aBarrier);
 
   NS_ABORT_IF_FALSE(InImageBridgeChildThread(),
                     "Should be in ImageBridgeChild thread.");
   if (sImageBridgeChildSingleton) {
-
     sImageBridgeChildSingleton->SendStop();
   }
   *aDone = true;
   aBarrier->NotifyAll();
 }
 
 // dispatched function
 static void DeleteImageBridgeSync(ReentrantMonitor *aBarrier, bool *aDone)
@@ -566,25 +565,24 @@ bool ImageBridgeChild::StartUpOnThread(T
     return true;
   } else {
     return false;
   }
 }
 
 void ImageBridgeChild::DestroyBridge()
 {
+  if (!IsCreated()) {
+    return;
+  }
   NS_ABORT_IF_FALSE(!InImageBridgeChildThread(),
                     "This method must not be called in this thread.");
   // ...because we are about to dispatch synchronous messages to the
   // ImageBridgeChild thread.
 
-  if (!IsCreated()) {
-    return;
-  }
-
   ReentrantMonitor barrier("ImageBridgeDestroyTask lock");
   ReentrantMonitorAutoEnter autoMon(barrier);
 
   bool done = false;
   sImageBridgeChildSingleton->GetMessageLoop()->PostTask(FROM_HERE,
                   NewRunnableFunction(&StopImageBridgeSync, &barrier, &done));
   while (!done) {
     barrier.Wait();
@@ -596,17 +594,18 @@ void ImageBridgeChild::DestroyBridge()
   while (!done) {
     barrier.Wait();
   }
 
 }
 
 bool InImageBridgeChildThread()
 {
-  return sImageBridgeChildThread->thread_id() == PlatformThread::CurrentId();
+  return ImageBridgeChild::IsCreated() &&
+    sImageBridgeChildThread->thread_id() == PlatformThread::CurrentId();
 }
 
 MessageLoop * ImageBridgeChild::GetMessageLoop() const
 {
   return sImageBridgeChildThread->message_loop();
 }
 
 void ImageBridgeChild::ConnectAsync(ImageBridgeParent* aParent)
@@ -643,17 +642,17 @@ ImageBridgeChild::CreateImageClient(Comp
   }
   return result.forget();
 }
 
 TemporaryRef<ImageClient>
 ImageBridgeChild::CreateImageClientNow(CompositableType aType)
 {
   RefPtr<ImageClient> client
-    = ImageClient::CreateImageClient(aType, this, 0);
+    = ImageClient::CreateImageClient(aType, this, TextureFlags::NO_FLAGS);
   MOZ_ASSERT(client, "failed to create ImageClient");
   if (client) {
     client->Connect();
   }
   return client.forget();
 }
 
 PGrallocBufferChild*
@@ -913,17 +912,17 @@ ImageBridgeChild::CreateTexture(const Su
 {
   return SendPTextureConstructor(aSharedData, aFlags);
 }
 
 void
 ImageBridgeChild::RemoveTextureFromCompositable(CompositableClient* aCompositable,
                                                 TextureClient* aTexture)
 {
-  if (aTexture->GetFlags() & TEXTURE_DEALLOCATE_CLIENT) {
+  if (aTexture->GetFlags() & TextureFlags::DEALLOCATE_CLIENT) {
     mTxn->AddEdit(OpRemoveTexture(nullptr, aCompositable->GetIPDLActor(),
                                   nullptr, aTexture->GetIPDLActor()));
   } else {
     mTxn->AddNoSwapEdit(OpRemoveTexture(nullptr, aCompositable->GetIPDLActor(),
                                         nullptr, aTexture->GetIPDLActor()));
   }
   // Hold texture until transaction complete.
   HoldUntilTransaction(aTexture);
--- a/gfx/layers/ipc/LayersMessages.ipdlh
+++ b/gfx/layers/ipc/LayersMessages.ipdlh
@@ -36,16 +36,17 @@ using mozilla::LayerMargin from "Units.h
 using mozilla::LayerPoint from "Units.h";
 using mozilla::LayerRect from "Units.h";
 using mozilla::layers::ScaleMode from "mozilla/layers/LayersTypes.h";
 using mozilla::layers::EventRegions from "mozilla/layers/LayersTypes.h";
 using mozilla::layers::DiagnosticTypes from "mozilla/layers/CompositorTypes.h";
 using struct mozilla::layers::FrameMetrics from "FrameMetrics.h";
 using mozilla::layers::FrameMetrics::ViewID from "FrameMetrics.h";
 using struct mozilla::layers::FenceHandle from "mozilla/layers/FenceUtils.h";
+using mozilla::layers::TextureIdentifier from "mozilla/layers/CompositorTypes.h";
 
 namespace mozilla {
 namespace layers {
 
 struct TargetConfig {
   nsIntRect naturalBounds;
   ScreenRotation rotation;
   nsIntRect clientBounds;
@@ -306,17 +307,17 @@ struct OpCreatedIncrementalTexture {
 struct OpPaintTextureRegion {
   PCompositable compositable;
   ThebesBufferData bufferData;
   nsIntRegion updatedRegion;
 };
 
 struct OpPaintTextureIncremental {
   PCompositable compositable;
-  uint32_t textureId;
+  TextureIdentifier textureId;
   SurfaceDescriptor image;
   nsIntRegion updatedRegion;
   nsIntRect bufferRect;
   nsIntPoint bufferRotation;
 };
 
 struct OpUpdatePictureRect {
   PCompositable compositable;
@@ -404,17 +405,17 @@ union Edit {
 
 struct OpContentBufferSwap {
   PCompositable compositable;
   nsIntRegion frontUpdatedRegion;
 };
 
 struct OpTextureSwap {
   PCompositable compositable;
-  uint32_t textureId;
+  TextureIdentifier textureId;
   SurfaceDescriptor image;
 };
 
 struct ReturnReleaseFence {
   PCompositable compositable;
   PTexture texture;
   FenceHandle fence;
 };
--- a/gfx/layers/ipc/PImageBridge.ipdl
+++ b/gfx/layers/ipc/PImageBridge.ipdl
@@ -8,16 +8,17 @@ include LayersMessages;
 include protocol PGrallocBuffer;
 include protocol PCompositable;
 include protocol PTexture;
 include ProtocolTypes;
 
 include "mozilla/GfxMessageUtils.h";
 
 using struct mozilla::layers::TextureInfo from "mozilla/layers/CompositorTypes.h";
+using mozilla::layers::TextureFlags from "mozilla/layers/CompositorTypes.h";
 
 namespace mozilla {
 namespace layers {
 
 /**
  * The PImageBridge protocol is used to allow isolated threads or processes to push
  * frames directly to the compositor thread/process without relying on the main thread
  * which might be too busy dealing with content script.
@@ -46,15 +47,15 @@ parent:
   // counterpart so as to not race with the upcomming __delete__ message.
   // In the child side, the __delete__ messages are not sent right after Stop,
   // they are scheduled in the ImageBridgeChild's message queue in order to ensure
   // that all the messages from the parent side have been received and processed
   // before sending __delete__.
   sync Stop();
 
   sync PCompositable(TextureInfo aInfo) returns (uint64_t id);
-  async PTexture(SurfaceDescriptor aSharedData, uint32_t aTextureFlags);
+  async PTexture(SurfaceDescriptor aSharedData, TextureFlags aTextureFlags);
 };
 
 
 } // namespace
 } // namespace
 
--- a/gfx/layers/ipc/PLayerTransaction.ipdl
+++ b/gfx/layers/ipc/PLayerTransaction.ipdl
@@ -13,16 +13,17 @@ include protocol PGrallocBuffer;
 include protocol PLayer;
 include protocol PRenderFrame;
 include protocol PTexture;
 
 include "mozilla/GfxMessageUtils.h";
 
 using struct mozilla::layers::TextureInfo from "mozilla/layers/CompositorTypes.h";
 using struct mozilla::void_t from "ipc/IPCMessageUtils.h";
+using mozilla::layers::TextureFlags from "mozilla/layers/CompositorTypes.h";
 
 /**
  * The layers protocol is spoken between thread contexts that manage
  * layer (sub)trees.  The protocol comprises atomically publishing
  * layer subtrees to a "shadow" thread context (which grafts the
  * subtree into its own tree), and atomically updating a published
  * subtree.  ("Atomic" in this sense is wrt painting.)
  */
@@ -69,17 +70,17 @@ parent:
    *   USAGE_HW_RENDER | USAGE_HW_TEXTURE
    *     - used for GL rendering to a buffer which the compositor
    *       treats as a texture
    */
   sync PGrallocBuffer(IntSize size, uint32_t format, uint32_t usage)
     returns (MaybeMagicGrallocBufferHandle handle);
   async PLayer();
   async PCompositable(TextureInfo aTextureInfo);
-  async PTexture(SurfaceDescriptor aSharedData, uint32_t aTextureFlags);
+  async PTexture(SurfaceDescriptor aSharedData, TextureFlags aTextureFlags);
 
   // The isFirstPaint flag can be used to indicate that this is the first update
   // for a particular document.
   sync Update(Edit[] cset, TargetConfig targetConfig, bool isFirstPaint, bool scheduleComposite)
     returns (EditReply[] reply);
 
   // Testing APIs
 
--- a/gfx/layers/ipc/ShadowLayers.cpp
+++ b/gfx/layers/ipc/ShadowLayers.cpp
@@ -161,17 +161,17 @@ struct AutoTxnEnd {
 
 void
 CompositableForwarder::IdentifyTextureHost(const TextureFactoryIdentifier& aIdentifier)
 {
   mTextureFactoryIdentifier = aIdentifier;
 }
 
 ShadowLayerForwarder::ShadowLayerForwarder()
- : mDiagnosticTypes(DIAGNOSTIC_NONE)
+ : mDiagnosticTypes(DiagnosticTypes::NO_DIAGNOSTIC)
  , mIsFirstPaint(false)
  , mWindowOverlayChanged(false)
 {
   mTxn = new Transaction();
 }
 
 ShadowLayerForwarder::~ShadowLayerForwarder()
 {
@@ -362,17 +362,17 @@ ShadowLayerForwarder::UpdatedTexture(Com
                                      nsIntRegion* aRegion)
 {
   MOZ_ASSERT(aCompositable);
   MOZ_ASSERT(aTexture);
   MOZ_ASSERT(aCompositable->GetIPDLActor());
   MOZ_ASSERT(aTexture->GetIPDLActor());
   MaybeRegion region = aRegion ? MaybeRegion(*aRegion)
                                : MaybeRegion(null_t());
-  if (aTexture->GetFlags() & TEXTURE_IMMEDIATE_UPLOAD) {
+  if (aTexture->GetFlags() & TextureFlags::IMMEDIATE_UPLOAD) {
     mTxn->AddPaint(OpUpdateTexture(nullptr, aCompositable->GetIPDLActor(),
                                    nullptr, aTexture->GetIPDLActor(),
                                    region));
   } else {
     mTxn->AddNoSwapPaint(OpUpdateTexture(nullptr, aCompositable->GetIPDLActor(),
                                          nullptr, aTexture->GetIPDLActor(),
                                          region));
   }
@@ -412,17 +412,17 @@ ShadowLayerForwarder::RemoveTextureFromC
                                                     TextureClient* aTexture)
 {
   MOZ_ASSERT(aCompositable);
   MOZ_ASSERT(aTexture);
   MOZ_ASSERT(aCompositable->GetIPDLActor());
   MOZ_ASSERT(aTexture->GetIPDLActor());
   mTxn->AddEdit(OpRemoveTexture(nullptr, aCompositable->GetIPDLActor(),
                                 nullptr, aTexture->GetIPDLActor()));
-  if (aTexture->GetFlags() & TEXTURE_DEALLOCATE_CLIENT) {
+  if (aTexture->GetFlags() & TextureFlags::DEALLOCATE_CLIENT) {
     mTxn->MarkSyncTransaction();
   }
   // Hold texture until transaction complete.
   HoldUntilTransaction(aTexture);
 }
 
 void
 ShadowLayerForwarder::RemoveTexture(TextureClient* aTexture)
--- a/gfx/layers/ipc/SharedPlanarYCbCrImage.cpp
+++ b/gfx/layers/ipc/SharedPlanarYCbCrImage.cpp
@@ -86,17 +86,17 @@ SharedPlanarYCbCrImage::SetData(const Pl
     Data data = aData;
     if (!Allocate(data)) {
       NS_WARNING("SharedPlanarYCbCrImage::SetData failed to allocate");
       return;
     }
   }
 
   MOZ_ASSERT(mTextureClient->AsTextureClientYCbCr());
-  if (!mTextureClient->Lock(OPEN_WRITE_ONLY)) {
+  if (!mTextureClient->Lock(OpenMode::OPEN_WRITE_ONLY)) {
     MOZ_ASSERT(false, "Failed to lock the texture.");
     return;
   }
   TextureClientAutoUnlock unlock(mTextureClient);
   if (!mTextureClient->AsTextureClientYCbCr()->UpdateYCbCr(aData)) {
     MOZ_ASSERT(false, "Failed to copy YCbCr data into the TextureClient");
     return;
   }
--- a/gfx/layers/opengl/CompositorOGL.cpp
+++ b/gfx/layers/opengl/CompositorOGL.cpp
@@ -798,54 +798,54 @@ CompositorOGL::CreateFBOWithTexture(cons
 }
 
 ShaderConfigOGL
 CompositorOGL::GetShaderConfigFor(Effect *aEffect, MaskType aMask) const
 {
   ShaderConfigOGL config;
 
   switch(aEffect->mType) {
-  case EFFECT_SOLID_COLOR:
+  case EffectTypes::SOLID_COLOR:
     config.SetRenderColor(true);
     break;
-  case EFFECT_YCBCR:
+  case EffectTypes::YCBCR:
     config.SetYCbCr(true);
     break;
-  case EFFECT_COMPONENT_ALPHA:
+  case EffectTypes::COMPONENT_ALPHA:
   {
     config.SetComponentAlpha(true);
     EffectComponentAlpha* effectComponentAlpha =
       static_cast<EffectComponentAlpha*>(aEffect);
     gfx::SurfaceFormat format = effectComponentAlpha->mOnWhite->GetFormat();
     config.SetRBSwap(format == gfx::SurfaceFormat::B8G8R8A8 ||
                      format == gfx::SurfaceFormat::B8G8R8X8);
     break;
   }
-  case EFFECT_RENDER_TARGET:
+  case EffectTypes::RENDER_TARGET:
     config.SetTextureTarget(mFBOTextureTarget);
     break;
   default:
   {
-    MOZ_ASSERT(aEffect->mType == EFFECT_RGB);
+    MOZ_ASSERT(aEffect->mType == EffectTypes::RGB);
     TexturedEffect* texturedEffect =
         static_cast<TexturedEffect*>(aEffect);
     TextureSourceOGL* source = texturedEffect->mTexture->AsSourceOGL();
     MOZ_ASSERT_IF(source->GetTextureTarget() == LOCAL_GL_TEXTURE_EXTERNAL,
                   source->GetFormat() == gfx::SurfaceFormat::R8G8B8A8);
     MOZ_ASSERT_IF(source->GetTextureTarget() == LOCAL_GL_TEXTURE_RECTANGLE_ARB,
                   source->GetFormat() == gfx::SurfaceFormat::R8G8B8A8 ||
                   source->GetFormat() == gfx::SurfaceFormat::R8G8B8X8 ||
                   source->GetFormat() == gfx::SurfaceFormat::R5G6B5);
     config = ShaderConfigFromTargetAndFormat(source->GetTextureTarget(),
                                              source->GetFormat());
     break;
   }
   }
-  config.SetMask2D(aMask == Mask2d);
-  config.SetMask3D(aMask == Mask3d);
+  config.SetMask2D(aMask == MaskType::Mask2d);
+  config.SetMask3D(aMask == MaskType::Mask3d);
   return config;
 }
 
 ShaderProgramOGL*
 CompositorOGL::GetShaderProgramFor(const ShaderConfigOGL &aConfig)
 {
   std::map<ShaderConfigOGL, ShaderProgramOGL *>::iterator iter = mPrograms.find(aConfig);
   if (iter != mPrograms.end())
@@ -904,18 +904,18 @@ CompositorOGL::DrawQuadInternal(const Re
 
   LayerScope::SendEffectChain(mGLContext, aEffectChain,
                               aRect.width, aRect.height);
 
   MaskType maskType;
   EffectMask* effectMask;
   TextureSourceOGL* sourceMask = nullptr;
   gfx::Matrix4x4 maskQuadTransform;
-  if (aEffectChain.mSecondaryEffects[EFFECT_MASK]) {
-    effectMask = static_cast<EffectMask*>(aEffectChain.mSecondaryEffects[EFFECT_MASK].get());
+  if (aEffectChain.mSecondaryEffects[EffectTypes::MASK]) {
+    effectMask = static_cast<EffectMask*>(aEffectChain.mSecondaryEffects[EffectTypes::MASK].get());
     sourceMask = effectMask->mMaskTexture->AsSourceOGL();
 
     // NS_ASSERTION(textureMask->IsAlpha(),
     //              "OpenGL mask layers must be backed by alpha surfaces");
 
     // We're assuming that the gl backend won't cheat and use NPOT
     // textures when glContext says it can't (which seems to happen
     // on a mac when you force POT textures)
@@ -927,28 +927,28 @@ CompositorOGL::DrawQuadInternal(const Re
     bounds = maskTransform.As2D().TransformBounds(bounds);
 
     maskQuadTransform._11 = 1.0f/bounds.width;
     maskQuadTransform._22 = 1.0f/bounds.height;
     maskQuadTransform._41 = float(-bounds.x)/bounds.width;
     maskQuadTransform._42 = float(-bounds.y)/bounds.height;
 
     maskType = effectMask->mIs3D
-                 ? Mask3d
-                 : Mask2d;
+                 ? MaskType::Mask3d
+                 : MaskType::Mask2d;
   } else {
-    maskType = MaskNone;
+    maskType = MaskType::MaskNone;
   }
 
   mPixelsFilled += aRect.width * aRect.height;
 
   // Determine the color if this is a color shader and fold the opacity into
   // the color since color shaders don't have an opacity uniform.
   Color color;
-  if (aEffectChain.mPrimaryEffect->mType == EFFECT_SOLID_COLOR) {
+  if (aEffectChain.mPrimaryEffect->mType == EffectTypes::SOLID_COLOR) {
     EffectSolidColor* effectSolidColor =
       static_cast<EffectSolidColor*>(aEffectChain.mPrimaryEffect.get());
     color = effectSolidColor->mColor;
 
     Float opacity = aOpacity * color.a;
     color.r *= opacity;
     color.g *= opacity;
     color.b *= opacity;
@@ -973,28 +973,28 @@ CompositorOGL::DrawQuadInternal(const Re
     TexturedEffect* texturedEffect =
         static_cast<TexturedEffect*>(aEffectChain.mPrimaryEffect.get());
     TextureSourceOGL* source = texturedEffect->mTexture->AsSourceOGL();
     // This is used by IOSurface that use 0,0...w,h coordinate rather then 0,0..1,1.
     program->SetTexCoordMultiplier(source->GetSize().width, source->GetSize().height);
   }
 
   switch (aEffectChain.mPrimaryEffect->mType) {
-    case EFFECT_SOLID_COLOR: {
+    case EffectTypes::SOLID_COLOR: {
       program->SetRenderColor(color);
 
-      if (maskType != MaskNone) {
+      if (maskType != MaskType::MaskNone) {
         BindMaskForProgram(program, sourceMask, LOCAL_GL_TEXTURE0, maskQuadTransform);
       }
 
       BindAndDrawQuad(program, aDrawMode);
     }
     break;
 
-  case EFFECT_RGB: {
+  case EffectTypes::RGB: {
       TexturedEffect* texturedEffect =
           static_cast<TexturedEffect*>(aEffectChain.mPrimaryEffect.get());
       TextureSource *source = texturedEffect->mTexture;
 
       if (!texturedEffect->mPremultiplied) {
         mGLContext->fBlendFuncSeparate(LOCAL_GL_SRC_ALPHA, LOCAL_GL_ONE_MINUS_SRC_ALPHA,
                                        LOCAL_GL_ONE, LOCAL_GL_ONE);
       }
@@ -1014,30 +1014,30 @@ CompositorOGL::DrawQuadInternal(const Re
         // code should not be needed!
         filter = gfx::Filter::POINT;
       }
 #endif
       source->AsSourceOGL()->BindTexture(LOCAL_GL_TEXTURE0, filter);
 
       program->SetTextureUnit(0);
 
-      if (maskType != MaskNone) {
+      if (maskType != MaskType::MaskNone) {
         BindMaskForProgram(program, sourceMask, LOCAL_GL_TEXTURE1, maskQuadTransform);
       }
 
       BindAndDrawQuadWithTextureRect(program, textureTransform,
                                      texturedEffect->mTextureCoords, source);
 
       if (!texturedEffect->mPremultiplied) {
         mGLContext->fBlendFuncSeparate(LOCAL_GL_ONE, LOCAL_GL_ONE_MINUS_SRC_ALPHA,
                                        LOCAL_GL_ONE, LOCAL_GL_ONE);
       }
     }
     break;
-  case EFFECT_YCBCR: {
+  case EffectTypes::YCBCR: {
       EffectYCbCr* effectYCbCr =
         static_cast<EffectYCbCr*>(aEffectChain.mPrimaryEffect.get());
       TextureSource* sourceYCbCr = effectYCbCr->mTexture;
       const int Y = 0, Cb = 1, Cr = 2;
       TextureSourceOGL* sourceY =  sourceYCbCr->GetSubSource(Y)->AsSourceOGL();
       TextureSourceOGL* sourceCb = sourceYCbCr->GetSubSource(Cb)->AsSourceOGL();
       TextureSourceOGL* sourceCr = sourceYCbCr->GetSubSource(Cr)->AsSourceOGL();
 
@@ -1047,59 +1047,59 @@ CompositorOGL::DrawQuadInternal(const Re
       }
 
       sourceY->BindTexture(LOCAL_GL_TEXTURE0, effectYCbCr->mFilter);
       sourceCb->BindTexture(LOCAL_GL_TEXTURE1, effectYCbCr->mFilter);
       sourceCr->BindTexture(LOCAL_GL_TEXTURE2, effectYCbCr->mFilter);
 
       program->SetYCbCrTextureUnits(Y, Cb, Cr);
 
-      if (maskType != MaskNone) {
+      if (maskType != MaskType::MaskNone) {
         BindMaskForProgram(program, sourceMask, LOCAL_GL_TEXTURE3, maskQuadTransform);
       }
       BindAndDrawQuadWithTextureRect(program,
                                      gfx3DMatrix(),
                                      effectYCbCr->mTextureCoords,
                                      sourceYCbCr->GetSubSource(Y));
     }
     break;
-  case EFFECT_RENDER_TARGET: {
+  case EffectTypes::RENDER_TARGET: {
       EffectRenderTarget* effectRenderTarget =
         static_cast<EffectRenderTarget*>(aEffectChain.mPrimaryEffect.get());
       RefPtr<CompositingRenderTargetOGL> surface
         = static_cast<CompositingRenderTargetOGL*>(effectRenderTarget->mRenderTarget.get());
 
       surface->BindTexture(LOCAL_GL_TEXTURE0, mFBOTextureTarget);
 
       // Drawing is always flipped, but when copying between surfaces we want to avoid
       // this, so apply a flip here to cancel the other one out.
       Matrix transform;
       transform.Translate(0.0, 1.0);
       transform.Scale(1.0f, -1.0f);
       program->SetTextureTransform(Matrix4x4::From2D(transform));
       program->SetTextureUnit(0);
 
-      if (maskType != MaskNone) {
+      if (maskType != MaskType::MaskNone) {
         sourceMask->BindTexture(LOCAL_GL_TEXTURE1, gfx::Filter::LINEAR);
         program->SetMaskTextureUnit(1);
         program->SetMaskLayerTransform(maskQuadTransform);
       }
 
       if (config.mFeatures & ENABLE_TEXTURE_RECT) {
         // 2DRect case, get the multiplier right for a sampler2DRect
         program->SetTexCoordMultiplier(aRect.width, aRect.height);
       }
 
       // Drawing is always flipped, but when copying between surfaces we want to avoid
       // this. Pass true for the flip parameter to introduce a second flip
       // that cancels the other one out.
       BindAndDrawQuad(program);
     }
     break;
-  case EFFECT_COMPONENT_ALPHA: {
+  case EffectTypes::COMPONENT_ALPHA: {
       MOZ_ASSERT(gfxPrefs::ComponentAlphaEnabled());
       EffectComponentAlpha* effectComponentAlpha =
         static_cast<EffectComponentAlpha*>(aEffectChain.mPrimaryEffect.get());
       TextureSourceOGL* sourceOnWhite = effectComponentAlpha->mOnWhite->AsSourceOGL();
       TextureSourceOGL* sourceOnBlack = effectComponentAlpha->mOnBlack->AsSourceOGL();
 
       if (!sourceOnBlack->IsValid() ||
           !sourceOnWhite->IsValid()) {
@@ -1109,17 +1109,17 @@ CompositorOGL::DrawQuadInternal(const Re
 
       sourceOnBlack->BindTexture(LOCAL_GL_TEXTURE0, effectComponentAlpha->mFilter);
       sourceOnWhite->BindTexture(LOCAL_GL_TEXTURE1, effectComponentAlpha->mFilter);
 
       program->SetBlackTextureUnit(0);
       program->SetWhiteTextureUnit(1);
       program->SetTextureTransform(gfx::Matrix4x4());
 
-      if (maskType != MaskNone) {
+      if (maskType != MaskType::MaskNone) {
         BindMaskForProgram(program, sourceMask, LOCAL_GL_TEXTURE2, maskQuadTransform);
       }
       // Pass 1.
       gl()->fBlendFuncSeparate(LOCAL_GL_ZERO, LOCAL_GL_ONE_MINUS_SRC_COLOR,
                                LOCAL_GL_ONE, LOCAL_GL_ONE);
       program->SetTexturePass2(false);
       BindAndDrawQuadWithTextureRect(program,
                                      gfx3DMatrix(),
--- a/gfx/layers/opengl/CompositorOGL.h
+++ b/gfx/layers/opengl/CompositorOGL.h
@@ -15,17 +15,17 @@
 #include "mozilla/Attributes.h"         // for MOZ_OVERRIDE, MOZ_FINAL
 #include "mozilla/RefPtr.h"             // for TemporaryRef, RefPtr
 #include "mozilla/gfx/2D.h"             // for DrawTarget
 #include "mozilla/gfx/BaseSize.h"       // for BaseSize
 #include "mozilla/gfx/Point.h"          // for IntSize, Point
 #include "mozilla/gfx/Rect.h"           // for Rect, IntRect
 #include "mozilla/gfx/Types.h"          // for Float, SurfaceFormat, etc
 #include "mozilla/layers/Compositor.h"  // for SurfaceInitMode, Compositor, etc
-#include "mozilla/layers/CompositorTypes.h"  // for MaskType::NumMaskTypes, etc
+#include "mozilla/layers/CompositorTypes.h"  // for MaskType::MaskType::NumMaskTypes, etc
 #include "mozilla/layers/LayersTypes.h"
 #include "nsAutoPtr.h"                  // for nsRefPtr, nsAutoPtr
 #include "nsCOMPtr.h"                   // for already_AddRefed
 #include "nsDebug.h"                    // for NS_ASSERTION, NS_WARNING
 #include "nsISupportsImpl.h"            // for MOZ_COUNT_CTOR, etc
 #include "nsSize.h"                     // for nsIntSize
 #include "nsTArray.h"                   // for nsAutoTArray, nsTArray, etc
 #include "nsThreadUtils.h"              // for nsRunnable
@@ -149,31 +149,33 @@ protected:
   void DestroyTextures();
 
   GLenum mTextureTarget;
   RefPtr<gl::GLContext> mGL;
   nsTArray<GLuint> mCreatedTextures;
   nsTArray<GLuint> mUnusedTextures;
 };
 
-class CompositorOGL : public Compositor
+// If you want to make this class not MOZ_FINAL, first remove calls to virtual
+// methods (Destroy) that are made in the destructor.
+class CompositorOGL MOZ_FINAL : public Compositor
 {
   typedef mozilla::gl::GLContext GLContext;
 
   friend class GLManagerCompositor;
 
   std::map<ShaderConfigOGL, ShaderProgramOGL*> mPrograms;
 public:
   CompositorOGL(nsIWidget *aWidget, int aSurfaceWidth = -1, int aSurfaceHeight = -1,
                 bool aUseExternalSurfaceSize = false);
 
   virtual ~CompositorOGL();
 
   virtual TemporaryRef<DataTextureSource>
-  CreateDataTextureSource(TextureFlags aFlags = 0) MOZ_OVERRIDE;
+  CreateDataTextureSource(TextureFlags aFlags = TextureFlags::NO_FLAGS) MOZ_OVERRIDE;
 
   virtual bool Initialize() MOZ_OVERRIDE;
 
   virtual void Destroy() MOZ_OVERRIDE;
 
   virtual TextureFactoryIdentifier GetTextureFactoryIdentifier() MOZ_OVERRIDE
   {
     return TextureFactoryIdentifier(LayersBackend::LAYERS_OPENGL,
@@ -353,17 +355,17 @@ private:
    */
   virtual void BeginFrame(const nsIntRegion& aInvalidRegion,
                           const gfx::Rect *aClipRectIn,
                           const gfx::Matrix& aTransform,
                           const gfx::Rect& aRenderBounds,
                           gfx::Rect *aClipRectOut = nullptr,
                           gfx::Rect *aRenderBoundsOut = nullptr) MOZ_OVERRIDE;
 
-  ShaderConfigOGL GetShaderConfigFor(Effect *aEffect, MaskType aMask = MaskNone) const;
+  ShaderConfigOGL GetShaderConfigFor(Effect *aEffect, MaskType aMask = MaskType::MaskNone) const;
   ShaderProgramOGL* GetShaderProgramFor(const ShaderConfigOGL &aConfig);
 
   /**
    * Create a FBO backed by a texture.
    * Note that the texture target type will be
    * of the type returned by FBOTextureTarget; different
    * shaders are required to sample from the different
    * texture types.
--- a/gfx/layers/opengl/GrallocTextureClient.cpp
+++ b/gfx/layers/opengl/GrallocTextureClient.cpp
@@ -140,20 +140,20 @@ GrallocTextureClientOGL::Lock(OpenMode a
 
   if (mMappedBuffer) {
     return true;
   }
 
   WaitReleaseFence();
 
   uint32_t usage = 0;
-  if (aMode & OPEN_READ) {
+  if (aMode & OpenMode::OPEN_READ) {
     usage |= GRALLOC_USAGE_SW_READ_OFTEN;
   }
-  if (aMode & OPEN_WRITE) {
+  if (aMode & OpenMode::OPEN_WRITE) {
     usage |= GRALLOC_USAGE_SW_WRITE_OFTEN;
   }
   int32_t rv = mGraphicBuffer->lock(usage, reinterpret_cast<void**>(&mMappedBuffer));
   if (rv) {
     mMappedBuffer = nullptr;
     NS_WARNING("Couldn't lock graphic buffer");
     return false;
   }
@@ -229,24 +229,24 @@ GrallocTextureClientOGL::AllocateForSurf
                    android::GraphicBuffer::USAGE_HW_TEXTURE;
 
   switch (mFormat) {
   case gfx::SurfaceFormat::R8G8B8A8:
     format = android::PIXEL_FORMAT_RGBA_8888;
     break;
   case gfx::SurfaceFormat::B8G8R8A8:
      format = android::PIXEL_FORMAT_RGBA_8888;
-     mFlags |= TEXTURE_RB_SWAPPED;
+     mFlags |= TextureFlags::RB_SWAPPED;
     break;
   case gfx::SurfaceFormat::R8G8B8X8:
     format = android::PIXEL_FORMAT_RGBX_8888;
     break;
   case gfx::SurfaceFormat::B8G8R8X8:
      format = android::PIXEL_FORMAT_RGBX_8888;
-     mFlags |= TEXTURE_RB_SWAPPED;
+     mFlags |= TextureFlags::RB_SWAPPED;
     break;
   case gfx::SurfaceFormat::R5G6B5:
     format = android::PIXEL_FORMAT_RGB_565;
     break;
   case gfx::SurfaceFormat::A8:
     NS_WARNING("gralloc does not support gfx::SurfaceFormat::A8");
     return false;
   default:
--- a/gfx/layers/opengl/GrallocTextureClient.h
+++ b/gfx/layers/opengl/GrallocTextureClient.h
@@ -35,21 +35,21 @@ namespace layers {
  * This is only used in Firefox OS
  */
 class GrallocTextureClientOGL : public BufferTextureClient
 {
 public:
   GrallocTextureClientOGL(GrallocBufferActor* aActor,
                           gfx::IntSize aSize,
                           gfx::BackendType aMoz2dBackend,
-                          TextureFlags aFlags = TEXTURE_FLAGS_DEFAULT);
+                          TextureFlags aFlags = TextureFlags::DEFAULT);
   GrallocTextureClientOGL(ISurfaceAllocator* aAllocator,
                           gfx::SurfaceFormat aFormat,
                           gfx::BackendType aMoz2dBackend,
-                          TextureFlags aFlags = TEXTURE_FLAGS_DEFAULT);
+                          TextureFlags aFlags = TextureFlags::DEFAULT);
 
   ~GrallocTextureClientOGL();
 
   virtual bool Lock(OpenMode aMode) MOZ_OVERRIDE;
 
   virtual void Unlock() MOZ_OVERRIDE;
 
   virtual bool ImplementsLocking() const MOZ_OVERRIDE { return true; }
--- a/gfx/layers/opengl/GrallocTextureHost.cpp
+++ b/gfx/layers/opengl/GrallocTextureHost.cpp
@@ -14,18 +14,19 @@
 
 namespace mozilla {
 namespace layers {
 
 using namespace android;
 
 static gfx::SurfaceFormat
 SurfaceFormatForAndroidPixelFormat(android::PixelFormat aFormat,
-                                   bool swapRB = false)
+                                   TextureFlags aFlags)
 {
+  bool swapRB = bool(aFlags & TextureFlags::RB_SWAPPED);
   switch (aFormat) {
   case android::PIXEL_FORMAT_BGRA_8888:
     return swapRB ? gfx::SurfaceFormat::R8G8B8A8 : gfx::SurfaceFormat::B8G8R8A8;
   case android::PIXEL_FORMAT_RGBA_8888:
     return swapRB ? gfx::SurfaceFormat::B8G8R8A8 : gfx::SurfaceFormat::R8G8B8A8;
   case android::PIXEL_FORMAT_RGBX_8888:
     return swapRB ? gfx::SurfaceFormat::B8G8R8X8 : gfx::SurfaceFormat::R8G8B8X8;
   case android::PIXEL_FORMAT_RGB_565:
@@ -285,17 +286,17 @@ GrallocTextureHostOGL::GrallocTextureHos
   if (mGrallocActor) {
     mGrallocActor->AddTextureHost(this);
     graphicBuffer = mGrallocActor->GetGraphicBuffer();
   }
 
   if (graphicBuffer) {
     format =
       SurfaceFormatForAndroidPixelFormat(graphicBuffer->getPixelFormat(),
-                                         aFlags & TEXTURE_RB_SWAPPED);
+                                         aFlags);
   }
   mTextureSource = new GrallocTextureSourceOGL(nullptr,
                                                graphicBuffer,
                                                format);
 }
 
 GrallocTextureHostOGL::~GrallocTextureHostOGL()
 {
@@ -364,22 +365,22 @@ GrallocTextureHostOGL::DeallocateDeviceD
 {
   mTextureSource->DeallocateDeviceData();
 }
 
 LayerRenderState
 GrallocTextureHostOGL::GetRenderState()
 {
   if (IsValid()) {
-    uint32_t flags = 0;
-    if (mFlags & TEXTURE_NEEDS_Y_FLIP) {
-      flags |= LAYER_RENDER_STATE_Y_FLIPPED;
+    LayerRenderStateFlags flags = LayerRenderStateFlags::LAYER_RENDER_STATE_DEFAULT;
+    if (mFlags & TextureFlags::NEEDS_Y_FLIP) {
+      flags |= LayerRenderStateFlags::Y_FLIPPED;
     }
-    if (mFlags & TEXTURE_RB_SWAPPED) {
-      flags |= LAYER_RENDER_STATE_FORMAT_RB_SWAP;
+    if (mFlags & TextureFlags::RB_SWAPPED) {
+      flags |= LayerRenderStateFlags::FORMAT_RB_SWAP;
     }
     return LayerRenderState(mTextureSource->mGraphicBuffer.get(),
                             gfx::ThebesIntSize(mSize),
                             flags,
                             this);
   }
 
   return LayerRenderState();
--- a/gfx/layers/opengl/TextureClientOGL.cpp
+++ b/gfx/layers/opengl/TextureClientOGL.cpp
@@ -18,17 +18,17 @@ namespace layers {
 class CompositableForwarder;
 
 SharedTextureClientOGL::SharedTextureClientOGL(TextureFlags aFlags)
   : TextureClient(aFlags)
   , mHandle(0)
   , mInverted(false)
 {
   // SharedTextureClient is always owned externally.
-  mFlags |= TEXTURE_DEALLOCATE_CLIENT;
+  mFlags |= TextureFlags::DEALLOCATE_CLIENT;
 }
 
 SharedTextureClientOGL::~SharedTextureClientOGL()
 {
   // the shared data is owned externally.
 }
 
 
@@ -51,17 +51,17 @@ SharedTextureClientOGL::InitWith(gl::Sha
 {
   MOZ_ASSERT(IsValid());
   MOZ_ASSERT(!IsAllocated());
   mHandle = aHandle;
   mSize = aSize;
   mShareType = aShareType;
   mInverted = aInverted;
   if (mInverted) {
-    AddFlags(TEXTURE_NEEDS_Y_FLIP);
+    AddFlags(TextureFlags::NEEDS_Y_FLIP);
   }
 }
 
 bool
 SharedTextureClientOGL::Lock(OpenMode mode)
 {
   MOZ_ASSERT(!mIsLocked);
   if (!IsValid() || !IsAllocated()) {
--- a/gfx/layers/opengl/TextureHostOGL.cpp
+++ b/gfx/layers/opengl/TextureHostOGL.cpp
@@ -101,30 +101,30 @@ CreateTextureHostOGL(const SurfaceDescri
   return result.forget();
 }
 
 static gl::TextureImage::Flags
 FlagsToGLFlags(TextureFlags aFlags)
 {
   uint32_t result = TextureImage::NoFlags;
 
-  if (aFlags & TEXTURE_USE_NEAREST_FILTER)
+  if (aFlags & TextureFlags::USE_NEAREST_FILTER)
     result |= TextureImage::UseNearestFilter;
-  if (aFlags & TEXTURE_NEEDS_Y_FLIP)
+  if (aFlags & TextureFlags::NEEDS_Y_FLIP)
     result |= TextureImage::NeedsYFlip;
-  if (aFlags & TEXTURE_DISALLOW_BIGIMAGE)
+  if (aFlags & TextureFlags::DISALLOW_BIGIMAGE)
     result |= TextureImage::DisallowBigImage;
 
   return static_cast<gl::TextureImage::Flags>(result);
 }
 
-GLenum
-WrapMode(gl::GLContext *aGl, bool aAllowRepeat)
+static GLenum
+WrapMode(gl::GLContext *aGl, TextureFlags aFlags)
 {
-  if (aAllowRepeat &&
+  if ((aFlags & TextureFlags::ALLOW_REPEAT) &&
       (aGl->IsExtensionSupported(GLContext::ARB_texture_non_power_of_two) ||
        aGl->IsExtensionSupported(GLContext::OES_texture_npot))) {
     return LOCAL_GL_REPEAT;
   }
   return LOCAL_GL_CLAMP_TO_EDGE;
 }
 
 CompositableDataGonkOGL::CompositableDataGonkOGL()
@@ -224,31 +224,31 @@ TextureImageTextureSourceOGL::Update(gfx
     return false;
   }
   MOZ_ASSERT(aSurface);
 
   IntSize size = aSurface->GetSize();
   if (!mTexImage ||
       (mTexImage->GetSize() != size && !aSrcOffset) ||
       mTexImage->GetContentType() != gfx::ContentForFormat(aSurface->GetFormat())) {
-    if (mFlags & TEXTURE_DISALLOW_BIGIMAGE) {
+    if (mFlags & TextureFlags::DISALLOW_BIGIMAGE) {
       mTexImage = CreateBasicTextureImage(mGL, size,
                                           gfx::ContentForFormat(aSurface->GetFormat()),
-                                          WrapMode(mGL, mFlags & TEXTURE_ALLOW_REPEAT),
+                                          WrapMode(mGL, mFlags),
                                           FlagsToGLFlags(mFlags),
                                           SurfaceFormatToImageFormat(aSurface->GetFormat()));
     } else {
       // XXX - clarify which size we want to use. IncrementalContentHost will
       // require the size of the destination surface to be different from
       // the size of aSurface.
       // See bug 893300 (tracks the implementation of ContentHost for new textures).
       mTexImage = CreateTextureImage(mGL,
                                      size,
                                      gfx::ContentForFormat(aSurface->GetFormat()),
-                                     WrapMode(mGL, mFlags & TEXTURE_ALLOW_REPEAT),
+                                     WrapMode(mGL, mFlags),
                                      FlagsToGLFlags(mFlags),
                                      SurfaceFormatToImageFormat(aSurface->GetFormat()));
     }
     ClearCachedFilter();
   }
 
   mTexImage->UpdateFromDataSource(aSurface, aDestRegion, aSrcOffset);
 
@@ -263,17 +263,17 @@ TextureImageTextureSourceOGL::EnsureBuff
                                            gfxContentType aContentType)
 {
   if (!mTexImage ||
       mTexImage->GetSize() != aSize.ToIntSize() ||
       mTexImage->GetContentType() != aContentType) {
     mTexImage = CreateTextureImage(mGL,
                                    aSize.ToIntSize(),
                                    aContentType,
-                                   WrapMode(mGL, mFlags & TEXTURE_ALLOW_REPEAT),
+                                   WrapMode(mGL, mFlags),
                                    FlagsToGLFlags(mFlags));
   }
   mTexImage->Resize(aSize.ToIntSize());
 }
 
 void
 TextureImageTextureSourceOGL::CopyTo(const nsIntRect& aSourceRect,
                                      DataTextureSource *aDest,
--- a/gfx/layers/opengl/TextureHostOGL.h
+++ b/gfx/layers/opengl/TextureHostOGL.h
@@ -180,28 +180,28 @@ protected:
   android::sp<android::Fence> mPrevReleaseFence;
 #endif
 };
 
 /**
  * A TextureSource backed by a TextureImage.
  *
  * Depending on the underlying TextureImage, may support texture tiling, so
- * make sure to check AsTileIterator() and use the texture accordingly.
+ * make sure to check AsBigImageIterator() and use the texture accordingly.
  *
  * This TextureSource can be used without a TextureHost and manage it's own
  * GL texture(s).
  */
 class TextureImageTextureSourceOGL : public DataTextureSource
                                    , public TextureSourceOGL
-                                   , public TileIterator
+                                   , public BigImageIterator
 {
 public:
   TextureImageTextureSourceOGL(gl::GLContext* aGL,
-                               TextureFlags aFlags = TEXTURE_FLAGS_DEFAULT)
+                               TextureFlags aFlags = TextureFlags::DEFAULT)
     : mGL(aGL)
     , mFlags(aFlags)
     , mIterating(false)
   {}
 
   // DataTextureSource
 
   virtual bool Update(gfx::DataSourceSurface* aSurface,
@@ -237,27 +237,27 @@ public:
 
   virtual void SetCompositor(Compositor* aCompositor) MOZ_OVERRIDE;
 
   virtual GLenum GetWrapMode() const MOZ_OVERRIDE
   {
     return mTexImage->GetWrapMode();
   }
 
-  // TileIterator
+  // BigImageIterator
 
-  virtual TileIterator* AsTileIterator() MOZ_OVERRIDE { return this; }
+  virtual BigImageIterator* AsBigImageIterator() MOZ_OVERRIDE { return this; }
 
-  virtual void BeginTileIteration() MOZ_OVERRIDE
+  virtual void BeginBigImageIteration() MOZ_OVERRIDE
   {
-    mTexImage->BeginTileIteration();
+    mTexImage->BeginBigImageIteration();
     mIterating = true;
   }
 
-  virtual void EndTileIteration() MOZ_OVERRIDE
+  virtual void EndBigImageIteration() MOZ_OVERRIDE
   {
     mIterating = false;
   }
 
   virtual nsIntRect GetTileRect() MOZ_OVERRIDE;
 
   virtual size_t GetTileCount() MOZ_OVERRIDE
   {
--- a/gfx/tests/gtest/TestTextures.cpp
+++ b/gfx/tests/gtest/TestTextures.cpp
@@ -146,17 +146,17 @@ void AssertYCbCrSurfacesEqual(PlanarYCbC
 // Run the test for a texture client and a surface
 void TestTextureClientSurface(TextureClient* texture, gfxImageSurface* surface) {
 
   // client allocation
   ASSERT_TRUE(texture->CanExposeDrawTarget());
   texture->AllocateForSurface(ToIntSize(surface->GetSize()));
   ASSERT_TRUE(texture->IsAllocated());
 
-  ASSERT_TRUE(texture->Lock(OPEN_READ_WRITE));
+  ASSERT_TRUE(texture->Lock(OpenMode::OPEN_READ_WRITE));
   // client painting
   RefPtr<DrawTarget> dt = texture->GetAsDrawTarget();
   RefPtr<SourceSurface> source =
     gfxPlatform::GetPlatform()->GetSourceSurfaceForSurface(dt, surface);
   dt->CopySurface(source, IntRect(IntPoint(), source->GetSize()), IntPoint());
 
   RefPtr<SourceSurface> snapshot = dt->Snapshot();
 
@@ -197,17 +197,17 @@ void TestTextureClientYCbCr(TextureClien
   // client allocation
   ASSERT_TRUE(client->AsTextureClientYCbCr() != nullptr);
   TextureClientYCbCr* texture = client->AsTextureClientYCbCr();
   texture->AllocateForYCbCr(ycbcrData.mYSize,
                             ycbcrData.mCbCrSize,
                             ycbcrData.mStereoMode);
   ASSERT_TRUE(client->IsAllocated());
 
-  ASSERT_TRUE(client->Lock(OPEN_READ_WRITE));
+  ASSERT_TRUE(client->Lock(OpenMode::OPEN_READ_WRITE));
   // client painting
   texture->UpdateYCbCr(ycbcrData);
   client->Unlock();
 
   // client serialization
   SurfaceDescriptor descriptor;
   ASSERT_TRUE(client->ToSurfaceDescriptor(descriptor));
 
@@ -265,17 +265,17 @@ TEST(Layers, TextureSerialization) {
     RefPtr<gfxImageSurface> surface = new gfxImageSurface(gfxIntSize(400,300), formats[f]);
     SetupSurface(surface.get());
     AssertSurfacesEqual(surface, surface);
 
     RefPtr<TextureClient> client
       = new MemoryTextureClient(nullptr,
                                 mozilla::gfx::ImageFormatToSurfaceFormat(surface->Format()),
                                 gfx::BackendType::CAIRO,
-                                TEXTURE_DEALLOCATE_CLIENT);
+                                TextureFlags::DEALLOCATE_CLIENT);
 
     TestTextureClientSurface(client, surface);
 
     // XXX - Test more texture client types.
   }
 }
 
 TEST(Layers, TextureYCbCrSerialization) {
@@ -302,14 +302,14 @@ TEST(Layers, TextureYCbCrSerialization) 
   clientData.mCrSkip = 0;
   clientData.mPicX = 0;
   clientData.mPicX = 0;
 
   RefPtr<TextureClient> client
     = new MemoryTextureClient(nullptr,
                               mozilla::gfx::SurfaceFormat::YUV,
                               gfx::BackendType::CAIRO,
-                              TEXTURE_DEALLOCATE_CLIENT);
+                              TextureFlags::DEALLOCATE_CLIENT);
 
   TestTextureClientYCbCr(client, clientData);
 
   // XXX - Test more texture client types.
 }
--- a/gfx/thebes/gfxPlatform.cpp
+++ b/gfx/thebes/gfxPlatform.cpp
@@ -1341,28 +1341,28 @@ gfxPlatform::IsLangCJK(eFontPrefLang aLa
         default:
             return false;
     }
 }
 
 mozilla::layers::DiagnosticTypes
 gfxPlatform::GetLayerDiagnosticTypes()
 {
-  mozilla::layers::DiagnosticTypes type = DIAGNOSTIC_NONE;
+  mozilla::layers::DiagnosticTypes type = DiagnosticTypes::NO_DIAGNOSTIC;
   if (gfxPrefs::DrawLayerBorders()) {
-    type |= mozilla::layers::DIAGNOSTIC_LAYER_BORDERS;
+    type |= mozilla::layers::DiagnosticTypes::LAYER_BORDERS;
   }
   if (gfxPrefs::DrawTileBorders()) {
-    type |= mozilla::layers::DIAGNOSTIC_TILE_BORDERS;
+    type |= mozilla::layers::DiagnosticTypes::TILE_BORDERS;
   }
   if (gfxPrefs::DrawBigImageBorders()) {
-    type |= mozilla::layers::DIAGNOSTIC_BIGIMAGE_BORDERS;
+    type |= mozilla::layers::DiagnosticTypes::BIGIMAGE_BORDERS;
   }
   if (gfxPrefs::FlashLayerBorders()) {
-    type |= mozilla::layers::DIAGNOSTIC_FLASH_BORDERS;
+    type |= mozilla::layers::DiagnosticTypes::FLASH_BORDERS;
   }
   return type;
 }
 
 void
 gfxPlatform::GetLangPrefs(eFontPrefLang aPrefLangs[], uint32_t &aLen, eFontPrefLang aCharLang, eFontPrefLang aPageLang)
 {
     if (IsLangCJK(aCharLang)) {
--- a/intl/unicharutil/tools/genUnicodePropertyData.pl
+++ b/intl/unicharutil/tools/genUnicodePropertyData.pl
@@ -191,30 +191,61 @@ my %scriptCode = (
   MANDAIC => 95,
 # unicode 6.1 additions
   CHAKMA => 96,
   MEROITIC_CURSIVE => 97,
   MEROITIC_HIEROGLYPHS => 98,
   MIAO => 99,
   SHARADA => 100,
   SORA_SOMPENG => 101,
-  TAKRI => 102
+  TAKRI => 102,
+
+# Expected unicode 7.0 additions, not yet supported; re-check when enabling
+# by comparison with harfbuzz and with PangoScript values
+#  BASSA_VAH => 103,
+#  CAUCASIAN_ALBANIAN => 104,
+#  DUPLOYAN => 105,
+#  ELBASAN => 106,
+#  GRANTHA => 107,
+#  KHOJKI => 108,
+#  KHUDAWADI => 109,
+#  LINEAR_A => 110,
+#  MAHAJANI => 111,
+#  MANICHAEAN => 112,
+#  MENDE_KIKAKUI => 113,
+#  MODI => 114,
+#  MRO => 115,
+#  NABATAEAN => 116,
+#  OLD_NORTH_ARABIAN => 117,
+#  OLD_PERMIC => 118,
+#  PAHAWH_HMONG => 119,
+#  PALMYRENE => 120,
+#  PAU_CIN_HAU => 121,
+#  PSALTER_PAHLAVI => 122,
+#  SIDDHAM => 123,
+#  TIRHUTA => 124,
+#  WARANG_CITI => 125,
+
+# additional "script" code, not from Unicode (but matches ISO 15924's Zmth tag)
+# XXX need to update this when the Unicode 7.0 scripts are enabled above
+  MATHEMATICAL_NOTATION => 103,
 );
 
 my $sc = -1;
 my $cc = -1;
 my %catCode;
 my @scriptCodeToTag;
 my @scriptCodeToName;
 
 sub readHarfBuzzHeader
 {
     my $file = shift;
     open FH, "< $ARGV[0]/$file" or die "can't open harfbuzz header $ARGV[0]/$file\n";
     while (<FH>) {
+        s/CANADIAN_SYLLABICS/CANADIAN_ABORIGINAL/; # harfbuzz and unicode disagree on this name :(
         if (m/HB_SCRIPT_([A-Z_]+)\s*=\s*HB_TAG\s*\(('.','.','.','.')\)\s*,/) {
             unless (exists $scriptCode{$1}) {
                 warn "unknown script name $1 found in $file\n";
                 next;
             }
             $sc = $scriptCode{$1};
             $scriptCodeToTag[$sc] = $2;
             $scriptCodeToName[$sc] = $1;
@@ -228,16 +259,21 @@ sub readHarfBuzzHeader
 }
 
 &readHarfBuzzHeader("hb-common.h");
 &readHarfBuzzHeader("hb-unicode.h");
 
 die "didn't find HarfBuzz script codes\n" if $sc == -1;
 die "didn't find HarfBuzz category codes\n" if $cc == -1;
 
+# Additional code not present in HarfBuzz headers:
+$sc = $scriptCode{"MATHEMATICAL_NOTATION"};
+$scriptCodeToTag[$sc] = "'Z','m','t','h'";
+$scriptCodeToName[$sc] = "MATHEMATICAL_NOTATION";
+
 my %xidmodCode = (
 'inclusion'         => 0,
 'recommended'       => 1,
 'default-ignorable' => 2,
 'historic'          => 3,
 'limited-use'       => 4,
 'not-NFKC'          => 5,
 'not-xid'           => 6,
--- a/intl/unicharutil/util/nsUnicodePropertyData.cpp
+++ b/intl/unicharutil/util/nsUnicodePropertyData.cpp
@@ -6,17 +6,17 @@
 
 /*
  * Derived from the Unicode Character Database by genUnicodePropertyData.pl
  *
  * For Unicode terms of use, see http://www.unicode.org/terms_of_use.html
  */
 
 /*
- * Created on Mon Oct 21 16:33:35 2013 from UCD data files with version info:
+ * Created on Mon Apr 28 11:24:35 2014 from UCD data files with version info:
  *
 
 # Date: 2013-09-27, 23:05:00 GMT [KW]
 #
 # Unicode Character Database
 # Copyright (c) 1991-2013 Unicode, Inc.
 # For terms of use, see http://www.unicode.org/terms_of_use.html
 #
@@ -155,17 +155,18 @@ static const uint32_t sScriptCodeToTag[]
   HB_TAG('B','r','a','h'),
   HB_TAG('M','a','n','d'),
   HB_TAG('C','a','k','m'),
   HB_TAG('M','e','r','c'),
   HB_TAG('M','e','r','o'),
   HB_TAG('P','l','r','d'),
   HB_TAG('S','h','r','d'),
   HB_TAG('S','o','r','a'),
-  HB_TAG('T','a','k','r')
+  HB_TAG('T','a','k','r'),
+  HB_TAG('Z','m','t','h')
 };
 
 static const int16_t sMirrorOffsets[] = {
   0,
   1,
   -1,
   2,
   -2,
--- a/intl/unicharutil/util/nsUnicodeScriptCodes.h
+++ b/intl/unicharutil/util/nsUnicodeScriptCodes.h
@@ -6,17 +6,17 @@
 
 /*
  * Derived from the Unicode Character Database by genUnicodePropertyData.pl
  *
  * For Unicode terms of use, see http://www.unicode.org/terms_of_use.html
  */
 
 /*
- * Created on Mon Oct 21 16:33:35 2013 from UCD data files with version info:
+ * Created on Mon Apr 28 11:24:35 2014 from UCD data files with version info:
  *
 
 # Date: 2013-09-27, 23:05:00 GMT [KW]
 #
 # Unicode Character Database
 # Copyright (c) 1991-2013 Unicode, Inc.
 # For terms of use, see http://www.unicode.org/terms_of_use.html
 #
@@ -176,18 +176,19 @@ enum {
   MOZ_SCRIPT_MANDAIC = 95,
   MOZ_SCRIPT_CHAKMA = 96,
   MOZ_SCRIPT_MEROITIC_CURSIVE = 97,
   MOZ_SCRIPT_MEROITIC_HIEROGLYPHS = 98,
   MOZ_SCRIPT_MIAO = 99,
   MOZ_SCRIPT_SHARADA = 100,
   MOZ_SCRIPT_SORA_SOMPENG = 101,
   MOZ_SCRIPT_TAKRI = 102,
+  MOZ_SCRIPT_MATHEMATICAL_NOTATION = 103,
 
-  MOZ_NUM_SCRIPT_CODES = 103,
+  MOZ_NUM_SCRIPT_CODES = 104,
 
   MOZ_SCRIPT_INVALID = -1
 };
 
 #endif
 /*
  * * * * * This file contains MACHINE-GENERATED DATA, do not edit! * * * * *
  */
--- a/js/src/builtin/TestingFunctions.cpp
+++ b/js/src/builtin/TestingFunctions.cpp
@@ -997,34 +997,61 @@ Terminate(JSContext *cx, unsigned arg, j
     // find uncatchable-exception bugs.
     fprintf(stderr, "terminate called\n");
 #endif
 
     JS_ClearPendingException(cx);
     return false;
 }
 
+#define SPS_PROFILING_STACK_MAX_SIZE 1000
+static ProfileEntry SPS_PROFILING_STACK[SPS_PROFILING_STACK_MAX_SIZE];
+static uint32_t SPS_PROFILING_STACK_SIZE = 0;
+
 static bool
-EnableSPSProfilingAssertions(JSContext *cx, unsigned argc, jsval *vp)
+EnableSPSProfiling(JSContext *cx, unsigned argc, jsval *vp)
 {
     CallArgs args = CallArgsFromVp(argc, vp);
-    if (!args.get(0).isBoolean()) {
-        RootedObject arg(cx, &args.callee());
-        ReportUsageError(cx, arg, "Must have one boolean argument");
-        return false;
-    }
-
-    static ProfileEntry stack[1000];
-    static uint32_t stack_size = 0;
 
     // Disable before re-enabling; see the assertion in |SPSProfiler::setProfilingStack|.
     if (cx->runtime()->spsProfiler.installed())
         cx->runtime()->spsProfiler.enable(false);
-    SetRuntimeProfilingStack(cx->runtime(), stack, &stack_size, 1000);
-    cx->runtime()->spsProfiler.enableSlowAssertions(args[0].toBoolean());
+
+    SetRuntimeProfilingStack(cx->runtime(), SPS_PROFILING_STACK, &SPS_PROFILING_STACK_SIZE,
+                             SPS_PROFILING_STACK_MAX_SIZE);
+    cx->runtime()->spsProfiler.enableSlowAssertions(false);
+    cx->runtime()->spsProfiler.enable(true);
+
+    args.rval().setUndefined();
+    return true;
+}
+
+static bool
+EnableSPSProfilingWithSlowAssertions(JSContext *cx, unsigned argc, jsval *vp)
+{
+    CallArgs args = CallArgsFromVp(argc, vp);
+
+    if (cx->runtime()->spsProfiler.enabled()) {
+        // If profiling already enabled with slow assertions disabled,
+        // this is a no-op.
+        if (cx->runtime()->spsProfiler.slowAssertionsEnabled())
+            return true;
+
+        // Slow assertions are off.  Disable profiling before re-enabling
+        // with slow assertions on.
+        cx->runtime()->spsProfiler.enable(false);
+    }
+
+    // Disable before re-enabling; see the assertion in |SPSProfiler::setProfilingStack|.
+    if (cx->runtime()->spsProfiler.installed())
+        cx->runtime()->spsProfiler.enable(false);
+
+    SetRuntimeProfilingStack(cx->runtime(), SPS_PROFILING_STACK, &SPS_PROFILING_STACK_SIZE,
+                             SPS_PROFILING_STACK_MAX_SIZE);
+    cx->runtime()->spsProfiler.enableSlowAssertions(true);
     cx->runtime()->spsProfiler.enable(true);
 
     args.rval().setUndefined();
     return true;
 }
 
 static bool
 DisableSPSProfiling(JSContext *cx, unsigned argc, jsval *vp)
@@ -1698,24 +1725,27 @@ static const JSFunctionSpecWithHelp Test
 "  'collectNurseryBeforeDump' is specified, a minor GC is performed first,\n"
 "  otherwise objects in the nursery are ignored."),
 
     JS_FN_HELP("terminate", Terminate, 0, 0,
 "terminate()",
 "  Terminate JavaScript execution, as if we had run out of\n"
 "  memory or been terminated by the slow script dialog."),
 
-    JS_FN_HELP("enableSPSProfilingAssertions", EnableSPSProfilingAssertions, 1, 0,
-"enableSPSProfilingAssertions(slow)",
-"  Enables SPS instrumentation and corresponding assertions. If 'slow' is\n"
-"  true, then even slower assertions are enabled for all generated JIT code.\n"
-"  When 'slow' is false, then instrumentation is enabled, but the slow\n"
-"  assertions are disabled."),
+    JS_FN_HELP("enableSPSProfiling", EnableSPSProfiling, 0, 0,
+"enableSPSProfiling()",
+"  Enables SPS instrumentation and corresponding assertions, with slow\n"
+"  assertions disabled.\n"),
 
-    JS_FN_HELP("disableSPSProfiling", DisableSPSProfiling, 1, 0,
+    JS_FN_HELP("enableSPSProfilingWithSlowAssertions", EnableSPSProfilingWithSlowAssertions, 0, 0,
+"enableSPSProfilingWithSlowAssertions()",
+"  Enables SPS instrumentation and corresponding assertions, with slow\n"
+"  assertions enabled.\n"),
+
+    JS_FN_HELP("disableSPSProfiling", DisableSPSProfiling, 0, 0,
 "disableSPSProfiling()",
 "  Disables SPS instrumentation"),
 
     JS_FN_HELP("enableOsiPointRegisterChecks", EnableOsiPointRegisterChecks, 0, 0,
 "enableOsiPointRegisterChecks()",
 "Emit extra code to verify live regs at the start of a VM call are not\n"
 "modified before its OsiPoint."),
 
new file mode 100644
--- /dev/null
+++ b/js/src/jit-test/tests/ion/bug1001850.js
@@ -0,0 +1,110 @@
+function t1() {
+  assertEq(thisValue, this);
+}
+
+thisValue = {};
+var f1 = t1.bind(thisValue);
+f1()
+f1()
+
+////////////////////////////////////////////////////////////
+
+function t2() {
+  bailout();
+}
+
+var f2 = t2.bind(thisValue);
+f2()
+f2()
+
+////////////////////////////////////////////////////////////
+
+function test3() {
+  function i3(a,b,c,d) {
+    bailout();
+  }
+
+  function t3(a,b,c,d) {
+    i3(a,b,c,d);
+  }
+
+  var f3 = t3.bind(thisValue);
+  for (var i=0;i<10; i++) {
+    f3(1,2,3,4)
+    f3(1,2,3,4)
+  }
+}
+test3();
+test3();
+
+////////////////////////////////////////////////////////////
+
+function test4() {
+  this.a = 1;
+  var inner = function(a,b,c,d) {
+    bailout();
+  }
+
+  var t = function(a,b,c,d) {
+    assertEq(this.a, undefined);
+    inner(a,b,c,d);
+    assertEq(this.a, undefined);
+  }
+
+  var f = t.bind(thisValue);
+  for (var i=0;i<5; i++) {
+    var res = f(1,2,3,4)
+    var res2 = new f(1,2,3,4)
+    assertEq(res, undefined);
+    assertEq(res2 == undefined, false);
+  }
+}
+test4();
+test4();
+
+////////////////////////////////////////////////////////////
+
+function test5() {
+  this.a = 1;
+  var inner = function(a,b,c,d) {
+    assertEq(a, 1);
+    assertEq(b, 2);
+    assertEq(c, 3);
+    assertEq(d, 1);
+    bailout();
+    assertEq(a, 1);
+    assertEq(b, 2);
+    assertEq(c, 3);
+    assertEq(d, 1);
+  }
+
+  var t = function(a,b,c,d) {
+    inner(a,b,c,d);
+  }
+
+  var f = t.bind(thisValue, 1,2,3);
+  for (var i=0;i<5; i++) {
+    f(1,2,3,4)
+  }
+}
+test5();
+test5();
+
+////////////////////////////////////////////////////////////
+
+function test6() {
+  function i6(a,b,c,d) {
+    if (a == 1)
+      bailout();
+  }
+
+  function t6(a,b,c,d) {
+    i6(a,b,c,d);
+  }
+
+  var f6 = t6.bind(thisValue, 1);
+  f6(1,2,3,4)
+  f6(0,2,3,4)
+}
+test6();
+test6();
--- a/js/src/jit-test/tests/ion/bug875656.js
+++ b/js/src/jit-test/tests/ion/bug875656.js
@@ -1,2 +1,2 @@
-enableSPSProfilingAssertions(false);
+enableSPSProfiling();
 Object.getOwnPropertyNames(this);
--- a/js/src/jit-test/tests/ion/bug901086.js
+++ b/js/src/jit-test/tests/ion/bug901086.js
@@ -1,9 +1,9 @@
-enableSPSProfilingAssertions(false);
+enableSPSProfiling();
 function foo(obj,x,y,z) {
     if (!y)
 	assertEq(0, 1);
     obj.x = x;
     return y + z;
 }
 function bar() {
     var objz = {x:2}
--- a/js/src/jit-test/tests/ion/bug925308.js
+++ b/js/src/jit-test/tests/ion/bug925308.js
@@ -1,13 +1,13 @@
 // |jit-test| error: ReferenceError
 
 var lfcode = new Array();
 lfcode.push("3");
-lfcode.push("enableSPSProfilingAssertions(false);foo();");
+lfcode.push("enableSPSProfiling();foo();");
 while (true) {
   var file = lfcode.shift(); if (file == undefined) { break; }
   loadFile(file)
 }
 function loadFile(lfVarx) {
     if (lfVarx.substr(-3) != ".js" && lfVarx.length != 1) {
         switch (lfRunTypeId) {
             default: function newFunc(x) { new Function(x)(); }; newFunc(lfVarx); break;
--- a/js/src/jit-test/tests/profiler/bug925309.js
+++ b/js/src/jit-test/tests/profiler/bug925309.js
@@ -1,2 +1,2 @@
 
-for(var i = 0; i < 100; enableSPSProfilingAssertions(false), i++) {}
+for(var i = 0; i < 100; enableSPSProfiling(), i++) {}
--- a/js/src/jit-test/tests/profiler/enterjit-osr-disabling-earlyret.js
+++ b/js/src/jit-test/tests/profiler/enterjit-osr-disabling-earlyret.js
@@ -1,13 +1,13 @@
 setJitCompilerOption("baseline.usecount.trigger", 10);
 setJitCompilerOption("ion.usecount.trigger", 20);
 
-enableSPSProfilingAssertions(true);
+enableSPSProfilingWithSlowAssertions();
 (function() {
    var n = 50;
    while (n--) {
        disableSPSProfiling();
        if (!n)
 	   return;
-       enableSPSProfilingAssertions(true);
+       enableSPSProfilingWithSlowAssertions();
    }
 })();
--- a/js/src/jit-test/tests/profiler/enterjit-osr-disabling.js
+++ b/js/src/jit-test/tests/profiler/enterjit-osr-disabling.js
@@ -1,9 +1,9 @@
 setJitCompilerOption("baseline.usecount.trigger", 10);
 setJitCompilerOption("ion.usecount.trigger", 20);
 
-enableSPSProfilingAssertions(true);
+enableSPSProfilingWithSlowAssertions();
 (function() {
    disableSPSProfiling();
    var n = 50;
    while (n--);
 })();
--- a/js/src/jit-test/tests/profiler/enterjit-osr-enabling-earlyret.js
+++ b/js/src/jit-test/tests/profiler/enterjit-osr-enabling-earlyret.js
@@ -1,12 +1,12 @@
 setJitCompilerOption("baseline.usecount.trigger", 10);
 setJitCompilerOption("ion.usecount.trigger", 20);
 
 (function() {
    var n = 50;
    while (n--) {
-       enableSPSProfilingAssertions(true);
+       enableSPSProfilingWithSlowAssertions();
        if (!n)
 	   return;
        disableSPSProfiling();
    }
 })();
--- a/js/src/jit-test/tests/profiler/enterjit-osr-enabling.js
+++ b/js/src/jit-test/tests/profiler/enterjit-osr-enabling.js
@@ -1,8 +1,8 @@
 setJitCompilerOption("baseline.usecount.trigger", 10);
 setJitCompilerOption("ion.usecount.trigger", 20);
 
 (function() {
-   enableSPSProfilingAssertions(true);
+   enableSPSProfilingWithSlowAssertions();
    var n = 50;
    while (n--);
 })();
--- a/js/src/jit-test/tests/profiler/enterjit-osr.js
+++ b/js/src/jit-test/tests/profiler/enterjit-osr.js
@@ -1,8 +1,8 @@
 setJitCompilerOption("baseline.usecount.trigger", 10);
 setJitCompilerOption("ion.usecount.trigger", 20);
 
-enableSPSProfilingAssertions(true);
+enableSPSProfilingWithSlowAssertions();
 (function() {
    var n = 50;
    while (n--);
 })();
--- a/js/src/jit/BaselineCompiler.cpp
+++ b/js/src/jit/BaselineCompiler.cpp
@@ -337,17 +337,17 @@ BaselineCompiler::emitPrologue()
     if (needsEarlyStackCheck())
         masm.bind(&earlyStackCheckFailed);
 
 #ifdef JS_TRACE_LOGGING
     TraceLogger *logger = TraceLoggerForMainThread(cx->runtime());
     Register loggerReg = RegisterSet::Volatile().takeGeneral();
     masm.Push(loggerReg);
     masm.movePtr(ImmPtr(logger), loggerReg);
-    masm.tracelogStart(loggerReg, TraceLogCreateTextId(logger, script.get()));
+    masm.tracelogStart(loggerReg, TraceLogCreateTextId(logger, script));
     masm.tracelogStart(loggerReg, TraceLogger::Baseline);
     masm.Pop(loggerReg);
 #endif
 
     // Record the offset of the prologue, because Ion can bailout before
     // the scope chain is initialized.
     prologueOffset_ = masm.currentOffset();
 
--- a/js/src/jit/Ion.cpp
+++ b/js/src/jit/Ion.cpp
@@ -1955,17 +1955,18 @@ CheckScriptSize(JSContext *cx, JSScript*
         return Method_Compiled;
 
     if (script->length() > MAX_OFF_THREAD_SCRIPT_SIZE) {
         // Some scripts are so large we never try to Ion compile them.
         IonSpew(IonSpew_Abort, "Script too large (%u bytes)", script->length());
         return Method_CantCompile;
     }
 
-    uint32_t numLocalsAndArgs = analyze::TotalSlots(script);
+    uint32_t numLocalsAndArgs = NumLocalsAndArgs(script);
+
     if (cx->runtime()->isWorkerRuntime()) {
         // DOM Workers don't have off thread compilation enabled. Since workers
         // don't block the browser's event loop, allow them to compile larger
         // scripts.
         JS_ASSERT(!cx->runtime()->canUseParallelIonCompilation());
 
         if (script->length() > MAX_DOM_WORKER_SCRIPT_SIZE ||
             numLocalsAndArgs > MAX_DOM_WORKER_LOCALS_AND_ARGS)
@@ -2759,17 +2760,17 @@ jit::Invalidate(JSContext *cx, JSScript 
             filename = "<unknown>";
 
         size_t len = strlen(filename) + 20;
         char *buf = js_pod_malloc<char>(len);
         if (!buf)
             return false;
 
         // Construct the descriptive string.
-        JS_snprintf(buf, len, "Invalidate %s:%llu", filename, script->lineno());
+        JS_snprintf(buf, len, "Invalidate %s:%u", filename, (unsigned int)script->lineno());
         cx->runtime()->spsProfiler.markEvent(buf);
         js_free(buf);
     }
 
     Vector<types::RecompileInfo> scripts(cx);
 
     switch (mode) {
       case SequentialExecution:
--- a/js/src/jit/Ion.h
+++ b/js/src/jit/Ion.h
@@ -173,16 +173,25 @@ IsIonInlinablePC(jsbytecode *pc) {
 }
 
 inline bool
 TooManyArguments(unsigned nargs)
 {
     return nargs >= SNAPSHOT_MAX_NARGS || nargs > js_JitOptions.maxStackArgs;
 }
 
+inline size_t
+NumLocalsAndArgs(JSScript *script)
+{
+    size_t num = 1 /* this */ + script->nfixed();
+    if (JSFunction *fun = script->functionNonDelazifying())
+        num += fun->nargs();
+    return num;
+}
+
 void ForbidCompilation(JSContext *cx, JSScript *script);
 void ForbidCompilation(JSContext *cx, JSScript *script, ExecutionMode mode);
 
 void PurgeCaches(JSScript *script, JS::Zone *zone);
 size_t SizeOfIonData(JSScript *script, mozilla::MallocSizeOf mallocSizeOf);
 void DestroyIonScripts(FreeOp *fop, JSScript *script);
 void TraceIonScripts(JSTracer* trc, JSScript *script);
 
--- a/js/src/jit/IonAnalysis.cpp
+++ b/js/src/jit/IonAnalysis.cpp
@@ -1,18 +1,16 @@
 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
  * vim: set ts=8 sts=4 et sw=4 tw=99:
  * 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 "jit/IonAnalysis.h"
 
-#include "jsanalyze.h"
-
 #include "jit/BaselineInspector.h"
 #include "jit/BaselineJIT.h"
 #include "jit/Ion.h"
 #include "jit/IonBuilder.h"
 #include "jit/IonOptimizationLevels.h"
 #include "jit/LIR.h"
 #include "jit/Lowering.h"
 #include "jit/MIRGraph.h"
--- a/js/src/jit/IonBuilder.cpp
+++ b/js/src/jit/IonBuilder.cpp
@@ -4283,17 +4283,17 @@ IonBuilder::getInlineableGetPropertyCach
     return nullptr;
 }
 
 IonBuilder::InliningStatus
 IonBuilder::inlineSingleCall(CallInfo &callInfo, JSFunction *target)
 {
     // Expects formals to be popped and wrapped.
     if (target->isNative())
-        return inlineNativeCall(callInfo, target->native());
+        return inlineNativeCall(callInfo, target);
 
     if (!inlineScriptedCall(callInfo, target))
         return InliningStatus_Error;
     return InliningStatus_Inlined;
 }
 
 IonBuilder::InliningStatus
 IonBuilder::inlineCallsite(ObjectVector &targets, ObjectVector &originals,
--- a/js/src/jit/IonBuilder.h
+++ b/js/src/jit/IonBuilder.h
@@ -712,18 +712,21 @@ class IonBuilder : public MIRGenerator
     }
     InliningStatus inlineHasClasses(CallInfo &callInfo, const Class *clasp1, const Class *clasp2);
 
     // Testing functions.
     InliningStatus inlineForceSequentialOrInParallelSection(CallInfo &callInfo);
     InliningStatus inlineBailout(CallInfo &callInfo);
     InliningStatus inlineAssertFloat32(CallInfo &callInfo);
 
+    // Bind function.
+    InliningStatus inlineBoundFunction(CallInfo &callInfo, JSFunction *target);
+
     // Main inlining functions
-    InliningStatus inlineNativeCall(CallInfo &callInfo, JSNative native);
+    InliningStatus inlineNativeCall(CallInfo &callInfo, JSFunction *target);
     bool inlineScriptedCall(CallInfo &callInfo, JSFunction *target);
     InliningStatus inlineSingleCall(CallInfo &callInfo, JSFunction *target);
 
     // Call functions
     InliningStatus inlineCallsite(ObjectVector &targets, ObjectVector &originals,
                                   bool lambda, CallInfo &callInfo);
     bool inlineCalls(CallInfo &callInfo, ObjectVector &targets, ObjectVector &originals,
                      BoolVector &choiceSet, MGetPropertyCache *maybeCache);
--- a/js/src/jit/IonOptimizationLevels.cpp
+++ b/js/src/jit/IonOptimizationLevels.cpp
@@ -1,19 +1,20 @@
 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
  * vim: set ts=8 sts=4 et sw=4 tw=99:
  * 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 "jit/IonOptimizationLevels.h"
 
-#include "jsanalyze.h"
 #include "jsscript.h"
 
+#include "jit/Ion.h"
+
 using namespace js;
 using namespace js::jit;
 
 namespace js {
 namespace jit {
 
 OptimizationInfos js_IonOptimizations;
 
@@ -72,17 +73,17 @@ OptimizationInfo::usesBeforeCompile(JSSc
     // If the script is too large to compile on the main thread, we can still
     // compile it off thread. In these cases, increase the use count threshold
     // to improve the compilation's type information and hopefully avoid later
     // recompilation.
 
     if (script->length() > MAX_MAIN_THREAD_SCRIPT_SIZE)
         minUses = minUses * (script->length() / (double) MAX_MAIN_THREAD_SCRIPT_SIZE);
 
-    uint32_t numLocalsAndArgs = analyze::TotalSlots(script);
+    uint32_t numLocalsAndArgs = NumLocalsAndArgs(script);
     if (numLocalsAndArgs > MAX_MAIN_THREAD_LOCALS_AND_ARGS)
         minUses = minUses * (numLocalsAndArgs / (double) MAX_MAIN_THREAD_LOCALS_AND_ARGS);
 
     if (!pc || js_JitOptions.eagerCompilation)
         return minUses;
 
     // It's more efficient to enter outer loops, rather than inner loops, via OSR.
     // To accomplish this, we use a slightly higher threshold for inner loops.
--- a/js/src/jit/Lowering.cpp
+++ b/js/src/jit/Lowering.cpp
@@ -3,18 +3,16 @@
  * 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 "jit/Lowering.h"
 
 #include "mozilla/DebugOnly.h"
 
-#include "jsanalyze.h"
-
 #include "jit/IonSpewer.h"
 #include "jit/LIR.h"
 #include "jit/MIR.h"
 #include "jit/MIRGraph.h"
 
 #include "jsinferinlines.h"
 #include "jsobjinlines.h"
 #include "jsopcodeinlines.h"
--- a/js/src/jit/MCallOptimize.cpp
+++ b/js/src/jit/MCallOptimize.cpp
@@ -8,27 +8,31 @@
 
 #include "builtin/TestingFunctions.h"
 #include "builtin/TypedObject.h"
 #include "jit/BaselineInspector.h"
 #include "jit/IonBuilder.h"
 #include "jit/Lowering.h"
 #include "jit/MIR.h"
 #include "jit/MIRGraph.h"
+#include "vm/ArgumentsObject.h"
 
 #include "jsscriptinlines.h"
 
 #include "vm/StringObject-inl.h"
 
 namespace js {
 namespace jit {
 
 IonBuilder::InliningStatus
-IonBuilder::inlineNativeCall(CallInfo &callInfo, JSNative native)
+IonBuilder::inlineNativeCall(CallInfo &callInfo, JSFunction *target)
 {
+    JS_ASSERT(target->isNative());
+    JSNative native = target->native();
+
     if (!optimizationInfo().inlineNative())
         return InliningStatus_NotInlined;
 
     // Array natives.
     if (native == js_Array)
         return inlineArray(callInfo);
     if (native == js::array_pop)
         return inlineArrayPopShift(callInfo, MArrayPopShift::Pop);
@@ -186,16 +190,20 @@ IonBuilder::inlineNativeCall(CallInfo &c
     // Testing Functions
     if (native == testingFunc_inParallelSection)
         return inlineForceSequentialOrInParallelSection(callInfo);
     if (native == testingFunc_bailout)
         return inlineBailout(callInfo);
     if (native == testingFunc_assertFloat32)
         return inlineAssertFloat32(callInfo);
 
+    // Bound function
+    if (native == js::CallOrConstructBoundFunction)
+        return inlineBoundFunction(callInfo, target);
+
     return InliningStatus_NotInlined;
 }
 
 types::TemporaryTypeSet *
 IonBuilder::getInlineReturnTypeSet()
 {
     return bytecodeTypes(pc);
 }
@@ -1899,10 +1907,53 @@ IonBuilder::inlineAssertFloat32(CallInfo
     current->add(MAssertFloat32::New(alloc(), callInfo.getArg(0), mustBeFloat32));
 
     MConstant *undefined = MConstant::New(alloc(), UndefinedValue());
     current->add(undefined);
     current->push(undefined);
     return InliningStatus_Inlined;
 }
 
+IonBuilder::InliningStatus
+IonBuilder::inlineBoundFunction(CallInfo &nativeCallInfo, JSFunction *target)
+{
+    JSFunction *scriptedTarget = &(target->getBoundFunctionTarget()->as<JSFunction>());
+    JSRuntime *runtime = scriptedTarget->runtimeFromMainThread();
+
+    if (gc::IsInsideNursery(runtime, scriptedTarget))
+        return InliningStatus_NotInlined;
+
+    for (size_t i = 0; i < target->getBoundFunctionArgumentCount(); i++) {
+        const Value val = target->getBoundFunctionArgument(i);
+        if (val.isObject() && gc::IsInsideNursery(runtime, &val.toObject()))
+            return InliningStatus_NotInlined;
+    }
+
+    const Value thisVal = target->getBoundFunctionThis();
+    if (thisVal.isObject() && gc::IsInsideNursery(runtime, &thisVal.toObject()))
+        return InliningStatus_NotInlined;
+
+    size_t argc = target->getBoundFunctionArgumentCount() + nativeCallInfo.argc();
+    if (argc > ARGS_LENGTH_MAX)
+        return InliningStatus_NotInlined;
+
+    nativeCallInfo.thisArg()->setImplicitlyUsedUnchecked();
+
+    CallInfo callInfo(alloc(), nativeCallInfo.constructing());
+    callInfo.setFun(constant(ObjectValue(*scriptedTarget)));
+    callInfo.setThis(constant(target->getBoundFunctionThis()));
+
+    if (!callInfo.argv().reserve(argc))
+        return InliningStatus_Error;
+
+    for (size_t i = 0; i < target->getBoundFunctionArgumentCount(); i++)
+        callInfo.argv().infallibleAppend(constant(target->getBoundFunctionArgument(i)));
+    for (size_t i = 0; i < nativeCallInfo.argc(); i++)
+        callInfo.argv().infallibleAppend(nativeCallInfo.getArg(i));
+
+    if (!makeCall(scriptedTarget, callInfo, false))
+        return InliningStatus_Error;
+
+    return InliningStatus_Inlined;
+}
+
 } // namespace jit
 } // namespace js
--- a/js/src/jit/MIR.cpp
+++ b/js/src/jit/MIR.cpp
@@ -552,16 +552,19 @@ MConstant::printOpcode(FILE *fp) const
         fprintf(fp, "magic lazyargs");
         break;
       case MIRType_MagicHole:
         fprintf(fp, "magic hole");
         break;
       case MIRType_MagicIsConstructing:
         fprintf(fp, "magic is-constructing");
         break;
+      case MIRType_MagicOptimizedOut:
+        fprintf(fp, "magic optimized-out");
+        break;
       default:
         MOZ_ASSUME_UNREACHABLE("unexpected type");
     }
 }
 
 bool
 MConstant::canProduceFloat32() const
 {
--- a/js/src/jit/RangeAnalysis.cpp
+++ b/js/src/jit/RangeAnalysis.cpp
@@ -3,18 +3,16 @@
  * 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 "jit/RangeAnalysis.h"
 
 #include "mozilla/MathAlgorithms.h"
 
-#include "jsanalyze.h"
-
 #include "jit/Ion.h"
 #include "jit/IonAnalysis.h"
 #include "jit/IonSpewer.h"
 #include "jit/MIR.h"
 #include "jit/MIRGenerator.h"
 #include "jit/MIRGraph.h"
 #include "vm/NumericConversions.h"
 
deleted file mode 100644
--- a/js/src/jsanalyze.cpp
+++ /dev/null
@@ -1,2399 +0,0 @@
-/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
- * vim: set ts=8 sts=4 et sw=4 tw=99:
- * 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 "mozilla/DebugOnly.h"
-#include "mozilla/MathAlgorithms.h"
-#include "mozilla/PodOperations.h"
-
-#include "jscntxt.h"
-#include "jscompartment.h"
-
-#include "vm/Opcodes.h"
-
-#include "jsinferinlines.h"
-#include "jsobjinlines.h"
-#include "jsopcodeinlines.h"
-
-using mozilla::DebugOnly;
-using mozilla::PodCopy;
-using mozilla::PodZero;
-using mozilla::FloorLog2;
-
-namespace js {
-namespace analyze {
-class LoopAnalysis;
-} // namespace analyze
-} // namespace js
-
-namespace mozilla {
-
-template <> struct IsPod<js::analyze::LifetimeVariable> : TrueType {};
-template <> struct IsPod<js::analyze::LoopAnalysis>     : TrueType {};
-template <> struct IsPod<js::analyze::SlotValue>        : TrueType {};
-template <> struct IsPod<js::analyze::SSAValue>         : TrueType {};
-template <> struct IsPod<js::analyze::SSAUseChain>      : TrueType {};
-
-} /* namespace mozilla */
-
-namespace js {
-namespace analyze {
-
-/*
- * There are three analyses we can perform on a JSScript, outlined below.
- * The results of all three are stored in ScriptAnalysis, but the analyses
- * themselves can be performed separately. Along with type inference results,
- * per-script analysis results are tied to the per-compartment analysis pool
- * and are freed on every garbage collection.
- *
- * - Basic bytecode analysis. For each bytecode, determine the stack depth at
- * that point and control flow information needed for compilation. Also does
- * a defined-variables analysis to look for local variables which have uses
- * before definitions.
- *
- * - Lifetime analysis. Makes a backwards pass over the script to approximate
- * the regions where each variable is live, avoiding a full fixpointing
- * live-variables pass. This is based on the algorithm described in:
- *
- *     "Quality and Speed in Linear-scan Register Allocation"
- *     Traub et. al.
- *     PLDI, 1998
- *
- * - SSA analysis of the script's variables and stack values. For each stack
- * value popped and non-escaping local variable or argument read, determines
- * which push(es) or write(s) produced that value.
- *
- * Intermediate type inference results are additionally stored here. The above
- * analyses are independent from type inference.
- */
-
-/* Information about a bytecode instruction. */
-class Bytecode
-{
-    friend class ScriptAnalysis;
-
-  public:
-    Bytecode() { mozilla::PodZero(this); }
-
-    /* --------- Bytecode analysis --------- */
-
-    /* Whether there are any incoming jumps to this instruction. */
-    bool jumpTarget : 1;
-
-    /* Whether there is fallthrough to this instruction from a non-branching instruction. */
-    bool fallthrough : 1;
-
-    /* Whether this instruction is the fall through point of a conditional jump. */
-    bool jumpFallthrough : 1;
-
-    /*
-     * Whether this instruction must always execute, unless the script throws
-     * an exception which it does not later catch.
-     */
-    bool unconditional : 1;
-
-    /* Whether this instruction has been analyzed to get its output defines and stack. */
-    bool analyzed : 1;
-
-    /* Whether this is a catch/finally entry point. */
-    bool exceptionEntry : 1;
-
-    /* Stack depth before this opcode. */
-    uint32_t stackDepth;
-
-  private:
-
-    /* If this is a JSOP_LOOPHEAD or JSOP_LOOPENTRY, information about the loop. */
-    LoopAnalysis *loop;
-
-    /* --------- SSA analysis --------- */
-
-    /* Generated location of each value popped by this bytecode. */
-    SSAValue *poppedValues;
-
-    /* Points where values pushed or written by this bytecode are popped. */
-    SSAUseChain **pushedUses;
-
-    union {
-        /*
-         * If this is a join point (implies jumpTarget), any slots at this
-         * point which can have a different values than at the immediate
-         * predecessor in the bytecode. Array is terminated by an entry with
-         * a zero slot.
-         */
-        SlotValue *newValues;
-
-        /*
-         * Vector used during SSA analysis to store values in need of merging
-         * at this point. If this has incoming forward jumps and we have not
-         * yet reached this point, stores values for entries on the stack and
-         * for variables which have changed since the branch. If this is a loop
-         * head and we haven't reached the back edge yet, stores loop phi nodes
-         * for variables and entries live at the head of the loop.
-         */
-        Vector<SlotValue> *pendingValues;
-    };
-};
-
-/*
- * Information about the lifetime of a local or argument. These form a linked
- * list describing successive intervals in the program where the variable's
- * value may be live. At points in the script not in one of these segments
- * (points in a 'lifetime hole'), the variable is dead and registers containing
- * its type/payload can be discarded without needing to be synced.
- */
-struct Lifetime
-{
-    /*
-     * Start and end offsets of this lifetime. The variable is live at the
-     * beginning of every bytecode in this (inclusive) range.
-     */
-    uint32_t start;
-    uint32_t end;
-
-    /*
-     * In a loop body, endpoint to extend this lifetime with if the variable is
-     * live in the next iteration.
-     */
-    uint32_t savedEnd;
-
-    /*
-     * The start of this lifetime is a bytecode writing the variable. Each
-     * write to a variable is associated with a lifetime.
-     */
-    bool write;
-
-    /* Next lifetime. The variable is dead from this->end to next->start. */
-    Lifetime *next;
-
-    Lifetime(uint32_t offset, uint32_t savedEnd, Lifetime *next)
-        : start(offset), end(offset), savedEnd(savedEnd),
-          write(false), next(next)
-    {}
-};
-
-/* Basic information for a loop. */
-class LoopAnalysis
-{
-  public:
-    /* Any loop this one is nested in. */
-    LoopAnalysis *parent;
-
-    /* Offset of the head of the loop. */
-    uint32_t head;
-
-    /*
-     * Offset of the unique jump going to the head of the loop. The code
-     * between the head and the backedge forms the loop body.
-     */
-    uint32_t backedge;
-};
-
-/* Current lifetime information for a variable. */
-struct LifetimeVariable
-{
-    /* If the variable is currently live, the lifetime segment. */
-    Lifetime *lifetime;
-
-    /* If the variable is currently dead, the next live segment. */
-    Lifetime *saved;
-
-    /* Jump preceding the basic block which killed this variable. */
-    uint32_t savedEnd : 31;
-
-    /* If the variable needs to be kept alive until lifetime->start. */
-    bool ensured : 1;
-
-    /* Whether this variable is live at offset. */
-    Lifetime * live(uint32_t offset) const {
-        if (lifetime && lifetime->end >= offset)
-            return lifetime;
-        Lifetime *segment = lifetime ? lifetime : saved;
-        while (segment && segment->start <= offset) {
-            if (segment->end >= offset)
-                return segment;
-            segment = segment->next;
-        }
-        return nullptr;
-    }
-
-    /*
-     * Get the offset of the first write to the variable in an inclusive range,
-     * UINT32_MAX if the variable is not written in the range.
-     */
-    uint32_t firstWrite(uint32_t start, uint32_t end) const {
-        Lifetime *segment = lifetime ? lifetime : saved;
-        while (segment && segment->start <= end) {
-            if (segment->start >= start && segment->write)
-                return segment->start;
-            segment = segment->next;
-        }
-        return UINT32_MAX;
-    }
-    uint32_t firstWrite(LoopAnalysis *loop) const {
-        return firstWrite(loop->head, loop->backedge);
-    }
-
-    /*
-     * If the variable is only written once in the body of a loop, offset of
-     * that write. UINT32_MAX otherwise.
-     */
-    uint32_t onlyWrite(LoopAnalysis *loop) const {
-        uint32_t offset = UINT32_MAX;
-        Lifetime *segment = lifetime ? lifetime : saved;
-        while (segment && segment->start <= loop->backedge) {
-            if (segment->start >= loop->head && segment->write) {
-                if (offset != UINT32_MAX)
-                    return UINT32_MAX;
-                offset = segment->start;
-            }
-            segment = segment->next;
-        }
-        return offset;
-    }
-
-#ifdef DEBUG
-    void print() const;
-#endif
-};
-
-struct SSAPhiNode;
-
-/*
- * Representation of values on stack or in slots at each point in the script.
- * Values are independent from the bytecode position, and mean the same thing
- * everywhere in the script. SSA values are immutable, except for contents of
- * the values and types in an SSAPhiNode.
- */
-class SSAValue
-{
-    friend class ScriptAnalysis;
-
-  public:
-    enum Kind {
-        EMPTY  = 0, /* Invalid entry. */
-        PUSHED = 1, /* Value pushed by some bytecode. */
-        VAR    = 2, /* Initial or written value to some argument or local. */
-        PHI    = 3  /* Selector for one of several values. */
-    };
-
-    Kind kind() const {
-        JS_ASSERT(u.pushed.kind == u.var.kind && u.pushed.kind == u.phi.kind);
-
-        /* Use a bitmask because MSVC wants to use -1 for PHI nodes. */
-        return (Kind) (u.pushed.kind & 0x3);
-    }
-
-    bool operator==(const SSAValue &o) const {
-        return !memcmp(this, &o, sizeof(SSAValue));
-    }
-
-    /* Accessors for values pushed by a bytecode within this script. */
-
-    uint32_t pushedOffset() const {
-        JS_ASSERT(kind() == PUSHED);
-        return u.pushed.offset;
-    }
-
-    uint32_t pushedIndex() const {
-        JS_ASSERT(kind() == PUSHED);
-        return u.pushed.index;
-    }
-
-    /* Accessors for initial and written values of arguments and (undefined) locals. */
-
-    bool varInitial() const {
-        JS_ASSERT(kind() == VAR);
-        return u.var.initial;
-    }
-
-    uint32_t varSlot() const {
-        JS_ASSERT(kind() == VAR);
-        return u.var.slot;
-    }
-
-    uint32_t varOffset() const {
-        JS_ASSERT(!varInitial());
-        return u.var.offset;
-    }
-
-    /* Accessors for phi nodes. */
-
-    uint32_t phiSlot() const;
-    uint32_t phiLength() const;
-    const SSAValue &phiValue(uint32_t i) const;
-
-    /* Offset at which this phi node was created. */
-    uint32_t phiOffset() const {
-        JS_ASSERT(kind() == PHI);
-        return u.phi.offset;
-    }
-
-    SSAPhiNode *phiNode() const {
-        JS_ASSERT(kind() == PHI);
-        return u.phi.node;
-    }
-
-    /* Other accessors. */
-
-#ifdef DEBUG
-    void print() const;
-#endif
-
-    void clear() {
-        mozilla::PodZero(this);
-        JS_ASSERT(kind() == EMPTY);
-    }
-
-    void initPushed(uint32_t offset, uint32_t index) {
-        clear();
-        u.pushed.kind = PUSHED;
-        u.pushed.offset = offset;
-        u.pushed.index = index;
-    }
-
-    static SSAValue PushedValue(uint32_t offset, uint32_t index) {
-        SSAValue v;
-        v.initPushed(offset, index);
-        return v;
-    }
-
-    void initInitial(uint32_t slot) {
-        clear();
-        u.var.kind = VAR;
-        u.var.initial = true;
-        u.var.slot = slot;
-    }
-
-    void initWritten(uint32_t slot, uint32_t offset) {
-        clear();
-        u.var.kind = VAR;
-        u.var.initial = false;
-        u.var.slot = slot;
-        u.var.offset = offset;
-    }
-
-    static SSAValue WrittenVar(uint32_t slot, uint32_t offset) {
-        SSAValue v;
-        v.initWritten(slot, offset);
-        return v;
-    }
-
-    void initPhi(uint32_t offset, SSAPhiNode *node) {
-        clear();
-        u.phi.kind = PHI;
-        u.phi.offset = offset;
-        u.phi.node = node;
-    }
-
-    static SSAValue PhiValue(uint32_t offset, SSAPhiNode *node) {
-        SSAValue v;
-        v.initPhi(offset, node);
-        return v;
-    }
-
-  private:
-    union {
-        struct {
-            Kind kind : 2;
-            uint32_t offset : 30;
-            uint32_t index;
-        } pushed;
-        struct {
-            Kind kind : 2;
-            bool initial : 1;
-            uint32_t slot : 29;
-            uint32_t offset;
-        } var;
-        struct {
-            Kind kind : 2;
-            uint32_t offset : 30;
-            SSAPhiNode *node;
-        } phi;
-    } u;
-};
-
-/*
- * Mutable component of a phi node, with the possible values of the phi
- * and the possible types of the node as determined by type inference.
- * When phi nodes are copied around, any updates to the original will
- * be seen by all copies made.
- */
-struct SSAPhiNode
-{
-    uint32_t slot;
-    uint32_t length;
-    SSAValue *options;
-    SSAUseChain *uses;
-    SSAPhiNode() { mozilla::PodZero(this); }
-};
-
-inline uint32_t
-SSAValue::phiSlot() const
-{
-    return u.phi.node->slot;
-}
-
-inline uint32_t
-SSAValue::phiLength() const
-{
-    JS_ASSERT(kind() == PHI);
-    return u.phi.node->length;
-}
-
-inline const SSAValue &
-SSAValue::phiValue(uint32_t i) const
-{
-    JS_ASSERT(kind() == PHI && i < phiLength());
-    return u.phi.node->options[i];
-}
-
-class SSAUseChain
-{
-  public:
-    bool popped : 1;
-    uint32_t offset : 31;
-    /* FIXME: Assert that only the proper arm of this union is accessed. */
-    union {
-        uint32_t which;
-        SSAPhiNode *phi;
-    } u;
-    SSAUseChain *next;
-
-    SSAUseChain() { mozilla::PodZero(this); }
-};
-
-class SlotValue
-{
-  public:
-    uint32_t slot;
-    SSAValue value;
-    SlotValue(uint32_t slot, const SSAValue &value) : slot(slot), value(value) {}
-};
-
-/////////////////////////////////////////////////////////////////////
-// Bytecode
-/////////////////////////////////////////////////////////////////////
-
-#ifdef DEBUG
-void
-PrintBytecode(JSContext *cx, HandleScript script, jsbytecode *pc)
-{
-    fprintf(stderr, "#%u:", script->id());
-    Sprinter sprinter(cx);
-    if (!sprinter.init())
-        return;
-    js_Disassemble1(cx, script, pc, script->pcToOffset(pc), true, &sprinter);
-    fprintf(stderr, "%s", sprinter.string());
-}
-#endif
-
-/*
- * For opcodes which assign to a local variable or argument, track an extra def
- * during SSA analysis for the value's use chain and assigned type.
- */
-static inline bool
-ExtendedDef(jsbytecode *pc)
-{
-    switch ((JSOp)*pc) {
-      case JSOP_SETARG:
-      case JSOP_SETLOCAL:
-        return true;
-      default:
-        return false;
-    }
-}
-
-/*
- * For opcodes which access local variables or arguments, we track an extra
- * use during SSA analysis for the value of the variable before/after the op.
- */
-static inline bool
-ExtendedUse(jsbytecode *pc)
-{
-    if (ExtendedDef(pc))
-        return true;
-    switch ((JSOp)*pc) {
-      case JSOP_GETARG:
-      case JSOP_GETLOCAL:
-        return true;
-      default:
-        return false;
-    }
-}
-
-static inline unsigned
-FollowBranch(JSContext *cx, JSScript *script, unsigned offset)
-{
-    /*
-     * Get the target offset of a branch. For GOTO opcodes implementing
-     * 'continue' statements, short circuit any artificial backwards jump
-     * inserted by the emitter.
-     */
-    jsbytecode *pc = script->offsetToPC(offset);
-    unsigned targetOffset = offset + GET_JUMP_OFFSET(pc);
-    if (targetOffset < offset) {
-        jsbytecode *target = script->offsetToPC(targetOffset);
-        JSOp nop = JSOp(*target);
-        if (nop == JSOP_GOTO)
-            return targetOffset + GET_JUMP_OFFSET(target);
-    }
-    return targetOffset;
-}
-
-static inline uint32_t StackSlot(JSScript *script, uint32_t index) {
-    return TotalSlots(script) + index;
-}
-
-static inline uint32_t GetBytecodeSlot(JSScript *script, jsbytecode *pc)
-{
-    switch (JSOp(*pc)) {
-
-      case JSOP_GETARG:
-      case JSOP_SETARG:
-        return ArgSlot(GET_ARGNO(pc));
-
-      case JSOP_GETLOCAL:
-      case JSOP_SETLOCAL:
-        return LocalSlot(script, GET_LOCALNO(pc));
-
-      case JSOP_THIS:
-        return ThisSlot();
-
-      default:
-        MOZ_ASSUME_UNREACHABLE("Bad slot opcode");
-    }
-}
-
-/////////////////////////////////////////////////////////////////////
-// Bytecode Analysis
-/////////////////////////////////////////////////////////////////////
-
-inline bool
-ScriptAnalysis::addJump(JSContext *cx, unsigned offset,
-                        unsigned *currentOffset, unsigned *forwardJump, unsigned *forwardLoop,
-                        unsigned stackDepth)
-{
-    JS_ASSERT(offset < script_->length());
-
-    Bytecode *&code = codeArray[offset];
-    if (!code) {
-        code = cx->typeLifoAlloc().new_<Bytecode>();
-        if (!code) {
-            js_ReportOutOfMemory(cx);
-            return false;
-        }
-        code->stackDepth = stackDepth;
-    }
-    JS_ASSERT(code->stackDepth == stackDepth);
-
-    code->jumpTarget = true;
-
-    if (offset < *currentOffset) {
-        if (!code->analyzed) {
-            /*
-             * Backedge in a while/for loop, whose body has not been analyzed
-             * due to a lack of fallthrough at the loop head. Roll back the
-             * offset to analyze the body.
-             */
-            if (*forwardJump == 0)
-                *forwardJump = *currentOffset;
-            if (*forwardLoop == 0)
-                *forwardLoop = *currentOffset;
-            *currentOffset = offset;
-        }
-    } else if (offset > *forwardJump) {
-        *forwardJump = offset;
-    }
-
-    return true;
-}
-
-inline bool
-ScriptAnalysis::jumpTarget(uint32_t offset)
-{
-    JS_ASSERT(offset < script_->length());
-    return codeArray[offset] && codeArray[offset]->jumpTarget;
-}
-
-inline bool
-ScriptAnalysis::jumpTarget(const jsbytecode *pc)
-{
-    return jumpTarget(script_->pcToOffset(pc));
-}
-
-inline const SSAValue &
-ScriptAnalysis::poppedValue(uint32_t offset, uint32_t which)
-{
-    JS_ASSERT(which < GetUseCount(script_, offset) +
-              (ExtendedUse(script_->offsetToPC(offset)) ? 1 : 0));
-    return getCode(offset).poppedValues[which];
-}
-
-inline const SSAValue &
-ScriptAnalysis::poppedValue(const jsbytecode *pc, uint32_t which)
-{
-    return poppedValue(script_->pcToOffset(pc), which);
-}
-
-inline const SlotValue *
-ScriptAnalysis::newValues(uint32_t offset)
-{
-    JS_ASSERT(offset < script_->length());
-    return getCode(offset).newValues;
-}
-
-inline const SlotValue *
-ScriptAnalysis::newValues(const jsbytecode *pc)
-{
-    return newValues(script_->pcToOffset(pc));
-}
-
-inline bool
-ScriptAnalysis::trackUseChain(const SSAValue &v)
-{
-    JS_ASSERT_IF(v.kind() == SSAValue::VAR, trackSlot(v.varSlot()));
-    return v.kind() != SSAValue::EMPTY &&
-        (v.kind() != SSAValue::VAR || !v.varInitial());
-}
-
-/*
- * Get the use chain for an SSA value.
- */
-inline SSAUseChain *&
-ScriptAnalysis::useChain(const SSAValue &v)
-{
-    JS_ASSERT(trackUseChain(v));
-    if (v.kind() == SSAValue::PUSHED)
-        return getCode(v.pushedOffset()).pushedUses[v.pushedIndex()];
-    if (v.kind() == SSAValue::VAR)
-        return getCode(v.varOffset()).pushedUses[GetDefCount(script_, v.varOffset())];
-    return v.phiNode()->uses;
-}
-
-/* For a JSOP_CALL* op, get the pc of the corresponding JSOP_CALL/NEW/etc. */
-inline jsbytecode *
-ScriptAnalysis::getCallPC(jsbytecode *pc)
-{
-    SSAUseChain *uses = useChain(SSAValue::PushedValue(script_->pcToOffset(pc), 0));
-    JS_ASSERT(uses && uses->popped);
-    JS_ASSERT(js_CodeSpec[script_->code()[uses->offset]].format & JOF_INVOKE);
-    return script_->offsetToPC(uses->offset);
-}
-
-/* Accessors for local variable information. */
-
-/*
- * Escaping slots include all slots that can be accessed in ways other than
- * through the corresponding LOCAL/ARG opcode. This includes all closed
- * slots in the script, all slots in scripts which use eval or are in debug
- * mode, and slots which are aliased by NAME or similar opcodes in the
- * containing script (which does not imply the variable is closed).
- */
-inline bool
-ScriptAnalysis::slotEscapes(uint32_t slot)
-{
-    JS_ASSERT(script_->compartment()->activeAnalysis);
-    if (slot >= numSlots)
-        return true;
-    return escapedSlots[slot];
-}
-
-/*
- * Whether we distinguish different writes of this variable while doing
- * SSA analysis. Escaping locals can be written in other scripts, and the
- * presence of NAME opcodes which could alias local variables or arguments
- * keeps us from tracking variable values at each point.
- */
-inline bool
-ScriptAnalysis::trackSlot(uint32_t slot)
-{
-    return !slotEscapes(slot) && canTrackVars && slot < 1000;
-}
-
-inline const LifetimeVariable &
-ScriptAnalysis::liveness(uint32_t slot)
-{
-    JS_ASSERT(script_->compartment()->activeAnalysis);
-    JS_ASSERT(!slotEscapes(slot));
-    return lifetimes[slot];
-}
-
-bool
-ScriptAnalysis::analyzeBytecode(JSContext *cx)
-{
-    JS_ASSERT(cx->compartment()->activeAnalysis);
-    JS_ASSERT(!codeArray);
-
-    LifoAlloc &alloc = cx->typeLifoAlloc();
-
-    numSlots = TotalSlots(script_);
-
-    unsigned length = script_->length();
-    codeArray = alloc.newArray<Bytecode*>(length);
-    escapedSlots = alloc.newArray<bool>(numSlots);
-
-    if (!codeArray || !escapedSlots) {
-        js_ReportOutOfMemory(cx);
-        return false;
-    }
-
-    PodZero(codeArray, length);
-
-    /*
-     * Populate arg and local slots which can escape and be accessed in ways
-     * other than through ARG* and LOCAL* opcodes (though arguments can still
-     * be indirectly read but not written through 'arguments' properties).
-     * All escaping locals are treated as having possible use-before-defs.
-     * Conservatively use 'argumentsHasVarBinding' instead of 'needsArgsObj'
-     * (needsArgsObj requires SSA which requires escapedSlots). Lastly, the
-     * debugger can access any local at any time. Even though debugger
-     * reads/writes are monitored by the DebugScopeProxy, this monitoring
-     * updates the flow-insensitive type sets, so we cannot use SSA.
-     */
-
-    PodZero(escapedSlots, numSlots);
-
-    bool allVarsAliased = script_->compartment()->debugMode();
-    bool allArgsAliased = allVarsAliased || script_->argumentsHasVarBinding();
-
-    RootedScript script(cx, script_);
-    for (BindingIter bi(script); bi; bi++) {
-        if (bi->kind() == Binding::ARGUMENT)
-            escapedSlots[ArgSlot(bi.frameIndex())] = allArgsAliased || bi->aliased();
-        else
-            escapedSlots[LocalSlot(script_, bi.frameIndex())] = allVarsAliased || bi->aliased();
-    }
-
-    canTrackVars = true;
-
-    /*
-     * If we are in the middle of one or more jumps, the offset of the highest
-     * target jumping over this bytecode.  Includes implicit jumps from
-     * try/catch/finally blocks.
-     */
-    unsigned forwardJump = 0;
-
-    /* If we are in the middle of a loop, the offset of the highest backedge. */
-    unsigned forwardLoop = 0;
-
-    /*
-     * If we are in the middle of a try block, the offset of the highest
-     * catch/finally/enditer.
-     */
-    unsigned forwardCatch = 0;
-
-    /* Fill in stack depth and definitions at initial bytecode. */
-    Bytecode *startcode = alloc.new_<Bytecode>();
-    if (!startcode) {
-        js_ReportOutOfMemory(cx);
-        return false;
-    }
-
-    startcode->stackDepth = 0;
-    codeArray[0] = startcode;
-
-    unsigned offset, nextOffset = 0;
-    while (nextOffset < length) {
-        offset = nextOffset;
-
-        JS_ASSERT(forwardCatch <= forwardJump);
-
-        /* Check if the current forward jump/try-block has finished. */
-        if (forwardJump && forwardJump == offset)
-            forwardJump = 0;
-        if (forwardCatch && forwardCatch == offset)
-            forwardCatch = 0;
-
-        Bytecode *code = maybeCode(offset);
-        jsbytecode *pc = script_->offsetToPC(offset);
-
-        JSOp op = (JSOp)*pc;
-        JS_ASSERT(op < JSOP_LIMIT);
-
-        /* Immediate successor of this bytecode. */
-        unsigned successorOffset = offset + GetBytecodeLength(pc);
-
-        /*
-         * Next bytecode to analyze.  This is either the successor, or is an
-         * earlier bytecode if this bytecode has a loop backedge.
-         */
-        nextOffset = successorOffset;
-
-        if (!code) {
-            /* Haven't found a path by which this bytecode is reachable. */
-            continue;
-        }
-
-        /*
-         * Update info about bytecodes inside loops, which may have been
-         * analyzed before the backedge was seen.
-         */
-        if (forwardLoop) {
-            if (forwardLoop <= offset)
-                forwardLoop = 0;
-        }
-
-        if (code->analyzed) {
-            /* No need to reanalyze, see Bytecode::mergeDefines. */
-            continue;
-        }
-
-        code->analyzed = true;
-
-        if (script_->hasBreakpointsAt(pc))
-            canTrackVars = false;
-
-        unsigned stackDepth = code->stackDepth;
-
-        if (!forwardJump)
-            code->unconditional = true;
-
-        unsigned nuses = GetUseCount(script_, offset);
-        unsigned ndefs = GetDefCount(script_, offset);
-
-        JS_ASSERT(stackDepth >= nuses);
-        stackDepth -= nuses;
-        stackDepth += ndefs;
-
-        switch (op) {
-
-          case JSOP_DEFFUN:
-          case JSOP_DEFVAR:
-          case JSOP_DEFCONST:
-          case JSOP_SETCONST:
-            canTrackVars = false;
-            break;
-
-          case JSOP_EVAL:
-          case JSOP_SPREADEVAL:
-          case JSOP_ENTERWITH:
-            canTrackVars = false;
-            break;
-
-          case JSOP_TABLESWITCH: {
-            unsigned defaultOffset = offset + GET_JUMP_OFFSET(pc);
-            jsbytecode *pc2 = pc + JUMP_OFFSET_LEN;
-            int32_t low = GET_JUMP_OFFSET(pc2);
-            pc2 += JUMP_OFFSET_LEN;
-            int32_t high = GET_JUMP_OFFSET(pc2);
-            pc2 += JUMP_OFFSET_LEN;
-
-            if (!addJump(cx, defaultOffset, &nextOffset, &forwardJump, &forwardLoop, stackDepth))
-                return false;
-
-            for (int32_t i = low; i <= high; i++) {
-                unsigned targetOffset = offset + GET_JUMP_OFFSET(pc2);
-                if (targetOffset != offset) {
-                    if (!addJump(cx, targetOffset, &nextOffset, &forwardJump, &forwardLoop, stackDepth))
-                        return false;
-                }
-                pc2 += JUMP_OFFSET_LEN;
-            }
-            break;
-          }
-
-          case JSOP_TRY: {
-            /*
-             * Everything between a try and corresponding catch or finally is conditional.
-             * Note that there is no problem with code which is skipped by a thrown
-             * exception but is not caught by a later handler in the same function:
-             * no more code will execute, and it does not matter what is defined.
-             */
-            JSTryNote *tn = script_->trynotes()->vector;
-            JSTryNote *tnlimit = tn + script_->trynotes()->length;
-            for (; tn < tnlimit; tn++) {
-                unsigned startOffset = script_->mainOffset() + tn->start;
-                if (startOffset == offset + 1) {
-                    unsigned catchOffset = startOffset + tn->length;
-
-                    /* This will overestimate try block code, for multiple catch/finally. */
-                    if (catchOffset > forwardCatch)
-                        forwardCatch = catchOffset;
-
-                    if (tn->kind != JSTRY_ITER && tn->kind != JSTRY_LOOP) {
-                        if (!addJump(cx, catchOffset, &nextOffset, &forwardJump, &forwardLoop, stackDepth))
-                            return false;
-                        getCode(catchOffset).exceptionEntry = true;
-                    }
-                }
-            }
-            break;
-          }
-
-          case JSOP_GETLOCAL:
-          case JSOP_SETLOCAL:
-            JS_ASSERT(GET_LOCALNO(pc) < script_->nfixed());
-            break;
-
-          default:
-            break;
-        }
-
-        bool jump = IsJumpOpcode(op);
-
-        /* Check basic jump opcodes, which may or may not have a fallthrough. */
-        if (jump) {
-            /* Case instructions do not push the lvalue back when branching. */
-            unsigned newStackDepth = stackDepth;
-            if (op == JSOP_CASE)
-                newStackDepth--;
-
-            unsigned targetOffset = offset + GET_JUMP_OFFSET(pc);
-            if (!addJump(cx, targetOffset, &nextOffset, &forwardJump, &forwardLoop, newStackDepth))
-                return false;
-        }
-
-        /* Handle any fallthrough from this opcode. */
-        if (BytecodeFallsThrough(op)) {
-            JS_ASSERT(successorOffset < script_->length());
-
-            Bytecode *&nextcode = codeArray[successorOffset];
-
-            if (!nextcode) {
-                nextcode = alloc.new_<Bytecode>();
-                if (!nextcode) {
-                    js_ReportOutOfMemory(cx);
-                    return false;
-                }
-                nextcode->stackDepth = stackDepth;
-            }
-            JS_ASSERT(nextcode->stackDepth == stackDepth);
-
-            if (jump)
-                nextcode->jumpFallthrough = true;
-
-            /* Treat the fallthrough of a branch instruction as a jump target. */
-            if (jump)
-                nextcode->jumpTarget = true;
-            else
-                nextcode->fallthrough = true;
-        }
-    }
-
-    JS_ASSERT(forwardJump == 0 && forwardLoop == 0 && forwardCatch == 0);
-
-    /*
-     * Always ensure that a script's arguments usage has been analyzed before
-     * entering the script. This allows the functionPrologue to ensure that
-     * arguments are always created eagerly which simplifies interp logic.
-     */
-    if (!script_->analyzedArgsUsage()) {
-        if (!analyzeLifetimes(cx))
-            return false;
-        if (!analyzeSSA(cx))
-            return false;
-
-        /*
-         * Now that we have full SSA information for the script, analyze whether
-         * we can avoid creating the arguments object.
-         */
-        script_->setNeedsArgsObj(needsArgsObj(cx));
-    }
-
-    return true;
-}
-
-/////////////////////////////////////////////////////////////////////
-// Lifetime Analysis
-/////////////////////////////////////////////////////////////////////
-
-bool
-ScriptAnalysis::analyzeLifetimes(JSContext *cx)
-{
-    JS_ASSERT(cx->compartment()->activeAnalysis);
-    JS_ASSERT(codeArray);
-    JS_ASSERT(!lifetimes);
-
-    LifoAlloc &alloc = cx->typeLifoAlloc();
-
-    lifetimes = alloc.newArray<LifetimeVariable>(numSlots);
-    if (!lifetimes) {
-        js_ReportOutOfMemory(cx);
-        return false;
-    }
-    PodZero(lifetimes, numSlots);
-
-    /*
-     * Variables which are currently dead. On forward branches to locations
-     * where these are live, they need to be marked as live.
-     */
-    LifetimeVariable **saved = cx->pod_calloc<LifetimeVariable*>(numSlots);
-    if (!saved) {
-        js_ReportOutOfMemory(cx);
-        return false;
-    }
-    unsigned savedCount = 0;
-
-    LoopAnalysis *loop = nullptr;
-
-    uint32_t offset = script_->length() - 1;
-    while (offset < script_->length()) {
-        Bytecode *code = maybeCode(offset);
-        if (!code) {
-            offset--;
-            continue;
-        }
-
-        jsbytecode *pc = script_->offsetToPC(offset);
-
-        JSOp op = (JSOp) *pc;
-
-        if (op == JSOP_LOOPHEAD && code->loop) {
-            /*
-             * This is the head of a loop, we need to go and make sure that any
-             * variables live at the head are live at the backedge and points prior.
-             * For each such variable, look for the last lifetime segment in the body
-             * and extend it to the end of the loop.
-             */
-            JS_ASSERT(loop == code->loop);
-            unsigned backedge = code->loop->backedge;
-            for (unsigned i = 0; i < numSlots; i++) {
-                if (lifetimes[i].lifetime) {
-                    if (!extendVariable(cx, lifetimes[i], offset, backedge))
-                        return false;
-                }
-            }
-
-            loop = loop->parent;
-            JS_ASSERT_IF(loop, loop->head < offset);
-        }
-
-        if (code->exceptionEntry) {
-            DebugOnly<bool> found = false;
-            JSTryNote *tn = script_->trynotes()->vector;
-            JSTryNote *tnlimit = tn + script_->trynotes()->length;
-            for (; tn < tnlimit; tn++) {
-                unsigned startOffset = script_->mainOffset() + tn->start;
-                if (startOffset + tn->length == offset) {
-                    /*
-                     * Extend all live variables at exception entry to the start of
-                     * the try block.
-                     */
-                    for (unsigned i = 0; i < numSlots; i++) {
-                        if (lifetimes[i].lifetime)
-                            ensureVariable(lifetimes[i], startOffset - 1);
-                    }
-
-                    found = true;
-                    break;
-                }
-            }
-            JS_ASSERT(found);
-        }
-
-        switch (op) {
-          case JSOP_GETARG:
-          case JSOP_GETLOCAL:
-          case JSOP_THIS: {
-            uint32_t slot = GetBytecodeSlot(script_, pc);
-            if (!slotEscapes(slot)) {
-                if (!addVariable(cx, lifetimes[slot], offset, saved, savedCount))
-                    return false;
-            }
-            break;
-          }
-
-          case JSOP_SETARG:
-          case JSOP_SETLOCAL: {
-            uint32_t slot = GetBytecodeSlot(script_, pc);
-            if (!slotEscapes(slot)) {
-                if (!killVariable(cx, lifetimes[slot], offset, saved, savedCount))
-                    return false;
-            }
-            break;
-          }
-
-          case JSOP_TABLESWITCH:
-            /* Restore all saved variables. :FIXME: maybe do this precisely. */
-            for (unsigned i = 0; i < savedCount; i++) {
-                LifetimeVariable &var = *saved[i];
-                uint32_t savedEnd = var.savedEnd;
-                var.lifetime = alloc.new_<Lifetime>(offset, savedEnd, var.saved);
-                if (!var.lifetime) {
-                    js_free(saved);
-                    js_ReportOutOfMemory(cx);
-                    return false;
-                }
-                var.saved = nullptr;
-                saved[i--] = saved[--savedCount];
-            }
-            savedCount = 0;
-            break;
-
-          case JSOP_TRY:
-            for (unsigned i = 0; i < numSlots; i++) {
-                LifetimeVariable &var = lifetimes[i];
-                if (var.ensured) {
-                    JS_ASSERT(var.lifetime);
-                    if (var.lifetime->start == offset)
-                        var.ensured = false;
-                }
-            }
-            break;
-
-          case JSOP_LOOPENTRY:
-            getCode(offset).loop = loop;
-            break;
-
-          default:;
-        }
-
-        if (IsJumpOpcode(op)) {
-            /*
-             * Forward jumps need to pull in all variables which are live at
-             * their target offset --- the variables live before the jump are
-             * the union of those live at the fallthrough and at the target.
-             */
-            uint32_t targetOffset = FollowBranch(cx, script_, offset);
-
-            if (targetOffset < offset) {
-                /* This is a loop back edge, no lifetime to pull in yet. */
-
-#ifdef DEBUG
-                JSOp nop = JSOp(script_->code()[targetOffset]);
-                JS_ASSERT(nop == JSOP_LOOPHEAD);
-#endif
-
-                LoopAnalysis *nloop = alloc.new_<LoopAnalysis>();
-                if (!nloop) {
-                    js_free(saved);
-                    js_ReportOutOfMemory(cx);
-                    return false;
-                }
-                PodZero(nloop);
-
-                nloop->parent = loop;
-                loop = nloop;
-
-                getCode(targetOffset).loop = loop;
-                loop->head = targetOffset;
-                loop->backedge = offset;
-
-                /*
-                 * Find the entry jump, which will be a GOTO for 'for' or
-                 * 'while' loops or a fallthrough for 'do while' loops.
-                 */
-                uint32_t entry = targetOffset;
-                if (entry) {
-                    do {
-                        entry--;
-                    } while (!maybeCode(entry));
-
-                    jsbytecode *entrypc = script_->offsetToPC(entry);
-
-                    if (JSOp(*entrypc) == JSOP_GOTO)
-                        entry += GET_JUMP_OFFSET(entrypc);
-                    else
-                        entry = targetOffset;
-                } else {
-                    /* Do-while loop at the start of the script. */
-                    entry = targetOffset;
-                }
-                JS_ASSERT(script_->code()[entry] == JSOP_LOOPHEAD ||
-                          script_->code()[entry] == JSOP_LOOPENTRY);
-            } else {
-                for (unsigned i = 0; i < savedCount; i++) {
-                    LifetimeVariable &var = *saved[i];
-                    JS_ASSERT(!var.lifetime && var.saved);
-                    if (var.live(targetOffset)) {
-                        /*
-                         * Jumping to a place where this variable is live. Make a new
-                         * lifetime segment for the variable.
-                         */
-                        uint32_t savedEnd = var.savedEnd;
-                        var.lifetime = alloc.new_<Lifetime>(offset, savedEnd, var.saved);
-                        if (!var.lifetime) {
-                            js_free(saved);
-                            js_ReportOutOfMemory(cx);
-                            return false;
-                        }
-                        var.saved = nullptr;
-                        saved[i--] = saved[--savedCount];
-                    } else if (loop && !var.savedEnd) {
-                        /*
-                         * This jump precedes the basic block which killed the variable,
-                         * remember it and use it for the end of the next lifetime
-                         * segment should the variable become live again. This is needed
-                         * for loops, as if we wrap liveness around the loop the isLive
-                         * test below may have given the wrong answer.
-                         */
-                        var.savedEnd = offset;
-                    }
-                }
-            }
-        }
-
-        offset--;
-    }
-
-    js_free(saved);
-
-    return true;
-}
-
-#ifdef DEBUG
-void
-LifetimeVariable::print() const
-{
-    Lifetime *segment = lifetime ? lifetime : saved;
-    while (segment) {
-        printf(" (%u,%u)", segment->start, segment->end);
-        segment = segment->next;
-    }
-    printf("\n");
-}
-#endif /* DEBUG */
-
-inline bool
-ScriptAnalysis::addVariable(JSContext *cx, LifetimeVariable &var, unsigned offset,
-                            LifetimeVariable **&saved, unsigned &savedCount)
-{
-    if (var.lifetime) {
-        if (var.ensured)
-            return true;
-
-        JS_ASSERT(offset < var.lifetime->start);
-        var.lifetime->start = offset;
-    } else {
-        if (var.saved) {
-            /* Remove from the list of saved entries. */
-            for (unsigned i = 0; i < savedCount; i++) {
-                if (saved[i] == &var) {
-                    JS_ASSERT(savedCount);
-                    saved[i--] = saved[--savedCount];
-                    break;
-                }
-            }
-        }
-        uint32_t savedEnd = var.savedEnd;
-        var.lifetime = cx->typeLifoAlloc().new_<Lifetime>(offset, savedEnd, var.saved);
-        if (!var.lifetime) {
-            js_ReportOutOfMemory(cx);
-            return false;
-        }
-        var.saved = nullptr;
-    }
-
-    return true;
-}
-
-inline bool
-ScriptAnalysis::killVariable(JSContext *cx, LifetimeVariable &var, unsigned offset,
-                             LifetimeVariable **&saved, unsigned &savedCount)
-{
-    if (!var.lifetime) {
-        /* Make a point lifetime indicating the write. */
-        uint32_t savedEnd = var.savedEnd;
-        Lifetime *lifetime = cx->typeLifoAlloc().new_<Lifetime>(offset, savedEnd, var.saved);
-        if (!lifetime) {
-            js_ReportOutOfMemory(cx);
-            return false;
-        }
-        if (!var.saved)
-            saved[savedCount++] = &var;
-        var.saved = lifetime;
-        var.saved->write = true;
-        var.savedEnd = 0;
-        return true;
-    }
-
-    JS_ASSERT_IF(!var.ensured, offset < var.lifetime->start);
-    unsigned start = var.lifetime->start;
-
-    /*
-     * The variable is considered to be live at the bytecode which kills it
-     * (just not at earlier bytecodes). This behavior is needed by downstream
-     * register allocation (see FrameState::bestEvictReg).
-     */
-    var.lifetime->start = offset;
-    var.lifetime->write = true;
-
-    if (var.ensured) {
-        /*
-         * The variable is live even before the write, due to an enclosing try
-         * block. We need to split the lifetime to indicate there was a write.
-         * We set the new interval's savedEnd to 0, since it will always be
-         * adjacent to the old interval, so it never needs to be extended.
-         */
-        var.lifetime = cx->typeLifoAlloc().new_<Lifetime>(start, 0, var.lifetime);
-        if (!var.lifetime) {
-            js_ReportOutOfMemory(cx);
-            return false;
-        }
-        var.lifetime->end = offset;
-    } else {
-        var.saved = var.lifetime;
-        var.savedEnd = 0;
-        var.lifetime = nullptr;
-
-        saved[savedCount++] = &var;
-    }
-
-    return true;
-}
-
-inline bool
-ScriptAnalysis::extendVariable(JSContext *cx, LifetimeVariable &var,
-                               unsigned start, unsigned end)
-{
-    JS_ASSERT(var.lifetime);
-    if (var.ensured) {
-        /*
-         * If we are still ensured to be live, the try block must scope over
-         * the loop, in which case the variable is already guaranteed to be
-         * live for the entire loop.
-         */
-        JS_ASSERT(var.lifetime->start < start);
-        return true;
-    }
-
-    var.lifetime->start = start;
-
-    /*
-     * Consider this code:
-     *
-     *   while (...) { (#1)
-     *       use x;    (#2)
-     *       ...
-     *       x = ...;  (#3)
-     *       ...
-     *   }             (#4)
-     *
-     * Just before analyzing the while statement, there would be a live range
-     * from #1..#2 and a "point range" at #3. The job of extendVariable is to
-     * create a new live range from #3..#4.
-     *
-     * However, more extensions may be required if the definition of x is
-     * conditional. Consider the following.
-     *
-     *   while (...) {     (#1)
-     *       use x;        (#2)
-     *       ...
-     *       if (...)      (#5)
-     *           x = ...;  (#3)
-     *       ...
-     *   }                 (#4)
-     *
-     * Assume that x is not used after the loop. Then, before extendVariable is
-     * run, the live ranges would be the same as before (#1..#2 and #3..#3). We
-     * still need to create a range from #3..#4. But, since the assignment at #3
-     * may never run, we also need to create a range from #2..#3. This is done
-     * as follows.
-     *
-     * Each time we create a Lifetime, we store the start of the most recently
-     * seen sequence of conditional code in the Lifetime's savedEnd field. So,
-     * when creating the Lifetime at #2, we set the Lifetime's savedEnd to
-     * #5. (The start of the most recent conditional is cached in each
-     * variable's savedEnd field.) Consequently, extendVariable is able to
-     * create a new interval from #2..#5 using the savedEnd field of the
-     * existing #1..#2 interval.
-     */
-
-    Lifetime *segment = var.lifetime;
-    while (segment && segment->start < end) {
-        uint32_t savedEnd = segment->savedEnd;
-        if (!segment->next || segment->next->start >= end) {
-            /*
-             * savedEnd is only set for variables killed in the middle of the
-             * loop. Make a tail segment connecting the last use with the
-             * back edge.
-             */
-            if (segment->end >= end) {
-                /* Variable known to be live after the loop finishes. */
-                break;
-            }
-            savedEnd = end;
-        }
-        JS_ASSERT(savedEnd <= end);
-        if (savedEnd > segment->end) {
-            Lifetime *tail = cx->typeLifoAlloc().new_<Lifetime>(savedEnd, 0, segment->next);
-            if (!tail) {
-                js_ReportOutOfMemory(cx);
-                return false;
-            }
-            tail->start = segment->end;
-
-            /*
-             * Clear the segment's saved end, but preserve in the tail if this
-             * is the last segment in the loop and the variable is killed in an
-             * outer loop before the backedge.
-             */
-            if (segment->savedEnd > end) {
-                JS_ASSERT(savedEnd == end);
-                tail->savedEnd = segment->savedEnd;
-            }
-            segment->savedEnd = 0;
-
-            segment->next = tail;
-            segment = tail->next;
-        } else {
-            JS_ASSERT(segment->savedEnd == 0);
-            segment = segment->next;
-        }
-    }
-    return true;
-}
-
-inline void
-ScriptAnalysis::ensureVariable(LifetimeVariable &var, unsigned until)
-{
-    JS_ASSERT(var.lifetime);
-
-    /*
-     * If we are already ensured, the current range we are trying to ensure
-     * should already be included.
-     */
-    if (var.ensured) {
-        JS_ASSERT(var.lifetime->start <= until);
-        return;
-    }
-
-    JS_ASSERT(until < var.lifetime->start);
-    var.lifetime->start = until;
-    var.ensured = true;
-}
-
-/////////////////////////////////////////////////////////////////////
-// SSA Analysis
-/////////////////////////////////////////////////////////////////////
-
-/* Current value for a variable or stack value, as tracked during SSA. */
-struct SSAValueInfo
-{
-    SSAValue v;
-
-    /*
-     * Sizes of branchTargets the last time this slot was written. Branches less
-     * than this threshold do not need to be inspected if the slot is written
-     * again, as they will already reflect the slot's value at the branch.
-     */
-    int32_t branchSize;
-};
-
-bool
-ScriptAnalysis::analyzeSSA(JSContext *cx)
-{
-    JS_ASSERT(cx->compartment()->activeAnalysis);
-    JS_ASSERT(codeArray);
-    JS_ASSERT(lifetimes);
-
-    LifoAlloc &alloc = cx->typeLifoAlloc();
-    unsigned maxDepth = script_->nslots() - script_->nfixed();
-
-    /*
-     * Current value of each variable and stack value. Empty for missing or
-     * untracked entries, i.e. escaping locals and arguments.
-     */
-    SSAValueInfo *values = cx->pod_calloc<SSAValueInfo>(numSlots + maxDepth);
-    if (!values) {
-        js_ReportOutOfMemory(cx);
-        return false;
-    }
-    struct FreeSSAValues {
-        SSAValueInfo *values;
-        FreeSSAValues(SSAValueInfo *values) : values(values) {}
-        ~FreeSSAValues() { js_free(values); }
-    } free(values);
-
-    SSAValueInfo *stack = values + numSlots;
-    uint32_t stackDepth = 0;
-
-    for (uint32_t slot = ArgSlot(0); slot < numSlots; slot++) {
-        if (trackSlot(slot))
-            values[slot].v.initInitial(slot);
-    }
-
-    /*
-     * All target offsets for forward jumps we have seen (including ones whose
-     * target we have advanced past). We lazily add pending entries at these
-     * targets for the original value of variables modified before the branch
-     * rejoins.
-     */
-    Vector<uint32_t> branchTargets(cx);
-
-    /*
-     * Subset of branchTargets which are exception handlers at future offsets.
-     * Any new value of a variable modified before the target is reached is a
-     * potential value at that target, along with the lazy original value.
-     */
-    Vector<uint32_t> exceptionTargets(cx);
-
-    uint32_t offset = 0;
-    while (offset < script_->length()) {
-        jsbytecode *pc = script_->offsetToPC(offset);
-        JSOp op = (JSOp)*pc;
-
-        uint32_t successorOffset = offset + GetBytecodeLength(pc);
-
-        Bytecode *code = maybeCode(pc);
-        if (!code) {
-            offset = successorOffset;
-            continue;
-        }
-
-        if (code->exceptionEntry) {
-            /* Remove from exception targets list, which reflects only future targets. */
-            for (size_t i = 0; i < exceptionTargets.length(); i++) {
-                if (exceptionTargets[i] == offset) {
-                    exceptionTargets[i] = exceptionTargets.back();
-                    exceptionTargets.popBack();
-                    break;
-                }
-            }
-        }
-
-        if (code->stackDepth > stackDepth)
-            PodZero(stack + stackDepth, code->stackDepth - stackDepth);
-        stackDepth = code->stackDepth;
-
-        if (op == JSOP_LOOPHEAD && code->loop) {
-            /*
-             * Make sure there is a pending value array for phi nodes at the
-             * loop head. We won't be able to clear these until we reach the
-             * loop's back edge.
-             *
-             * We need phi nodes for all variables which might be modified
-             * during the loop. This ensures that in the loop body we have
-             * already updated state to reflect possible changes that happen
-             * before the back edge, and don't need to go back and fix things
-             * up when we *do* get to the back edge. This could be made lazier.
-             *
-             * We don't make phi nodes for values on the stack at the head of
-             * the loop. These may be popped during the loop (i.e. for ITER
-             * loops), but in such cases the original value is pushed back.
-             */
-            Vector<SlotValue> *&pending = code->pendingValues;
-            if (!pending) {
-                pending = cx->new_< Vector<SlotValue> >(cx);
-                if (!pending) {
-                    js_ReportOutOfMemory(cx);
-                    return false;
-                }
-            }
-
-            /*
-             * Make phi nodes and update state for slots which are already in
-             * pending from previous branches to the loop head, and which are
-             * modified in the body of the loop.
-             */
-            for (unsigned i = 0; i < pending->length(); i++) {
-                SlotValue &v = (*pending)[i];
-                if (v.slot < numSlots && liveness(v.slot).firstWrite(code->loop) != UINT32_MAX) {
-                    if (v.value.kind() != SSAValue::PHI || v.value.phiOffset() != offset) {
-                        JS_ASSERT(v.value.phiOffset() < offset);
-                        SSAValue ov = v.value;
-                        if (!makePhi(cx, v.slot, offset, &ov))
-                            return false;
-                        if (!insertPhi(cx, ov, v.value))
-                            return false;
-                        v.value = ov;
-                    }
-                }
-                if (code->fallthrough || code->jumpFallthrough) {
-                    if (!mergeValue(cx, offset, values[v.slot].v, &v))
-                        return false;
-                }
-                if (!mergeBranchTarget(cx, values[v.slot], v.slot, branchTargets, offset - 1))
-                    return false;
-                values[v.slot].v = v.value;
-            }
-
-            /*
-             * Make phi nodes for all other slots which might be modified
-             * during the loop. This ensures that in the loop body we have
-             * already updated state to reflect possible changes that happen
-             * before the back edge, and don't need to go back and fix things
-             * up when we *do* get to the back edge. This could be made lazier.
-             */
-            for (uint32_t slot = ArgSlot(0); slot < numSlots + stackDepth; slot++) {
-                if (slot >= numSlots || !trackSlot(slot))
-                    continue;
-                if (liveness(slot).firstWrite(code->loop) == UINT32_MAX)
-                    continue;
-                if (values[slot].v.kind() == SSAValue::PHI && values[slot].v.phiOffset() == offset) {
-                    /* There is already a pending entry for this slot. */
-                    continue;
-                }
-                SSAValue ov;
-                if (!makePhi(cx, slot, offset, &ov))
-                    return false;
-                if (code->fallthrough || code->jumpFallthrough) {
-                    if (!insertPhi(cx, ov, values[slot].v))
-                        return false;
-                }
-                if (!mergeBranchTarget(cx, values[slot], slot, branchTargets, offset - 1))
-                    return false;
-                values[slot].v = ov;
-                if (!pending->append(SlotValue(slot, ov))) {
-                    js_ReportOutOfMemory(cx);
-                    return false;
-                }
-            }
-        } else if (code->pendingValues) {
-            /*
-             * New values at this point from a previous jump to this bytecode.
-             * If there is fallthrough from the previous instruction, merge
-             * with the current state and create phi nodes where necessary,
-             * otherwise replace current values with the new values.
-             *
-             * Catch blocks are artifically treated as having fallthrough, so
-             * that values written inside the block but not subsequently
-             * overwritten are picked up.
-             */
-            bool exception = getCode(offset).exceptionEntry;
-            Vector<SlotValue> *pending = code->pendingValues;
-            for (unsigned i = 0; i < pending->length(); i++) {
-                SlotValue &v = (*pending)[i];
-                if (code->fallthrough || code->jumpFallthrough ||
-                    (exception && values[v.slot].v.kind() != SSAValue::EMPTY)) {
-                    if (!mergeValue(cx, offset, values[v.slot].v, &v))
-                        return false;
-                }
-                if (!mergeBranchTarget(cx, values[v.slot], v.slot, branchTargets, offset))
-                    return false;
-                values[v.slot].v = v.value;
-            }
-            if (!freezeNewValues(cx, offset))
-                return false;
-        }
-
-        unsigned nuses = GetUseCount(script_, offset);
-        unsigned ndefs = GetDefCount(script_, offset);
-        JS_ASSERT(stackDepth >= nuses);
-
-        unsigned xuses = ExtendedUse(pc) ? nuses + 1 : nuses;
-
-        if (xuses) {
-            code->poppedValues = alloc.newArray<SSAValue>(xuses);
-            if (!code->poppedValues) {
-                js_ReportOutOfMemory(cx);
-                return false;
-            }
-            for (unsigned i = 0; i < nuses; i++) {
-                SSAValue &v = stack[stackDepth - 1 - i].v;
-                code->poppedValues[i] = v;
-                v.clear();
-            }
-            if (xuses > nuses) {
-                /*
-                 * For SETLOCAL, etc. opcodes, add an extra popped value
-                 * holding the value of the local before the op.
-                 */
-                uint32_t slot = GetBytecodeSlot(script_, pc);
-                if (trackSlot(slot))
-                    code->poppedValues[nuses] = values[slot].v;
-                else
-                    code->poppedValues[nuses].clear();
-            }
-
-            if (xuses) {
-                SSAUseChain *useChains = alloc.newArray<SSAUseChain>(xuses);
-                if (!useChains) {
-                    js_ReportOutOfMemory(cx);
-                    return false;
-                }
-                PodZero(useChains, xuses);
-                for (unsigned i = 0; i < xuses; i++) {
-                    const SSAValue &v = code->poppedValues[i];
-                    if (trackUseChain(v)) {
-                        SSAUseChain *&uses = useChain(v);
-                        useChains[i].popped = true;
-                        useChains[i].offset = offset;
-                        useChains[i].u.which = i;
-                        useChains[i].next = uses;
-                        uses = &useChains[i];
-                    }
-                }
-            }
-        }
-
-        stackDepth -= nuses;
-
-        for (unsigned i = 0; i < ndefs; i++)
-            stack[stackDepth + i].v.initPushed(offset, i);
-
-        unsigned xdefs = ExtendedDef(pc) ? ndefs + 1 : ndefs;
-        if (xdefs) {
-            code->pushedUses = alloc.newArray<SSAUseChain *>(xdefs);
-            if (!code->pushedUses) {
-                js_ReportOutOfMemory(cx);
-                return false;
-            }
-            PodZero(code->pushedUses, xdefs);
-        }
-
-        stackDepth += ndefs;
-
-        if (op == JSOP_SETARG || op == JSOP_SETLOCAL) {
-            uint32_t slot = GetBytecodeSlot(script_, pc);
-            if (trackSlot(slot)) {
-                if (!mergeBranchTarget(cx, values[slot], slot, branchTargets, offset))
-                    return false;
-                if (!mergeExceptionTarget(cx, values[slot].v, slot, exceptionTargets))
-                    return false;
-                values[slot].v.initWritten(slot, offset);
-            }
-        }
-
-        switch (op) {
-          case JSOP_GETARG:
-          case JSOP_GETLOCAL: {
-            uint32_t slot = GetBytecodeSlot(script_, pc);
-            if (trackSlot(slot)) {
-                /*
-                 * Propagate the current value of the local to the pushed value,
-                 * and remember it with an extended use on the opcode.
-                 */
-                stack[stackDepth - 1].v = code->poppedValues[0] = values[slot].v;
-            }
-            break;
-          }
-
-          /* Short circuit ops which push back one of their operands. */
-
-          case JSOP_MOREITER:
-            stack[stackDepth - 2].v = code->poppedValues[0];
-            break;
-
-          case JSOP_MUTATEPROTO:
-          case JSOP_INITPROP:
-          case JSOP_INITPROP_GETTER:
-          case JSOP_INITPROP_SETTER:
-            stack[stackDepth - 1].v = code->poppedValues[1];
-            break;
-
-          case JSOP_SPREAD:
-          case JSOP_INITELEM_INC:
-            stack[stackDepth - 2].v = code->poppedValues[2];
-            break;
-
-          case JSOP_INITELEM_ARRAY:
-            stack[stackDepth - 1].v = code->poppedValues[1];
-            break;
-
-          case JSOP_INITELEM:
-          case JSOP_INITELEM_GETTER:
-          case JSOP_INITELEM_SETTER:
-            stack[stackDepth - 1].v = code->poppedValues[2];
-            break;
-
-          case JSOP_DUP:
-            stack[stackDepth - 1].v = stack[stackDepth - 2].v = code->poppedValues[0];
-            break;
-
-          case JSOP_DUP2:
-            stack[stackDepth - 1].v = stack[stackDepth - 3].v = code->poppedValues[0];
-            stack[stackDepth - 2].v = stack[stackDepth - 4].v = code->poppedValues[1];
-            break;
-
-          case JSOP_DUPAT: {
-            unsigned pickedDepth = GET_UINT24 (pc);
-            JS_ASSERT(pickedDepth < stackDepth - 1);
-            stack[stackDepth - 1].v = stack[stackDepth - 2 - pickedDepth].v;
-            break;
-          }
-
-          case JSOP_SWAP:
-            /* Swap is like pick 1. */
-          case JSOP_PICK: {
-            unsigned pickedDepth = (op == JSOP_SWAP ? 1 : pc[1]);
-            stack[stackDepth - 1].v = code->poppedValues[pickedDepth];
-            for (unsigned i = 0; i < pickedDepth; i++)
-                stack[stackDepth - 2 - i].v = code->poppedValues[i];
-            break;
-          }
-
-          /*
-           * Switch and try blocks preserve the stack between the original op
-           * and all case statements or exception/finally handlers.
-           */
-
-          case JSOP_TABLESWITCH: {
-            unsigned defaultOffset = offset + GET_JUMP_OFFSET(pc);
-            jsbytecode *pc2 = pc + JUMP_OFFSET_LEN;
-            int32_t low = GET_JUMP_OFFSET(pc2);
-            pc2 += JUMP_OFFSET_LEN;
-            int32_t high = GET_JUMP_OFFSET(pc2);
-            pc2 += JUMP_OFFSET_LEN;
-
-            for (int32_t i = low; i <= high; i++) {
-                unsigned targetOffset = offset + GET_JUMP_OFFSET(pc2);
-                if (targetOffset != offset) {
-                    if (!checkBranchTarget(cx, targetOffset, branchTargets, values, stackDepth))
-                        return false;
-                }
-                pc2 += JUMP_OFFSET_LEN;
-            }
-
-            if (!checkBranchTarget(cx, defaultOffset, branchTargets, values, stackDepth))
-                return false;
-            break;
-          }
-
-          case JSOP_TRY: {
-            JSTryNote *tn = script_->trynotes()->vector;
-            JSTryNote *tnlimit = tn + script_->trynotes()->length;
-            for (; tn < tnlimit; tn++) {
-                unsigned startOffset = script_->mainOffset() + tn->start;
-                if (startOffset == offset + 1) {
-                    unsigned catchOffset = startOffset + tn->length;
-
-                    if (tn->kind != JSTRY_ITER && tn->kind != JSTRY_LOOP) {
-                        if (!checkBranchTarget(cx, catchOffset, branchTargets, values, stackDepth))
-                            return false;
-                        if (!checkExceptionTarget(cx, catchOffset, exceptionTargets))
-                            return false;
-                    }
-                }
-            }
-            break;
-          }
-
-          case JSOP_THROW:
-          case JSOP_RETURN:
-          case JSOP_RETRVAL:
-            if (!mergeAllExceptionTargets(cx, values, exceptionTargets))
-                return false;
-            break;
-
-          default:;
-        }
-
-        if (IsJumpOpcode(op)) {
-            unsigned targetOffset = FollowBranch(cx, script_, offset);
-            if (!checkBranchTarget(cx, targetOffset, branchTargets, values, stackDepth))
-                return false;
-
-            /*
-             * If this is a back edge, we're done with the loop and can freeze
-             * the phi values at the head now.
-             */
-            if (targetOffset < offset) {
-                if (!freezeNewValues(cx, targetOffset))
-                    return false;
-            }
-        }
-
-        offset = successorOffset;
-    }
-
-    return true;
-}
-
-/* Get a phi node's capacity for a given length. */
-static inline unsigned
-PhiNodeCapacity(unsigned length)
-{
-    if (length <= 4)
-        return 4;
-
-    return 1 << (FloorLog2(length - 1) + 1);
-}
-
-bool
-ScriptAnalysis::makePhi(JSContext *cx, uint32_t slot, uint32_t offset, SSAValue *pv)
-{
-    SSAPhiNode *node = cx->typeLifoAlloc().new_<SSAPhiNode>();
-    SSAValue *options = cx->typeLifoAlloc().newArray<SSAValue>(PhiNodeCapacity(0));
-    if (!node || !options) {
-        js_ReportOutOfMemory(cx);
-        return false;
-    }
-    node->slot = slot;
-    node->options = options;
-    pv->initPhi(offset, node);
-    return true;
-}
-
-bool
-ScriptAnalysis::insertPhi(JSContext *cx, SSAValue &phi, const SSAValue &v)
-{
-    JS_ASSERT(phi.kind() == SSAValue::PHI);
-    SSAPhiNode *node = phi.phiNode();
-
-    /*
-     * Filter dupes inserted into small nodes to keep things clean and avoid
-     * extra type constraints, but don't bother on large phi nodes to avoid
-     * quadratic behavior.
-     */
-    if (node->length <= 8) {
-        for (unsigned i = 0; i < node->length; i++) {
-            if (v == node->options[i])
-                return true;
-        }
-    }
-
-    if (trackUseChain(v)) {
-        SSAUseChain *&uses = useChain(v);
-
-        SSAUseChain *use = cx->typeLifoAlloc().new_<SSAUseChain>();
-        if (!use) {
-            js_ReportOutOfMemory(cx);
-            return false;
-        }
-
-        use->popped = false;
-        use->offset = phi.phiOffset();
-        use->u.phi = node;
-        use->next = uses;
-        uses = use;
-    }
-
-    if (node->length < PhiNodeCapacity(node->length)) {
-        node->options[node->length++] = v;
-        return true;
-    }
-
-    SSAValue *newOptions =
-        cx->typeLifoAlloc().newArray<SSAValue>(PhiNodeCapacity(node->length + 1));
-    if (!newOptions) {
-        js_ReportOutOfMemory(cx);
-        return false;
-    }
-
-    PodCopy(newOptions, node->options, node->length);
-    node->options = newOptions;
-    node->options[node->length++] = v;
-
-    return true;
-}
-
-inline bool
-ScriptAnalysis::mergeValue(JSContext *cx, uint32_t offset, const SSAValue &v, SlotValue *pv)
-{
-    /* Make sure that v is accounted for in the pending value or phi value at pv. */
-    JS_ASSERT(v.kind() != SSAValue::EMPTY && pv->value.kind() != SSAValue::EMPTY);
-
-    if (v == pv->value)
-        return true;
-
-    if (pv->value.kind() != SSAValue::PHI || pv->value.phiOffset() < offset) {
-        SSAValue ov = pv->value;
-        return makePhi(cx, pv->slot, offset, &pv->value)
-            && insertPhi(cx, pv->value, v)
-            && insertPhi(cx, pv->value, ov);
-    }
-
-    JS_ASSERT(pv->value.phiOffset() == offset);
-    return insertPhi(cx, pv->value, v);
-}
-
-bool
-ScriptAnalysis::checkPendingValue(JSContext *cx, const SSAValue &v, uint32_t slot,
-                                  Vector<SlotValue> *pending)
-{
-    JS_ASSERT(v.kind() != SSAValue::EMPTY);
-
-    for (unsigned i = 0; i < pending->length(); i++) {
-        if ((*pending)[i].slot == slot)
-            return true;
-    }
-
-    if (!pending->append(SlotValue(slot, v))) {
-        js_ReportOutOfMemory(cx);
-        return false;
-    }
-
-    return true;
-}
-
-bool
-ScriptAnalysis::checkBranchTarget(JSContext *cx, uint32_t targetOffset,
-                                  Vector<uint32_t> &branchTargets,
-                                  SSAValueInfo *values, uint32_t stackDepth)
-{
-    unsigned targetDepth = getCode(targetOffset).stackDepth;
-    JS_ASSERT(targetDepth <= stackDepth);
-
-    /*
-     * If there is already an active branch to target, make sure its pending
-     * values reflect any changes made since the first branch. Otherwise, add a
-     * new pending branch and determine its pending values lazily.
-     */
-    Vector<SlotValue> *&pending = getCode(targetOffset).pendingValues;
-    if (pending) {
-        for (unsigned i = 0; i < pending->length(); i++) {
-            SlotValue &v = (*pending)[i];
-            if (!mergeValue(cx, targetOffset, values[v.slot].v, &v))
-                return false;
-        }
-    } else {
-        pending = cx->new_< Vector<SlotValue> >(cx);
-        if (!pending || !branchTargets.append(targetOffset)) {
-            js_ReportOutOfMemory(cx);
-            return false;
-        }
-    }
-
-    /*
-     * Make sure there is a pending entry for each value on the stack.
-     * The number of stack entries at join points is usually zero, and
-     * we don't want to look at the active branches while popping and
-     * pushing values in each opcode.
-     */
-    for (unsigned i = 0; i < targetDepth; i++) {
-        uint32_t slot = StackSlot(script_, i);
-        if (!checkPendingValue(cx, values[slot].v, slot, pending))
-            return false;
-    }
-
-    return true;
-}
-
-bool
-ScriptAnalysis::checkExceptionTarget(JSContext *cx, uint32_t catchOffset,
-                                     Vector<uint32_t> &exceptionTargets)
-{
-    JS_ASSERT(getCode(catchOffset).exceptionEntry);
-
-    /*
-     * The catch offset will already be in the branch targets, just check
-     * whether this is already a known exception target.
-     */
-    for (unsigned i = 0; i < exceptionTargets.length(); i++) {
-        if (exceptionTargets[i] == catchOffset)
-            return true;
-    }
-    if (!exceptionTargets.append(catchOffset)) {
-        js_ReportOutOfMemory(cx);
-        return false;
-    }
-
-    return true;
-}
-
-bool
-ScriptAnalysis::mergeBranchTarget(JSContext *cx, SSAValueInfo &value, uint32_t slot,
-                                  const Vector<uint32_t> &branchTargets, uint32_t currentOffset)
-{
-    if (slot >= numSlots) {
-        /*
-         * There is no need to lazily check that there are pending values at
-         * branch targets for slots on the stack, these are added to pending
-         * eagerly.
-         */
-        return true;
-    }
-
-    JS_ASSERT(trackSlot(slot));
-
-    /*
-     * Before changing the value of a variable, make sure the old value is
-     * marked at the target of any branches jumping over the current opcode.
-     * Only look at new branch targets which have appeared since the last time
-     * the variable was written.
-     */
-    for (int i = branchTargets.length() - 1; i >= value.branchSize; i--) {
-        if (branchTargets[i] <= currentOffset)
-            continue;
-
-        const Bytecode &code = getCode(branchTargets[i]);
-
-        Vector<SlotValue> *pending = code.pendingValues;
-        if (!checkPendingValue(cx, value.v, slot, pending))
-            return false;
-    }
-
-    value.branchSize = branchTargets.length();
-    return true;
-}
-
-bool
-ScriptAnalysis::mergeExceptionTarget(JSContext *cx, const SSAValue &value, uint32_t slot,
-                                     const Vector<uint32_t> &exceptionTargets)
-{
-    JS_ASSERT(trackSlot(slot));
-
-    /*
-     * Update the value at exception targets with the value of a variable
-     * before it is overwritten. Unlike mergeBranchTarget, this is done whether
-     * or not the overwritten value is the value of the variable at the
-     * original branch. Values for a variable which are written after the
-     * try block starts and overwritten before it is finished can still be
-     * seen at exception handlers via exception paths.
-     */
-    for (unsigned i = 0; i < exceptionTargets.length(); i++) {
-        unsigned offset = exceptionTargets[i];
-        Vector<SlotValue> *pending = getCode(offset).pendingValues;
-
-        bool duplicate = false;
-        for (unsigned i = 0; i < pending->length(); i++) {
-            if ((*pending)[i].slot == slot) {
-                duplicate = true;
-                SlotValue &v = (*pending)[i];
-                if (!mergeValue(cx, offset, value, &v))
-                    return false;
-                break;
-            }
-        }
-
-        if (!duplicate && !pending->append(SlotValue(slot, value))) {
-            js_ReportOutOfMemory(cx);
-            return false;
-        }
-    }
-
-    return true;
-}
-
-bool
-ScriptAnalysis::mergeAllExceptionTargets(JSContext *cx, SSAValueInfo *values,
-                                         const Vector<uint32_t> &exceptionTargets)
-{
-    for (unsigned i = 0; i < exceptionTargets.length(); i++) {
-        Vector<SlotValue> *pending = getCode(exceptionTargets[i]).pendingValues;
-        for (unsigned i = 0; i < pending->length(); i++) {
-            const SlotValue &v = (*pending)[i];
-            if (trackSlot(v.slot)) {
-                if (!mergeExceptionTarget(cx, values[v.slot].v, v.slot, exceptionTargets))
-                    return false;
-            }
-        }
-    }
-    return true;
-}
-
-bool
-ScriptAnalysis::freezeNewValues(JSContext *cx, uint32_t offset)
-{
-    Bytecode &code = getCode(offset);
-
-    Vector<SlotValue> *pending = code.pendingValues;
-    code.pendingValues = nullptr;
-
-    unsigned count = pending->length();
-    if (count == 0) {
-        js_delete(pending);
-        return true;
-    }
-
-    code.newValues = cx->typeLifoAlloc().newArray<SlotValue>(count + 1);
-    if (!code.newValues) {
-        js_ReportOutOfMemory(cx);
-        return false;
-    }
-
-    for (unsigned i = 0; i < count; i++)
-        code.newValues[i] = (*pending)[i];
-    code.newValues[count].slot = 0;
-    code.newValues[count].value.clear();
-
-    js_delete(pending);
-    return true;
-}
-
-bool
-ScriptAnalysis::needsArgsObj(JSContext *cx, SeenVector &seen, const SSAValue &v)
-{
-    /*
-     * trackUseChain is false for initial values of variables, which
-     * cannot hold the script's arguments object.
-     */
-    if (!trackUseChain(v))
-        return false;
-
-    for (unsigned i = 0; i < seen.length(); i++) {
-        if (v == seen[i])
-            return false;
-    }
-    if (!seen.append(v))
-        return true;
-
-    SSAUseChain *use = useChain(v);
-    while (use) {
-        if (needsArgsObj(cx, seen, use))
-            return true;
-        use = use->next;
-    }
-
-    return false;
-}
-
-bool
-ScriptAnalysis::needsArgsObj(JSContext *cx, SeenVector &seen, SSAUseChain *use)
-{
-    if (!use->popped)
-        return needsArgsObj(cx, seen, SSAValue::PhiValue(use->offset, use->u.phi));
-
-    jsbytecode *pc = script_->offsetToPC(use->offset);
-    JSOp op = JSOp(*pc);
-
-    if (op == JSOP_POP || op == JSOP_POPN)
-        return false;
-
-    /* We can read the frame's arguments directly for f.apply(x, arguments). */
-    if (op == JSOP_FUNAPPLY && GET_ARGC(pc) == 2 && use->u.which == 0) {
-        argumentsContentsObserved_ = true;
-        return false;
-    }
-
-    /* arguments[i] can read fp->canonicalActualArg(i) directly. */
-    if (op == JSOP_GETELEM && use->u.which == 1) {
-        argumentsContentsObserved_ = true;
-        return false;
-    }
-
-    /* arguments.length length can read fp->numActualArgs() directly. */
-    if (op == JSOP_LENGTH)
-        return false;
-
-    /* Allow assignments to non-closed locals (but not arguments). */
-
-    if (op == JSOP_SETLOCAL) {
-        uint32_t slot = GetBytecodeSlot(script_, pc);
-        if (!trackSlot(slot))
-            return true;
-        return needsArgsObj(cx, seen, SSAValue::PushedValue(use->offset, 0)) ||
-               needsArgsObj(cx, seen, SSAValue::WrittenVar(slot, use->offset));
-    }
-
-    if (op == JSOP_GETLOCAL)
-        return needsArgsObj(cx, seen, SSAValue::PushedValue(use->offset, 0));
-
-    return true;
-}
-
-bool
-ScriptAnalysis::needsArgsObj(JSContext *cx)
-{
-    JS_ASSERT(script_->argumentsHasVarBinding());
-
-    /*
-     * Always construct arguments objects when in debug mode and for generator
-     * scripts (generators can be suspended when speculation fails).
-     *
-     * FIXME: Don't build arguments for ES6 generator expressions.
-     */
-    if (cx->compartment()->debugMode() || script_->isGenerator())
-        return true;
-
-    /*
-     * If the script has dynamic name accesses which could reach 'arguments',
-     * the parser will already have checked to ensure there are no explicit
-     * uses of 'arguments' in the function. If there are such uses, the script
-     * will be marked as definitely needing an arguments object.
-     *
-     * New accesses on 'arguments' can occur through 'eval' or the debugger
-     * statement. In the former case, we will dynamically detect the use and
-     * mark the arguments optimization as having failed.
-     */
-    if (script_->bindingsAccessedDynamically())
-        return false;
-
-    unsigned pcOff = script_->pcToOffset(script_->argumentsBytecode());
-
-    SeenVector seen(cx);
-    if (needsArgsObj(cx, seen, SSAValue::PushedValue(pcOff, 0)))
-        return true;
-
-    /*
-     * If a script explicitly accesses the contents of 'arguments', and has
-     * formals which may be stored as part of a call object, don't use lazy
-     * arguments. The compiler can then assume that accesses through
-     * arguments[i] will be on unaliased variables.
-     */
-    if (script_->funHasAnyAliasedFormal() && argumentsContentsObserved_)
-        return true;
-
-    return false;
-}
-
-#ifdef DEBUG
-
-void
-ScriptAnalysis::printSSA(JSContext *cx)
-{
-    types::AutoEnterAnalysis enter(cx);
-
-    printf("\n");
-
-    RootedScript script(cx, script_);
-    for (unsigned offset = 0; offset < script_->length(); offset++) {
-        Bytecode *code = maybeCode(offset);
-        if (!code)
-            continue;
-
-        jsbytecode *pc = script_->offsetToPC(offset);
-
-        PrintBytecode(cx, script, pc);
-
-        SlotValue *newv = code->newValues;
-        if (newv) {
-            while (newv->slot) {
-                if (newv->value.kind() != SSAValue::PHI || newv->value.phiOffset() != offset) {
-                    newv++;
-                    continue;
-                }
-                printf("  phi ");
-                newv->value.print();
-                printf(" [");
-                for (unsigned i = 0; i < newv->value.phiLength(); i++) {
-                    if (i)
-                        printf(",");
-                    newv->value.phiValue(i).print();
-                }
-                printf("]\n");
-                newv++;
-            }
-        }
-
-        unsigned nuses = GetUseCount(script_, offset);
-        unsigned xuses = ExtendedUse(pc) ? nuses + 1 : nuses;
-
-        for (unsigned i = 0; i < xuses; i++) {
-            printf("  popped%d: ", i);
-            code->poppedValues[i].print();
-            printf("\n");
-        }
-    }
-
-    printf("\n");
-}
-
-void
-SSAValue::print() const
-{
-    switch (kind()) {
-
-      case EMPTY:
-        printf("empty");
-        break;
-
-      case PUSHED:
-        printf("pushed:%05u#%u", pushedOffset(), pushedIndex());
-        break;
-
-      case VAR:
-        if (varInitial())
-            printf("initial:%u", varSlot());
-        else
-            printf("write:%05u", varOffset());
-        break;
-
-      case PHI:
-        printf("phi:%05u#%u", phiOffset(), phiSlot());
-        break;
-
-      default:
-        MOZ_ASSUME_UNREACHABLE("Bad kind");
-    }
-}
-
-void
-ScriptAnalysis::assertMatchingDebugMode()
-{
-    JS_ASSERT(!!script_->compartment()->debugMode() == !!originalDebugMode_);
-}
-
-void
-ScriptAnalysis::assertMatchingStackDepthAtOffset(uint32_t offset, uint32_t stackDepth) {
-    JS_ASSERT_IF(maybeCode(offset), getCode(offset).stackDepth == stackDepth);
-}
-
-#endif  /* DEBUG */
-
-} // namespace analyze
-} // namespace js
deleted file mode 100644
--- a/js/src/jsanalyze.h
+++ /dev/null
@@ -1,216 +0,0 @@
-/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
- * vim: set ts=8 sts=4 et sw=4 tw=99:
- * 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/. */
-
-/* Definitions for javascript analysis. */
-
-#ifndef jsanalyze_h
-#define jsanalyze_h
-
-#include "jscompartment.h"
-
-namespace js {
-namespace analyze {
-
-class Bytecode;
-struct LifetimeVariable;
-class SlotValue;
-class SSAValue;
-struct SSAValueInfo;
-class SSAUseChain;
-
-// Common representation of slots between ScriptAnalysis, TypeScript, and in the
-// case of TotalSlots, Ion.
-static inline uint32_t ThisSlot() {
-    return 0;
-}
-static inline uint32_t ArgSlot(uint32_t arg) {
-    return 1 + arg;
-}
-static inline uint32_t LocalSlot(JSScript *script, uint32_t local) {
-    return 1 + local +
-           (script->functionNonDelazifying() ? script->functionNonDelazifying()->nargs() : 0);
-}
-static inline uint32_t TotalSlots(JSScript *script) {
-    return LocalSlot(script, 0) + script->nfixed();
-}
-
-// Analysis information about a script.  FIXME: At this point, the entire
-// purpose of this class is to compute JSScript::needsArgsObj, and to support
-// isReachable() in order for jsinfer.cpp:FindPreviousInnerInitializer to get
-// the previous opcode.  For that purpose, it is completely overkill.
-class ScriptAnalysis
-{
-    friend class Bytecode;
-
-    JSScript *script_;
-
-    Bytecode **codeArray;
-
-    uint32_t numSlots;
-
-    bool *escapedSlots;
-
-#ifdef DEBUG
-    /* Whether the compartment was in debug mode when we performed the analysis. */
-    bool originalDebugMode_: 1;
-#endif
-
-    /* --------- Bytecode analysis --------- */
-
-    bool canTrackVars:1;
-    bool argumentsContentsObserved_:1;
-
-    /* --------- Lifetime analysis --------- */
-
-    LifetimeVariable *lifetimes;
-
-  public:
-    ScriptAnalysis(JSScript *script) {
-        mozilla::PodZero(this);
-        this->script_ = script;
-#ifdef DEBUG
-        this->originalDebugMode_ = script_->compartment()->debugMode();
-#endif
-    }
-
-    MOZ_WARN_UNUSED_RESULT
-    bool analyzeBytecode(JSContext *cx);
-
-    bool isReachable(const jsbytecode *pc) { return maybeCode(pc); }
-
-  private:
-    MOZ_WARN_UNUSED_RESULT
-    bool analyzeSSA(JSContext *cx);
-    MOZ_WARN_UNUSED_RESULT
-    bool analyzeLifetimes(JSContext *cx);
-
-    /* Accessors for bytecode information. */
-    Bytecode& getCode(uint32_t offset) {
-        JS_ASSERT(offset < script_->length());
-        JS_ASSERT(codeArray[offset]);
-        return *codeArray[offset];
-    }
-    Bytecode& getCode(const jsbytecode *pc) { return getCode(script_->pcToOffset(pc)); }
-
-    Bytecode* maybeCode(uint32_t offset) {
-        JS_ASSERT(offset < script_->length());
-        return codeArray[offset];
-    }
-    Bytecode* maybeCode(const jsbytecode *pc) { return maybeCode(script_->pcToOffset(pc)); }
-
-    inline bool jumpTarget(uint32_t offset);
-    inline bool jumpTarget(const jsbytecode *pc);
-
-    inline const SSAValue &poppedValue(uint32_t offset, uint32_t which);
-    inline const SSAValue &poppedValue(const jsbytecode *pc, uint32_t which);
-
-    inline const SlotValue *newValues(uint32_t offset);
-    inline const SlotValue *newValues(const jsbytecode *pc);
-
-    inline bool trackUseChain(const SSAValue &v);
-
-    /*
-     * Get the use chain for an SSA value.
-     */
-    inline SSAUseChain *& useChain(const SSAValue &v);
-
-
-    /* For a JSOP_CALL* op, get the pc of the corresponding JSOP_CALL/NEW/etc. */
-    inline jsbytecode *getCallPC(jsbytecode *pc);
-
-    /* Accessors for local variable information. */
-
-    /*
-     * Escaping slots include all slots that can be accessed in ways other than
-     * through the corresponding LOCAL/ARG opcode. This includes all closed
-     * slots in the script, all slots in scripts which use eval or are in debug
-     * mode, and slots which are aliased by NAME or similar opcodes in the
-     * containing script (which does not imply the variable is closed).
-     */
-    inline bool slotEscapes(uint32_t slot);
-
-    /*
-     * Whether we distinguish different writes of this variable while doing
-     * SSA analysis. Escaping locals can be written in other scripts, and the
-     * presence of NAME opcodes which could alias local variables or arguments
-     * keeps us from tracking variable values at each point.
-     */
-    inline bool trackSlot(uint32_t slot);
-
-    inline const LifetimeVariable & liveness(uint32_t slot);
-
-    void printSSA(JSContext *cx);
-    void printTypes(JSContext *cx);
-
-    /* Bytecode helpers */
-    MOZ_WARN_UNUSED_RESULT
-    inline bool addJump(JSContext *cx, unsigned offset,
-                        unsigned *currentOffset, unsigned *forwardJump, unsigned *forwardLoop,
-                        unsigned stackDepth);
-
-    /* Lifetime helpers */
-    MOZ_WARN_UNUSED_RESULT
-    inline bool addVariable(JSContext *cx, LifetimeVariable &var, unsigned offset,
-                            LifetimeVariable **&saved, unsigned &savedCount);
-    MOZ_WARN_UNUSED_RESULT
-    inline bool killVariable(JSContext *cx, LifetimeVariable &var, unsigned offset,
-                             LifetimeVariable **&saved, unsigned &savedCount);
-    MOZ_WARN_UNUSED_RESULT
-    inline bool extendVariable(JSContext *cx, LifetimeVariable &var, unsigned start, unsigned end);
-
-    inline void ensureVariable(LifetimeVariable &var, unsigned until);
-
-    /* SSA helpers */
-    MOZ_WARN_UNUSED_RESULT
-    bool makePhi(JSContext *cx, uint32_t slot, uint32_t offset, SSAValue *pv);
-    MOZ_WARN_UNUSED_RESULT
-    bool insertPhi(JSContext *cx, SSAValue &phi, const SSAValue &v);
-    MOZ_WARN_UNUSED_RESULT
-    bool mergeValue(JSContext *cx, uint32_t offset, const SSAValue &v, SlotValue *pv);
-    MOZ_WARN_UNUSED_RESULT
-    bool checkPendingValue(JSContext *cx, const SSAValue &v, uint32_t slot,
-                           Vector<SlotValue> *pending);
-    MOZ_WARN_UNUSED_RESULT
-    bool checkBranchTarget(JSContext *cx, uint32_t targetOffset, Vector<uint32_t> &branchTargets,
-                           SSAValueInfo *values, uint32_t stackDepth);
-    MOZ_WARN_UNUSED_RESULT
-    bool checkExceptionTarget(JSContext *cx, uint32_t catchOffset,
-                              Vector<uint32_t> &exceptionTargets);
-    MOZ_WARN_UNUSED_RESULT
-    bool mergeBranchTarget(JSContext *cx, SSAValueInfo &value, uint32_t slot,
-                           const Vector<uint32_t> &branchTargets, uint32_t currentOffset);
-    MOZ_WARN_UNUSED_RESULT
-    bool mergeExceptionTarget(JSContext *cx, const SSAValue &value, uint32_t slot,
-                              const Vector<uint32_t> &exceptionTargets);
-    MOZ_WARN_UNUSED_RESULT
-    bool mergeAllExceptionTargets(JSContext *cx, SSAValueInfo *values,
-                                  const Vector<uint32_t> &exceptionTargets);
-    MOZ_WARN_UNUSED_RESULT
-    bool freezeNewValues(JSContext *cx, uint32_t offset);
-
-    typedef Vector<SSAValue, 16> SeenVector;
-    bool needsArgsObj(JSContext *cx, SeenVector &seen, const SSAValue &v);
-    bool needsArgsObj(JSContext *cx, SeenVector &seen, SSAUseChain *use);
-    bool needsArgsObj(JSContext *cx);
-
-  public:
-#ifdef DEBUG
-    void assertMatchingDebugMode();
-    void assertMatchingStackDepthAtOffset(uint32_t offset, uint32_t stackDepth);
-#else
-    void assertMatchingDebugMode() { }
-    void assertMatchingStackDepthAtOffset(uint32_t offset, uint32_t stackDepth) { }
-#endif
-};
-
-#ifdef DEBUG
-void PrintBytecode(JSContext *cx, HandleScript script, jsbytecode *pc);
-#endif
-
-} /* namespace analyze */
-} /* namespace js */
-
-#endif /* jsanalyze_h */
--- a/js/src/jsfun.cpp
+++ b/js/src/jsfun.cpp
@@ -1052,34 +1052,34 @@ JSFunction::initBoundFunction(JSContext 
     self->setSlot(JSSLOT_BOUND_FUNCTION_THIS, thisArg);
     self->setSlot(JSSLOT_BOUND_FUNCTION_ARGS_COUNT, PrivateUint32Value(argslen));
 
     self->initSlotRange(BOUND_FUNCTION_RESERVED_SLOTS, args, argslen);
 
     return true;
 }
 
-inline const js::Value &
+const js::Value &
 JSFunction::getBoundFunctionThis() const
 {
     JS_ASSERT(isBoundFunction());
 
     return getSlot(JSSLOT_BOUND_FUNCTION_THIS);
 }
 
-inline const js::Value &
+const js::Value &
 JSFunction::getBoundFunctionArgument(unsigned which) const
 {
     JS_ASSERT(isBoundFunction());
     JS_ASSERT(which < getBoundFunctionArgumentCount());
 
     return getSlot(BOUND_FUNCTION_RESERVED_SLOTS + which);
 }
 
-inline size_t
+size_t
 JSFunction::getBoundFunctionArgumentCount() const
 {
     JS_ASSERT(isBoundFunction());
 
     return getSlot(JSSLOT_BOUND_FUNCTION_ARGS_COUNT).toPrivateUint32();
 }
 
 /* static */ bool
--- a/js/src/jsfun.h
+++ b/js/src/jsfun.h
@@ -442,19 +442,19 @@ class JSFunction : public JSObject
 
     JSObject *getBoundFunctionTarget() const {
         JS_ASSERT(isBoundFunction());
 
         /* Bound functions abuse |parent| to store their target function. */
         return getParent();
     }
 
-    inline const js::Value &getBoundFunctionThis() const;
-    inline const js::Value &getBoundFunctionArgument(unsigned which) const;
-    inline size_t getBoundFunctionArgumentCount() const;
+    const js::Value &getBoundFunctionThis() const;
+    const js::Value &getBoundFunctionArgument(unsigned which) const;
+    size_t getBoundFunctionArgumentCount() const;
 
   private:
     inline js::FunctionExtended *toExtended();
     inline const js::FunctionExtended *toExtended() const;
 
   public:
     inline bool isExtended() const {
         JS_STATIC_ASSERT(FinalizeKind != ExtendedFinalizeKind);
--- a/js/src/jsinfer.cpp
+++ b/js/src/jsinfer.cpp
@@ -37,17 +37,16 @@
 #include "jsobjinlines.h"
 #include "jsscriptinlines.h"
 
 #include "jit/ExecutionMode-inl.h"
 
 using namespace js;
 using namespace js::gc;
 using namespace js::types;
-using namespace js::analyze;
 
 using mozilla::DebugOnly;
 using mozilla::Maybe;
 using mozilla::PodArrayZero;
 using mozilla::PodCopy;
 using mozilla::PodZero;
 
 static inline jsid
@@ -4501,17 +4500,24 @@ TypeScript::printTypes(JSContext *cx, Ha
          i++)
     {
         fprintf(stderr, "\n    arg%u:", i);
         TypeScript::ArgTypes(script, i)->print();
     }
     fprintf(stderr, "\n");
 
     for (jsbytecode *pc = script->code(); pc < script->codeEnd(); pc += GetBytecodeLength(pc)) {
-        PrintBytecode(cx, script, pc);
+        {
+            fprintf(stderr, "#%u:", script->id());
+            Sprinter sprinter(cx);
+            if (!sprinter.init())
+                return;
+            js_Disassemble1(cx, script, pc, script->pcToOffset(pc), true, &sprinter);
+            fprintf(stderr, "%s", sprinter.string());
+        }
 
         if (js_CodeSpec[*pc].format & JOF_TYPESET) {
             StackTypeSet *types = TypeScript::BytecodeTypes(script, pc);
             fprintf(stderr, "  typeset %u:", unsigned(types - typeArray()));
             types->print();
             fprintf(stderr, "\n");
         }
     }
--- a/js/src/jsinferinlines.h
+++ b/js/src/jsinferinlines.h
@@ -8,18 +8,16 @@
 
 #ifndef jsinferinlines_h
 #define jsinferinlines_h
 
 #include "jsinfer.h"
 
 #include "mozilla/PodOperations.h"
 
-#include "jsanalyze.h"
-
 #include "vm/ArrayObject.h"
 #include "vm/BooleanObject.h"
 #include "vm/NumberObject.h"
 #include "vm/SharedArrayObject.h"
 #include "vm/StringObject.h"
 #include "vm/TypedArrayObject.h"
 
 #include "jscntxtinlines.h"
@@ -538,36 +536,39 @@ extern void TypeDynamicResult(JSContext 
 
 /////////////////////////////////////////////////////////////////////
 // Script interface functions
 /////////////////////////////////////////////////////////////////////
 
 /* static */ inline unsigned
 TypeScript::NumTypeSets(JSScript *script)
 {
-    return script->nTypeSets() + analyze::LocalSlot(script, 0);
+    size_t num = script->nTypeSets() + 1 /* this */;
+    if (JSFunction *fun = script->functionNonDelazifying())
+        num += fun->nargs();
+    return num;
 }
 
 /* static */ inline StackTypeSet *
 TypeScript::ThisTypes(JSScript *script)
 {
-    return script->types->typeArray() + script->nTypeSets() + analyze::ThisSlot();
+    return script->types->typeArray() + script->nTypeSets();
 }
 
 /*
- * Note: for non-escaping arguments and locals, argTypes/localTypes reflect
- * only the initial type of the variable (e.g. passed values for argTypes,
- * or undefined for localTypes) and not types from subsequent assignments.
+ * Note: for non-escaping arguments, argTypes reflect only the initial type of
+ * the variable (e.g. passed values for argTypes, or undefined for localTypes)
+ * and not types from subsequent assignments.
  */
 
 /* static */ inline StackTypeSet *
 TypeScript::ArgTypes(JSScript *script, unsigned i)
 {
     JS_ASSERT(i < script->functionNonDelazifying()->nargs());
-    return script->types->typeArray() + script->nTypeSets() + analyze::ArgSlot(i);
+    return script->types->typeArray() + script->nTypeSets() + 1 + i;
 }
 
 template <typename TYPESET>
 /* static */ inline TYPESET *
 TypeScript::BytecodeTypes(JSScript *script, jsbytecode *pc, uint32_t *bytecodeMap,
                           uint32_t *hint, TYPESET *typeArray)
 {
     JS_ASSERT(js_CodeSpec[*pc].format & JOF_TYPESET);
--- a/js/src/jsopcode.cpp
+++ b/js/src/jsopcode.cpp
@@ -10,17 +10,16 @@
 
 #include "jsopcodeinlines.h"
 
 #include <ctype.h>
 #include <stdarg.h>
 #include <stdio.h>
 #include <string.h>
 
-#include "jsanalyze.h"
 #include "jsapi.h"
 #include "jsatom.h"
 #include "jscntxt.h"
 #include "jscompartment.h"
 #include "jsfun.h"
 #include "jsnum.h"
 #include "jsobj.h"
 #include "jsprf.h"
--- a/js/src/moz.build
+++ b/js/src/moz.build
@@ -118,17 +118,16 @@ UNIFIED_SOURCES += [
     'gc/Nursery.cpp',
     'gc/RootMarking.cpp',
     'gc/Statistics.cpp',
     'gc/StoreBuffer.cpp',
     'gc/Tracer.cpp',
     'gc/Verifier.cpp',
     'gc/Zone.cpp',
     'jsalloc.cpp',
-    'jsanalyze.cpp',
     'jsapi.cpp',
     'jsbool.cpp',
     'jscntxt.cpp',
     'jscompartment.cpp',
     'jscrashreport.cpp',
     'jsdate.cpp',
     'jsdtoa.cpp',
     'jsexn.cpp',
--- a/js/src/tests/user.js
+++ b/js/src/tests/user.js
@@ -17,9 +17,9 @@ user_pref("browser.warnOnQuit", false);
 user_pref("browser.cache.check_doc_frequency", 1);
 user_pref("extensions.checkCompatibility", false);
 user_pref("extensions.checkUpdateSecurity", false);
 user_pref("browser.EULA.override", true);
 user_pref("javascript.options.strict", false);
 user_pref("javascript.options.werror", false);
 user_pref("toolkit.startup.max_resumed_crashes", -1);
 user_pref("security.turn_off_all_security_so_that_viruses_can_take_over_this_computer", true);
-
+user_pref("toolkit.telemetry.enabled", false);
--- a/layout/tools/reftest/reftest-preferences.js
+++ b/layout/tools/reftest/reftest-preferences.js
@@ -41,10 +41,8 @@
     // Disable interruptible reflow since (1) it's normally not going to
     // happen, but (2) it might happen if we somehow end up with both
     // pending user events and clock skew.  So to avoid having to change
     // MakeProgress to deal with waiting for interruptible reflows to
     // complete for a rare edge case, we just disable interruptible
     // reflow so that that rare edge case doesn't lead to reftest
     // failures.
     branch.setBoolPref("layout.interruptible-reflow.enabled", false);
-    // Don't try to connect to the telemetry server.
-    branch.setBoolPref("toolkit.telemetry.enabled", false);
--- a/layout/tools/reftest/runreftest.py
+++ b/layout/tools/reftest/runreftest.py
@@ -160,16 +160,20 @@ class RefTest(object):
     if options.ignoreWindowSize:
       prefs['reftest.ignoreWindowSize'] = True
     if options.filter:
       prefs['reftest.filter'] = options.filter
     if options.shuffle:
       prefs['reftest.shuffle'] = True
     prefs['reftest.focusFilterMode'] = options.focusFilterMode
 
+    # Ensure that telemetry is disabled, so we don't connect to the telemetry
+    # server in the middle of the tests.
+    prefs['toolkit.telemetry.enabled'] = False
+
     if options.e10s:
       prefs['browser.tabs.remote.autostart'] = True
 
     for v in options.extraPrefs:
       thispref = v.split('=')
       if len(thispref) < 2:
         print "Error: syntax error in --setpref=" + v
         sys.exit(1)
--- a/media/webrtc/signaling/src/media-conduit/WebrtcOMXH264VideoCodec.cpp
+++ b/media/webrtc/signaling/src/media-conduit/WebrtcOMXH264VideoCodec.cpp
@@ -21,17 +21,16 @@
 using namespace android;
 
 // WebRTC
 #include "common_video/interface/texture_video_frame.h"
 #include "video_engine/include/vie_external_codec.h"
 
 // Gecko
 #include "GonkNativeWindow.h"
-#include "GonkNativeWindowClient.h"
 #include "mozilla/Atomics.h"
 #include "mozilla/Mutex.h"
 #include "nsThreadUtils.h"
 #include "OMXCodecWrapper.h"
 #include "TextureClient.h"
 
 #define DEQUEUE_BUFFER_TIMEOUT_US (100 * 1000ll) // 100ms.
 #define START_DEQUEUE_BUFFER_TIMEOUT_US (10 * DEQUEUE_BUFFER_TIMEOUT_US) // 1s.
@@ -85,39 +84,16 @@ public:
   {
     return DummyRefCountBase::Release();
   }
 
 private:
   RefPtr<layers::Image> mImage;
 };
 
-// Graphic buffer lifecycle management.
-// Return buffer to OMX codec when renderer is done with it.
-class RecycleCallback
-{
-public:
-  RecycleCallback(const sp<MediaCodec>& aOmx, uint32_t aBufferIndex)
-    : mOmx(aOmx)
-    , mBufferIndex(aBufferIndex)
-  {}
-  typedef void* CallbackPtr;
-  static void ReturnOMXBuffer(layers::TextureClient* aClient, CallbackPtr aClosure)
-  {
-    aClient->ClearRecycleCallback();
-    RecycleCallback* self = static_cast<RecycleCallback*>(aClosure);
-    self->mOmx->releaseOutputBuffer(self->mBufferIndex);
-    delete self;
-  }
-
-private:
-  sp<MediaCodec> mOmx;
-  uint32_t mBufferIndex;
-};
-
 struct EncodedFrame
 {
   uint32_t mWidth;
   uint32_t mHeight;
   uint32_t mTimestamp;
   int64_t mRenderTimeMs;
 };
 
@@ -224,24 +200,29 @@ private:
   // wait/notify queued input.
   Monitor mMonitor;
   nsCOMPtr<nsIThread> mThread;
   std::queue<EncodedFrame> mInputFrames;
   bool mEnding;
 };
 
 // H.264 decoder using stagefright.
-class WebrtcOMXDecoder MOZ_FINAL
+// It implements gonk native window callback to receive buffers from
+// MediaCodec::RenderOutputBufferAndRelease().
+class WebrtcOMXDecoder MOZ_FINAL : public GonkNativeWindowNewFrameCallback
 {
   NS_INLINE_DECL_THREADSAFE_REFCOUNTING(WebrtcOMXDecoder)
 public:
-  WebrtcOMXDecoder(const char* aMimeType)
+  WebrtcOMXDecoder(const char* aMimeType,
+                   webrtc::DecodedImageCallback* aCallback)
     : mWidth(0)
     , mHeight(0)
     , mStarted(false)
+    , mDecodedFrameLock("WebRTC decoded frame lock")
+    , mCallback(aCallback)
   {
     // Create binder thread pool required by stagefright.
     android::ProcessState::self()->startThreadPool();
 
     mLooper = new ALooper;
     mLooper->start();
     mCodec = MediaCodec::CreateByType(mLooper, aMimeType, false /* encoder */);
   }
@@ -285,31 +266,30 @@ public:
     config->setInt32("width", width);
     config->setInt32("height", height);
     mWidth = width;
     mHeight = height;
 
     sp<Surface> surface = nullptr;
     mNativeWindow = new GonkNativeWindow();
     if (mNativeWindow.get()) {
-      mNativeWindowClient = new GonkNativeWindowClient(mNativeWindow->getBufferQueue());
-      if (mNativeWindowClient.get()) {
-        surface = new Surface(mNativeWindowClient->getIGraphicBufferProducer());
-      }
+      // listen to buffers queued by MediaCodec::RenderOutputBufferAndRelease().
+      mNativeWindow->setNewFrameCallback(this);
+      surface = new Surface(mNativeWindow->getBufferQueue());
     }
     status_t result = mCodec->configure(config, surface, nullptr, 0);
     if (result == OK) {
       result = Start();
     }
     return result;
   }
 
   status_t
   FillInput(const webrtc::EncodedImage& aEncoded, bool aIsFirstFrame,
-            int64_t& aRenderTimeMs, webrtc::DecodedImageCallback* aCallback)
+            int64_t& aRenderTimeMs)
   {
     MOZ_ASSERT(mCodec != nullptr);
     if (mCodec == nullptr) {
       return INVALID_OPERATION;
     }
 
     size_t index;
     status_t err = mCodec->dequeueInputBuffer(&index,
@@ -330,32 +310,32 @@ public:
     omxIn->setRange(0, size);
     // Copying is needed because MediaCodec API doesn't support externallay
     // allocated buffer as input.
     memcpy(omxIn->data(), aEncoded._buffer, size);
     int64_t inputTimeUs = aEncoded._timeStamp * 1000 / 90; // 90kHz -> us.
     err = mCodec->queueInputBuffer(index, 0, size, inputTimeUs, flags);
     if (err == OK && !(flags & MediaCodec::BUFFER_FLAG_CODECCONFIG)) {
       if (mOutputDrain == nullptr) {
-        mOutputDrain = new OutputDrain(this, aCallback);
+        mOutputDrain = new OutputDrain(this);
         mOutputDrain->Start();
       }
       EncodedFrame frame;
       frame.mWidth = mWidth;
       frame.mHeight = mHeight;
       frame.mTimestamp = aEncoded._timeStamp;
       frame.mRenderTimeMs = aRenderTimeMs;
       mOutputDrain->QueueInput(frame);
     }
 
     return err;
   }
 
   status_t
-  DrainOutput(const EncodedFrame& aFrame, webrtc::DecodedImageCallback* aCallback)
+  DrainOutput(const EncodedFrame& aFrame)
   {
     MOZ_ASSERT(mCodec != nullptr);
     if (mCodec == nullptr) {
       return INVALID_OPERATION;
     }
 
     size_t index = 0;
     size_t outOffset = 0;
@@ -385,49 +365,91 @@ public:
         MOZ_ASSERT(err == OK);
         return INFO_OUTPUT_BUFFERS_CHANGED;
       default:
         CODEC_LOGE("decode dequeue OMX output buffer error:%d", err);
         // Return OK to instruct OutputDrain to drop input from queue.
         return OK;
     }
 
-    sp<ABuffer> omxOut = mOutputBuffers.itemAt(index);
-    nsAutoPtr<webrtc::I420VideoFrame> videoFrame(GenerateVideoFrame(aFrame,
-                                                                    index,
-                                                                    omxOut));
-    if (videoFrame == nullptr) {
+    if (mCallback) {
+      {
+        // Store info of this frame. OnNewFrame() will need the timestamp later.
+        MutexAutoLock lock(mDecodedFrameLock);
+        mDecodedFrames.push(aFrame);
+      }
+      // Ask codec to queue buffer back to native window. OnNewFrame() will be
+      // called.
+      mCodec->renderOutputBufferAndRelease(index);
+      // Once consumed, buffer will be queued back to GonkNativeWindow for codec
+      // to dequeue/use.
+    } else {
       mCodec->releaseOutputBuffer(index);
-    } else if (aCallback) {
-      aCallback->Decoded(*videoFrame);
-      // OMX buffer will be released by RecycleCallback after rendered.
     }
 
     return err;
   }
 
+  // Will be called when MediaCodec::RenderOutputBufferAndRelease() returns
+  // buffers back to native window for rendering.
+  void OnNewFrame() MOZ_OVERRIDE
+  {
+    RefPtr<layers::TextureClient> buffer = mNativeWindow->getCurrentBuffer();
+    MOZ_ASSERT(buffer != nullptr);
+
+    layers::GrallocImage::GrallocData grallocData;
+    grallocData.mPicSize = buffer->GetSize();
+    grallocData.mGraphicBuffer = buffer;
+
+    nsAutoPtr<layers::GrallocImage> grallocImage(new layers::GrallocImage());
+    grallocImage->SetData(grallocData);
+
+    // Get timestamp of the frame about to render.
+    int64_t timestamp = -1;
+    int64_t renderTimeMs = -1;
+    {
+      MutexAutoLock lock(mDecodedFrameLock);
+      if (mDecodedFrames.empty()) {
+        return;
+      }
+      EncodedFrame decoded = mDecodedFrames.front();
+      timestamp = decoded.mTimestamp;
+      renderTimeMs = decoded.mRenderTimeMs;
+      mDecodedFrames.pop();
+    }
+    MOZ_ASSERT(timestamp >= 0 && renderTimeMs >= 0);
+
+    nsAutoPtr<webrtc::I420VideoFrame> videoFrame(
+      new webrtc::TextureVideoFrame(new ImageNativeHandle(grallocImage.forget()),
+                                    grallocData.mPicSize.width,
+                                    grallocData.mPicSize.height,
+                                    timestamp,
+                                    renderTimeMs));
+    if (videoFrame != nullptr) {
+      mCallback->Decoded(*videoFrame);
+    }
+  }
+
 private:
   class OutputDrain : public OMXOutputDrain
   {
   public:
-    OutputDrain(WebrtcOMXDecoder* aOMX, webrtc::DecodedImageCallback* aCallback)
+    OutputDrain(WebrtcOMXDecoder* aOMX)
       : OMXOutputDrain()
       , mOMX(aOMX)
-      , mCallback(aCallback)
     {}
 
   protected:
     virtual bool DrainOutput(const EncodedFrame& aFrame) MOZ_OVERRIDE
     {
-      return (mOMX->DrainOutput(aFrame, mCallback) == OK