Merge last PGO-green changeset of mozilla-inbound to mozilla-central
authorEd Morley <emorley@mozilla.com>
Wed, 12 Dec 2012 10:01:04 +0000
changeset 115730 634180132e686fd07b00ca088937cd9ce370d459
parent 115629 553a3bcf1fe771c09cdfd1640e8059c312622b4a (current diff)
parent 115729 3eafe802b846e08ae6194de2a2919c14cbc5fd30 (diff)
child 115731 aed7413b2efceb2759f979ddcc779cfc24477dd9
child 115784 b3b5e2392ea57375ddafd681e6bc85bb8f78ab05
push id24020
push useremorley@mozilla.com
push dateWed, 12 Dec 2012 10:01:41 +0000
treeherdermozilla-central@634180132e68 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
milestone20.0a1
first release with
nightly linux32
634180132e68 / 20.0a1 / 20121212034329 / files
nightly linux64
634180132e68 / 20.0a1 / 20121212034329 / files
nightly mac
634180132e68 / 20.0a1 / 20121212034329 / files
nightly win32
634180132e68 / 20.0a1 / 20121212034329 / files
nightly win64
634180132e68 / 20.0a1 / 20121212034329 / files
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
releases
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Merge last PGO-green changeset of mozilla-inbound to mozilla-central
--- a/accessible/src/jsat/AccessFu.jsm
+++ b/accessible/src/jsat/AccessFu.jsm
@@ -9,17 +9,16 @@ const Ci = Components.interfaces;
 const Cu = Components.utils;
 const Cr = Components.results;
 
 this.EXPORTED_SYMBOLS = ['AccessFu'];
 
 Cu.import('resource://gre/modules/Services.jsm');
 
 Cu.import('resource://gre/modules/accessibility/Utils.jsm');
-Cu.import('resource://gre/modules/accessibility/TouchAdapter.jsm');
 
 const ACCESSFU_DISABLE = 0;
 const ACCESSFU_ENABLE = 1;
 const ACCESSFU_AUTO = 2;
 
 this.AccessFu = {
   /**
    * Initialize chrome-layer accessibility functionality.
@@ -53,16 +52,18 @@ this.AccessFu = {
     }
 
     try {
       this._activatePref = this.prefsBranch.getIntPref('activate');
     } catch (x) {
       this._activatePref = ACCESSFU_DISABLE;
     }
 
+    Input.quickNavMode.updateModes(this.prefsBranch);
+
     this._enableOrDisable();
   },
 
   /**
    * Start AccessFu mode, this primarily means controlling the virtual cursor
    * with arrow keys.
    */
   _enable: function _enable() {
@@ -71,32 +72,29 @@ this.AccessFu = {
     this._enabled = true;
 
     Cu.import('resource://gre/modules/accessibility/Utils.jsm');
     Cu.import('resource://gre/modules/accessibility/TouchAdapter.jsm');
     Cu.import('resource://gre/modules/accessibility/Presentation.jsm');
 
     Logger.info('enable');
 
-    this.touchAdapter = (Utils.MozBuildApp == 'mobile/android') ?
-      AndroidTouchAdapter : TouchAdapter;
-
     for each (let mm in Utils.getAllMessageManagers(this.chromeWin))
       this._loadFrameScript(mm);
 
     // Add stylesheet
     let stylesheetURL = 'chrome://global/content/accessibility/AccessFu.css';
     this.stylesheet = this.chromeWin.document.createProcessingInstruction(
       'xml-stylesheet', 'href="' + stylesheetURL + '" type="text/css"');
     this.chromeWin.document.insertBefore(this.stylesheet,
                                          this.chromeWin.document.firstChild);
 
     Input.attach(this.chromeWin);
     Output.attach(this.chromeWin);
-    this.touchAdapter.attach(this.chromeWin);
+    TouchAdapter.attach(this.chromeWin);
 
     Services.obs.addObserver(this, 'remote-browser-frame-shown', false);
     Services.obs.addObserver(this, 'Accessibility:NextObject', false);
     Services.obs.addObserver(this, 'Accessibility:PreviousObject', false);
     Services.obs.addObserver(this, 'Accessibility:Focus', false);
     this.chromeWin.addEventListener('TabOpen', this);
     this.chromeWin.addEventListener('TabSelect', this);
   },
@@ -112,17 +110,17 @@ this.AccessFu = {
 
     Logger.info('disable');
 
     this.chromeWin.document.removeChild(this.stylesheet);
     for each (let mm in Utils.getAllMessageManagers(this.chromeWin))
       mm.sendAsyncMessage('AccessFu:Stop');
 
     Input.detach();
-    this.touchAdapter.detach(this.chromeWin);
+    TouchAdapter.detach(this.chromeWin);
 
     this.chromeWin.removeEventListener('TabOpen', this);
     this.chromeWin.removeEventListener('TabSelect', this);
 
     Services.obs.removeObserver(this, 'remote-browser-frame-shown');
     Services.obs.removeObserver(this, 'Accessibility:NextObject');
     Services.obs.removeObserver(this, 'Accessibility:PreviousObject');
     Services.obs.removeObserver(this, 'Accessibility:Focus');
@@ -200,16 +198,18 @@ this.AccessFu = {
           mm.sendAsyncMessage('AccessFu:VirtualCursor',
                               {action: 'whereIsIt', move: true});
         }
         break;
       case 'nsPref:changed':
         if (aData == 'activate') {
           this._activatePref = this.prefsBranch.getIntPref('activate');
           this._enableOrDisable();
+        } else if (aData == 'quicknav_modes') {
+          Input.quickNavMode.updateModes(this.prefsBranch);
         }
         break;
       case 'remote-browser-frame-shown':
       {
         this._loadFrameScript(
           aSubject.QueryInterface(Ci.nsIFrameLoader).messageManager);
         break;
       }
@@ -384,62 +384,74 @@ var Input = {
 
   handleEvent: function Input_handleEvent(aEvent) {
     try {
       switch (aEvent.type) {
       case 'keypress':
         this._handleKeypress(aEvent);
         break;
       case 'mozAccessFuGesture':
-        this._handleGesture(aEvent);
+        this._handleGesture(aEvent.detail);
         break;
       }
     } catch (x) {
       Logger.logException(x);
     }
   },
 
-  _handleGesture: function _handleGesture(aEvent) {
-    let detail = aEvent.detail;
-    Logger.info('Gesture', detail.type,
-                '(fingers: ' + detail.touches.length + ')');
+  _handleGesture: function _handleGesture(aGesture) {
+    let gestureName = aGesture.type + aGesture.touches.length;
+    Logger.info('Gesture', aGesture.type,
+                '(fingers: ' + aGesture.touches.length + ')');
 
-    if (detail.touches.length == 1) {
-      switch (detail.type) {
-        case 'swiperight':
-          this.moveCursor('moveNext', 'Simple', 'gestures');
-          break;
-        case 'swipeleft':
-          this.moveCursor('movePrevious', 'Simple', 'gesture');
-          break;
-        case 'doubletap':
-          this.activateCurrent();
-          break;
-        case 'explore':
-          this.moveCursor('moveToPoint', 'Simple', 'gesture',
-                          detail.x, detail.y);
-          break;
-      }
-    }
-
-    if (detail.touches.length == 3) {
-      switch (detail.type) {
-        case 'swiperight':
-          this.scroll(-1, true);
-          break;
-        case 'swipedown':
-          this.scroll(-1);
-          break;
-        case 'swipeleft':
-          this.scroll(1, true);
-          break;
-        case 'swipeup':
-          this.scroll(1);
-          break;
-      }
+    switch (gestureName) {
+      case 'dwell1':
+      case 'explore1':
+        this.moveCursor('moveToPoint', 'Simple', 'gesture',
+                        aGesture.x, aGesture.y);
+        break;
+      case 'doubletap1':
+        this.activateCurrent();
+        break;
+      case 'swiperight1':
+        this.moveCursor('moveNext', 'Simple', 'gestures');
+        break;
+      case 'swipeleft1':
+        this.moveCursor('movePrevious', 'Simple', 'gesture');
+        break;
+      case 'swiperight2':
+        this.scroll(-1, true);
+        break;
+      case 'swipedown2':
+        this.scroll(-1);
+        break;
+      case 'swipeleft2':
+        this.scroll(1, true);
+        break;
+      case 'swipeup2':
+        this.scroll(1);
+        break;
+      case 'explore2':
+        Utils.getCurrentBrowser(this.chromeWin).contentWindow.scrollBy(
+          -aGesture.deltaX, -aGesture.deltaY);
+        break;
+      case 'swiperight3':
+        this.moveCursor('moveNext', this.quickNavMode.current, 'gesture');
+        break;
+      case 'swipeleft3':
+        this.moveCursor('movePrevious', this.quickNavMode.current, 'gesture');
+        break;
+      case 'swipedown3':
+        this.quickNavMode.next();
+        AccessFu.announce('quicknav_' + this.quickNavMode.current);
+        break;
+      case 'swipeup3':
+        this.quickNavMode.previous();
+        AccessFu.announce('quicknav_' + this.quickNavMode.current);
+        break;
     }
   },
 
   _handleKeypress: function _handleKeypress(aEvent) {
     let target = aEvent.target;
 
     // Ignore keys with modifiers so the content could take advantage of them.
     if (aEvent.ctrlKey || aEvent.altKey || aEvent.metaKey)
@@ -563,10 +575,39 @@ var Input = {
       R: ['movePrevious', 'RadioButton'],
       s: ['moveNext', 'Separator'],
       S: ['movePrevious', 'Separator'],
       t: ['moveNext', 'Table'],
       T: ['movePrevious', 'Table'],
       x: ['moveNext', 'Checkbox'],
       X: ['movePrevious', 'Checkbox']
     };
+
+    return this.keyMap;
+  },
+
+  quickNavMode: {
+    get current() {
+      return this.modes[this._currentIndex];
+    },
+
+    previous: function quickNavMode_previous() {
+      if (--this._currentIndex < 0)
+        this._currentIndex = this.modes.length - 1;
+    },
+
+    next: function quickNavMode_next() {
+      if (++this._currentIndex >= this.modes.length)
+        this._currentIndex = 0;
+    },
+
+    updateModes: function updateModes(aPrefsBranch) {
+      try {
+        this.modes = aPrefsBranch.getCharPref('quicknav_modes').split(',');
+      } catch (x) {
+        // Fallback
+        this.modes = [];
+      }
+    },
+
+    _currentIndex: -1
   }
 };
--- a/accessible/src/jsat/TouchAdapter.jsm
+++ b/accessible/src/jsat/TouchAdapter.jsm
@@ -4,17 +4,17 @@
 
 'use strict';
 
 const Cc = Components.classes;
 const Ci = Components.interfaces;
 const Cu = Components.utils;
 const Cr = Components.results;
 
-this.EXPORTED_SYMBOLS = ['TouchAdapter', 'AndroidTouchAdapter'];
+this.EXPORTED_SYMBOLS = ['TouchAdapter'];
 
 Cu.import('resource://gre/modules/accessibility/Utils.jsm');
 
 // We should not be emitting explore events more than 10 times a second.
 // It is granular enough to feel natural, and it does not hammer the CPU.
 const EXPLORE_THROTTLE = 100;
 
 this.TouchAdapter = {
@@ -34,99 +34,141 @@ this.TouchAdapter = {
   DWELL_THRESHOLD: 500,
 
   // delay before distinct dwell events
   DWELL_REPEAT_DELAY: 300,
 
   // maximum distance the mouse could move during a tap in inches
   TAP_MAX_RADIUS: 0.2,
 
+  // The virtual touch ID generated by an Android hover event.
+  HOVER_ID: 'hover',
+
   attach: function TouchAdapter_attach(aWindow) {
     if (this.chromeWin)
       return;
 
     Logger.info('TouchAdapter.attach');
 
     this.chromeWin = aWindow;
     this._touchPoints = {};
     this._dwellTimeout = 0;
     this._prevGestures = {};
     this._lastExploreTime = 0;
     this._dpi = this.chromeWin.QueryInterface(Ci.nsIInterfaceRequestor).
       getInterface(Ci.nsIDOMWindowUtils).displayDPI;
 
-    this.glass = this.chromeWin.document.
-      createElementNS('http://www.w3.org/1999/xhtml', 'div');
-    this.glass.id = 'accessfu-glass';
-    this.chromeWin.document.documentElement.appendChild(this.glass);
+    let target = this.chromeWin;
+
+    if (Utils.MozBuildApp == 'b2g') {
+      this.glass = this.chromeWin.document.
+        createElementNS('http://www.w3.org/1999/xhtml', 'div');
+      this.glass.id = 'accessfu-glass';
+      this.chromeWin.document.documentElement.appendChild(this.glass);
+      target = this.glass;
+    }
 
-    this.glass.addEventListener('touchend', this, true, true);
-    this.glass.addEventListener('touchmove', this, true, true);
-    this.glass.addEventListener('touchstart', this, true, true);
+    target.addEventListener('mousemove', this, true, true);
+    target.addEventListener('mouseenter', this, true, true);
+    target.addEventListener('mouseleave', this, true, true);
+    target.addEventListener('mousedown', this, true, true);
+    target.addEventListener('mouseup', this, true, true);
+    target.addEventListener('click', this, true, true);
+
+    target.addEventListener('touchend', this, true, true);
+    target.addEventListener('touchmove', this, true, true);
+    target.addEventListener('touchstart', this, true, true);
 
     if (Utils.OS != 'Android')
       Mouse2Touch.attach(aWindow);
   },
 
   detach: function TouchAdapter_detach(aWindow) {
     if (!this.chromeWin)
       return;
 
     Logger.info('TouchAdapter.detach');
 
-    this.glass.removeEventListener('touchend', this, true, true);
-    this.glass.removeEventListener('touchmove', this, true, true);
-    this.glass.removeEventListener('touchstart', this, true, true);
-    this.glass.parentNode.removeChild(this.glass);
+    let target = this.chromeWin;
+
+    if (Utils.MozBuildApp == 'b2g') {
+      target = this.glass;
+      this.glass.parentNode.removeChild(this.glass);
+    }
+
+    target.removeEventListener('mousemove', this, true, true);
+    target.removeEventListener('mouseenter', this, true, true);
+    target.removeEventListener('mouseleave', this, true, true);
+    target.removeEventListener('mousedown', this, true, true);
+    target.removeEventListener('mouseup', this, true, true);
+    target.removeEventListener('click', this, true, true);
+
+    target.removeEventListener('touchend', this, true, true);
+    target.removeEventListener('touchmove', this, true, true);
+    target.removeEventListener('touchstart', this, true, true);
 
     if (Utils.OS != 'Android')
       Mouse2Touch.detach(aWindow);
 
     delete this.chromeWin;
   },
 
   handleEvent: function TouchAdapter_handleEvent(aEvent) {
-    let touches = aEvent.changedTouches;
+    if (this._delayedEvent) {
+      this.chromeWin.clearTimeout(this._delayedEvent);
+      delete this._delayedEvent;
+    }
+
+    let changedTouches = aEvent.changedTouches || [aEvent];
+
     // XXX: Until bug 77992 is resolved, on desktop we get microseconds
     // instead of milliseconds.
     let timeStamp = (Utils.OS == 'Android') ? aEvent.timeStamp : Date.now();
     switch (aEvent.type) {
+      case 'mouseenter':
       case 'touchstart':
-        for (var i = 0; i < touches.length; i++) {
-          let touch = touches[i];
+        for (var i = 0; i < changedTouches.length; i++) {
+          let touch = changedTouches[i];
           let touchPoint = new TouchPoint(touch, timeStamp, this._dpi);
-          this._touchPoints[touch.identifier] = touchPoint;
+          this._touchPoints[touch.identifier || this.HOVER_ID] = touchPoint;
           this._lastExploreTime = timeStamp + this.SWIPE_MAX_DURATION;
         }
         this._dwellTimeout = this.chromeWin.setTimeout(
           (function () {
              this.compileAndEmit(timeStamp + this.DWELL_THRESHOLD);
            }).bind(this), this.DWELL_THRESHOLD);
         break;
+      case 'mousemove':
       case 'touchmove':
-        for (var i = 0; i < touches.length; i++) {
-          let touch = touches[i];
-          let touchPoint = this._touchPoints[touch.identifier];
-          touchPoint.update(touch, timeStamp);
+        for (var i = 0; i < changedTouches.length; i++) {
+          let touch = changedTouches[i];
+          let touchPoint = this._touchPoints[touch.identifier || this.HOVER_ID];
+          if (touchPoint)
+            touchPoint.update(touch, timeStamp);
         }
         if (timeStamp - this._lastExploreTime >= EXPLORE_THROTTLE) {
           this.compileAndEmit(timeStamp);
           this._lastExploreTime = timeStamp;
         }
         break;
+      case 'mouseleave':
       case 'touchend':
-        for (var i = 0; i < touches.length; i++) {
-          let touch = touches[i];
-          let touchPoint = this._touchPoints[touch.identifier];
-          touchPoint.update(touch, timeStamp);
-          touchPoint.finish();
+        for (var i = 0; i < changedTouches.length; i++) {
+          let touch = changedTouches[i];
+          let touchPoint = this._touchPoints[touch.identifier || this.HOVER_ID];
+          if (touchPoint) {
+            touchPoint.update(touch, timeStamp);
+            touchPoint.finish();
+          }
         }
         this.compileAndEmit(timeStamp);
         break;
     }
+
+    aEvent.preventDefault();
   },
 
   cleanupTouches: function cleanupTouches() {
     for (var identifier in this._touchPoints) {
       if (!this._touchPoints[identifier].done)
         continue;
 
       delete this._touchPoints[identifier];
@@ -165,38 +207,75 @@ this.TouchAdapter = {
 
       if (prevGesture) {
         // The time delta is calculated as the period between the end of the
         // last gesture and the start of this one.
         let timeDelta = details.startTime - prevGesture.endTime;
         if (timeDelta > this.MAX_CONSECUTIVE_GESTURE_DELAY) {
           delete this._prevGestures[idhash];
         } else {
-          if (details.type == 'tap' && prevGesture.type == 'tap')
-            details.type = 'doubletap';
-          if (details.type == 'tap' && prevGesture.type == 'doubletap')
-            details.type = 'tripletap';
-          if (details.type == 'dwell' && prevGesture.type == 'tap')
-            details.type = 'taphold';
+          let sequence = prevGesture.type + '-' + details.type;
+          switch (sequence) {
+            case 'tap-tap':
+              details.type = 'doubletap';
+              break;
+            case 'doubletap-tap':
+              details.type = 'tripletap';
+              break;
+            case 'tap-dwell':
+              details.type = 'taphold';
+              break;
+            case 'explore-explore':
+              details.deltaX = details.x - prevGesture.x;
+              details.deltaY = details.y - prevGesture.y;
+              break;
+          }
         }
       }
 
       this._prevGestures[idhash] = details;
     }
 
     this.chromeWin.clearTimeout(this._dwellTimeout);
     this.cleanupTouches();
 
     return multiDetails;
   },
 
   emitGesture: function TouchAdapter_emitGesture(aDetails) {
-    let evt = this.chromeWin.document.createEvent('CustomEvent');
-    evt.initCustomEvent('mozAccessFuGesture', true, true, aDetails);
-    this.chromeWin.dispatchEvent(evt);
+    let emitDelay = 0;
+
+    // Unmutate gestures we are getting from Android when EBT is enabled.
+    // Two finger gestures are translated to one. Double taps are translated
+    // to single taps.
+    if (Utils.MozBuildApp == 'mobile/android' &&
+        Utils.AndroidSdkVersion >= 14 &&
+        aDetails.touches[0] != this.HOVER_ID) {
+      if (aDetails.touches.length == 1) {
+        if (aDetails.type == 'tap') {
+          emitDelay = 50;
+          aDetails.type = 'doubletap';
+        } else {
+          aDetails.touches.push(this.HOVER_ID);
+        }
+      }
+    }
+
+    let emit = function emit() {
+      let evt = this.chromeWin.document.createEvent('CustomEvent');
+      evt.initCustomEvent('mozAccessFuGesture', true, true, aDetails);
+      this.chromeWin.dispatchEvent(evt);
+      delete this._delayedEvent;
+    }.bind(this);
+
+    if (emitDelay) {
+      this._delayedEvent = this.chromeWin.setTimeout(emit, emitDelay);
+    } else {
+      emit();
+    }
   },
 
   compileAndEmit: function TouchAdapter_compileAndEmit(aTime) {
     for each (let details in this.compile(aTime)) {
       this.emitGesture(details);
     }
   }
 };
@@ -359,46 +438,8 @@ var Mouse2Touch = {
       evt.initTouchEvent(name, true, true, this.chromeWin, 0,
                          false, false, false, false, touches, touches, touches);
     }
     aEvent.target.dispatchEvent(evt);
     aEvent.preventDefault();
     aEvent.stopImmediatePropagation();
   }
 };
-
-this.AndroidTouchAdapter = {
-  attach: function AndroidTouchAdapter_attach(aWindow) {
-    if (this.chromeWin)
-      return;
-
-    Logger.info('AndroidTouchAdapter.attach');
-
-    this.chromeWin = aWindow;
-    this.chromeWin.addEventListener('mousemove', this, true, true);
-    this._lastExploreTime = 0;
-  },
-
-  detach: function AndroidTouchAdapter_detach(aWindow) {
-    if (!this.chromeWin)
-      return;
-
-    Logger.info('AndroidTouchAdapter.detach');
-
-    this.chromeWin.removeEventListener('mousemove', this, true, true);
-    delete this.chromeWin;
-  },
-
-  handleEvent: function AndroidTouchAdapter_handleEvent(aEvent) {
-    // On non-Android we use the shift key to simulate touch.
-    if (Utils.MozBuildApp != 'mobile/android' && !aEvent.shiftKey)
-      return;
-
-    if (aEvent.timeStamp - this._lastExploreTime >= EXPLORE_THROTTLE) {
-      let evt = this.chromeWin.document.createEvent('CustomEvent');
-      evt.initCustomEvent(
-        'mozAccessFuGesture', true, true,
-       {type: 'explore', x: aEvent.screenX, y: aEvent.screenY, touches: [1]});
-      this.chromeWin.dispatchEvent(evt);
-      this._lastExploreTime = aEvent.timeStamp;
-    }
-  }
-};
\ No newline at end of file
--- a/b2g/app/b2g.js
+++ b/b2g/app/b2g.js
@@ -229,26 +229,35 @@ pref("ui.windowframe", "#efebe7");
 // replace newlines with spaces on paste into single-line text boxes
 pref("editor.singleLine.pasteNewlines", 2);
 
 // threshold where a tap becomes a drag, in 1/240" reference pixels
 // The names of the preferences are to be in sync with nsEventStateManager.cpp
 pref("ui.dragThresholdX", 25);
 pref("ui.dragThresholdY", 25);
 
-// Layers Acceleration
+// Layers Acceleration.  We can only have nice things on gonk, because
+// they're not maintained anywhere else.
+#ifndef MOZ_WIDGET_GONK
+pref("dom.ipc.tabs.disabled", true);
+pref("layers.offmainthreadcomposition.enabled", false);
+pref("layers.offmainthreadcomposition.animate-opacity", false);
+pref("layers.offmainthreadcomposition.animate-transform", false);
+pref("layers.offmainthreadcomposition.throttle-animations", false);
+pref("layers.async-video.enabled", false);
+#else
+pref("dom.ipc.tabs.disabled", false);
+pref("layers.offmainthreadcomposition.enabled", true);
 pref("layers.acceleration.disabled", false);
-#ifndef XP_WIN
-//TODO: turn this on for Windows in bug 808016
-pref("layers.offmainthreadcomposition.enabled", true);
-#endif
 pref("layers.offmainthreadcomposition.animate-opacity", true);
 pref("layers.offmainthreadcomposition.animate-transform", true);
+pref("layers.offmainthreadcomposition.throttle-animations", true);
 pref("layers.async-video.enabled", true);
 pref("layers.async-pan-zoom.enabled", true);
+#endif
 
 // Web Notifications
 pref("notification.feature.enabled", true);
 
 // IndexedDB
 pref("indexedDB.feature.enabled", true);
 pref("dom.indexedDB.warningQuota", 5);
 
@@ -374,17 +383,16 @@ pref("browser.link.open_newwindow.restri
 // Enable browser frames (including OOP, except on Windows, where it doesn't
 // work), but make in-process browser frames the default.
 pref("dom.mozBrowserFramesEnabled", true);
 
 // Enable a (virtually) unlimited number of mozbrowser processes.
 // We'll run out of PIDs on UNIX-y systems before we hit this limit.
 pref("dom.ipc.processCount", 100000);
 
-pref("dom.ipc.tabs.disabled", false);
 pref("dom.ipc.browser_frames.oop_by_default", false);
 
 // Temporary permission hack for WebSMS
 pref("dom.sms.enabled", true);
 pref("dom.sms.strict7BitEncoding", false); // Disabled by default.
 
 // Temporary permission hack for WebContacts
 pref("dom.mozContacts.enabled", true);
--- a/b2g/app/nsBrowserApp.cpp
+++ b/b2g/app/nsBrowserApp.cpp
@@ -163,20 +163,16 @@ static int do_main(int argc, char* argv[
 
   return XRE_main(argc, argv, &sAppData, 0);
 }
 
 int main(int argc, char* argv[])
 {
   char exePath[MAXPATHLEN];
 
-#if defined(MOZ_X11)
-  putenv("MOZ_USE_OMTC=1");
-#endif
-
   nsresult rv = mozilla::BinaryPath::Get(argv[0], exePath);
   if (NS_FAILED(rv)) {
     Output("Couldn't calculate the application directory.\n");
     return 255;
   }
 
   char *lastSlash = strrchr(exePath, XPCOM_FILE_PATH_SEPARATOR[0]);
   if (!lastSlash || ((lastSlash - exePath) + sizeof(XPCOM_DLL) + 1 > MAXPATHLEN))
--- a/browser/base/content/test/head.js
+++ b/browser/base/content/test/head.js
@@ -145,26 +145,28 @@ function runSocialTestWithProvider(manif
       // If we've added all the providers we need, call the callback to start
       // the tests (and give it a callback it can call to finish them)
       if (providersAdded == manifests.length) {
         // Set the UI's provider and enable the feature
         Social.provider = firstProvider;
         Social.enabled = true;
 
         registerCleanupFunction(function () {
+          // disable social before removing the providers to avoid providers
+          // being activated immediately before we get around to removing it.
+          Services.prefs.clearUserPref("social.enabled");
           // if one test happens to fail, it is likely finishSocialTest will not
           // be called, causing most future social tests to also fail as they
           // attempt to add a provider which already exists - so work
           // around that by also attempting to remove the test provider.
           manifests.forEach(function (m) {
             try {
               SocialService.removeProvider(m.origin, finish);
             } catch (ex) {}
           });
-          Services.prefs.clearUserPref("social.enabled");
         });
         function finishSocialTest() {
           SocialService.removeProvider(provider.origin, finish);
         }
         callback(finishSocialTest);
       }
     });
   });
--- a/browser/devtools/commandline/test/Makefile.in
+++ b/browser/devtools/commandline/test/Makefile.in
@@ -9,18 +9,16 @@ srcdir    = @srcdir@
 VPATH     = @srcdir@
 relativesrcdir  = @relativesrcdir@
 
 include $(DEPTH)/config/autoconf.mk
 
 MOCHITEST_BROWSER_FILES = \
   browser_dbg_cmd_break.html \
   browser_dbg_cmd_break.js \
-  browser_dbg_cmd.html \
-  browser_dbg_cmd.js \
   browser_cmd_addon.js \
   browser_cmd_commands.js \
   browser_cmd_cookie.js \
   browser_cmd_integrate.js \
   browser_cmd_jsb.js \
   browser_cmd_jsb_script.jsi \
   browser_cmd_pagemod_export.html \
   browser_cmd_pagemod_export.js \
@@ -62,17 +60,20 @@ MOCHITEST_BROWSER_FILES += \
 else
 MOCHITEST_BROWSER_FILES += \
  browser_cmd_screenshot.js \
  $(NULL)
 endif
 
 ifneq ($(OS_ARCH),WINNT)
 MOCHITEST_BROWSER_FILES += \
+  browser_dbg_cmd.html \
+  browser_dbg_cmd.js \
   browser_cmd_calllog.js \
   browser_cmd_calllog_chrome.js \
   $(NULL)
 else
+$(filter disabled-temporarily--bug-820221, browser_dbg_cmd.js)
 $(filter disabled-temporarily--bug-817304, browser_cmd_calllog.js)
 $(filter disabled-temporarily--bug-819017, browser_cmd_calllog_chrome.js)
 endif
 
 include $(topsrcdir)/config/rules.mk
--- a/browser/themes/gnomestripe/Makefile.in
+++ b/browser/themes/gnomestripe/Makefile.in
@@ -6,19 +6,13 @@ DEPTH		= @DEPTH@
 topsrcdir	= @top_srcdir@
 srcdir		= @srcdir@
 VPATH		= @srcdir@
 
 include $(DEPTH)/config/autoconf.mk
 
 DIRS = communicator
 
-include $(topsrcdir)/config/rules.mk
-
-FILES := \
-	icon.png \
-	$(NULL)
+ICON_FILES := icon.png
+ICON_DEST = $(FINAL_TARGET)/extensions/{972ce4c6-7e08-4474-a285-3208198ce6fd}
+INSTALL_TARGETS += ICON
 
-libs:: $(FILES)
-	$(INSTALL) $(foreach f,$^,"$f") $(DIST)/bin/extensions/{972ce4c6-7e08-4474-a285-3208198ce6fd}
-
-install:: $(FILES)
-	$(SYSINSTALL) $(IFLAGS1) $(foreach f,$^,"$f") $(DESTDIR)$(mozappdir)/extensions/{972ce4c6-7e08-4474-a285-3208198ce6fd}
+include $(topsrcdir)/config/rules.mk
--- a/browser/themes/pinstripe/Makefile.in
+++ b/browser/themes/pinstripe/Makefile.in
@@ -6,19 +6,13 @@ DEPTH		= @DEPTH@
 topsrcdir	= @top_srcdir@
 srcdir		= @srcdir@
 VPATH		= @srcdir@
 
 include $(DEPTH)/config/autoconf.mk
 
 DIRS = communicator
 
-include $(topsrcdir)/config/rules.mk
-
-FILES := \
-	icon.png \
-	$(NULL)
+ICON_FILES := icon.png
+ICON_DEST = $(FINAL_TARGET)/extensions/{972ce4c6-7e08-4474-a285-3208198ce6fd}
+INSTALL_TARGETS += ICON
 
-libs:: $(FILES)
-	$(INSTALL) $(foreach f,$^,"$f") $(DIST)/bin/extensions/{972ce4c6-7e08-4474-a285-3208198ce6fd}
-
-install:: $(FILES)
-	$(SYSINSTALL) $(IFLAGS1) $(foreach f,$^,"$f") $(DESTDIR)$(mozappdir)/extensions/{972ce4c6-7e08-4474-a285-3208198ce6fd}
+include $(topsrcdir)/config/rules.mk
--- a/browser/themes/winstripe/Makefile.in
+++ b/browser/themes/winstripe/Makefile.in
@@ -6,19 +6,13 @@ DEPTH		= @DEPTH@
 topsrcdir	= @top_srcdir@
 srcdir		= @srcdir@
 VPATH		= @srcdir@
 
 include $(DEPTH)/config/autoconf.mk
 
 DIRS = communicator
 
-include $(topsrcdir)/config/rules.mk
-
-FILES := \
-	icon.png \
-	$(NULL)
+ICON_FILES := icon.png
+ICON_DEST = $(FINAL_TARGET)/extensions/{972ce4c6-7e08-4474-a285-3208198ce6fd}
+INSTALL_TARGETS += ICON
 
-libs:: $(FILES)
-	$(INSTALL) $(foreach f,$^,"$f") $(DIST)/bin/extensions/{972ce4c6-7e08-4474-a285-3208198ce6fd}
-
-install:: $(FILES)
-	$(SYSINSTALL) $(IFLAGS1) $(foreach f,$^,"$f") $(DESTDIR)$(mozappdir)/extensions/{972ce4c6-7e08-4474-a285-3208198ce6fd}
+include $(topsrcdir)/config/rules.mk
--- a/build/pymake/pymake/builtins.py
+++ b/build/pymake/pymake/builtins.py
@@ -81,13 +81,40 @@ def sleep(args):
         except ValueError:
             raise PythonException, ("sleep: invalid time interval '%s'" % a, 1)
     time.sleep(total)
 
 def touch(args):
     """
     Emulate the behavior of touch(1).
     """
+    try:
+        opts, args = getopt(args, "t:")
+    except GetoptError, e:
+        raise PythonException, ("touch: %s" % e, 1)
+    opts = dict(opts)
+    times = None
+    if '-t' in opts:
+        import re
+        from time import mktime, localtime
+        m = re.match('^(?P<Y>(?:\d\d)?\d\d)?(?P<M>\d\d)(?P<D>\d\d)(?P<h>\d\d)(?P<m>\d\d)(?:\.(?P<s>\d\d))?$', opts['-t'])
+        if not m:
+            raise PythonException, ("touch: invalid date format '%s'" % opts['-t'], 1)
+        def normalized_field(m, f):
+            if f == 'Y':
+                if m.group(f) is None:
+                    return localtime()[0]
+                y = int(m.group(f))
+                if y < 69:
+                    y += 2000
+                elif y < 100:
+                    y += 1900
+                return y
+            if m.group(f) is None:
+                return localtime()[0] if f == 'Y' else 0
+            return int(m.group(f))
+        time = [normalized_field(m, f) for f in ['Y', 'M', 'D', 'h', 'm', 's']] + [0, 0, -1]
+        time = mktime(time)
+        times = (time, time)
     for f in args:
-        if os.path.exists(f):
-            os.utime(f, None)
-        else:
-            open(f, 'w').close()
+        if not os.path.exists(f):
+            open(f, 'a').close()
+        os.utime(f, times)
--- a/build/pymake/pymake/data.py
+++ b/build/pymake/pymake/data.py
@@ -1409,19 +1409,19 @@ class _NativeWrapper(_CommandWrapper):
                                           pycommandpath)
         else:
             self.pycommandpath = None
 
     def __call__(self, cb):
         # get the module and method to call
         parts, badchar = process.clinetoargv(self.cline, self.kwargs['cwd'])
         if parts is None:
-            raise DataError("native command '%s': shell metacharacter '%s' in command line" % (cline, badchar), self.loc)
+            raise DataError("native command '%s': shell metacharacter '%s' in command line" % (self.cline, badchar), self.loc)
         if len(parts) < 2:
-            raise DataError("native command '%s': no method name specified" % cline, self.loc)
+            raise DataError("native command '%s': no method name specified" % self.cline, self.loc)
         module = parts[0]
         method = parts[1]
         cline_list = parts[2:]
         self.usercb = cb
         process.call_native(module, method, cline_list,
                             loc=self.loc, cb=self._cb, context=self.context,
                             pycommandpath=self.pycommandpath, **self.kwargs)
 
new file mode 100644
--- /dev/null
+++ b/build/pymake/tests/native-touch.mk
@@ -0,0 +1,15 @@
+TOUCH ?= touch
+
+foo:
+	$(TOUCH) bar
+	$(TOUCH) baz
+	$(MAKE) -f $(TESTPATH)/native-touch.mk baz
+	$(TOUCH) -t 198007040802 baz
+	$(MAKE) -f $(TESTPATH)/native-touch.mk baz
+
+bar:
+	$(TOUCH) $@
+
+baz: bar
+	echo TEST-PASS
+	$(TOUCH) $@
--- a/config/config.mk
+++ b/config/config.mk
@@ -71,19 +71,19 @@ RM = rm -f
 
 # LIBXUL_DIST is not defined under js/src, thus we make it mean DIST there.
 LIBXUL_DIST ?= $(DIST)
 
 # FINAL_TARGET specifies the location into which we copy end-user-shipped
 # build products (typelibs, components, chrome).
 #
 # If XPI_NAME is set, the files will be shipped to $(DIST)/xpi-stage/$(XPI_NAME)
-# If DIST_SUBDIR is set, the files will be shipped to $(DIST)/$(DIST_SUBDIR)
-# Otherwise, the default $(DIST)/bin will be used.
-FINAL_TARGET = $(if $(XPI_NAME),$(DIST)/xpi-stage/$(XPI_NAME),$(if $(DIST_SUBDIR),$(DIST)/bin/$(DIST_SUBDIR),$(DIST)/bin))
+# instead of $(DIST)/bin. In both cases, if DIST_SUBDIR is set, the files will be
+# shipped to a $(DIST_SUBDIR) subdirectory.
+FINAL_TARGET = $(if $(XPI_NAME),$(DIST)/xpi-stage/$(XPI_NAME),$(DIST)/bin)$(DIST_SUBDIR:%=/%)
 
 ifdef XPI_NAME
 DEFINES += -DXPI_NAME=$(XPI_NAME)
 endif
 
 # The VERSION_NUMBER is suffixed onto the end of the DLLs we ship.
 VERSION_NUMBER		= 50
 
--- a/config/makefiles/autotargets.mk
+++ b/config/makefiles/autotargets.mk
@@ -51,28 +51,28 @@ mkdir_stem =$(foreach val,$(getargv),$(s
 ## Generate timestamp file for threadsafe directory creation
 mkdir_deps =$(foreach dir,$(getargv),$(call slash_strip,$(dir)/.mkdir.done))
 
 #######################
 ##---]  TARGETS  [---##
 #######################
 
 %/.mkdir.done: # mkdir -p -p => mkdir -p
-	$(subst $(space)-p,$(null),$(MKDIR)) -p $(dir $@)
+	$(subst $(space)-p,$(null),$(MKDIR)) -p "$(dir $@)"
 # Make the timestamp old enough for not being a problem with symbolic links
 # targets depending on it. Use Jan 3, 1980 to accomodate any timezone where
 # 198001010000 would translate to something older than FAT epoch.
-	@touch -t 198001030000 $@
+	@$(TOUCH) -t 198001030000 "$@"
 
 # A handful of makefiles are attempting "mkdir dot".  Likely not intended
 # or stale logic so add a stub target to handle the request and warn for now.
 .mkdir.done:
 ifndef NOWARN_AUTOTARGETS # {
 	@echo "WARNING: $(MKDIR) -dot- requested by $(MAKE) -C $(CURDIR) $(MAKECMDGOALS)"
-	@touch -t 198001030000 $@
+	@$(TOUCH) -t 198001030000 $@
 endif #}
 
 INCLUDED_AUTOTARGETS_MK = 1
 endif #}
 
 
 ## Accumulate deps and cleanup
 ifneq (,$(GENERATED_DIRS))
--- a/config/rules.mk
+++ b/config/rules.mk
@@ -1539,17 +1539,17 @@ define install_cmd_override
 $(1): install_cmd = $$(if $$(nsinstall_is_usable),$$(INSTALL),$$(NSINSTALL_PY)) $$(1)
 endef
 endif
 
 define install_file_template
 $(or $(3),libs):: $(2)/$(notdir $(1))
 $(call install_cmd_override,$(2)/$(notdir $(1)))
 $(2)/$(notdir $(1)): $(1) $$(call mkdir_deps,$(2))
-	$$(call install_cmd,$(4) $$< $${@D})
+	$$(call install_cmd,$(4) "$$<" "$${@D}")
 endef
 $(foreach category,$(INSTALL_TARGETS),\
   $(if $($(category)_DEST),,$(error Missing $(category)_DEST))\
   $(foreach file,$($(category)_FILES),\
     $(eval $(call install_file_template,$(file),$($(category)_DEST),$($(category)_TARGET),$(IFLAGS1)))\
   )\
   $(foreach file,$($(category)_EXECUTABLES),\
     $(eval $(call install_file_template,$(file),$($(category)_DEST),$($(category)_TARGET),$(IFLAGS2)))\
@@ -1586,18 +1586,18 @@ endef
 #   files. Setting this variable is optional; if unset, we preprocess the
 #   files for the 'libs' target.
 
 # preprocess_file_template defines preprocessing rules.
 # $(call preprocess_file_template, source_file, output_file,
 #                                  makefile_target, extra_flags)
 define preprocess_file_template
 $(2): $(1) $$(call mkdir_deps,$(dir $(2))) $$(GLOBAL_DEPS)
-	$$(RM) $$@
-	$$(PYTHON) $$(topsrcdir)/config/Preprocessor.py $(4) $$(DEFINES) $$(ACDEFINES) $$(XULPPFLAGS) $$< > $$@
+	$$(RM) "$$@"
+	$$(PYTHON) $$(topsrcdir)/config/Preprocessor.py $(4) $$(DEFINES) $$(ACDEFINES) $$(XULPPFLAGS) "$$<" > "$$@"
 $(3):: $(2)
 endef
 
 $(foreach category,$(PP_TARGETS),						\
   $(foreach file,$($(category)),						\
     $(eval $(call preprocess_file_template,					\
                   $(file),							\
                   $(or $($(category)_PATH),$(CURDIR))/$(notdir $(file:.in=)),	\
--- a/config/writemozinfo.py
+++ b/config/writemozinfo.py
@@ -24,17 +24,17 @@ def build_dict(env=os.environ):
     if missing:
         raise Exception("Missing required environment variables: %s" %
                         ', '.join(missing))
     # os
     o = env["OS_TARGET"]
     known_os = {"Linux": "linux",
                 "WINNT": "win",
                 "Darwin": "mac",
-                "Android": "android"}
+                "Android": "b2g" if env["MOZ_WIDGET_TOOLKIT"] == "gonk" else "android"}
     if o in known_os:
         d["os"] = known_os[o]
     else:
         # Allow unknown values, just lowercase them.
         d["os"] = o.lower()
 
     # Widget toolkit, just pass the value directly through.
     d["toolkit"] = env["MOZ_WIDGET_TOOLKIT"]
--- a/content/base/public/DirectionalityUtils.h
+++ b/content/base/public/DirectionalityUtils.h
@@ -2,18 +2,17 @@
  *
  * This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #ifndef DirectionalityUtils_h___
 #define DirectionalityUtils_h___
 
-#include "prtypes.h"
-#include "mozilla/StandardInteger.h"
+#include "nscore.h"
 
 class nsIContent;
 class nsIDocument;
 class nsINode;
 class nsAString;
 class nsAttrValue;
 class nsTextNode;
 
--- a/content/base/public/mozFlushType.h
+++ b/content/base/public/mozFlushType.h
@@ -22,9 +22,22 @@ enum mozFlushType {
   Flush_InterruptibleLayout = 4, /* As above, plus flush reflow,
                                     but allow it to be interrupted (so
                                     an incomplete layout may result) */
   Flush_Layout           = 5, /* As above, but layout must run to
                                  completion */
   Flush_Display          = 6  /* As above, plus flush painting */
 };
 
+namespace mozilla {
+
+struct ChangesToFlush {
+  ChangesToFlush(mozFlushType aFlushType, bool aFlushAnimations)
+    : mFlushType(aFlushType)
+    , mFlushAnimations(aFlushAnimations)
+  {}
+
+  mozFlushType mFlushType;
+  bool mFlushAnimations;
+};
+
+}
 #endif /* mozFlushType_h___ */
--- a/content/base/public/nsContentUtils.h
+++ b/content/base/public/nsContentUtils.h
@@ -29,18 +29,16 @@
 #include "nsIDOMNode.h"
 #include "nsHtml5StringParser.h"
 #include "nsIDocument.h"
 #include "nsContentSink.h"
 #include "nsMathUtils.h"
 #include "nsThreadUtils.h"
 #include "nsIContent.h"
 #include "nsCharSeparatedTokenizer.h"
-#include "gfxContext.h"
-#include "gfxFont.h"
 #include "nsContentList.h"
 
 #include "mozilla/AutoRestore.h"
 #include "mozilla/GuardObjects.h"
 #include "mozilla/TimeStamp.h"
 #include "mozilla/Assertions.h"
 
 struct nsNativeKeyEvent; // Don't include nsINativeKeyBindings.h here: it will force strange compilation error!
@@ -97,17 +95,16 @@ class nsIMIMEHeaderParam;
 class nsIObserver;
 class nsPresContext;
 class nsIChannel;
 class nsAutoScriptBlockerSuppressNodeRemoved;
 struct nsIntMargin;
 class nsPIDOMWindow;
 class nsIDocumentLoaderFactory;
 class nsIDOMHTMLInputElement;
-class gfxTextObjectPaint;
 
 namespace mozilla {
 
 class Selection;
 
 namespace layers {
   class LayerManager;
 } // namespace layers
@@ -2117,23 +2114,16 @@ public:
    */
   static void GetSelectionInTextControl(mozilla::Selection* aSelection,
                                         Element* aRoot,
                                         int32_t& aOutStartOffset,
                                         int32_t& aOutEndOffset);
 
   static nsIEditor* GetHTMLEditor(nsPresContext* aPresContext);
 
-  static bool PaintSVGGlyph(Element *aElement, gfxContext *aContext,
-                            gfxFont::DrawMode aDrawMode,
-                            gfxTextObjectPaint *aObjectPaint);
-
-  static bool GetSVGGlyphExtents(Element *aElement, const gfxMatrix& aSVGToAppSpace,
-                                 gfxRect *aResult);
-
   /**
    * Check whether a spec feature/version is supported.
    * @param aObject the object, which should support the feature,
    *        for example nsIDOMNode or nsIDOMDOMImplementation
    * @param aFeature the feature ("Views", "Core", "HTML", "Range" ...)
    * @param aVersion the version ("1.0", "2.0", ...)
    * @return whether the feature is supported or not
    */
--- a/content/base/public/nsDOMFile.h
+++ b/content/base/public/nsDOMFile.h
@@ -12,17 +12,16 @@
 #include "nsIDOMFileList.h"
 #include "nsIInputStream.h"
 #include "nsIJSNativeInitializer.h"
 #include "nsIMutable.h"
 #include "nsCOMArray.h"
 #include "nsCOMPtr.h"
 #include "nsString.h"
 #include "nsIXMLHttpRequest.h"
-#include "prmem.h"
 #include "nsAutoPtr.h"
 
 #include "mozilla/GuardObjects.h"
 #include "mozilla/LinkedList.h"
 #include "mozilla/StandardInteger.h"
 #include "mozilla/StaticPtr.h"
 #include "mozilla/dom/DOMError.h"
 #include "mozilla/dom/indexedDB/FileInfo.h"
@@ -196,18 +195,17 @@ public:
   : nsDOMFileBase(aContentType, aStart, aLength)
   { }
 
   NS_DECL_CYCLE_COLLECTING_ISUPPORTS
 
   NS_DECL_CYCLE_COLLECTION_CLASS_AMBIGUOUS(nsDOMFileCC, nsIDOMFile)
 };
 
-class nsDOMFileFile : public nsDOMFile,
-                      public nsIJSNativeInitializer
+class nsDOMFileFile : public nsDOMFile
 {
 public:
   // Create as a file
   nsDOMFileFile(nsIFile *aFile)
     : nsDOMFile(EmptyString(), EmptyString(), UINT64_MAX, UINT64_MAX),
       mFile(aFile), mWholeFile(true), mStoredFile(false)
   {
     NS_ASSERTION(mFile, "must have file");
@@ -285,37 +283,24 @@ public:
     : nsDOMFile(EmptyString(), EmptyString(), UINT64_MAX, UINT64_MAX),
       mWholeFile(true), mStoredFile(false)
   {
     // Lazily get the content type and size
     mContentType.SetIsVoid(true);
     mName.SetIsVoid(true);
   }
 
-  NS_DECL_ISUPPORTS_INHERITED
-
-  // nsIJSNativeInitializer
-  NS_IMETHOD Initialize(nsISupports* aOwner,
-                        JSContext* aCx,
-                        JSObject* aObj,
-                        uint32_t aArgc,
-                        jsval* aArgv);
-
   // Overrides
   NS_IMETHOD GetSize(uint64_t* aSize);
   NS_IMETHOD GetType(nsAString& aType);
   NS_IMETHOD GetLastModifiedDate(JSContext* cx, JS::Value* aLastModifiedDate);
   NS_IMETHOD GetMozLastModifiedDate(uint64_t* aLastModifiedDate);
   NS_IMETHOD GetMozFullPathInternal(nsAString& aFullPath);
   NS_IMETHOD GetInternalStream(nsIInputStream**);
 
-  // DOMClassInfo constructor (for File("foo"))
-  static nsresult
-  NewFile(nsISupports* *aNewObject);
-
 protected:
   // Create slice
   nsDOMFileFile(const nsDOMFileFile* aOther, uint64_t aStart, uint64_t aLength,
                 const nsAString& aContentType)
     : nsDOMFile(aContentType, aOther->mStart + aStart, aLength),
       mFile(aOther->mFile), mWholeFile(false),
       mStoredFile(aOther->mStoredFile)
   {
@@ -418,17 +403,17 @@ protected:
 
     ~DataOwner() {
       remove();
       if (sDataOwners->isEmpty()) {
         // Free the linked list if it's empty.
         sDataOwners = nullptr;
       }
 
-      PR_Free(mData);
+      moz_free(mData);
     }
 
     static void EnsureMemoryReporterRegistered();
 
     static bool sMemoryReporterRegistered;
     static mozilla::StaticAutoPtr<mozilla::LinkedList<DataOwner> > sDataOwners;
     void* mData;
     uint64_t mLength;
--- a/content/base/src/DirectionalityUtils.cpp
+++ b/content/base/src/DirectionalityUtils.cpp
@@ -268,17 +268,17 @@ inline static bool NodeAffectsDirAutoAnc
           parent->NodeOrAncestorHasDirAuto());
 }
 
 /**
  * Various methods for returning the directionality of a string using the
  * first-strong algorithm defined in http://unicode.org/reports/tr9/#P2
  *
  * @param[out] aFirstStrong the offset to the first character in the string with
- *             strong directionality, or PR_UINT32_MAX if there is none (return
+ *             strong directionality, or UINT32_MAX if there is none (return
                value is eDir_NotSet).
  * @return the directionality of the string
  */
 static Directionality
 GetDirectionFromText(const PRUnichar* aText, const uint32_t aLength,
                      uint32_t* aFirstStrong = nullptr)
 {
   const PRUnichar* start = aText;
@@ -299,17 +299,17 @@ GetDirectionFromText(const PRUnichar* aT
       if (aFirstStrong) {
         *aFirstStrong = current;
       }
       return dir;
     }
   }
 
   if (aFirstStrong) {
-    *aFirstStrong = PR_UINT32_MAX;
+    *aFirstStrong = UINT32_MAX;
   }
   return eDir_NotSet;
 }
 
 static Directionality
 GetDirectionFromText(const char* aText, const uint32_t aLength,
                         uint32_t* aFirstStrong = nullptr)
 {
@@ -325,17 +325,17 @@ GetDirectionFromText(const char* aText, 
       if (aFirstStrong) {
         *aFirstStrong = current;
       }
       return dir;
     }
   }
 
   if (aFirstStrong) {
-    *aFirstStrong = PR_UINT32_MAX;
+    *aFirstStrong = UINT32_MAX;
   }
   return eDir_NotSet;
 }
 
 static Directionality
 GetDirectionFromText(const nsTextFragment* aFrag,
                      uint32_t* aFirstStrong = nullptr)
 {
--- a/content/base/src/WebSocket.cpp
+++ b/content/base/src/WebSocket.cpp
@@ -37,17 +37,16 @@
 #include "nsIScriptError.h"
 #include "nsNetUtil.h"
 #include "nsILoadGroup.h"
 #include "mozilla/Preferences.h"
 #include "nsDOMLists.h"
 #include "xpcpublic.h"
 #include "nsContentPolicyUtils.h"
 #include "jsfriendapi.h"
-#include "prmem.h"
 #include "nsDOMFile.h"
 #include "nsWrapperCacheInlines.h"
 #include "nsDOMEventTargetHelper.h"
 #include "nsIObserverService.h"
 #include "GeneratedEvents.h"
 
 namespace mozilla {
 namespace dom {
--- a/content/base/src/nsAttrAndChildArray.cpp
+++ b/content/base/src/nsAttrAndChildArray.cpp
@@ -5,17 +5,16 @@
 
 /*
  * Storage of the children and attributes of a DOM node; storage for
  * the two is unified to minimize footprint.
  */
 
 #include "nsAttrAndChildArray.h"
 #include "nsMappedAttributeElement.h"
-#include "prmem.h"
 #include "prbit.h"
 #include "nsString.h"
 #include "nsHTMLStyleSheet.h"
 #include "nsRuleWalker.h"
 #include "nsMappedAttributes.h"
 #include "nsUnicharUtils.h"
 #include "nsAutoPtr.h"
 #include "nsContentUtils.h" // nsAutoScriptBlocker
@@ -95,17 +94,17 @@ nsAttrAndChildArray::nsAttrAndChildArray
 nsAttrAndChildArray::~nsAttrAndChildArray()
 {
   if (!mImpl) {
     return;
   }
 
   Clear();
 
-  PR_Free(mImpl);
+  moz_free(mImpl);
 }
 
 nsIContent*
 nsAttrAndChildArray::GetSafeChildAt(uint32_t aPos) const
 {
   if (aPos < ChildCount()) {
     return ChildAt(aPos);
   }
@@ -611,21 +610,21 @@ nsAttrAndChildArray::Compact()
             mImpl->mBuffer + slotCount * ATTRSIZE,
             childCount * sizeof(nsIContent*));
     SetAttrSlotCount(attrCount);
   }
 
   // Then resize or free buffer
   uint32_t newSize = attrCount * ATTRSIZE + childCount;
   if (!newSize && !mImpl->mMappedAttrs) {
-    PR_Free(mImpl);
+    moz_free(mImpl);
     mImpl = nullptr;
   }
   else if (newSize < mImpl->mBufferSize) {
-    mImpl = static_cast<Impl*>(PR_Realloc(mImpl, (newSize + NS_IMPL_EXTRA_SIZE) * sizeof(nsIContent*)));
+    mImpl = static_cast<Impl*>(moz_realloc(mImpl, (newSize + NS_IMPL_EXTRA_SIZE) * sizeof(nsIContent*)));
     NS_ASSERTION(mImpl, "failed to reallocate to smaller buffer");
 
     mImpl->mBufferSize = newSize;
   }
 }
 
 void
 nsAttrAndChildArray::Clear()
@@ -752,17 +751,17 @@ nsAttrAndChildArray::GrowBy(uint32_t aGr
       size += ATTRCHILD_ARRAY_GROWSIZE;
     } while (size < minSize);
   }
   else {
     size = 1u << PR_CeilingLog2(minSize);
   }
 
   bool needToInitialize = !mImpl;
-  Impl* newImpl = static_cast<Impl*>(PR_Realloc(mImpl, size * sizeof(void*)));
+  Impl* newImpl = static_cast<Impl*>(moz_realloc(mImpl, size * sizeof(void*)));
   NS_ENSURE_TRUE(newImpl, false);
 
   mImpl = newImpl;
 
   // Set initial counts if we didn't have a buffer before
   if (needToInitialize) {
     mImpl->mMappedAttrs = nullptr;
     SetAttrSlotAndChildCount(0, 0);
--- a/content/base/src/nsContentUtils.cpp
+++ b/content/base/src/nsContentUtils.cpp
@@ -117,20 +117,16 @@
 #include "nsIViewManager.h"
 #include "nsEventStateManager.h"
 #include "nsIDOMHTMLInputElement.h"
 #include "nsParserConstants.h"
 #include "nsIWebNavigation.h"
 #include "nsILoadContext.h"
 #include "nsTextFragment.h"
 #include "mozilla/Selection.h"
-#include "nsSVGUtils.h"
-#include "nsISVGChildFrame.h"
-#include "nsRenderingContext.h"
-#include "gfxSVGGlyphs.h"
 
 #ifdef IBMBIDI
 #include "nsIBidiKeyboard.h"
 #endif
 #include "nsCycleCollectionParticipant.h"
 
 // for ReportToConsole
 #include "nsIStringBundle.h"
@@ -6131,17 +6127,17 @@ nsContentUtils::CreateArrayBuffer(JSCont
 // Initial implementation: only stores to RAM, not file
 // TODO: bug 704447: large file support
 nsresult
 nsContentUtils::CreateBlobBuffer(JSContext* aCx,
                                  const nsACString& aData,
                                  jsval& aBlob)
 {
   uint32_t blobLen = aData.Length();
-  void* blobData = PR_Malloc(blobLen);
+  void* blobData = moz_malloc(blobLen);
   nsCOMPtr<nsIDOMBlob> blob;
   if (blobData) {
     memcpy(blobData, aData.BeginReading(), blobLen);
     blob = new nsDOMMemoryFile(blobData, blobLen, EmptyString());
   } else {
     return NS_ERROR_OUT_OF_MEMORY;
   }
   JSObject* scope = JS_GetGlobalForScopeChain(aCx);
@@ -6899,70 +6895,16 @@ nsContentUtils::JSArrayToAtomArray(JSCon
     if (!a) {
       return NS_ERROR_OUT_OF_MEMORY;
     }
     aRetVal.AppendObject(a);
   }
   return NS_OK;
 }
 
-/* static */
-bool
-nsContentUtils::PaintSVGGlyph(Element *aElement, gfxContext *aContext,
-                              gfxFont::DrawMode aDrawMode,
-                              gfxTextObjectPaint *aObjectPaint)
-{
-  nsIFrame *frame = aElement->GetPrimaryFrame();
-  if (!frame) {
-    NS_WARNING("No frame for SVG glyph");
-    return false;
-  }
-
-  nsISVGChildFrame *displayFrame = do_QueryFrame(frame);
-  if (!displayFrame) {
-    NS_WARNING("Non SVG frame for SVG glyph");
-    return false;
-  }
-
-  nsRenderingContext context;
-
-  context.Init(frame->PresContext()->DeviceContext(), aContext);
-  context.AddUserData(&gfxTextObjectPaint::sUserDataKey, aObjectPaint, nullptr);
-
-  nsresult rv = displayFrame->PaintSVG(&context, nullptr);
-  NS_ENSURE_SUCCESS(rv, false);
-
-  return true;
-}
-
-/* static */
-bool
-nsContentUtils::GetSVGGlyphExtents(Element *aElement, const gfxMatrix& aSVGToAppSpace,
-                                   gfxRect *aResult)
-{
-  nsIFrame *frame = aElement->GetPrimaryFrame();
-  if (!frame) {
-    NS_WARNING("No frame for SVG glyph");
-    return false;
-  }
-
-  nsISVGChildFrame *displayFrame = do_QueryFrame(frame);
-  if (!displayFrame) {
-    NS_WARNING("Non SVG frame for SVG glyph");
-    return false;
-  }
-
-  *aResult = displayFrame->GetBBoxContribution(aSVGToAppSpace,
-      nsSVGUtils::eBBoxIncludeFill | nsSVGUtils::eBBoxIncludeFillGeometry |
-      nsSVGUtils::eBBoxIncludeStroke | nsSVGUtils::eBBoxIncludeStrokeGeometry |
-      nsSVGUtils::eBBoxIncludeMarkers);
-
-  return true;
-}
-
 // static
 void
 nsContentUtils::GetSelectionInTextControl(Selection* aSelection,
                                           Element* aRoot,
                                           int32_t& aOutStartOffset,
                                           int32_t& aOutEndOffset)
 {
   MOZ_ASSERT(aSelection && aRoot);
--- a/content/base/src/nsDOMBlobBuilder.cpp
+++ b/content/base/src/nsDOMBlobBuilder.cpp
@@ -1,16 +1,17 @@
 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "nsDOMBlobBuilder.h"
 #include "jsfriendapi.h"
 #include "mozilla/dom/BlobBinding.h"
+#include "mozilla/dom/FileBinding.h"
 #include "nsAutoPtr.h"
 #include "nsDOMClassInfoID.h"
 #include "nsIMultiplexInputStream.h"
 #include "nsStringStream.h"
 #include "nsTArray.h"
 #include "nsJSUtils.h"
 #include "nsContentUtils.h"
 #include "nsIScriptError.h"
@@ -166,24 +167,27 @@ GetXPConnectNative(JSContext* aCx, JSObj
 
 NS_IMETHODIMP
 nsDOMMultipartFile::Initialize(nsISupports* aOwner,
                                JSContext* aCx,
                                JSObject* aObj,
                                uint32_t aArgc,
                                jsval* aArgv)
 {
-  return InitInternal(aCx, aArgc, aArgv, GetXPConnectNative);
+  if (!mIsFile) {
+    return InitBlob(aCx, aArgc, aArgv, GetXPConnectNative);
+  }
+  return InitFile(aCx, aArgc, aArgv);
 }
 
 nsresult
-nsDOMMultipartFile::InitInternal(JSContext* aCx,
-                                 uint32_t aArgc,
-                                 jsval* aArgv,
-                                 UnwrapFuncPtr aUnwrapFunc)
+nsDOMMultipartFile::InitBlob(JSContext* aCx,
+                             uint32_t aArgc,
+                             jsval* aArgv,
+                             UnwrapFuncPtr aUnwrapFunc)
 {
   bool nativeEOL = false;
   if (aArgc > 1) {
     if (NS_IsMainThread()) {
       BlobPropertyBag d;
       if (!d.Init(aCx, nullptr, aArgv[1])) {
         return NS_ERROR_TYPE_ERR;
       }
@@ -256,16 +260,110 @@ nsDOMMultipartFile::InitInternal(JSConte
 
     mBlobs = blobSet.GetBlobs();
   }
 
   return NS_OK;
 }
 
 nsresult
+nsDOMMultipartFile::InitFile(JSContext* aCx,
+                             uint32_t aArgc,
+                             jsval* aArgv)
+{
+  nsresult rv;
+
+  NS_ASSERTION(!mImmutable, "Something went wrong ...");
+  NS_ENSURE_TRUE(!mImmutable, NS_ERROR_UNEXPECTED);
+
+  if (!nsContentUtils::IsCallerChrome()) {
+    return NS_ERROR_DOM_SECURITY_ERR; // Real short trip
+  }
+
+  NS_ENSURE_TRUE(aArgc > 0, NS_ERROR_UNEXPECTED);
+
+  bool nativeEOL = false;
+  if (aArgc > 1) {
+    FilePropertyBag d;
+    if (!d.Init(aCx, nullptr, aArgv[1])) {
+      return NS_ERROR_TYPE_ERR;
+    }
+    mName = d.name;
+    mContentType = d.type;
+    nativeEOL = d.endings == EndingTypesValues::Native;
+  }
+
+  // We expect to get a path to represent as a File object,
+  // an nsIFile, or an nsIDOMFile.
+  nsCOMPtr<nsIFile> file;
+  nsCOMPtr<nsIDOMFile> domFile;
+  if (!aArgv[0].isString()) {
+    // Lets see if it's an nsIFile
+    if (!aArgv[0].isObject()) {
+      return NS_ERROR_UNEXPECTED; // We're not interested
+    }
+
+    JSObject* obj = &aArgv[0].toObject();
+
+    nsISupports* supports =
+      nsContentUtils::XPConnect()->GetNativeOfWrapper(aCx, obj);
+    if (!supports) {
+      return NS_ERROR_UNEXPECTED;
+    }
+
+    domFile = do_QueryInterface(supports);
+    file = do_QueryInterface(supports);
+    if (!domFile && !file) {
+      return NS_ERROR_UNEXPECTED;
+    }
+  } else {
+    // It's a string
+    JSString* str = JS_ValueToString(aCx, aArgv[0]);
+    NS_ENSURE_TRUE(str, NS_ERROR_XPC_BAD_CONVERT_JS);
+
+    nsDependentJSString xpcomStr;
+    if (!xpcomStr.init(aCx, str)) {
+      return NS_ERROR_XPC_BAD_CONVERT_JS;
+    }
+
+    rv = NS_NewLocalFile(xpcomStr, false, getter_AddRefs(file));
+    NS_ENSURE_SUCCESS(rv, rv);
+  }
+
+  if (file) {
+    bool exists;
+    rv = file->Exists(&exists);
+    NS_ENSURE_SUCCESS(rv, rv);
+    NS_ENSURE_TRUE(exists, NS_ERROR_FILE_NOT_FOUND);
+
+    bool isDir;
+    rv = file->IsDirectory(&isDir);
+    NS_ENSURE_SUCCESS(rv, rv);
+    NS_ENSURE_FALSE(isDir, NS_ERROR_FILE_IS_DIRECTORY);
+
+    if (mName.IsEmpty()) {
+      file->GetLeafName(mName);
+    }
+
+    domFile = new nsDOMFileFile(file);
+  }
+  
+  // XXXkhuey this is terrible
+  if (mContentType.IsEmpty()) {
+    domFile->GetType(mContentType);
+  }
+
+  BlobSet blobSet;
+  blobSet.AppendBlob(domFile);
+  mBlobs = blobSet.GetBlobs();
+
+  return NS_OK;
+}
+
+nsresult
 BlobSet::AppendVoidPtr(const void* aData, uint32_t aLength)
 {
   NS_ENSURE_ARG_POINTER(aData);
 
   uint64_t offset = mDataLen;
 
   if (!ExpandBufferSize(aLength))
     return NS_ERROR_OUT_OF_MEMORY;
--- a/content/base/src/nsDOMBlobBuilder.h
+++ b/content/base/src/nsDOMBlobBuilder.h
@@ -49,34 +49,47 @@ public:
   // nsIJSNativeInitializer
   NS_IMETHOD Initialize(nsISupports* aOwner,
                         JSContext* aCx,
                         JSObject* aObj,
                         uint32_t aArgc,
                         jsval* aArgv);
 
   typedef nsIDOMBlob* (*UnwrapFuncPtr)(JSContext*, JSObject*);
-  nsresult InitInternal(JSContext* aCx,
-                        uint32_t aArgc,
-                        jsval* aArgv,
-                        UnwrapFuncPtr aUnwrapFunc);
+  nsresult InitBlob(JSContext* aCx,
+                    uint32_t aArgc,
+                    jsval* aArgv,
+                    UnwrapFuncPtr aUnwrapFunc);
+  nsresult InitFile(JSContext* aCx,
+                    uint32_t aArgc,
+                    jsval* aArgv);
 
   already_AddRefed<nsIDOMBlob>
   CreateSlice(uint64_t aStart, uint64_t aLength, const nsAString& aContentType);
 
   NS_IMETHOD GetSize(uint64_t*);
   NS_IMETHOD GetInternalStream(nsIInputStream**);
 
   static nsresult
   NewFile(const nsAString& aName, nsISupports* *aNewObject);
 
   // DOMClassInfo constructor (for Blob([b1, "foo"], { type: "image/png" }))
   static nsresult
   NewBlob(nsISupports* *aNewObject);
 
+  // DOMClassInfo constructor (for File([b1, "foo"], { type: "image/png",
+  //                                                   name: "foo.png" }))
+  inline static nsresult
+  NewFile(nsISupports* *aNewObject)
+  {
+    // Initialization will set the filename, so we can pass in an empty string
+    // for now.
+    return NewFile(EmptyString(), aNewObject);
+  }
+
   virtual const nsTArray<nsCOMPtr<nsIDOMBlob> >*
   GetSubBlobs() const { return &mBlobs; }
 
 protected:
   nsTArray<nsCOMPtr<nsIDOMBlob> > mBlobs;
 };
 
 class BlobSet {
@@ -114,18 +127,17 @@ protected:
     // Start at 1 or we'll loop forever.
     CheckedUint32 bufferLen = NS_MAX<uint32_t>(mDataBufferLen, 1);
     while (bufferLen.isValid() && bufferLen.value() < mDataLen + aSize)
       bufferLen *= 2;
 
     if (!bufferLen.isValid())
       return false;
 
-    // PR_ memory functions are still fallible
-    void* data = PR_Realloc(mData, bufferLen.value());
+    void* data = moz_realloc(mData, bufferLen.value());
     if (!data)
       return false;
 
     mData = data;
     mDataBufferLen = bufferLen.value();
     mDataLen += aSize;
     return true;
   }
--- a/content/base/src/nsDOMDataChannel.cpp
+++ b/content/base/src/nsDOMDataChannel.cpp
@@ -330,17 +330,17 @@ nsDOMDataChannel::GetSendParams(nsIVaria
     if (blob) {
       rv = blob->GetInternalStream(getter_AddRefs(aStreamOut));
       NS_ENSURE_SUCCESS(rv, rv);
 
       // GetSize() should not perform blocking I/O (unlike Available())
       uint64_t blobLen;
       rv = blob->GetSize(&blobLen);
       NS_ENSURE_SUCCESS(rv, rv);
-      if (blobLen > PR_UINT32_MAX) {
+      if (blobLen > UINT32_MAX) {
         return NS_ERROR_FILE_TOO_BIG;
       }
       aOutgoingLength = static_cast<uint32_t>(blobLen);
 
       aIsBinary = true;
       return NS_OK;
     }
   }
--- a/content/base/src/nsDOMFile.cpp
+++ b/content/base/src/nsDOMFile.cpp
@@ -31,18 +31,16 @@
 #include "nsStringStream.h"
 #include "nsJSUtils.h"
 #include "nsPrintfCString.h"
 #include "mozilla/SHA1.h"
 #include "mozilla/CheckedInt.h"
 #include "mozilla/Preferences.h"
 #include "mozilla/Attributes.h"
 
-#include "plbase64.h"
-#include "prmem.h"
 #include "mozilla/dom/FileListBinding.h"
 
 using namespace mozilla;
 using namespace mozilla::dom;
 
 // XXXkhuey the input stream that we pass out of a DOMFile
 // can outlive the actual DOMFile object.  Thus, we must
 // ensure that the buffer underlying the stream we get
@@ -465,35 +463,24 @@ NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(
 NS_INTERFACE_MAP_END
 
 NS_IMPL_CYCLE_COLLECTING_ADDREF(nsDOMFileCC)
 NS_IMPL_CYCLE_COLLECTING_RELEASE(nsDOMFileCC)
 
 ////////////////////////////////////////////////////////////////////////////
 // nsDOMFileFile implementation
 
-NS_IMPL_ISUPPORTS_INHERITED1(nsDOMFileFile, nsDOMFile,
-                             nsIJSNativeInitializer)
-
 already_AddRefed<nsIDOMBlob>
 nsDOMFileFile::CreateSlice(uint64_t aStart, uint64_t aLength,
                            const nsAString& aContentType)
 {
   nsCOMPtr<nsIDOMBlob> t = new nsDOMFileFile(this, aStart, aLength, aContentType);
   return t.forget();
 }
 
-/* static */ nsresult
-nsDOMFileFile::NewFile(nsISupports* *aNewObject)
-{
-  nsCOMPtr<nsISupports> file = do_QueryObject(new nsDOMFileFile());
-  file.forget(aNewObject);
-  return NS_OK;
-}
-
 NS_IMETHODIMP
 nsDOMFileFile::GetMozFullPathInternal(nsAString &aFilename)
 {
   NS_ASSERTION(mIsFile, "Should only be called on files");
   return mFile->GetPath(aFilename);
 }
 
 NS_IMETHODIMP
@@ -588,81 +575,16 @@ NS_IMETHODIMP
 nsDOMFileFile::GetInternalStream(nsIInputStream **aStream)
 {
   return mWholeFile ?
     NS_NewLocalFileInputStream(aStream, mFile, -1, -1, sFileStreamFlags) :
     NS_NewPartialLocalFileInputStream(aStream, mFile, mStart, mLength,
                                       -1, -1, sFileStreamFlags);
 }
 
-NS_IMETHODIMP
-nsDOMFileFile::Initialize(nsISupports* aOwner,
-                          JSContext* aCx,
-                          JSObject* aObj,
-                          uint32_t aArgc,
-                          JS::Value* aArgv)
-{
-  nsresult rv;
-
-  NS_ASSERTION(!mImmutable, "Something went wrong ...");
-  NS_ENSURE_TRUE(!mImmutable, NS_ERROR_UNEXPECTED);
-
-  if (!nsContentUtils::IsCallerChrome()) {
-    return NS_ERROR_DOM_SECURITY_ERR; // Real short trip
-  }
-
-  NS_ENSURE_TRUE(aArgc > 0, NS_ERROR_UNEXPECTED);
-
-  // We expect to get a path to represent as a File object,
-  // or an nsIFile
-  nsCOMPtr<nsIFile> file;
-  if (!aArgv[0].isString()) {
-    // Lets see if it's an nsIFile
-    if (!aArgv[0].isObject()) {
-      return NS_ERROR_UNEXPECTED; // We're not interested
-    }
-
-    JSObject* obj = &aArgv[0].toObject();
-
-    // Is it an nsIFile
-    file = do_QueryInterface(
-      nsContentUtils::XPConnect()->
-        GetNativeOfWrapper(aCx, obj));
-    if (!file)
-      return NS_ERROR_UNEXPECTED;
-  } else {
-    // It's a string
-    JSString* str = JS_ValueToString(aCx, aArgv[0]);
-    NS_ENSURE_TRUE(str, NS_ERROR_XPC_BAD_CONVERT_JS);
-
-    nsDependentJSString xpcomStr;
-    if (!xpcomStr.init(aCx, str)) {
-      return NS_ERROR_XPC_BAD_CONVERT_JS;
-    }
-
-    rv = NS_NewLocalFile(xpcomStr, false, getter_AddRefs(file));
-    NS_ENSURE_SUCCESS(rv, rv);
-  }
-
-  bool exists;
-  rv = file->Exists(&exists);
-  NS_ENSURE_SUCCESS(rv, rv);
-  NS_ENSURE_TRUE(exists, NS_ERROR_FILE_NOT_FOUND);
-
-  bool isDir;
-  rv = file->IsDirectory(&isDir);
-  NS_ENSURE_SUCCESS(rv, rv);
-  NS_ENSURE_FALSE(isDir, NS_ERROR_FILE_IS_DIRECTORY);
-
-  mFile = file;
-  file->GetLeafName(mName);
-
-  return NS_OK;
-}
-
 ////////////////////////////////////////////////////////////////////////////
 // nsDOMMemoryFile implementation
 
 already_AddRefed<nsIDOMBlob>
 nsDOMMemoryFile::CreateSlice(uint64_t aStart, uint64_t aLength,
                              const nsAString& aContentType)
 {
   nsCOMPtr<nsIDOMBlob> t =
--- a/content/base/src/nsDOMFileReader.cpp
+++ b/content/base/src/nsDOMFileReader.cpp
@@ -15,35 +15,33 @@
 #include "nsIFile.h"
 #include "nsIFileStreams.h"
 #include "nsIInputStream.h"
 #include "nsIMIMEService.h"
 #include "nsIUnicodeDecoder.h"
 #include "nsNetCID.h"
 #include "nsNetUtil.h"
 
-#include "plbase64.h"
-#include "prmem.h"
-
 #include "nsLayoutCID.h"
 #include "nsXPIDLString.h"
 #include "nsReadableUtils.h"
 #include "nsIURI.h"
 #include "nsStreamUtils.h"
 #include "nsXPCOM.h"
 #include "nsIDOMEventListener.h"
 #include "nsIJSContextStack.h"
 #include "nsJSEnvironment.h"
 #include "nsIScriptGlobalObject.h"
 #include "nsCExternalHandlerService.h"
 #include "nsIStreamConverterService.h"
 #include "nsCycleCollectionParticipant.h"
 #include "nsLayoutStatics.h"
 #include "nsIScriptObjectPrincipal.h"
 #include "nsHostObjectProtocolHandler.h"
+#include "mozilla/Base64.h"
 #include "mozilla/Preferences.h"
 #include "mozilla/dom/EncodingUtils.h"
 #include "xpcpublic.h"
 #include "nsIScriptSecurityManager.h"
 #include "nsDOMJSUtils.h"
 #include "nsDOMEventTargetHelper.h"
 
 #include "jsfriendapi.h"
@@ -314,17 +312,17 @@ nsDOMFileReader::DoOnDataAvailable(nsIRe
     NS_ASSERTION(bytesRead == aCount, "failed to read data");
   }
   else {
     //Update memory buffer to reflect the contents of the file
     if (aOffset + aCount > UINT32_MAX) {
       // PR_Realloc doesn't support over 4GB memory size even if 64-bit OS
       return NS_ERROR_OUT_OF_MEMORY;
     }
-    mFileData = (char *)PR_Realloc(mFileData, aOffset + aCount);
+    mFileData = (char *)moz_realloc(mFileData, aOffset + aCount);
     NS_ENSURE_TRUE(mFileData, NS_ERROR_OUT_OF_MEMORY);
 
     uint32_t bytesRead = 0;
     aInputStream->Read(mFileData + aOffset, aCount, &bytesRead);
     NS_ASSERTION(bytesRead == aCount, "failed to read data");
 
     mDataLen += aCount;
   }
@@ -486,36 +484,21 @@ nsDOMFileReader::GetAsDataURL(nsIDOMBlob
   rv = aFile->GetType(contentType);
   if (NS_SUCCEEDED(rv) && !contentType.IsEmpty()) {
     aResult.Append(contentType);
   } else {
     aResult.AppendLiteral("application/octet-stream");
   }
   aResult.AppendLiteral(";base64,");
 
-  uint32_t totalRead = 0;
-  while (aDataLen > totalRead) {
-    uint32_t numEncode = 4096;
-    uint32_t amtRemaining = aDataLen - totalRead;
-    if (numEncode > amtRemaining)
-      numEncode = amtRemaining;
+  nsCString encodedData;
+  rv = Base64Encode(Substring(aFileData, aDataLen), encodedData);
+  NS_ENSURE_SUCCESS(rv, rv);
 
-    //Unless this is the end of the file, encode in multiples of 3
-    if (numEncode > 3) {
-      uint32_t leftOver = numEncode % 3;
-      numEncode -= leftOver;
-    }
-
-    //Out buffer should be at least 4/3rds the read buf, plus a terminator
-    char *base64 = PL_Base64Encode(aFileData + totalRead, numEncode, nullptr);
-    AppendASCIItoUTF16(nsDependentCString(base64), aResult);
-    PR_Free(base64);
-
-    totalRead += numEncode;
-  }
+  AppendASCIItoUTF16(encodedData, aResult);
 
   return NS_OK;
 }
 
 nsresult
 nsDOMFileReader::ConvertStream(const char *aFileData,
                                uint32_t aDataLen,
                                const char *aCharset,
--- a/content/base/src/nsDOMFileReader.h
+++ b/content/base/src/nsDOMFileReader.h
@@ -19,17 +19,16 @@
 
 #include "nsIDOMFile.h"
 #include "nsIDOMFileReader.h"
 #include "nsIDOMFileList.h"
 #include "nsIInputStream.h"
 #include "nsCOMPtr.h"
 #include "nsIStreamLoader.h"
 #include "nsIChannel.h"
-#include "prmem.h"
 
 #include "FileIOObject.h"
 
 class nsDOMFileReader : public mozilla::dom::FileIOObject,
                         public nsIDOMFileReader,
                         public nsIInterfaceRequestor,
                         public nsSupportsWeakReference,
                         public nsIJSNativeInitializer
@@ -76,17 +75,17 @@ protected:
 
   nsresult ReadFileContent(JSContext* aCx, nsIDOMBlob *aFile, const nsAString &aCharset, eDataFormat aDataFormat); 
   nsresult GetAsText(const nsACString &aCharset,
                      const char *aFileData, uint32_t aDataLen, nsAString &aResult);
   nsresult GetAsDataURL(nsIDOMBlob *aFile, const char *aFileData, uint32_t aDataLen, nsAString &aResult); 
   nsresult ConvertStream(const char *aFileData, uint32_t aDataLen, const char *aCharset, nsAString &aResult); 
 
   void FreeFileData() {
-    PR_Free(mFileData);
+    moz_free(mFileData);
     mFileData = nullptr;
     mDataLen = 0;
   }
 
   char *mFileData;
   nsCOMPtr<nsIDOMBlob> mFile;
   nsCString mCharset;
   uint32_t mDataLen;
--- a/content/base/src/nsDOMParser.cpp
+++ b/content/base/src/nsDOMParser.cpp
@@ -415,17 +415,17 @@ nsDOMParser::InitInternal(nsISupports* a
     // Does that matter?
 
     // Also note that |cx| matches what GetDocumentFromContext() would return,
     // while GetDocumentFromCaller() gives us the window that the DOMParser()
     // call was made on.
 
     nsCOMPtr<nsIDocument> doc;
     nsCOMPtr<nsPIDOMWindow> window = do_QueryInterface(aOwner);
-    if (aOwner) {
+    if (window) {
       nsCOMPtr<nsIDOMDocument> domdoc = window->GetExtantDocument();
       doc = do_QueryInterface(domdoc);
     }
 
     if (!doc) {
       return NS_ERROR_UNEXPECTED;
     }
 
--- a/content/base/src/nsFormData.cpp
+++ b/content/base/src/nsFormData.cpp
@@ -1,71 +1,68 @@
 /* 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 "nsFormData.h"
 #include "nsIVariant.h"
 #include "nsIInputStream.h"
 #include "nsIDOMFile.h"
-#include "nsContentUtils.h"
 #include "nsHTMLFormElement.h"
+#include "mozilla/dom/FormDataBinding.h"
+
+using namespace mozilla;
+using namespace mozilla::dom;
 
-nsFormData::nsFormData()
+nsFormData::nsFormData(nsISupports* aOwner)
   : nsFormSubmission(NS_LITERAL_CSTRING("UTF-8"), nullptr)
+  , mOwner(aOwner)
 {
+  SetIsDOMBinding();
 }
 
 // -------------------------------------------------------------------------
 // nsISupports
 
-DOMCI_DATA(FormData, nsFormData)
-
-NS_IMPL_ADDREF(nsFormData)
-NS_IMPL_RELEASE(nsFormData)
-NS_INTERFACE_MAP_BEGIN(nsFormData)
+NS_IMPL_CYCLE_COLLECTION_WRAPPERCACHE_1(nsFormData, mOwner)
+NS_IMPL_CYCLE_COLLECTING_ADDREF(nsFormData)
+NS_IMPL_CYCLE_COLLECTING_RELEASE(nsFormData)
+NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(nsFormData)
+  NS_WRAPPERCACHE_INTERFACE_MAP_ENTRY
   NS_INTERFACE_MAP_ENTRY(nsIDOMFormData)
   NS_INTERFACE_MAP_ENTRY(nsIXHRSendable)
-  NS_INTERFACE_MAP_ENTRY(nsIJSNativeInitializer)
-  NS_DOM_INTERFACE_MAP_ENTRY_CLASSINFO(FormData)
   NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIDOMFormData)
 NS_INTERFACE_MAP_END
 
 // -------------------------------------------------------------------------
 // nsFormSubmission
 nsresult
 nsFormData::GetEncodedSubmission(nsIURI* aURI,
                                  nsIInputStream** aPostDataStream)
 {
   NS_NOTREACHED("Shouldn't call nsFormData::GetEncodedSubmission");
   return NS_OK;
 }
 
-nsresult
-nsFormData::AddNameValuePair(const nsAString& aName,
-                             const nsAString& aValue)
+void
+nsFormData::Append(const nsAString& aName, const nsAString& aValue)
 {
   FormDataTuple* data = mFormData.AppendElement();
   data->name = aName;
   data->stringValue = aValue;
   data->valueIsFile = false;
-
-  return NS_OK;
 }
 
-nsresult
-nsFormData::AddNameFilePair(const nsAString& aName,
-                            nsIDOMBlob* aBlob)
+void
+nsFormData::Append(const nsAString& aName, nsIDOMBlob* aBlob)
 {
   FormDataTuple* data = mFormData.AppendElement();
   data->name = aName;
   data->fileValue = aBlob;
   data->valueIsFile = true;
-
-  return NS_OK;
 }
 
 // -------------------------------------------------------------------------
 // nsIDOMFormData
 
 NS_IMETHODIMP
 nsFormData::Append(const nsAString& aName, nsIVariant* aValue)
 {
@@ -79,29 +76,50 @@ nsFormData::Append(const nsAString& aNam
     nsID *iid;
     rv = aValue->GetAsInterface(&iid, getter_AddRefs(supports));
     NS_ENSURE_SUCCESS(rv, rv);
 
     nsMemory::Free(iid);
 
     nsCOMPtr<nsIDOMBlob> domBlob = do_QueryInterface(supports);
     if (domBlob) {
-      return AddNameFilePair(aName, domBlob);
+      Append(aName, domBlob);
+      return NS_OK;
     }
   }
 
   PRUnichar* stringData = nullptr;
   uint32_t stringLen = 0;
   rv = aValue->GetAsWStringWithSize(&stringLen, &stringData);
   NS_ENSURE_SUCCESS(rv, rv);
 
   nsString valAsString;
   valAsString.Adopt(stringData, stringLen);
 
-  return AddNameValuePair(aName, valAsString);
+  Append(aName, valAsString);
+  return NS_OK;
+}
+
+/* virtual */ JSObject*
+nsFormData::WrapObject(JSContext* aCx, JSObject* aScope, bool* aTriedToWrap)
+{
+  return FormDataBinding::Wrap(aCx, aScope, this, aTriedToWrap);
+}
+
+/* static */ already_AddRefed<nsFormData>
+nsFormData::Constructor(nsISupports* aGlobal,
+                        const Optional<nsHTMLFormElement*>& aFormElement,
+                        ErrorResult& aRv)
+{
+  nsRefPtr<nsFormData> formData = new nsFormData(aGlobal);
+  if (aFormElement.WasPassed()) {
+    MOZ_ASSERT(aFormElement.Value());
+    aRv = aFormElement.Value()->WalkFormElements(formData);
+  }
+  return formData.forget();
 }
 
 // -------------------------------------------------------------------------
 // nsIXHRSendable
 
 NS_IMETHODIMP
 nsFormData::GetSendInfo(nsIInputStream** aBody, uint64_t* aContentLength,
                         nsACString& aContentType, nsACString& aCharset)
@@ -119,40 +137,8 @@ nsFormData::GetSendInfo(nsIInputStream**
 
   fs.GetContentType(aContentType);
   aCharset.Truncate();
   *aContentLength = 0;
   NS_ADDREF(*aBody = fs.GetSubmissionBody(aContentLength));
 
   return NS_OK;
 }
-
-
-// -------------------------------------------------------------------------
-// nsIJSNativeInitializer
-
-NS_IMETHODIMP
-nsFormData::Initialize(nsISupports* aOwner,
-                       JSContext* aCx,
-                       JSObject* aObj,
-                       uint32_t aArgc,
-                       jsval* aArgv)
-{
-  if (aArgc > 0) {
-    if (JSVAL_IS_PRIMITIVE(aArgv[0])) {
-      return NS_ERROR_UNEXPECTED;
-    }
-    nsCOMPtr<nsIContent> formCont = do_QueryInterface(
-      nsContentUtils::XPConnect()->
-        GetNativeOfWrapper(aCx, JSVAL_TO_OBJECT(aArgv[0])));
-    
-    if (!formCont || !formCont->IsHTML(nsGkAtoms::form)) {
-      return NS_ERROR_UNEXPECTED;
-    }
-
-    nsresult rv = static_cast<nsHTMLFormElement*>(formCont.get())->
-      WalkFormElements(this);
-    NS_ENSURE_SUCCESS(rv, rv);
-  }
-
-
-  return NS_OK;
-}
--- a/content/base/src/nsFormData.h
+++ b/content/base/src/nsFormData.h
@@ -3,48 +3,86 @@
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #ifndef nsFormData_h__
 #define nsFormData_h__
 
 #include "nsIDOMFormData.h"
 #include "nsIXMLHttpRequest.h"
 #include "nsFormSubmission.h"
-#include "nsIJSNativeInitializer.h"
+#include "nsWrapperCache.h"
 #include "nsTArray.h"
+#include "mozilla/ErrorResult.h"
 
+class nsHTMLFormElement;
 class nsIDOMFile;
 
+namespace mozilla {
+class ErrorResult;
+
+namespace dom {
+template<class> class Optional;
+} // namespace dom
+} // namespace mozilla
+
 class nsFormData : public nsIDOMFormData,
                    public nsIXHRSendable,
-                   public nsIJSNativeInitializer,
-                   public nsFormSubmission
+                   public nsFormSubmission,
+                   public nsWrapperCache
 {
 public:
-  nsFormData();
+  nsFormData(nsISupports* aOwner = nullptr);
 
-  NS_DECL_ISUPPORTS
+  NS_DECL_CYCLE_COLLECTING_ISUPPORTS
+  NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS_AMBIGUOUS(nsFormData,
+                                                         nsIDOMFormData)
+
   NS_DECL_NSIDOMFORMDATA
   NS_DECL_NSIXHRSENDABLE
 
+  // nsWrapperCache
+  virtual JSObject*
+  WrapObject(JSContext* aCx, JSObject* aScope, bool* aTriedToWrap) MOZ_OVERRIDE;
+
+  // WebIDL
+  nsISupports*
+  GetParentObject() const
+  {
+    return mOwner;
+  }
+  static already_AddRefed<nsFormData>
+  Constructor(nsISupports* aGlobal,
+              const mozilla::dom::Optional<nsHTMLFormElement*>& aFormElement,
+              mozilla::ErrorResult& aRv);
+  void Append(const nsAString& aName, const nsAString& aValue);
+  void Append(const nsAString& aName, nsIDOMBlob* aBlob);
+
   // nsFormSubmission
   virtual nsresult GetEncodedSubmission(nsIURI* aURI,
                                         nsIInputStream** aPostDataStream);
   virtual nsresult AddNameValuePair(const nsAString& aName,
-                                    const nsAString& aValue);
+                                    const nsAString& aValue)
+  {
+    Append(aName, aValue);
+    return NS_OK;
+  }
   virtual nsresult AddNameFilePair(const nsAString& aName,
-                                   nsIDOMBlob* aBlob);
+                                   nsIDOMBlob* aBlob)
+  {
+    Append(aName, aBlob);
+    return NS_OK;
+  }
 
-  NS_IMETHOD Initialize(nsISupports* aOwner, JSContext* aCx, JSObject* aObj,
-                        uint32_t aArgc, jsval* aArgv);
 private:
+  nsCOMPtr<nsISupports> mOwner;
+
   struct FormDataTuple
   {
     nsString name;
     nsString stringValue;
     nsCOMPtr<nsIDOMBlob> fileValue;
     bool valueIsFile;
   };
-  
+
   nsTArray<FormDataTuple> mFormData;
 };
 
 #endif // nsFormData_h__
--- a/content/base/src/nsXMLHttpRequest.cpp
+++ b/content/base/src/nsXMLHttpRequest.cpp
@@ -74,19 +74,20 @@
 #include "mozilla/dom/EncodingUtils.h"
 #include "mozilla/dom/XMLHttpRequestBinding.h"
 #include "nsIDOMFormData.h"
 #include "DictionaryHelpers.h"
 #include "mozilla/Attributes.h"
 #include "nsIPermissionManager.h"
 #include "nsMimeTypes.h"
 #include "nsIHttpChannelInternal.h"
+#include "nsFormData.h"
+#include "nsStreamListenerWrapper.h"
 
 #include "nsWrapperCacheInlines.h"
-#include "nsStreamListenerWrapper.h"
 
 using namespace mozilla;
 using namespace mozilla::dom;
 
 #define LOAD_STR "load"
 #define ERROR_STR "error"
 #define ABORT_STR "abort"
 #define TIMEOUT_STR "timeout"
@@ -2661,21 +2662,19 @@ nsXMLHttpRequest::GetRequestBody(nsIVari
     }
     case nsXMLHttpRequest::RequestBody::DOMString:
     {
       return ::GetRequestBody(*value.mString, aResult, aContentLength,
                               aContentType, aCharset);
     }
     case nsXMLHttpRequest::RequestBody::FormData:
     {
-      nsresult rv;
-      nsCOMPtr<nsIXHRSendable> sendable = do_QueryInterface(value.mFormData, &rv);
-      NS_ENSURE_SUCCESS(rv, rv);
-
-      return ::GetRequestBody(sendable, aResult, aContentLength, aContentType, aCharset);
+      MOZ_ASSERT(value.mFormData);
+      return ::GetRequestBody(value.mFormData, aResult, aContentLength,
+                              aContentType, aCharset);
     }
     case nsXMLHttpRequest::RequestBody::InputStream:
     {
       return ::GetRequestBody(value.mStream, aResult, aContentLength,
                               aContentType, aCharset);
     }
     default:
     {
--- a/content/base/src/nsXMLHttpRequest.h
+++ b/content/base/src/nsXMLHttpRequest.h
@@ -47,17 +47,17 @@
 /* Xlib headers insist on this for some reason... Nuke it because
    it'll override our member name */
 #undef Status
 #endif
 
 class nsILoadGroup;
 class AsyncVerifyRedirectCallbackForwarder;
 class nsIUnicodeDecoder;
-class nsIDOMFormData;
+class nsFormData;
 
 class nsXHREventTarget : public nsDOMEventTargetHelper,
                          public nsIXMLHttpRequestEventTarget
 {
 public:
   typedef mozilla::dom::XMLHttpRequestResponseType
           XMLHttpRequestResponseType;
   typedef mozilla::ErrorResult
@@ -283,19 +283,19 @@ private:
     RequestBody(nsIDocument* aDocument) : mType(Document)
     {
       mValue.mDocument = aDocument;
     }
     RequestBody(const nsAString& aString) : mType(DOMString)
     {
       mValue.mString = &aString;
     }
-    RequestBody(nsIDOMFormData* aFormData) : mType(FormData)
+    RequestBody(nsFormData& aFormData) : mType(FormData)
     {
-      mValue.mFormData = aFormData;
+      mValue.mFormData = &aFormData;
     }
     RequestBody(nsIInputStream* aStream) : mType(InputStream)
     {
       mValue.mStream = aStream;
     }
 
     enum Type {
       Uninitialized,
@@ -306,17 +306,17 @@ private:
       FormData,
       InputStream
     };
     union Value {
       mozilla::dom::ArrayBuffer* mArrayBuffer;
       nsIDOMBlob* mBlob;
       nsIDocument* mDocument;
       const nsAString* mString;
-      nsIDOMFormData* mFormData;
+      nsFormData* mFormData;
       nsIInputStream* mStream;
     };
 
     Type GetType() const
     {
       MOZ_ASSERT(mType != Uninitialized);
       return mType;
     }
@@ -371,19 +371,18 @@ public:
   {
     if (DOMStringIsNull(aString)) {
       Send(aRv);
     }
     else {
       aRv = Send(RequestBody(aString));
     }
   }
-  void Send(nsIDOMFormData* aFormData, ErrorResult& aRv)
+  void Send(nsFormData& aFormData, ErrorResult& aRv)
   {
-    NS_ASSERTION(aFormData, "Null should go to string version");
     aRv = Send(RequestBody(aFormData));
   }
   void Send(nsIInputStream* aStream, ErrorResult& aRv)
   {
     NS_ASSERTION(aStream, "Null should go to string version");
     aRv = Send(RequestBody(aStream));
   }
   void SendAsBinary(const nsAString& aBody, ErrorResult& aRv);
--- a/content/canvas/src/WebGLContext.cpp
+++ b/content/canvas/src/WebGLContext.cpp
@@ -154,16 +154,17 @@ WebGLContext::WebGLContext()
     mBackbufferClearingStatus = BackbufferClearingStatus::NotClearedSinceLastPresented;
     
     // initialize some GL values: we're going to get them from the GL and use them as the sizes of arrays,
     // so in case glGetIntegerv leaves them uninitialized because of a GL bug, we would have very weird crashes.
     mGLMaxVertexAttribs = 0;
     mGLMaxTextureUnits = 0;
     mGLMaxTextureSize = 0;
     mGLMaxCubeMapTextureSize = 0;
+    mGLMaxRenderbufferSize = 0;
     mGLMaxTextureImageUnits = 0;
     mGLMaxVertexTextureImageUnits = 0;
     mGLMaxVaryingVectors = 0;
     mGLMaxFragmentUniformVectors = 0;
     mGLMaxVertexUniformVectors = 0;
 
     // See OpenGL ES 2.0.25 spec, 6.2 State Tables, table 6.13
     mPixelStorePackAlignment = 4;
--- a/content/canvas/src/WebGLContext.h
+++ b/content/canvas/src/WebGLContext.h
@@ -853,16 +853,17 @@ protected:
     // whether shader validation is supported
     bool mShaderValidation;
 
     // some GL constants
     int32_t mGLMaxVertexAttribs;
     int32_t mGLMaxTextureUnits;
     int32_t mGLMaxTextureSize;
     int32_t mGLMaxCubeMapTextureSize;
+    int32_t mGLMaxRenderbufferSize;
     int32_t mGLMaxTextureImageUnits;
     int32_t mGLMaxVertexTextureImageUnits;
     int32_t mGLMaxVaryingVectors;
     int32_t mGLMaxFragmentUniformVectors;
     int32_t mGLMaxVertexUniformVectors;
 
     // Cache the max number of elements that can be read from bound VBOs
     // (result of ValidateBuffers).
@@ -1122,16 +1123,18 @@ protected:
     void LoseOldestWebGLContextIfLimitExceeded();
     void UpdateLastUseIndex();
 
     template <typename WebGLObjectType>
     JS::Value WebGLObjectAsJSValue(JSContext *cx, const WebGLObjectType *, ErrorResult& rv) const;
     template <typename WebGLObjectType>
     JSObject* WebGLObjectAsJSObject(JSContext *cx, const WebGLObjectType *, ErrorResult& rv) const;
 
+    void ReattachTextureToAnyFramebufferToWorkAroundBugs(WebGLTexture *tex, WebGLint level);
+
 #ifdef XP_MACOSX
     // see bug 713305. This RAII helper guarantees that we're on the discrete GPU, during its lifetime
     // Debouncing note: we don't want to switch GPUs too frequently, so try to not create and destroy
     // these objects at high frequency. Having WebGLContext's hold one such object seems fine,
     // because WebGLContext objects only go away during GC, which shouldn't happen too frequently.
     // If in the future GC becomes much more frequent, we may have to revisit then (maybe use a timer).
     ForceDiscreteGPUHelperCGL mForceDiscreteGPUHelper;
 #endif
--- a/content/canvas/src/WebGLContextGL.cpp
+++ b/content/canvas/src/WebGLContextGL.cpp
@@ -743,16 +743,19 @@ WebGLContext::CopyTexSubImage2D_base(Web
 
         GLint   actual_y             = clamped(y, 0, framebufferHeight);
         GLint   actual_y_plus_height = clamped(y + height, 0, framebufferHeight);
         GLsizei actual_height  = actual_y_plus_height - actual_y;
         GLint   actual_yoffset = yoffset + actual_y - y;
 
         gl->fCopyTexSubImage2D(target, level, actual_xoffset, actual_yoffset, actual_x, actual_y, actual_width, actual_height);
     }
+
+    if (!sub)
+        ReattachTextureToAnyFramebufferToWorkAroundBugs(tex, level);
 }
 
 void
 WebGLContext::CopyTexImage2D(WebGLenum target,
                              WebGLint level,
                              WebGLenum internalformat,
                              WebGLint x,
                              WebGLint y,
@@ -1957,25 +1960,22 @@ WebGLContext::GetParameter(JSContext* cx
         }
         // int
         case LOCAL_GL_STENCIL_CLEAR_VALUE:
         case LOCAL_GL_STENCIL_REF:
         case LOCAL_GL_STENCIL_BACK_REF:
         case LOCAL_GL_UNPACK_ALIGNMENT:
         case LOCAL_GL_PACK_ALIGNMENT:
         case LOCAL_GL_SUBPIXEL_BITS:
-        case LOCAL_GL_MAX_TEXTURE_SIZE:
-        case LOCAL_GL_MAX_CUBE_MAP_TEXTURE_SIZE:
         case LOCAL_GL_SAMPLE_BUFFERS:
         case LOCAL_GL_SAMPLES:
         case LOCAL_GL_MAX_VERTEX_ATTRIBS:
         case LOCAL_GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS:
         case LOCAL_GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS:
         case LOCAL_GL_MAX_TEXTURE_IMAGE_UNITS:
-        case LOCAL_GL_MAX_RENDERBUFFER_SIZE:
         case LOCAL_GL_RED_BITS:
         case LOCAL_GL_GREEN_BITS:
         case LOCAL_GL_BLUE_BITS:
         case LOCAL_GL_ALPHA_BITS:
         case LOCAL_GL_DEPTH_BITS:
         case LOCAL_GL_STENCIL_BITS:
         {
             GLint i = 0;
@@ -1988,16 +1988,25 @@ WebGLContext::GetParameter(JSContext* cx
                 gl->fGetIntegerv(pname, &i);
                 return JS::Int32Value(i);
             }
             else {
                 ErrorInvalidEnum("getParameter: parameter", pname);
                 return JS::NullValue();
             }
 
+        case LOCAL_GL_MAX_TEXTURE_SIZE:
+            return JS::Int32Value(mGLMaxTextureSize);
+
+        case LOCAL_GL_MAX_CUBE_MAP_TEXTURE_SIZE:
+            return JS::Int32Value(mGLMaxCubeMapTextureSize);
+
+        case LOCAL_GL_MAX_RENDERBUFFER_SIZE:
+            return JS::Int32Value(mGLMaxRenderbufferSize);
+
         case LOCAL_GL_MAX_VERTEX_UNIFORM_VECTORS:
             return JS::Int32Value(mGLMaxVertexUniformVectors);
 
         case LOCAL_GL_MAX_FRAGMENT_UNIFORM_VECTORS:
             return JS::Int32Value(mGLMaxFragmentUniformVectors);
 
         case LOCAL_GL_MAX_VARYING_VECTORS:
             return JS::Int32Value(mGLMaxVaryingVectors);
@@ -3368,18 +3377,18 @@ WebGLContext::RenderbufferStorage(WebGLe
         return ErrorInvalidOperation("renderbufferStorage called on renderbuffer 0");
 
     if (target != LOCAL_GL_RENDERBUFFER)
         return ErrorInvalidEnumInfo("renderbufferStorage: target", target);
 
     if (width < 0 || height < 0)
         return ErrorInvalidValue("renderbufferStorage: width and height must be >= 0");
 
-    if (!mBoundRenderbuffer || !mBoundRenderbuffer->GLName())
-        return ErrorInvalidOperation("renderbufferStorage called on renderbuffer 0");
+    if (width > mGLMaxRenderbufferSize || height > mGLMaxRenderbufferSize)
+        return ErrorInvalidValue("renderbufferStorage: width or height exceeds maximum renderbuffer size");
 
     // certain OpenGL ES renderbuffer formats may not exist on desktop OpenGL
     WebGLenum internalformatForGL = internalformat;
 
     switch (internalformat) {
     case LOCAL_GL_RGBA4:
     case LOCAL_GL_RGB5_A1:
         // 16-bit RGBA formats are not supported on desktop GL
@@ -4178,17 +4187,18 @@ WebGLContext::CompileShader(WebGLShader 
 
         const char *s = sourceCString.get();
 
         compiler = ShConstructCompiler((ShShaderType) shader->ShaderType(),
                                        SH_WEBGL_SPEC,
                                        targetShaderSourceLanguage,
                                        &resources);
 
-        int compileOptions = SH_ATTRIBUTES_UNIFORMS;
+        int compileOptions = SH_ATTRIBUTES_UNIFORMS |
+                             SH_ENFORCE_PACKING_RESTRICTIONS;
         if (useShaderSourceTranslation) {
             compileOptions |= SH_OBJECT_CODE
                             | SH_MAP_LONG_VARIABLE_NAMES;
 #ifdef XP_MACOSX
             if (gl->WorkAroundDriverBugs()) {
                 // Work around bug 665578 and bug 769810
                 if (gl->Vendor() == gl::GLContext::VendorATI) {
                     compileOptions |= SH_EMULATE_BUILT_IN_FUNCTIONS;
@@ -4340,16 +4350,18 @@ WebGLContext::CompressedTexImage2D(WebGL
 
     uint32_t byteLength = view.Length();
     if (!ValidateCompressedTextureSize(target, level, internalformat, width, height, byteLength, "compressedTexImage2D")) {
         return;
     }
 
     gl->fCompressedTexImage2D(target, level, internalformat, width, height, border, byteLength, view.Data());
     tex->SetImageInfo(target, level, width, height, internalformat, LOCAL_GL_UNSIGNED_BYTE);
+
+    ReattachTextureToAnyFramebufferToWorkAroundBugs(tex, level);
 }
 
 void
 WebGLContext::CompressedTexSubImage2D(WebGLenum target, WebGLint level, WebGLint xoffset,
                                       WebGLint yoffset, WebGLsizei width, WebGLsizei height,
                                       WebGLenum format, ArrayBufferView& view)
 {
     if (!IsContextStable()) {
@@ -4852,23 +4864,25 @@ WebGLContext::TexImage2D_base(WebGLenum 
         if (!tempZeroData)
             return ErrorOutOfMemory("texImage2D: could not allocate %d bytes (for zero fill)", bytesNeeded);
 
         error = CheckedTexImage2D(target, level, internalformat,
                                   width, height, border, format, type, tempZeroData);
 
         free(tempZeroData);
     }
-    
+
     if (error) {
         GenerateWarning("texImage2D generated error %s", ErrorName(error));
         return;
     }
 
     tex->SetImageInfo(target, level, width, height, format, type);
+
+    ReattachTextureToAnyFramebufferToWorkAroundBugs(tex, level);
 }
 
 void
 WebGLContext::TexImage2D(WebGLenum target, WebGLint level,
                          WebGLenum internalformat, WebGLsizei width,
                          WebGLsizei height, WebGLint border, WebGLenum format,
                          WebGLenum type, ArrayBufferView *pixels, ErrorResult& rv)
 {
@@ -5271,8 +5285,48 @@ InternalFormatForFormatAndType(WebGLenum
     default:
         break;
     }
 
     NS_ASSERTION(false, "Coding mistake -- bad format/type passed?");
     return 0;
 }
 
+void
+WebGLContext::ReattachTextureToAnyFramebufferToWorkAroundBugs(WebGLTexture *tex,
+                                                              WebGLint level)
+{
+    MOZ_ASSERT(tex);
+
+    if (!gl->WorkAroundDriverBugs())
+        return;
+
+    if (!mIsMesa)
+        return;
+
+    MakeContextCurrent();
+
+    for(WebGLFramebuffer *framebuffer = mFramebuffers.getFirst();
+        framebuffer;
+        framebuffer = framebuffer->getNext())
+    {
+        if (framebuffer->ColorAttachment().Texture() == tex) {
+            framebuffer->FramebufferTexture2D(
+              LOCAL_GL_FRAMEBUFFER, LOCAL_GL_COLOR_ATTACHMENT0,
+              tex->Target(), tex, level);
+        }
+        if (framebuffer->DepthAttachment().Texture() == tex) {
+            framebuffer->FramebufferTexture2D(
+              LOCAL_GL_FRAMEBUFFER, LOCAL_GL_DEPTH_ATTACHMENT,
+              tex->Target(), tex, level);
+        }
+        if (framebuffer->StencilAttachment().Texture() == tex) {
+            framebuffer->FramebufferTexture2D(
+              LOCAL_GL_FRAMEBUFFER, LOCAL_GL_STENCIL_ATTACHMENT,
+              tex->Target(), tex, level);
+        }
+        if (framebuffer->DepthStencilAttachment().Texture() == tex) {
+            framebuffer->FramebufferTexture2D(
+              LOCAL_GL_FRAMEBUFFER, LOCAL_GL_DEPTH_STENCIL_ATTACHMENT,
+              tex->Target(), tex, level);
+        }
+    }
+}
--- a/content/canvas/src/WebGLContextValidate.cpp
+++ b/content/canvas/src/WebGLContextValidate.cpp
@@ -907,21 +907,23 @@ WebGLContext::InitAndValidateGL()
     }
 
     mBound2DTextures.SetLength(mGLMaxTextureUnits);
     mBoundCubeMapTextures.SetLength(mGLMaxTextureUnits);
 
     if (MinCapabilityMode()) {
         mGLMaxTextureSize = MINVALUE_GL_MAX_TEXTURE_SIZE;
         mGLMaxCubeMapTextureSize = MINVALUE_GL_MAX_CUBE_MAP_TEXTURE_SIZE;
+        mGLMaxRenderbufferSize = MINVALUE_GL_MAX_RENDERBUFFER_SIZE;
         mGLMaxTextureImageUnits = MINVALUE_GL_MAX_TEXTURE_IMAGE_UNITS;
         mGLMaxVertexTextureImageUnits = MINVALUE_GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS;
     } else {
         gl->fGetIntegerv(LOCAL_GL_MAX_TEXTURE_SIZE, &mGLMaxTextureSize);
         gl->fGetIntegerv(LOCAL_GL_MAX_CUBE_MAP_TEXTURE_SIZE, &mGLMaxCubeMapTextureSize);
+        gl->fGetIntegerv(LOCAL_GL_MAX_RENDERBUFFER_SIZE, &mGLMaxRenderbufferSize);
         gl->fGetIntegerv(LOCAL_GL_MAX_TEXTURE_IMAGE_UNITS, &mGLMaxTextureImageUnits);
         gl->fGetIntegerv(LOCAL_GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS, &mGLMaxVertexTextureImageUnits);
     }
 
     if (MinCapabilityMode()) {
         mGLMaxFragmentUniformVectors = MINVALUE_GL_MAX_FRAGMENT_UNIFORM_VECTORS;
         mGLMaxVertexUniformVectors = MINVALUE_GL_MAX_VERTEX_UNIFORM_VECTORS;
         mGLMaxVaryingVectors = MINVALUE_GL_MAX_VARYING_VECTORS;
--- a/content/html/content/src/nsGenericHTMLElement.cpp
+++ b/content/html/content/src/nsGenericHTMLElement.cpp
@@ -374,18 +374,28 @@ static bool IS_TABLE_CELL(nsIAtom* frame
   return nsGkAtoms::tableCellFrame == frameType ||
     nsGkAtoms::bcTableCellFrame == frameType;
 }
 
 static bool
 IsOffsetParent(nsIFrame* aFrame)
 {
   nsIAtom* frameType = aFrame->GetType();
-  return (IS_TABLE_CELL(frameType) ||
-          frameType == nsGkAtoms::tableFrame);
+  
+  if (IS_TABLE_CELL(frameType) || frameType == nsGkAtoms::tableFrame) {
+    // Per the IDL for Element, only td, th, and table are acceptable offsetParents
+    // apart from body or positioned elements; we need to check the content type as
+    // well as the frame type so we ignore anonymous tables created by an element
+    // with display: table-cell with no actual table
+    nsIContent* content = aFrame->GetContent();
+
+    return content->IsHTML(nsGkAtoms::table) || content->IsHTML(nsGkAtoms::td)
+      || content->IsHTML(nsGkAtoms::th);
+  }
+  return false;
 }
 
 Element*
 nsGenericHTMLElement::GetOffsetRect(nsRect& aRect)
 {
   aRect = nsRect();
 
   nsIFrame* frame = GetStyledFrame();
--- a/content/html/content/test/Makefile.in
+++ b/content/html/content/test/Makefile.in
@@ -265,16 +265,17 @@ MOCHITEST_FILES = \
 		test_bug742549.html \
 		test_bug745685.html \
 		test_input_file_picker.html \
 		test_bug763626.html \
 		test_bug780993.html \
 		test_bug786564.html \
 		test_bug797113.html \
 		test_bug787134.html \
+		test_bug803677.html \
 		test_iframe_sandbox_inheritance.html \
 		file_iframe_sandbox_a_if1.html \
 		file_iframe_sandbox_a_if2.html \
 		file_iframe_sandbox_a_if3.html \
 		file_iframe_sandbox_a_if4.html \
 		file_iframe_sandbox_a_if5.html \
 		file_iframe_sandbox_a_if6.html \
 		file_iframe_sandbox_a_if7.html \
new file mode 100644
--- /dev/null
+++ b/content/html/content/test/test_bug803677.html
@@ -0,0 +1,50 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=803677
+-->
+<head>
+  <meta charset="utf-8">
+  <title>Test for Bug 803677</title>
+  <script type="application/javascript" src="/MochiKit/packed.js"></script>
+  <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+  <script src="reflect.js"></script>
+  <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+<style>
+	.base { border:1px solid gray; }
+	.bad-table { display:table-cell; border:1px solid red; }
+</style>
+</head>
+<body>
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=803677">Mozilla Bug 803677</a>
+<p id="display"></p>
+<div id="content">
+	<p class="base">1</p>
+	<p class="base">2</p>
+	<p class="base">3</p>
+	<p class="base bad-table">4</p>
+	<p class="base">7</p>
+	<p class="base">8</p>
+	<p class="base">9</p>
+</div>
+<pre id="test">
+<script type="application/javascript">
+    var p = document.querySelectorAll(".base");
+    var parent = document.querySelector("body");
+    var prevOffset = 0;
+    for (var i = 0; i < p.length; i++) {
+        var t = 0, e = p[i];
+        is(e.offsetParent, parent, "Offset parent of all paragraphs should be the body.");
+        while (e) {
+            t += e.offsetTop;
+            e = e.offsetParent;
+        }
+        p[i].innerHTML = t;
+
+        ok(t > prevOffset, "Offset should increase down the page");
+        prevOffset = t;
+    }
+</script>
+</pre>
+</body>
+</html>
--- a/content/smil/nsSMILAnimationController.cpp
+++ b/content/smil/nsSMILAnimationController.cpp
@@ -9,16 +9,17 @@
 #include "nsCSSProps.h"
 #include "nsITimer.h"
 #include "mozilla/dom/Element.h"
 #include "nsIDocument.h"
 #include "nsISMILAnimationElement.h"
 #include "nsIDOMSVGAnimationElement.h"
 #include "nsSMILTimedElement.h"
 
+using namespace mozilla;
 using namespace mozilla::dom;
 
 //----------------------------------------------------------------------
 // nsSMILAnimationController implementation
 
 //----------------------------------------------------------------------
 // ctors, dtors, factory methods
 
@@ -361,24 +362,18 @@ nsSMILAnimationController::DoSample(bool
   if (mRunningSample) {
     NS_ERROR("Shouldn't be recursively sampling");
     return;
   }
 
   mResampleNeeded = false;
   // Set running sample flag -- do this before flushing styles so that when we
   // flush styles we don't end up requesting extra samples
+  AutoRestore<bool> autoRestoreRunningSample(mRunningSample);
   mRunningSample = true;
-  nsCOMPtr<nsIDocument> kungFuDeathGrip(mDocument);  // keeps 'this' alive too
-  mDocument->FlushPendingNotifications(Flush_Style);
-
-  // WARNING: 
-  // WARNING: the above flush may have destroyed the pres shell and/or
-  // WARNING: frames and other layout related objects.
-  // WARNING:
   
   // STEP 1: Bring model up to date
   // (i)  Rewind elements where necessary
   // (ii) Run milestone samples
   RewindElements();
   DoMilestoneSamples();
 
   // STEP 2: Sample the child time containers
@@ -436,23 +431,36 @@ nsSMILAnimationController::DoSample(bool
     currentCompositorTable->EnumerateEntries(RemoveCompositorFromTable,
                                              mLastCompositorTable);
 
     // * For each entry that remains in prev sample's hash table (i.e. for
     // every target that's no longer animated), clear animation effects.
     mLastCompositorTable->EnumerateEntries(DoClearAnimationEffects, nullptr);
   }
 
+  // return early if there are no active animations to avoid a style flush
+  if (currentCompositorTable->Count() == 0) {
+    mLastCompositorTable = nullptr;
+    return;
+  }
+
+  nsCOMPtr<nsIDocument> kungFuDeathGrip(mDocument);  // keeps 'this' alive too
+  mDocument->FlushPendingNotifications(Flush_Style);
+
+  // WARNING: 
+  // WARNING: the above flush may have destroyed the pres shell and/or
+  // WARNING: frames and other layout related objects.
+  // WARNING:
+
   // STEP 5: Compose currently-animated attributes.
   // XXXdholbert: This step traverses our animation targets in an effectively
   // random order. For animation from/to 'inherit' values to work correctly
   // when the inherited value is *also* being animated, we really should be
   // traversing our animated nodes in an ancestors-first order (bug 501183)
   currentCompositorTable->EnumerateEntries(DoComposeAttribute, nullptr);
-  mRunningSample = false;
 
   // Update last compositor table
   mLastCompositorTable = currentCompositorTable.forget();
 
   NS_ASSERTION(!mResampleNeeded, "Resample dirty flag set during sample!");
 }
 
 void
--- a/content/xul/templates/src/nsXULTreeBuilder.cpp
+++ b/content/xul/templates/src/nsXULTreeBuilder.cpp
@@ -235,17 +235,17 @@ protected:
     /*
      * Sort hints (compare case, etc)
      */
     uint32_t mSortHints;
 
     /** 
      * The builder observers.
      */
-    nsCOMPtr<nsISupportsArray> mObservers;
+    nsCOMArray<nsIXULTreeBuilderObserver> mObservers;
 };
 
 //----------------------------------------------------------------------
 
 nsresult
 NS_NewXULTreeBuilder(nsISupports* aOuter, REFNSIID aIID, void** aResult)
 {
     *aResult = nullptr;
@@ -277,32 +277,21 @@ NS_IMPL_RELEASE_INHERITED(nsXULTreeBuild
 
 NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN_INHERITED(nsXULTreeBuilder, nsXULTemplateBuilder)
     NS_IMPL_CYCLE_COLLECTION_UNLINK(mBoxObject)
     NS_IMPL_CYCLE_COLLECTION_UNLINK(mSelection)
     NS_IMPL_CYCLE_COLLECTION_UNLINK(mPersistStateStore)
     NS_IMPL_CYCLE_COLLECTION_UNLINK(mObservers)
 NS_IMPL_CYCLE_COLLECTION_UNLINK_END
 
-static bool TraverseObservers(nsISupports* aElement, void *aData)
-{
-    nsCycleCollectionTraversalCallback *cb =
-        static_cast<nsCycleCollectionTraversalCallback*>(aData);
-    NS_CYCLE_COLLECTION_NOTE_EDGE_NAME(*cb, "mObservers[i]");
-    cb->NoteXPCOMChild(aElement);
-    return true;
-}
-
 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INHERITED(nsXULTreeBuilder, nsXULTemplateBuilder)
     NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mBoxObject)
     NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mSelection)
     NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mPersistStateStore)
-    if (tmp->mObservers) {
-        tmp->mObservers->EnumerateForwards(TraverseObservers, &cb);
-    }
+    NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mObservers)
 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
 
 DOMCI_DATA(XULTreeBuilder, nsXULTreeBuilder)
 
 NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION_INHERITED(nsXULTreeBuilder)
     NS_INTERFACE_MAP_ENTRY(nsIXULTreeBuilder)
     NS_INTERFACE_MAP_ENTRY(nsITreeView)
     NS_DOM_INTERFACE_MAP_ENTRY_CLASSINFO(XULTreeBuilder)
@@ -356,30 +345,23 @@ nsXULTreeBuilder::GetIndexOfResource(nsI
     else
         *aResult = iter.GetRowIndex();
     return NS_OK;
 }
 
 NS_IMETHODIMP
 nsXULTreeBuilder::AddObserver(nsIXULTreeBuilderObserver* aObserver)
 {
-    nsresult rv;  
-    if (!mObservers) {
-        rv = NS_NewISupportsArray(getter_AddRefs(mObservers));
-        if (NS_FAILED(rv))
-            return rv;
-    }
-
-    return mObservers->AppendElement(aObserver);
+    return mObservers.AppendObject(aObserver) ? NS_OK : NS_ERROR_FAILURE;
 }
 
 NS_IMETHODIMP
 nsXULTreeBuilder::RemoveObserver(nsIXULTreeBuilderObserver* aObserver)
 {
-    return mObservers ? mObservers->RemoveElement(aObserver) : NS_ERROR_FAILURE;
+    return mObservers.RemoveObject(aObserver) ? NS_OK : NS_ERROR_FAILURE;
 }
 
 NS_IMETHODIMP
 nsXULTreeBuilder::Sort(nsIDOMElement* aElement)
 {
     nsCOMPtr<nsIContent> header = do_QueryInterface(aElement);
     if (! header)
         return NS_ERROR_FAILURE;
@@ -850,24 +832,21 @@ nsXULTreeBuilder::ToggleOpenState(int32_
     if (result && result != mRootResult) {
         // don't open containers if child processing isn't allowed
         bool mayProcessChildren;
         nsresult rv = result->GetMayProcessChildren(&mayProcessChildren);
         if (NS_FAILED(rv) || !mayProcessChildren)
             return rv;
     }
 
-    if (mObservers) {
-        uint32_t count;
-        mObservers->Count(&count);
-        for (uint32_t i = 0; i < count; ++i) {
-            nsCOMPtr<nsIXULTreeBuilderObserver> observer = do_QueryElementAt(mObservers, i);
-            if (observer)
-                observer->OnToggleOpenState(aIndex);
-        }
+    uint32_t count = mObservers.Count();
+    for (uint32_t i = 0; i < count; ++i) {
+        nsCOMPtr<nsIXULTreeBuilderObserver> observer = mObservers.SafeObjectAt(i);
+        if (observer)
+            observer->OnToggleOpenState(aIndex);
     }
 
     if (mPersistStateStore) {
         bool isOpen;
         IsContainerOpen(aIndex, &isOpen);
 
         nsCOMPtr<nsIRDFResource> container;
         GetResourceFor(aIndex, getter_AddRefs(container));
@@ -903,63 +882,55 @@ nsXULTreeBuilder::ToggleOpenState(int32_
 
 NS_IMETHODIMP
 nsXULTreeBuilder::CycleHeader(nsITreeColumn* aCol)
 {
     NS_ENSURE_ARG_POINTER(aCol);
     nsCOMPtr<nsIDOMElement> element;
     aCol->GetElement(getter_AddRefs(element));
 
-    if (mObservers) {
-        nsAutoString id;
-        aCol->GetId(id);
+    nsAutoString id;
+    aCol->GetId(id);
 
-        uint32_t count;
-        mObservers->Count(&count);
-        for (uint32_t i = 0; i < count; ++i) {
-            nsCOMPtr<nsIXULTreeBuilderObserver> observer = do_QueryElementAt(mObservers, i);
-            if (observer)
-                observer->OnCycleHeader(id.get(), element);
-        }
+    uint32_t count = mObservers.Count();
+    for (uint32_t i = 0; i < count; ++i) {
+        nsCOMPtr<nsIXULTreeBuilderObserver> observer = mObservers.SafeObjectAt(i);
+        if (observer)
+            observer->OnCycleHeader(id.get(), element);
     }
 
     return Sort(element);
 }
 
 NS_IMETHODIMP
 nsXULTreeBuilder::SelectionChanged()
 {
-    if (mObservers) {
-        uint32_t count;
-        mObservers->Count(&count);
-        for (uint32_t i = 0; i < count; ++i) {
-            nsCOMPtr<nsIXULTreeBuilderObserver> observer = do_QueryElementAt(mObservers, i);
-            if (observer)
-                observer->OnSelectionChanged();
-        }
+    uint32_t count = mObservers.Count();
+    for (uint32_t i = 0; i < count; ++i) {
+        nsCOMPtr<nsIXULTreeBuilderObserver> observer = mObservers.SafeObjectAt(i);
+        if (observer)
+            observer->OnSelectionChanged();
     }
 
     return NS_OK;
 }
 
 NS_IMETHODIMP
 nsXULTreeBuilder::CycleCell(int32_t aRow, nsITreeColumn* aCol)
 {
     NS_ENSURE_ARG_POINTER(aCol);
-    if (mObservers) {
-        nsAutoString id;
-        aCol->GetId(id);
+
+    nsAutoString id;
+    aCol->GetId(id);
 
-        uint32_t count;
-        mObservers->Count(&count);
-        for (uint32_t i = 0; i < count; ++i) {
-            nsCOMPtr<nsIXULTreeBuilderObserver> observer = do_QueryElementAt(mObservers, i);
-            if (observer)
-                observer->OnCycleCell(aRow, id.get());
-        }
+    uint32_t count = mObservers.Count();
+    for (uint32_t i = 0; i < count; ++i) {
+        nsCOMPtr<nsIXULTreeBuilderObserver> observer = mObservers.SafeObjectAt(i);
+        if (observer)
+            observer->OnCycleCell(aRow, id.get());
     }
 
     return NS_OK;
 }
 
 NS_IMETHODIMP
 nsXULTreeBuilder::IsEditable(int32_t aRow, nsITreeColumn* aCol, bool* _retval)
 {
@@ -1024,72 +995,62 @@ nsXULTreeBuilder::SetCellText(int32_t aR
 {
     NS_ENSURE_ARG_POINTER(aCol);
     return NS_OK;
 }
 
 NS_IMETHODIMP
 nsXULTreeBuilder::PerformAction(const PRUnichar* aAction)
 {
-    if (mObservers) {  
-        uint32_t count;
-        mObservers->Count(&count);
-        for (uint32_t i = 0; i < count; ++i) {
-            nsCOMPtr<nsIXULTreeBuilderObserver> observer = do_QueryElementAt(mObservers, i);
-            if (observer)
-                observer->OnPerformAction(aAction);
-        }
+    uint32_t count = mObservers.Count();
+    for (uint32_t i = 0; i < count; ++i) {
+        nsCOMPtr<nsIXULTreeBuilderObserver> observer = mObservers.SafeObjectAt(i);
+        if (observer)
+            observer->OnPerformAction(aAction);
     }
 
     return NS_OK;
 }
 
 NS_IMETHODIMP
 nsXULTreeBuilder::PerformActionOnRow(const PRUnichar* aAction, int32_t aRow)
 {
-    if (mObservers) {  
-        uint32_t count;
-        mObservers->Count(&count);
-        for (uint32_t i = 0; i < count; ++i) {
-            nsCOMPtr<nsIXULTreeBuilderObserver> observer = do_QueryElementAt(mObservers, i);
-            if (observer)
-                observer->OnPerformActionOnRow(aAction, aRow);
-        }
+    uint32_t count = mObservers.Count();
+    for (uint32_t i = 0; i < count; ++i) {
+        nsCOMPtr<nsIXULTreeBuilderObserver> observer = mObservers.SafeObjectAt(i);
+        if (observer)
+            observer->OnPerformActionOnRow(aAction, aRow);
     }
 
     return NS_OK;
 }
 
 NS_IMETHODIMP
 nsXULTreeBuilder::PerformActionOnCell(const PRUnichar* aAction, int32_t aRow, nsITreeColumn* aCol)
 {
     NS_ENSURE_ARG_POINTER(aCol);
-    if (mObservers) {  
-        nsAutoString id;
-        aCol->GetId(id);
+    nsAutoString id;
+    aCol->GetId(id);
 
-        uint32_t count;
-        mObservers->Count(&count);
-        for (uint32_t i = 0; i < count; ++i) {
-            nsCOMPtr<nsIXULTreeBuilderObserver> observer = do_QueryElementAt(mObservers, i);
-            if (observer)
-                observer->OnPerformActionOnCell(aAction, aRow, id.get());
-        }
+    uint32_t count = mObservers.Count();
+    for (uint32_t i = 0; i < count; ++i) {
+        nsCOMPtr<nsIXULTreeBuilderObserver> observer = mObservers.SafeObjectAt(i);
+        if (observer)
+            observer->OnPerformActionOnCell(aAction, aRow, id.get());
     }
 
     return NS_OK;
 }
 
 
 void
 nsXULTreeBuilder::NodeWillBeDestroyed(const nsINode* aNode)
 {
     nsCOMPtr<nsIMutationObserver> kungFuDeathGrip(this);
-    if (mObservers)
-        mObservers->Clear();
+    mObservers.Clear();
 
     nsXULTemplateBuilder::NodeWillBeDestroyed(aNode);
 }
 
 NS_IMETHODIMP
 nsXULTreeBuilder::HasGeneratedContent(nsIRDFResource* aResource,
                                       nsIAtom* aTag,
                                       bool* aGenerated)
@@ -1913,46 +1874,40 @@ nsXULTreeBuilder::SortSubtree(nsTreeRows
 
 
 /* boolean canDrop (in long index, in long orientation); */
 NS_IMETHODIMP
 nsXULTreeBuilder::CanDrop(int32_t index, int32_t orientation,
                           nsIDOMDataTransfer* dataTransfer, bool *_retval)
 {
     *_retval = false;
-    if (mObservers) {
-        uint32_t count;
-        mObservers->Count(&count);
-        for (uint32_t i = 0; i < count; ++i) {
-            nsCOMPtr<nsIXULTreeBuilderObserver> observer = do_QueryElementAt(mObservers, i);
-            if (observer) {
-                observer->CanDrop(index, orientation, dataTransfer, _retval);
-                if (*_retval)
-                    break;
-            }
+    uint32_t count = mObservers.Count();
+    for (uint32_t i = 0; i < count; ++i) {
+        nsCOMPtr<nsIXULTreeBuilderObserver> observer = mObservers.SafeObjectAt(i);
+        if (observer) {
+            observer->CanDrop(index, orientation, dataTransfer, _retval);
+            if (*_retval)
+                break;
         }
     }
 
     return NS_OK;
 }
 
 NS_IMETHODIMP
 nsXULTreeBuilder::Drop(int32_t row, int32_t orient, nsIDOMDataTransfer* dataTransfer)
 {
-    if (mObservers) {
-        uint32_t count;
-        mObservers->Count(&count);
-        for (uint32_t i = 0; i < count; ++i) {
-            nsCOMPtr<nsIXULTreeBuilderObserver> observer = do_QueryElementAt(mObservers, i);
-            if (observer) {
-                bool canDrop = false;
-                observer->CanDrop(row, orient, dataTransfer, &canDrop);
-                if (canDrop)
-                    observer->OnDrop(row, orient, dataTransfer);
-            }
+    uint32_t count = mObservers.Count();
+    for (uint32_t i = 0; i < count; ++i) {
+        nsCOMPtr<nsIXULTreeBuilderObserver> observer = mObservers.SafeObjectAt(i);
+        if (observer) {
+            bool canDrop = false;
+            observer->CanDrop(row, orient, dataTransfer, &canDrop);
+            if (canDrop)
+                observer->OnDrop(row, orient, dataTransfer);
         }
     }
 
     return NS_OK;
 }
 
 NS_IMETHODIMP
 nsXULTreeBuilder::IsSorted(bool *_retval)
--- a/dom/apps/src/Webapps.jsm
+++ b/dom/apps/src/Webapps.jsm
@@ -201,16 +201,17 @@ this.DOMApplicationRegistry = {
       appId: aId,
       origin: app.origin,
       localId: app.localId
     });
   },
 
   // Installs a 3rd party packaged app.
   installPreinstalledPackage: function installPreinstalledPackage(aId) {
+#ifdef MOZ_WIDGET_GONK
     let app = this.webapps[aId];
     let baseDir;
     try {
       baseDir = FileUtils.getDir("coreAppsDir", ["webapps", aId], true, true);
     } catch(e) {
       // In ENG builds, we don't have apps in coreAppsDir.
       return;
     }
@@ -262,16 +263,17 @@ this.DOMApplicationRegistry = {
     } catch(e) {
       // If we are unable to extract the manifest, cleanup and remove this app.
       debug("Cleaning up: " + e);
       destDir.remove(true);
       delete this.webapps[aId];
     } finally {
       zipReader.close();
     }
+#endif
   },
 
   // Implements the core of bug 787439
   // if at first run, go through these steps:
   //   a. load the core apps registry.
   //   b. uninstall any core app from the current registry but not in the
   //      new core apps registry.
   //   c. for all apps in the new core registry, install them if they are not
@@ -932,19 +934,21 @@ this.DOMApplicationRegistry = {
 
     this._loadJSONAsync(file, (function(aJSON) {
       if (!aJSON) {
         debug("startDownload: No update manifest found at " + file.path + " " + aManifestURL);
         return;
       }
 
       let manifest = new ManifestHelper(aJSON, app.installOrigin);
-      this.downloadPackage(manifest, { manifestURL: aManifestURL,
-                                       origin: app.origin }, isUpdate,
-        function(aId, aManifest) {
+      this.downloadPackage(manifest, {
+          manifestURL: aManifestURL,
+          origin: app.origin,
+          downloadSize: app.downloadSize
+        }, isUpdate, function(aId, aManifest) {
           // Success! Keep the zip in of TmpD, we'll move it out when
           // applyDownload() will be called.
           let tmpDir = FileUtils.getDir("TmpD", ["webapps", aId], true, true);
 
           // Save the manifest in TmpD also
           let manFile = tmpDir.clone();
           manFile.append("manifest.webapp");
           DOMApplicationRegistry._writeFile(manFile,
--- a/dom/base/Navigator.cpp
+++ b/dom/base/Navigator.cpp
@@ -747,17 +747,17 @@ Navigator::RemoveIdleObserver(nsIIdleObs
 }
 
 NS_IMETHODIMP
 Navigator::Vibrate(const jsval& aPattern, JSContext* cx)
 {
   nsCOMPtr<nsPIDOMWindow> win = do_QueryReferent(mWindow);
   NS_ENSURE_TRUE(win, NS_OK);
 
-  nsIDOMDocument* domDoc = win->GetExtantDocument();
+  nsCOMPtr<nsIDOMDocument> domDoc = win->GetExtantDocument();
   NS_ENSURE_TRUE(domDoc, NS_ERROR_FAILURE);
 
   bool hidden = true;
   domDoc->GetHidden(&hidden);
   if (hidden) {
     // Hidden documents cannot start or stop a vibration.
     return NS_OK;
   }
--- a/dom/base/ObjectWrapper.jsm
+++ b/dom/base/ObjectWrapper.jsm
@@ -8,74 +8,63 @@ const Cu = Components.utils;
 const Cc = Components.classes;
 const Ci = Components.interfaces;
 
 this.EXPORTED_SYMBOLS = ["ObjectWrapper"];
 
 // Makes sure that we expose correctly chrome JS objects to content.
 
 this.ObjectWrapper = {
-  getObjectKind: function objWrapper_getobjectkind(aObject) {
+  getObjectKind: function objWrapper_getObjectKind(aObject) {
     if (!aObject) {
       return "null";
     }
 
     if (Array.isArray(aObject)) {
       return "array";
-    } else if (aObject.mozSlice && (typeof aObject.mozSlice == "function")) {
+    } else if (aObject instanceof Ci.nsIDOMFile) {
+      return "file";
+    } else if (aObject instanceof Ci.nsIDOMBlob) {
       return "blob";
     } else if (typeof aObject == "object") {
       return "object";
     } else {
       return "primitive";
     }
   },
 
   wrap: function objWrapper_wrap(aObject, aCtxt) {
-    if (!aObject) {
-      return null;
-    }
-
     // First check wich kind of object we have.
     let kind = this.getObjectKind(aObject);
-    if (kind == "array") {
+    if (kind == "null") {
+      return null;
+    } else if (kind == "array") {
       let res = Cu.createArrayIn(aCtxt);
       aObject.forEach(function(aObj) {
         res.push(this.wrap(aObj, aCtxt));
       }, this);
       return res;
+    } else if (kind == "file") {
+      return new aCtxt.File(aObject,
+                            { name: aObject.name,
+                              type: aObject.type });
     } else if (kind == "blob") {
       return new aCtxt.Blob([aObject]);
     } else if (kind == "primitive") {
       return aObject;
     }
 
-    //  Fall-through, we now have a dictionnary object.
+    // Fall-through, we now have a dictionnary object.
     let res = Cu.createObjectIn(aCtxt);
     let propList = { };
     for (let prop in aObject) {
-      let value;
-      let objProp = aObject[prop];
-      let propKind = this.getObjectKind(objProp);
-      if (propKind == "array") {
-        value = Cu.createArrayIn(aCtxt);
-        objProp.forEach(function(aObj) {
-          value.push(this.wrap(aObj, aCtxt));
-        }, this);
-      } else if (propKind == "blob") {
-        value = new aCtxt.Blob([objProp]);
-      } else if (propKind == "object") {
-        value = this.wrap(objProp, aCtxt);
-      } else {
-        value = objProp;
-      }
       propList[prop] = {
         enumerable: true,
         configurable: true,
         writable: true,
-        value: value
+        value: this.wrap(aObject[prop], aCtxt)
       }
     }
     Object.defineProperties(res, propList);
     Cu.makeObjectPropsNormal(res);
     return res;
   }
 }
--- a/dom/base/nsDOMClassInfo.cpp
+++ b/dom/base/nsDOMClassInfo.cpp
@@ -422,17 +422,16 @@
 #include "nsIDOMNavigatorUserMedia.h"
 #endif
 
 // Workers
 #include "mozilla/dom/workers/Workers.h"
 
 #include "nsDOMFile.h"
 #include "nsDOMFileReader.h"
-#include "nsIDOMFormData.h"
 #include "ArchiveReader.h"
 #include "ArchiveRequest.h"
 
 #include "nsIDOMDesktopNotification.h"
 #include "nsIDOMNavigatorDesktopNotification.h"
 #include "nsIDOMNavigatorDeviceStorage.h"
 #include "nsIDOMNavigatorGeolocation.h"
 #include "Navigator.h"
@@ -1561,19 +1560,16 @@ static nsDOMClassInfoData sClassInfoData
   NS_DEFINE_CHROME_ONLY_CLASSINFO_DATA(ContentFrameMessageManager, nsEventTargetSH,
                                        DOM_DEFAULT_SCRIPTABLE_FLAGS |
                                        nsIXPCScriptable::IS_GLOBAL_OBJECT)
   NS_DEFINE_CHROME_ONLY_CLASSINFO_DATA(ChromeMessageBroadcaster, nsDOMGenericSH,
                                        DOM_DEFAULT_SCRIPTABLE_FLAGS)
   NS_DEFINE_CHROME_ONLY_CLASSINFO_DATA(ChromeMessageSender, nsDOMGenericSH,
                                        DOM_DEFAULT_SCRIPTABLE_FLAGS)
 
-  NS_DEFINE_CLASSINFO_DATA(FormData, nsDOMGenericSH,
-                           DOM_DEFAULT_SCRIPTABLE_FLAGS)
-
   NS_DEFINE_CLASSINFO_DATA(DesktopNotification, nsDOMGenericSH,
                            DOM_DEFAULT_SCRIPTABLE_FLAGS)
   NS_DEFINE_CLASSINFO_DATA(DesktopNotificationCenter, nsDOMGenericSH,
                            DOM_DEFAULT_SCRIPTABLE_FLAGS)
 
   NS_DEFINE_CLASSINFO_DATA(IDBFactory, IDBFactorySH,
                            DOM_DEFAULT_SCRIPTABLE_FLAGS)
   NS_DEFINE_CLASSINFO_DATA_WITH_NAME(IDBFileHandle, FileHandle, nsEventTargetSH,
@@ -1704,17 +1700,16 @@ static nsDOMClassInfoData sClassInfoData
     nsresult rv = NS_OK;                                                        \
     nsCOMPtr<nsISupports> native = do_CreateInstance(_contract_id, &rv);        \
     native.forget(aInstancePtrResult);                                          \
     return rv;                                                                  \
   }
 
 NS_DEFINE_CONTRACT_CTOR(FileReader, NS_FILEREADER_CONTRACTID)
 NS_DEFINE_CONTRACT_CTOR(ArchiveReader, NS_ARCHIVEREADER_CONTRACTID)
-NS_DEFINE_CONTRACT_CTOR(FormData, NS_FORMDATA_CONTRACTID)
 NS_DEFINE_CONTRACT_CTOR(XPathEvaluator, NS_XPATH_EVALUATOR_CONTRACTID)
 NS_DEFINE_CONTRACT_CTOR(XSLTProcessor,
                         "@mozilla.org/document-transformer;1?type=xslt")
 NS_DEFINE_CONTRACT_CTOR(EventSource, NS_EVENTSOURCE_CONTRACTID)
 NS_DEFINE_CONTRACT_CTOR(MutationObserver, NS_DOMMUTATIONOBSERVER_CONTRACTID)
 #ifdef MOZ_SYS_MSG
 NS_DEFINE_CONTRACT_CTOR(MozActivity, NS_DOMACTIVITY_CONTRACTID)
 #endif
@@ -1752,34 +1747,33 @@ struct nsConstructorFuncMapData
   { eDOMClassInfo_##_class##_id, _func },
 
 #define NS_DEFINE_EVENT_CONSTRUCTOR_FUNC_DATA(_class)   \
   { eDOMClassInfo_##_class##_id, NS_DOM##_class##Ctor },
 
 static const nsConstructorFuncMapData kConstructorFuncMap[] =
 {
   NS_DEFINE_CONSTRUCTOR_FUNC_DATA(Blob, nsDOMMultipartFile::NewBlob)
-  NS_DEFINE_CONSTRUCTOR_FUNC_DATA(File, nsDOMFileFile::NewFile)
+  NS_DEFINE_CONSTRUCTOR_FUNC_DATA(File, nsDOMMultipartFile::NewFile)
   NS_DEFINE_EVENT_CONSTRUCTOR_FUNC_DATA(Event)
   NS_DEFINE_EVENT_CONSTRUCTOR_FUNC_DATA(UIEvent)
   NS_DEFINE_EVENT_CONSTRUCTOR_FUNC_DATA(MouseEvent)
   NS_DEFINE_EVENT_CONSTRUCTOR_FUNC_DATA(WheelEvent)
 #ifdef MOZ_B2G_RIL
   NS_DEFINE_EVENT_CONSTRUCTOR_FUNC_DATA(MozWifiStatusChangeEvent)
   NS_DEFINE_EVENT_CONSTRUCTOR_FUNC_DATA(MozWifiConnectionInfoEvent)
 #endif
 #define MOZ_GENERATED_EVENT_LIST
 #define MOZ_GENERATED_EVENT(_event_interface) \
   NS_DEFINE_EVENT_CONSTRUCTOR_FUNC_DATA(_event_interface)
 #include "GeneratedEvents.h"
 #undef MOZ_GENERATED_EVENT_LIST
   NS_DEFINE_CONSTRUCTOR_FUNC_DATA(MozSmsFilter, sms::SmsFilter::NewSmsFilter)
   NS_DEFINE_CONSTRUCTOR_FUNC_DATA(FileReader, FileReaderCtor)
   NS_DEFINE_CONSTRUCTOR_FUNC_DATA(ArchiveReader, ArchiveReaderCtor)
-  NS_DEFINE_CONSTRUCTOR_FUNC_DATA(FormData, FormDataCtor)
   NS_DEFINE_CONSTRUCTOR_FUNC_DATA(XPathEvaluator, XPathEvaluatorCtor)
   NS_DEFINE_CONSTRUCTOR_FUNC_DATA(XSLTProcessor, XSLTProcessorCtor)
   NS_DEFINE_CONSTRUCTOR_FUNC_DATA(EventSource, EventSourceCtor)
   NS_DEFINE_CONSTRUCTOR_FUNC_DATA(MutationObserver, MutationObserverCtor)
 #ifdef MOZ_SYS_MSG
   NS_DEFINE_CONSTRUCTOR_FUNC_DATA(MozActivity, MozActivityCtor)
 #endif
 };
@@ -4196,20 +4190,16 @@ nsDOMClassInfo::Init()
 
   DOM_CLASSINFO_MAP_BEGIN_NO_CLASS_IF(ChromeMessageSender, nsISupports)
     DOM_CLASSINFO_MAP_ENTRY(nsIPermissionChecker)
     DOM_CLASSINFO_MAP_ENTRY(nsIFrameScriptLoader)
     DOM_CLASSINFO_MAP_ENTRY(nsIMessageListenerManager)
     DOM_CLASSINFO_MAP_ENTRY(nsIMessageSender)
   DOM_CLASSINFO_MAP_END
 
-  DOM_CLASSINFO_MAP_BEGIN(FormData, nsIDOMFormData)
-    DOM_CLASSINFO_MAP_ENTRY(nsIDOMFormData)
-  DOM_CLASSINFO_MAP_END
-
   DOM_CLASSINFO_MAP_BEGIN(DesktopNotification, nsIDOMDesktopNotification)
     DOM_CLASSINFO_MAP_ENTRY(nsIDOMDesktopNotification)
   DOM_CLASSINFO_MAP_END
 
   DOM_CLASSINFO_MAP_BEGIN(DesktopNotificationCenter, nsIDOMDesktopNotificationCenter)
     DOM_CLASSINFO_MAP_ENTRY(nsIDOMDesktopNotificationCenter)
   DOM_CLASSINFO_MAP_END
 
--- a/dom/base/nsDOMClassInfoClasses.h
+++ b/dom/base/nsDOMClassInfoClasses.h
@@ -443,18 +443,16 @@ DOMCI_CLASS(EventListenerInfo)
 
 DOMCI_CLASS(TransitionEvent)
 DOMCI_CLASS(AnimationEvent)
 
 DOMCI_CLASS(ContentFrameMessageManager)
 DOMCI_CLASS(ChromeMessageBroadcaster)
 DOMCI_CLASS(ChromeMessageSender)
 
-DOMCI_CLASS(FormData)
-
 DOMCI_CLASS(DesktopNotification)
 DOMCI_CLASS(DesktopNotificationCenter)
 
 DOMCI_CLASS(IDBFactory)
 DOMCI_CLASS(IDBFileHandle)
 DOMCI_CLASS(IDBRequest)
 DOMCI_CLASS(IDBDatabase)
 DOMCI_CLASS(IDBObjectStore)
--- a/dom/base/nsDOMWindowUtils.cpp
+++ b/dom/base/nsDOMWindowUtils.cpp
@@ -2541,16 +2541,23 @@ nsDOMWindowUtils::PreventFurtherDialogs(
 
   nsCOMPtr<nsPIDOMWindow> window = do_QueryReferent(mWindow);
   NS_ENSURE_TRUE(window, NS_ERROR_FAILURE);
 
   static_cast<nsGlobalWindow*>(window.get())->PreventFurtherDialogs(true);
   return NS_OK;
 }
 
+static nsIDOMBlob*
+GetXPConnectNative(JSContext* aCx, JSObject* aObj) {
+  nsCOMPtr<nsIDOMBlob> blob = do_QueryInterface(
+    nsContentUtils::XPConnect()->GetNativeOfWrapper(aCx, aObj));
+  return blob;
+}
+
 static nsresult
 GetFileOrBlob(const nsAString& aName, const jsval& aBlobParts,
               const jsval& aParameters, JSContext* aCx,
               uint8_t aOptionalArgCount, nsISupports** aResult)
 {
   if (!nsContentUtils::IsCallerChrome()) {
     return NS_ERROR_DOM_SECURITY_ERR;
   }
@@ -2562,22 +2569,22 @@ GetFileOrBlob(const nsAString& aName, co
   if (aName.IsVoid()) {
     rv = nsDOMMultipartFile::NewBlob(getter_AddRefs(file));
   }
   else {
     rv = nsDOMMultipartFile::NewFile(aName, getter_AddRefs(file));
   }
   NS_ENSURE_SUCCESS(rv, rv);
 
-  nsCOMPtr<nsIJSNativeInitializer> initializer = do_QueryInterface(file);
-  NS_ASSERTION(initializer, "what?");
+  nsDOMMultipartFile* domFile =
+    static_cast<nsDOMMultipartFile*>(static_cast<nsIDOMFile*>(file.get()));
 
   jsval args[2] = { aBlobParts, aParameters };
 
-  rv = initializer->Initialize(nullptr, aCx, nullptr, aOptionalArgCount, args);
+  rv = domFile->InitBlob(aCx, aOptionalArgCount, args, GetXPConnectNative);
   NS_ENSURE_SUCCESS(rv, rv);
 
   file.forget(aResult);
   return NS_OK;
 }
 
 NS_IMETHODIMP
 nsDOMWindowUtils::GetFile(const nsAString& aName, const jsval& aBlobParts,
--- a/dom/bindings/Bindings.conf
+++ b/dom/bindings/Bindings.conf
@@ -241,17 +241,22 @@ DOMInterfaces = {
 },
 
 'FileReaderSync': {
     'workers': True,
 },
 
 'FormData': [
 {
+    'nativeType': 'nsFormData'
+},
+{
     'workers': True,
+    'skipGen': True,
+    'nativeType': 'JSObject'
 }],
 
 'GainNode': [
 {
     'resultNotAddRefed': [ 'gain' ],
 }],
 
 'HTMLCollection': {
@@ -738,16 +743,17 @@ def addExternalIface(iface, nativeType=N
 # If you add one of these, you need to make sure nsDOMQS.h has the relevant
 # macros added for it
 def addExternalHTMLElement(element):
    nativeElement = 'ns' + element
    addExternalIface(element, nativeType=nativeElement,
                     headerFile=nativeElement + '.h')
 
 addExternalHTMLElement('HTMLCanvasElement')
+addExternalHTMLElement('HTMLFormElement')
 addExternalHTMLElement('HTMLImageElement')
 addExternalHTMLElement('HTMLMenuElement')
 addExternalHTMLElement('HTMLOptionElement')
 addExternalHTMLElement('HTMLOptGroupElement')
 addExternalHTMLElement('HTMLVideoElement')
 addExternalIface('Attr')
 addExternalIface('CanvasGradient', headerFile='nsIDOMCanvasRenderingContext2D.h')
 addExternalIface('CanvasPattern', headerFile='nsIDOMCanvasRenderingContext2D.h')
--- a/dom/bindings/Codegen.py
+++ b/dom/bindings/Codegen.py
@@ -2191,16 +2191,17 @@ def getJSToNativeConversionTemplate(type
             arrayRef = "${declName}.Value()"
         else:
             arrayRef = "${declName}"
         # If we're optional, the const will come from the Optional
         mutableTypeName = typeName
         if not isOptional:
             typeName = CGWrapper(typeName, pre="const ")
 
+        # NOTE: Keep this in sync with variadic conversions as needed
         templateBody = ("""JSObject* seq = &${val}.toObject();\n
 if (!IsArrayLike(cx, seq)) {
 %s
 }
 uint32_t length;
 // JS_GetArrayLength actually works on all objects
 if (!JS_GetArrayLength(cx, seq, &length)) {
 %s
@@ -3037,19 +3038,16 @@ class CGArgumentConverter(CGThing):
     A class that takes an IDL argument object, its index in the
     argument list, and the argv and argc strings and generates code to
     unwrap the argument to the right native type.
     """
     def __init__(self, argument, index, argv, argc, descriptorProvider,
                  invalidEnumValueFatal=True, lenientFloatCode=None):
         CGThing.__init__(self)
         self.argument = argument
-        if argument.variadic:
-            raise TypeError("We don't support variadic arguments yet " +
-                            str(argument.location))
         assert(not argument.defaultValue or argument.optional)
 
         replacer = {
             "index" : index,
             "argc" : argc,
             "argv" : argv
             }
         self.replacementVariables = {
@@ -3069,29 +3067,80 @@ class CGArgumentConverter(CGThing):
         if self.argument.optional and not self.argument.defaultValue:
             self.argcAndIndex = replacer
         else:
             self.argcAndIndex = None
         self.invalidEnumValueFatal = invalidEnumValueFatal
         self.lenientFloatCode = lenientFloatCode
 
     def define(self):
-        return instantiateJSToNativeConversionTemplate(
-            getJSToNativeConversionTemplate(self.argument.type,
-                                            self.descriptorProvider,
-                                            isOptional=(self.argcAndIndex is not None),
-                                            invalidEnumValueFatal=self.invalidEnumValueFatal,
-                                            defaultValue=self.argument.defaultValue,
-                                            treatNullAs=self.argument.treatNullAs,
-                                            treatUndefinedAs=self.argument.treatUndefinedAs,
-                                            isEnforceRange=self.argument.enforceRange,
-                                            isClamp=self.argument.clamp,
-                                            lenientFloatCode=self.lenientFloatCode),
-            self.replacementVariables,
-            self.argcAndIndex).define()
+        typeConversion = getJSToNativeConversionTemplate(
+            self.argument.type,
+            self.descriptorProvider,
+            isOptional=(self.argcAndIndex is not None and
+                        not self.argument.variadic),
+            invalidEnumValueFatal=self.invalidEnumValueFatal,
+            defaultValue=self.argument.defaultValue,
+            treatNullAs=self.argument.treatNullAs,
+            treatUndefinedAs=self.argument.treatUndefinedAs,
+            isEnforceRange=self.argument.enforceRange,
+            isClamp=self.argument.clamp,
+            lenientFloatCode=self.lenientFloatCode,
+            isMember=self.argument.variadic)
+
+        if not self.argument.variadic:
+            return instantiateJSToNativeConversionTemplate(
+                typeConversion,
+                self.replacementVariables,
+                self.argcAndIndex).define()
+
+        # Variadic arguments get turned into a sequence.
+        (elementTemplate, elementDeclType,
+         elementHolderType, dealWithOptional) = typeConversion
+        if dealWithOptional:
+            raise TypeError("Shouldn't have optional things in variadics")
+        if elementHolderType is not None:
+            raise TypeError("Shouldn't need holders for variadics")
+
+        replacer = dict(self.argcAndIndex, **self.replacementVariables)
+        replacer["seqType"] = CGWrapper(elementDeclType, pre="Sequence< ", post=" >").define()
+        replacer["elemType"] = elementDeclType.define()
+
+        # NOTE: Keep this in sync with sequence conversions as needed
+        variadicConversion = string.Template("""const ${seqType} ${declName};
+if (${argc} > ${index}) {
+  ${seqType}& arr = const_cast< ${seqType}& >(${declName});
+  if (!arr.SetCapacity(${argc} - ${index})) {
+    JS_ReportOutOfMemory(cx);
+    return false;
+  }
+  for (uint32_t variadicArg = ${index}; variadicArg < ${argc}; ++variadicArg) {
+    ${elemType}& slot = *arr.AppendElement();
+""").substitute(replacer)
+
+        val = string.Template("${argv}[variadicArg]").substitute(replacer)
+        variadicConversion += CGIndenter(CGGeneric(
+                string.Template(elementTemplate).substitute(
+                    {
+                        "val" : val,
+                        "valPtr": "&" + val,
+                        "declName" : "slot",
+                        # We only need holderName here to handle isExternal()
+                        # interfaces, which use an internal holder for the
+                        # conversion even when forceOwningType ends up true.
+                        "holderName": "tempHolder",
+                        # Use the same ${obj} as for the variadic arg itself
+                        "obj": replacer["obj"]
+                        }
+                    )), 4).define()
+
+        variadicConversion += ("\n"
+                               "  }\n"
+                               "}")
+        return variadicConversion
 
 def getWrapTemplateForType(type, descriptorProvider, result, successCode,
                            isCreator, exceptionCode):
     """
     Reflect a C++ value stored in "result", of IDL type "type" into JS.  The
     "successCode" is the code to run once we have successfully done the
     conversion.  The resulting string should be used with string.Template, it
     needs the following keys when substituting: jsvalPtr/jsvalRef/obj.
@@ -3772,26 +3821,54 @@ class CGMethodCall(CGThing):
                         CGCase(str(argCount), None, True))
                 else:
                     argCountCases.append(
                         CGCase(str(argCount), getPerSignatureCall(signature)))
                 continue
 
             distinguishingIndex = method.distinguishingIndexForArgCount(argCount)
 
-            for (_, args) in possibleSignatures:
+            def distinguishingArgument(signature):
+                args = signature[1]
+                if distinguishingIndex < len(args):
+                    return args[distinguishingIndex]
+                assert args[-1].variadic
+                return args[-1]
+
+            def distinguishingType(signature):
+                return distinguishingArgument(signature).type
+
+            for sig in possibleSignatures:
                 # We should not have "any" args at distinguishingIndex,
                 # since we have multiple possible signatures remaining,
                 # but "any" is never distinguishable from anything else.
-                assert not args[distinguishingIndex].type.isAny()
+                assert not distinguishingType(sig).isAny()
                 # We can't handle unions at the distinguishing index.
-                if args[distinguishingIndex].type.isUnion():
+                if distinguishingType(sig).isUnion():
                     raise TypeError("No support for unions as distinguishing "
                                     "arguments yet: %s",
-                                    args[distinguishingIndex].location)
+                                    distinguishingArgument(sig).location)
+                # We don't support variadics as the distinguishingArgument yet.
+                # If you want to add support, consider this case:
+                #
+                #   void(long... foo);
+                #   void(long bar, Int32Array baz);
+                #
+                # in which we have to convert argument 0 to long before picking
+                # an overload... but all the variadic stuff needs to go into a
+                # single array in case we pick that overload, so we have to have
+                # machinery for converting argument 0 to long and then either
+                # placing it in the variadic bit or not.  Or something.  We may
+                # be able to loosen this restriction if the variadic arg is in
+                # fact at distinguishingIndex, perhaps.  Would need to
+                # double-check.
+                if distinguishingArgument(sig).variadic:
+                    raise TypeError("No support for variadics as distinguishing "
+                                    "arguments yet: %s",
+                                    distinguishingArgument(sig).location)
 
             # Convert all our arguments up to the distinguishing index.
             # Doesn't matter which of the possible signatures we use, since
             # they all have the same types up to that point; just use
             # possibleSignatures[0]
             caseBody = [CGGeneric("JS::Value* argv_start = JS_ARGV(cx, vp);")]
             caseBody.extend([ CGArgumentConverter(possibleSignatures[0][1][i],
                                                   i, "argv_start", "argc",
@@ -3811,19 +3888,16 @@ class CGMethodCall(CGThing):
                     else:
                         caseBody.append(CGGeneric("if (" + condition + ") {"))
                         caseBody.append(CGIndenter(
                                 getPerSignatureCall(sigs[0], distinguishingIndex)))
                         caseBody.append(CGGeneric("}"))
                     return True
                 return False
 
-            def distinguishingType(signature):
-                return signature[1][distinguishingIndex].type
-
             def tryCall(signature, indent, isDefinitelyObject=False,
                         isNullOrUndefined=False):
                 assert not isDefinitelyObject or not isNullOrUndefined
                 assert isDefinitelyObject or isNullOrUndefined
                 if isDefinitelyObject:
                     failureCode = "break;"
                 else:
                     failureCode = None
@@ -6813,28 +6887,29 @@ class CGBindingRoot(CGThing):
     def declare(self):
         return stripTrailingWhitespace(self.root.declare())
     def define(self):
         return stripTrailingWhitespace(self.root.define())
 
 class CGNativeMember(ClassMethod):
     def __init__(self, descriptor, member, name, signature, extendedAttrs,
                  breakAfter=True, passCxAsNeeded=True, visibility="public",
-                 jsObjectsArePtr=False):
+                 jsObjectsArePtr=False, variadicIsSequence=False):
         """
         If jsObjectsArePtr is true, typed arrays and "object" will be
         passed as JSObject*
         """
         self.descriptor = descriptor
         self.member = member
         self.extendedAttrs = extendedAttrs
         self.resultAlreadyAddRefed = isResultAlreadyAddRefed(self.descriptor,
                                                              self.extendedAttrs)
         self.passCxAsNeeded = passCxAsNeeded
         self.jsObjectsArePtr = jsObjectsArePtr
+        self.variadicIsSequence = variadicIsSequence
         breakAfterSelf = "\n" if breakAfter else ""
         ClassMethod.__init__(self, name,
                              self.getReturnType(signature[0], False),
                              self.getArgs(signature[0], signature[1]),
                              static=member.isStatic(),
                              # Mark our getters, which are attrs that
                              # have a non-void return type, as const.
                              const=(not member.isStatic() and member.isAttr() and
@@ -7105,17 +7180,18 @@ class CGNativeMember(ClassMethod):
         """
         (decl, ref, handleNullable) = self.doGetArgType(type, optional,
                                                         isMember or variadic)
         decl = CGGeneric(decl)
         if handleNullable and type.nullable():
             decl = CGWrapper(decl, pre="Nullable< ", post=" >")
             ref = True
         if variadic:
-            decl = CGWrapper(decl, pre="nsTArray< ", post=" >")
+            arrayType = "Sequence" if self.variadicIsSequence else "nsTArray"
+            decl = CGWrapper(decl, pre="%s< " % arrayType, post=" >")
             ref = True
         elif optional:
             # Note: All variadic args claim to be optional, but we can just use
             # empty arrays to represent them not being present.
             decl = CGWrapper(decl, pre="Optional< ", post=" >")
             ref = True
         return (decl, ref)
 
@@ -7135,17 +7211,18 @@ class CGNativeMember(ClassMethod):
 
 class CGExampleMethod(CGNativeMember):
     def __init__(self, descriptor, method, signature, breakAfter=True):
         CGNativeMember.__init__(self, descriptor, method,
                                 CGSpecializedMethod.makeNativeName(descriptor,
                                                                    method),
                                 signature,
                                 descriptor.getExtendedAttributes(method),
-                                breakAfter)
+                                breakAfter=breakAfter,
+                                variadicIsSequence=True)
     def define(self, cgClass):
         return ''
 
 class CGExampleGetter(CGNativeMember):
     def __init__(self, descriptor, attr):
         CGNativeMember.__init__(self, descriptor, attr,
                                 CGSpecializedGetter.makeNativeName(descriptor,
                                                                    attr),
--- a/dom/bindings/parser/WebIDL.py
+++ b/dom/bindings/parser/WebIDL.py
@@ -2602,34 +2602,42 @@ class IDLMethod(IDLInterfaceMember, IDLS
                             (self.identifier.name, argCount, idx,
                              distinguishingIndex),
                             [self.location, overload.location])
 
     def overloadsForArgCount(self, argc):
         return [overload for overload in self._overloads if
                 len(overload.arguments) == argc or
                 (len(overload.arguments) > argc and
-                 overload.arguments[argc].optional)]
+                 overload.arguments[argc].optional) or
+                (len(overload.arguments) < argc and
+                 len(overload.arguments) > 0 and
+                 overload.arguments[-1].variadic)]
 
     def signaturesForArgCount(self, argc):
         return [(overload.returnType, overload.arguments) for overload
                 in self.overloadsForArgCount(argc)]
 
     def locationsForArgCount(self, argc):
-        return [overload.location for overload in self._overloads if
-                len(overload.arguments) == argc or
-                (len(overload.arguments) > argc and
-                 overload.arguments[argc].optional)]
+        return [overload.location for overload in self.overloadsForArgCount(argc)]
 
     def distinguishingIndexForArgCount(self, argc):
         def isValidDistinguishingIndex(idx, signatures):
             for (firstSigIndex, (firstRetval, firstArgs)) in enumerate(signatures[:-1]):
                 for (secondRetval, secondArgs) in signatures[firstSigIndex+1:]:
-                    firstType = firstArgs[idx].type
-                    secondType = secondArgs[idx].type
+                    if idx < len(firstArgs):
+                        firstType = firstArgs[idx].type
+                    else:
+                        assert(firstArgs[-1].variadic)
+                        firstType = firstArgs[-1].type
+                    if idx < len(secondArgs):
+                        secondType = secondArgs[idx].type
+                    else:
+                        assert(secondArgs[-1].variadic)
+                        secondType = secondArgs[-1].type
                     if not firstType.isDistinguishableFrom(secondType):
                         return False
             return True
         signatures = self.signaturesForArgCount(argc)
         for idx in range(argc):
             if isValidDistinguishingIndex(idx, signatures):
                 return idx
         # No valid distinguishing index.  Time to throw
--- a/dom/bindings/parser/tests/test_overload.py
+++ b/dom/bindings/parser/tests/test_overload.py
@@ -3,29 +3,32 @@ import WebIDL
 def WebIDLTest(parser, harness):
     parser.parse("""
         interface TestOverloads {
           void basic();
           void basic(long arg1);
           boolean abitharder(TestOverloads foo);
           boolean abitharder(boolean foo);
           void abitharder(ArrayBuffer? foo);
+          void withVariadics(long... numbers);
+          void withVariadics(TestOverloads iface);
+          void withVariadics(long num, TestOverloads iface);
         };
     """)
 
     results = parser.finish()
 
     harness.ok(True, "TestOverloads interface parsed without error.")
     harness.check(len(results), 1, "Should be one production.")
     iface = results[0]
     harness.ok(isinstance(iface, WebIDL.IDLInterface),
                "Should be an IDLInterface")
     harness.check(iface.identifier.QName(), "::TestOverloads", "Interface has the right QName")
     harness.check(iface.identifier.name, "TestOverloads", "Interface has the right name")
-    harness.check(len(iface.members), 2, "Expect %s members" % 2)
+    harness.check(len(iface.members), 3, "Expect %s members" % 3)
 
     member = iface.members[0]
     harness.check(member.identifier.QName(), "::TestOverloads::basic", "Method has the right QName")
     harness.check(member.identifier.name, "basic", "Method has the right name")
     harness.check(member.hasOverloads(), True, "Method has overloads")
 
     signatures = member.signatures()
     harness.check(len(signatures), 2, "Method should have 2 signatures")
--- a/dom/bindings/parser/tests/test_variadic_constraints.py
+++ b/dom/bindings/parser/tests/test_variadic_constraints.py
@@ -32,8 +32,21 @@ def WebIDLTest(parser, harness):
               void foo(optional byte... arg1);
             };
         """)
 
     except:
         threw = True
 
     harness.ok(threw, "Should have thrown.")
+
+    threw = False
+    try:
+        results = parser.parse("""
+            interface VariadicConstraints4 {
+              void foo(byte... arg1 = 0);
+            };
+        """)
+
+    except:
+        threw = True
+
+    harness.ok(threw, "Should have thrown on variadic argument with default value.")
--- a/dom/bindings/test/TestBindingHeader.h
+++ b/dom/bindings/test/TestBindingHeader.h
@@ -149,16 +149,17 @@ public:
   int8_t WritableByte();
   void SetWritableByte(int8_t);
   void PassByte(int8_t);
   int8_t ReceiveByte();
   void PassOptionalByte(const Optional<int8_t>&);
   void PassOptionalByteWithDefault(int8_t);
   void PassNullableByte(const Nullable<int8_t>&);
   void PassOptionalNullableByte(const Optional< Nullable<int8_t> >&);
+  void PassVariadicByte(const Sequence<int8_t>&);
 
   int16_t ReadonlyShort();
   int16_t WritableShort();
   void SetWritableShort(int16_t);
   void PassShort(int16_t);
   int16_t ReceiveShort();
   void PassOptionalShort(const Optional<int16_t>&);
   void PassOptionalShortWithDefault(int16_t);
@@ -376,16 +377,17 @@ public:
 
   // String types
   void PassString(const nsAString&);
   void PassNullableString(const nsAString&);
   void PassOptionalString(const Optional<nsAString>&);
   void PassOptionalStringWithDefaultValue(const nsAString&);
   void PassOptionalNullableString(const Optional<nsAString>&);
   void PassOptionalNullableStringWithDefaultValue(const nsAString&);
+  void PassVariadicString(const Sequence<nsString>&);
 
   // Enumerated types
   void PassEnum(TestEnum);
   void PassOptionalEnum(const Optional<TestEnum>&);
   void PassEnumWithDefault(TestEnum);
   TestEnum ReceiveEnum();
   TestEnum EnumAttribute();
   TestEnum ReadonlyEnumAttribute();
@@ -468,16 +470,24 @@ public:
   already_AddRefed<TestInterface> ExerciseTypedefInterfaces2(TestInterface*);
   void ExerciseTypedefInterfaces3(TestInterface&);
 
   // Static methods and attributes
   static void StaticMethod(nsISupports*, bool);
   static bool StaticAttribute(nsISupports*);
   static void SetStaticAttribute(nsISupports*, bool);
 
+  // Overload resolution tests
+  bool Overload1(TestInterface&);
+  TestInterface* Overload1(const nsAString&, TestInterface&);
+
+  // Variadic handling
+  void PassVariadicThirdArg(const nsAString&, int32_t,
+                            const Sequence<OwningNonNull<TestInterface> >&);
+
   // Miscellania
   int32_t AttrWithLenientThis();
   void SetAttrWithLenientThis(int32_t);
   uint32_t UnforgeableAttr();
   uint32_t UnforgeableAttr2();
   void Stringify(nsString&);
   void PassRenamedInterface(nsRenamedInterface&);
   TestInterface* PutForwardsAttr();
@@ -517,16 +527,17 @@ private:
   void SetWritableByte(T) MOZ_DELETE;
   template<typename T>
   void PassByte(T) MOZ_DELETE;
   void PassNullableByte(Nullable<int8_t>&) MOZ_DELETE;
   template<typename T>
   void PassOptionalByte(const Optional<T>&) MOZ_DELETE;
   template<typename T>
   void PassOptionalByteWithDefault(T) MOZ_DELETE;
+  void PassVariadicByte(Sequence<int8_t>&) MOZ_DELETE;
 
   void SetReadonlyShort(int16_t) MOZ_DELETE;
   template<typename T>
   void SetWritableShort(T) MOZ_DELETE;
   template<typename T>
   void PassShort(T) MOZ_DELETE;
   template<typename T>
   void PassOptionalShort(const Optional<T>&) MOZ_DELETE;
@@ -626,17 +637,17 @@ private:
 
   // And test that string stuff is always const
   void PassString(nsAString&) MOZ_DELETE;
   void PassNullableString(nsAString&) MOZ_DELETE;
   void PassOptionalString(Optional<nsAString>&) MOZ_DELETE;
   void PassOptionalStringWithDefaultValue(nsAString&) MOZ_DELETE;
   void PassOptionalNullableString(Optional<nsAString>&) MOZ_DELETE;
   void PassOptionalNullableStringWithDefaultValue(nsAString&) MOZ_DELETE;
-
+  void PassVariadicString(Sequence<nsString>&) MOZ_DELETE;
 };
 
 class TestIndexedGetterInterface : public nsISupports,
                                    public nsWrapperCache
 {
 public:
   NS_DECL_ISUPPORTS
 
--- a/dom/bindings/test/TestCodeGen.webidl
+++ b/dom/bindings/test/TestCodeGen.webidl
@@ -95,16 +95,17 @@ interface TestInterface {
   readonly attribute byte readonlyByte;
   attribute byte writableByte;
   void passByte(byte arg);
   byte receiveByte();
   void passOptionalByte(optional byte arg);
   void passOptionalByteWithDefault(optional byte arg = 0);
   void passNullableByte(byte? arg);
   void passOptionalNullableByte(optional byte? arg);
+  void passVariadicByte(byte... arg);
 
   readonly attribute short readonlyShort;
   attribute short writableShort;
   void passShort(short arg);
   short receiveShort();
   void passOptionalShort(optional short arg);
   void passOptionalShortWithDefault(optional short arg = 5);
 
@@ -328,16 +329,17 @@ interface TestInterface {
 
   // String types
   void passString(DOMString arg);
   void passNullableString(DOMString? arg);
   void passOptionalString(optional DOMString arg);
   void passOptionalStringWithDefaultValue(optional DOMString arg = "abc");
   void passOptionalNullableString(optional DOMString? arg);
   void passOptionalNullableStringWithDefaultValue(optional DOMString? arg = null);
+  void passVariadicString(DOMString... arg);
 
   // Enumerated types
   void passEnum(TestEnum arg);
   // No support for nullable enums yet
   // void passNullableEnum(TestEnum? arg);
   void passOptionalEnum(optional TestEnum arg);
   void passEnumWithDefault(optional TestEnum arg = "a");
   // void passOptionalNullableEnum(optional TestEnum? arg);
@@ -419,16 +421,24 @@ interface TestInterface {
   void exerciseTypedefInterfaces1(AnotherNameForTestInterface arg);
   AnotherNameForTestInterface exerciseTypedefInterfaces2(NullableTestInterface arg);
   void exerciseTypedefInterfaces3(YetAnotherNameForTestInterface arg);
 
   // Static methods and attributes
   static attribute boolean staticAttribute;
   static void staticMethod(boolean arg);
 
+  // Overload resolution tests
+  //void overload1(DOMString... strs);
+  boolean overload1(TestInterface arg);
+  TestInterface overload1(DOMString strs, TestInterface arg);
+
+  // Variadic handling
+  void passVariadicThirdArg(DOMString arg1, long arg2, TestInterface... arg3);
+
   // Miscellania
   [LenientThis] attribute long attrWithLenientThis;
   [Unforgeable] readonly attribute long unforgeableAttr;
   [Unforgeable, ChromeOnly] readonly attribute long unforgeableAttr2;
   stringifier;
   void passRenamedInterface(TestRenamedInterface arg);
   [PutForwards=writableByte] readonly attribute TestInterface putForwardsAttr;
   [PutForwards=writableByte, LenientThis] readonly attribute TestInterface putForwardsAttr2;
--- a/dom/bindings/test/TestExampleGen.webidl
+++ b/dom/bindings/test/TestExampleGen.webidl
@@ -16,16 +16,17 @@ interface TestExampleInterface {
   readonly attribute byte readonlyByte;
   attribute byte writableByte;
   void passByte(byte arg);
   byte receiveByte();
   void passOptionalByte(optional byte arg);
   void passOptionalByteWithDefault(optional byte arg = 0);
   void passNullableByte(byte? arg);
   void passOptionalNullableByte(optional byte? arg);
+  void passVariadicByte(byte... arg);
 
   readonly attribute short readonlyShort;
   attribute short writableShort;
   void passShort(short arg);
   short receiveShort();
   void passOptionalShort(optional short arg);
   void passOptionalShortWithDefault(optional short arg = 5);
 
@@ -249,16 +250,17 @@ interface TestExampleInterface {
 
   // String types
   void passString(DOMString arg);
   void passNullableString(DOMString? arg);
   void passOptionalString(optional DOMString arg);
   void passOptionalStringWithDefaultValue(optional DOMString arg = "abc");
   void passOptionalNullableString(optional DOMString? arg);
   void passOptionalNullableStringWithDefaultValue(optional DOMString? arg = null);
+  void passVariadicString(DOMString... arg);
 
   // Enumerated types
   void passEnum(TestEnum arg);
   // No support for nullable enums yet
   // void passNullableEnum(TestEnum? arg);
   void passOptionalEnum(optional TestEnum arg);
   void passEnumWithDefault(optional TestEnum arg = "a");
   // void passOptionalNullableEnum(optional TestEnum? arg);
@@ -340,16 +342,24 @@ interface TestExampleInterface {
   void exerciseTypedefInterfaces1(AnotherNameForTestInterface arg);
   AnotherNameForTestInterface exerciseTypedefInterfaces2(NullableTestInterface arg);
   void exerciseTypedefInterfaces3(YetAnotherNameForTestInterface arg);
 
   // Static methods and attributes
   static attribute boolean staticAttribute;
   static void staticMethod(boolean arg);
 
+  // Overload resolution tests
+  //void overload1(DOMString... strs);
+  boolean overload1(TestInterface arg);
+  TestInterface overload1(DOMString strs, TestInterface arg);
+
+  // Variadic handling
+  void passVariadicThirdArg(DOMString arg1, long arg2, TestInterface... arg3);
+
   // Miscellania
   [LenientThis] attribute long attrWithLenientThis;
   [Unforgeable] readonly attribute long unforgeableAttr;
   [Unforgeable, ChromeOnly] readonly attribute long unforgeableAttr2;
   stringifier;
   void passRenamedInterface(TestRenamedInterface arg);
   [PutForwards=writableByte] readonly attribute TestExampleInterface putForwardsAttr;
   [PutForwards=writableByte, LenientThis] readonly attribute TestExampleInterface putForwardsAttr2;
--- a/dom/bluetooth/linux/BluetoothDBusService.cpp
+++ b/dom/bluetooth/linux/BluetoothDBusService.cpp
@@ -146,16 +146,17 @@ static const char* sBluetoothDBusSignals
 /**
  * DBus Connection held for the BluetoothCommandThread to use. Should never be
  * used by any other thread.
  *
  */
 static nsAutoPtr<RawDBusConnection> gThreadConnection;
 static nsDataHashtable<nsStringHashKey, DBusMessage* > sPairingReqTable;
 static nsDataHashtable<nsStringHashKey, DBusMessage* > sAuthorizeReqTable;
+static bool sIsPairing = false;
 typedef void (*UnpackFunc)(DBusMessage*, DBusError*, BluetoothValue&, nsAString&);
 
 class DistributeBluetoothSignalTask : public nsRunnable {
   BluetoothSignal mSignal;
 public:
   DistributeBluetoothSignalTask(const BluetoothSignal& aSignal) :
     mSignal(aSignal)
   {
@@ -814,18 +815,22 @@ RunDBusCallback(DBusMessage* aMsg, void*
   BluetoothValue v;
   aFunc(aMsg, nullptr, v, replyError);
   DispatchBluetoothReply(replyRunnable, v, replyError);
 }
 
 void
 GetObjectPathCallback(DBusMessage* aMsg, void* aBluetoothReplyRunnable)
 {
-  RunDBusCallback(aMsg, aBluetoothReplyRunnable,
-                  UnpackObjectPathMessage);
+  if (sIsPairing) {
+    RunDBusCallback(aMsg, aBluetoothReplyRunnable,
+                    UnpackObjectPathMessage);
+
+    sIsPairing = false;
+  }
 }
 
 void
 UnpackVoidMessage(DBusMessage* aMsg, DBusError* aErr, BluetoothValue& aValue,
                   nsAString& aErrorStr)
 {
   DBusError err;
   dbus_error_init(&err);
@@ -1561,16 +1566,18 @@ BluetoothDBusService::StopInternal()
 
   // unref stored DBusMessages before clear the hashtable
   sPairingReqTable.EnumerateRead(UnrefDBusMessages, nullptr);
   sPairingReqTable.Clear();
 
   sAuthorizeReqTable.EnumerateRead(UnrefDBusMessages, nullptr);
   sAuthorizeReqTable.Clear();
 
+  sIsPairing = false;
+
   StopDBus();
   return NS_OK;
 }
 
 class DefaultAdapterPropertiesRunnable : public nsRunnable
 {
 public:
   DefaultAdapterPropertiesRunnable(BluetoothReplyRunnable* aRunnable)
@@ -2082,16 +2089,31 @@ BluetoothDBusService::CreatePairedDevice
                                   DBUS_TYPE_STRING, &capabilities,
                                   DBUS_TYPE_INVALID);
 
   if (!ret) {
     NS_WARNING("Could not start async function!");
     return NS_ERROR_FAILURE;
   }
 
+
+  /**
+   * FIXME: Bug 820274
+   *
+   * If the user turns off Bluetooth in the middle of pairing process, the
+   * callback function GetObjectPathCallback (see the third argument of the
+   * function call above) may still be called while enabling next time by
+   * dbus daemon. To prevent this from happening, added a flag to distinguish
+   * if Bluetooth has been turned off. Nevertheless, we need a check if there
+   * is a better solution.
+   *
+   * Please see Bug 818696 for more information.
+   */
+  sIsPairing = true;
+
   runnable.forget();
   return NS_OK;
 }
 
 nsresult
 BluetoothDBusService::RemoveDeviceInternal(const nsAString& aAdapterPath,
                                            const nsAString& aDeviceAddress,
                                            BluetoothReplyRunnable* aRunnable)
--- a/dom/camera/GonkCameraControl.cpp
+++ b/dom/camera/GonkCameraControl.cpp
@@ -24,16 +24,17 @@
 #include "camera/CameraParameters.h"
 #include "nsCOMPtr.h"
 #include "nsDOMClassInfo.h"
 #include "nsMemory.h"
 #include "jsapi.h"
 #include "nsThread.h"
 #include <media/MediaProfiles.h>
 #include "mozilla/FileUtils.h"
+#include "mozilla/Services.h"
 #include "nsAlgorithm.h"
 #include <media/mediaplayer.h>
 #include "nsPrintfCString.h"
 #include "nsIObserverService.h"
 #include "DOMCameraManager.h"
 #include "GonkCameraHwMgr.h"
 #include "DOMCameraCapabilities.h"
 #include "DOMCameraControl.h"
--- a/dom/imptests/failures/webapps/XMLHttpRequest/tests/submissions/Ms2ger/test_interfaces.html.json
+++ b/dom/imptests/failures/webapps/XMLHttpRequest/tests/submissions/Ms2ger/test_interfaces.html.json
@@ -1,15 +1,6 @@
 {
   "XMLHttpRequest interface constructor": true,
   "XMLHttpRequest interface: operation open(DOMString,DOMString,boolean,DOMString,DOMString)": true,
   "XMLHttpRequest interface: operation send(union)": true,
-  "FormData interface: existence and properties of interface object": true,
-  "FormData interface constructor": true,
-  "FormData interface: existence and properties of interface prototype object": true,
-  "FormData interface: existence and properties of interface prototype object's \"constructor\" property": true,
-  "Stringification of new FormData()": "debug",
-  "FormData interface: calling append(DOMString,Blob,DOMString) on new FormData() with too few arguments must throw TypeError": true,
-  "FormData interface: calling append(DOMString,DOMString) on new FormData() with too few arguments must throw TypeError": true,
-  "Stringification of new FormData(form)": "debug",
-  "FormData interface: calling append(DOMString,Blob,DOMString) on new FormData(form) with too few arguments must throw TypeError": true,
-  "FormData interface: calling append(DOMString,DOMString) on new FormData(form) with too few arguments must throw TypeError": true
+  "FormData interface constructor": true
 }
--- a/dom/locales/en-US/chrome/accessibility/AccessFu.properties
+++ b/dom/locales/en-US/chrome/accessibility/AccessFu.properties
@@ -108,9 +108,27 @@ stateNotChecked  =    not checked
 stateExpanded    =    expanded
 stateCollapsed   =    collapsed
 stateUnavailable =    unavailable
 stateRequired    =    required
 stateTraversed   =    visited
 
 # App modes
 editingMode    =      editing
-navigationMode =      navigating
\ No newline at end of file
+navigationMode =      navigating
+
+# Quick navigation modes
+quicknav_Simple      = Default
+quicknav_Anchor      = Anchors
+quicknav_Button      = Buttons
+quicknav_Combobox    = Combo boxes
+quicknav_Entry       = Entries
+quicknav_FormElement = Form elements
+quicknav_Graphic     = Images
+quicknav_Heading     = Headings
+quicknav_ListItem    = List items
+quicknav_Link        = Links
+quicknav_List        = Lists
+quicknav_PageTab     = Page tabs
+quicknav_RadioButton = Radio buttons
+quicknav_Separator   = Separators
+quicknav_Table       = Tables
+quicknav_Checkbox    = Check boxes
\ No newline at end of file
--- a/dom/media/PeerConnection.js
+++ b/dom/media/PeerConnection.js
@@ -18,19 +18,21 @@ const PC_CID = Components.ID("{7cb2b368-
 const PC_ICE_CID = Components.ID("{8c5dbd70-2c8e-4ecb-a5ad-2fc919099f01}");
 const PC_SESSION_CID = Components.ID("{5f21ffd9-b73f-4ba0-a685-56b4667aaf1c}");
 const PC_MANAGER_CID = Components.ID("{7293e901-2be3-4c02-b4bd-cbef6fc24f78}");
 
 // Global list of PeerConnection objects, so they can be cleaned up when
 // a page is torn down. (Maps inner window ID to an array of PC objects).
 function GlobalPCList() {
   this._list = [];
+  this._networkdown = false; // XXX Need to query current state somehow
   Services.obs.addObserver(this, "inner-window-destroyed", true);
   Services.obs.addObserver(this, "profile-change-net-teardown", true);
   Services.obs.addObserver(this, "network:offline-about-to-go-offline", true);
+  Services.obs.addObserver(this, "network:offline-status-changed", true);
 }
 GlobalPCList.prototype = {
   QueryInterface: XPCOMUtils.generateQI([Ci.nsIObserver,
                                          Ci.nsISupportsWeakReference,
                                          Ci.IPeerConnectionManager]),
 
   classID: PC_MANAGER_CID,
   classInfo: XPCOMUtils.generateCI({classID: PC_MANAGER_CID,
@@ -84,16 +86,25 @@ GlobalPCList.prototype = {
       let array;
       while ((array = this._list.pop()) != undefined) {
         array.forEach(function(pc) {
           pc._pc.close(true);
           delete pc._observer;
           pc._pc = null;
         });
       };
+      this._networkdown = true;
+    }
+    else if (topic == "network:offline-status-changed") {
+      if (data == "offline") {
+	// this._list shold be empty here
+        this._networkdown = true;
+      } else if (data == "online") {
+        this._networkdown = false;
+      }
     }
   },
 };
 let _globalPCList = new GlobalPCList();
 
 function IceCandidate(candidate) {
   this.candidate = candidate;
   this.sdpMid = null;
@@ -223,16 +234,19 @@ PeerConnection.prototype = {
   // Constructor is an explicit function, because of nsIDOMGlobalObjectConstructor.
   constructor: function(win) {
     if (!Services.prefs.getBoolPref("media.peerconnection.enabled")) {
       throw new Error("PeerConnection not enabled (did you set the pref?)");
     }
     if (this._win) {
       throw new Error("Constructor already called");
     }
+    if (_globalPCList._networkdown) {
+      throw new Error("Can't create RTPPeerConnections when the network is down");
+    }
 
     this._pc = Cc["@mozilla.org/peerconnection;1"].
              createInstance(Ci.IPeerConnection);
     this._observer = new PeerConnectionObserver(this);
 
     // Nothing starts until ICE gathering completes.
     this._queueOrRun({
       func: this._pc.initialize,
--- a/dom/system/OSFileConstants.cpp
+++ b/dom/system/OSFileConstants.cpp
@@ -23,16 +23,18 @@
 
 #include "jsapi.h"
 #include "jsfriendapi.h"
 #include "BindingUtils.h"
 
 // Used to provide information on the OS
 
 #include "nsThreadUtils.h"
+#include "nsIObserverService.h"
+#include "nsIObserver.h"
 #include "nsDirectoryServiceUtils.h"
 #include "nsIXULRuntime.h"
 #include "nsXPCOMCIDInternal.h"
 #include "nsServiceManagerUtils.h"
 #include "nsString.h"
 #include "nsAutoPtr.h"
 #include "nsDirectoryServiceDefs.h"
 #include "nsAppDirectoryServiceDefs.h"
@@ -86,27 +88,68 @@ Paths* gPaths = NULL;
  * @param aOutPath The path to the special directory. In case of error,
  * the string is set to void.
  */
 nsresult GetPathToSpecialDir(const char *aKey, nsString& aOutPath)
 {
   nsCOMPtr<nsIFile> file;
   nsresult rv = NS_GetSpecialDirectory(aKey, getter_AddRefs(file));
   if (NS_FAILED(rv) || !file) {
+    aOutPath.SetIsVoid(true);
     return rv;
   }
 
   rv = file->GetPath(aOutPath);
   if (NS_FAILED(rv)) {
     aOutPath.SetIsVoid(true);
   }
   return rv;
 }
 
 /**
+ * In some cases, OSFileConstants may be instantiated before the
+ * profile is setup. In such cases, |OS.Constants.Path.profileDir| and
+ * |OS.Constants.Path.localProfileDir| are undefined. However, we want
+ * to ensure that this does not break existing code, so that future
+ * workers spawned after the profile is setup have these constants.
+ *
+ * For this purpose, we register an observer to set |gPaths->profileDir|
+ * and |gPaths->localProfileDir| once the profile is setup.
+ */
+class DelayedPathSetter MOZ_FINAL: public nsIObserver
+{
+  NS_DECL_ISUPPORTS
+  NS_DECL_NSIOBSERVER
+
+  DelayedPathSetter() {}
+};
+
+NS_IMPL_ISUPPORTS1(DelayedPathSetter, nsIObserver)
+
+NS_IMETHODIMP
+DelayedPathSetter::Observe(nsISupports*, const char * aTopic, const PRUnichar*)
+{
+  if (gPaths == nullptr) {
+    // Initialization of gPaths has not taken place, something is wrong,
+    // don't make things worse.
+    return NS_OK;
+  }
+  nsresult rv = GetPathToSpecialDir(NS_APP_USER_PROFILE_50_DIR, gPaths->profileDir);
+  if (NS_FAILED(rv)) {
+    return rv;
+  }
+  rv = GetPathToSpecialDir(NS_APP_USER_PROFILE_LOCAL_50_DIR, gPaths->localProfileDir);
+  if (NS_FAILED(rv)) {
+    return rv;
+  }
+
+  return NS_OK;
+}
+
+/**
  * Perform the part of initialization that can only be
  * executed on the main thread.
  */
 nsresult InitOSFileConstants()
 {
   MOZ_ASSERT(NS_IsMainThread());
   if (gInitialized) {
     return NS_OK;
@@ -129,22 +172,42 @@ nsresult InitOSFileConstants()
     return rv;
   }
 
   rv = libDir->GetPath(paths->libDir);
   if (NS_FAILED(rv)) {
     return rv;
   }
 
+  // Setup profileDir and localProfileDir immediately if possible (we
+  // assume that NS_APP_USER_PROFILE_50_DIR and
+  // NS_APP_USER_PROFILE_LOCAL_50_DIR are set simultaneously)
+  rv = GetPathToSpecialDir(NS_APP_USER_PROFILE_50_DIR, paths->profileDir);
+  if (NS_SUCCEEDED(rv)) {
+    rv = GetPathToSpecialDir(NS_APP_USER_PROFILE_LOCAL_50_DIR, paths->localProfileDir);
+  }
+
+  // Otherwise, delay setup of profileDir/localProfileDir until they
+  // become available.
+  if (NS_FAILED(rv)) {
+    nsCOMPtr<nsIObserverService> obsService = do_GetService(NS_OBSERVERSERVICE_CONTRACTID, &rv);
+    if (NS_FAILED(rv)) {
+      return rv;
+    }
+    nsRefPtr<DelayedPathSetter> pathSetter = new DelayedPathSetter();
+    rv = obsService->AddObserver(pathSetter, "profile-do-change", false);
+    if (NS_FAILED(rv)) {
+      return rv;
+    }
+  }
+
   // For other directories, ignore errors (they may be undefined on
   // some platforms or in non-Firefox embeddings of Gecko).
 
   GetPathToSpecialDir(NS_OS_TEMP_DIR, paths->tmpDir);
-  GetPathToSpecialDir(NS_APP_USER_PROFILE_50_DIR, paths->profileDir);
-  GetPathToSpecialDir(NS_APP_USER_PROFILE_LOCAL_50_DIR, paths->localProfileDir);
 
   gPaths = paths.forget();
   return NS_OK;
 }
 
 /**
  * Perform the cleaning up that can only be executed on the main thread.
  */
@@ -674,21 +737,25 @@ bool DefineOSFileConstants(JSContext *cx
   if (!SetStringProperty(cx, objPath, "libDir", gPaths->libDir)) {
     return false;
   }
 
   if (!SetStringProperty(cx, objPath, "tmpDir", gPaths->tmpDir)) {
     return false;
   }
 
-  if (!SetStringProperty(cx, objPath, "profileDir", gPaths->profileDir)) {
+  // Configure profileDir only if it is available at this stage
+  if (!gPaths->profileDir.IsVoid()
+    && !SetStringProperty(cx, objPath, "profileDir", gPaths->profileDir)) {
     return false;
   }
 
-  if (!SetStringProperty(cx, objPath, "localProfileDir", gPaths->localProfileDir)) {
+  // Configure localProfileDir only if it is available at this stage
+  if (!gPaths->localProfileDir.IsVoid()
+    && !SetStringProperty(cx, objPath, "localProfileDir", gPaths->localProfileDir)) {
     return false;
   }
 
   return true;
 }
 
 NS_IMPL_ISUPPORTS1(OSFileConstantsService, nsIOSFileConstantsService)
 
--- a/dom/system/gonk/SystemWorkerManager.cpp
+++ b/dom/system/gonk/SystemWorkerManager.cpp
@@ -26,16 +26,17 @@
 #include "jsfriendapi.h"
 #include "mozilla/dom/workers/Workers.h"
 #ifdef MOZ_WIDGET_GONK
 #include "mozilla/ipc/Netd.h"
 #include "AutoMounter.h"
 #include "TimeZoneSettingObserver.h"
 #endif
 #include "mozilla/ipc/Ril.h"
+#include "nsIObserverService.h"
 #include "nsContentUtils.h"
 #include "nsServiceManagerUtils.h"
 #include "nsThreadUtils.h"
 #include "nsRadioInterfaceLayer.h"
 #include "WifiWorker.h"
 
 USING_WORKERS_NAMESPACE
 
--- a/dom/system/gonk/ril_consts.js
+++ b/dom/system/gonk/ril_consts.js
@@ -417,16 +417,17 @@ this.ICC_EF_SPN    = 0x6f46;
 this.ICC_EF_SDN    = 0x6f49;
 this.ICC_EF_EXT1   = 0x6f4a;
 this.ICC_EF_EXT2   = 0x6f4b;
 this.ICC_EF_EXT3   = 0x6f4c;
 this.ICC_EF_CBMIR  = 0x6f50;
 this.ICC_EF_AD     = 0x6fad;
 this.ICC_EF_PHASE  = 0x6fae;
 this.ICC_EF_PNN    = 0x6fc5;
+this.ICC_EF_OPL    = 0x6fc6;
 this.ICC_EF_MBDN   = 0x6fc7;
 this.ICC_EF_EXT6   = 0x6fc8;   // Ext record for EF[MBDN]
 this.ICC_EF_MBI    = 0x6fc9;
 this.ICC_EF_MWIS   = 0x6fca;
 this.ICC_EF_CFIS   = 0x6fcb;
 this.ICC_EF_SPDI   = 0x6fcd;
 
 this.ICC_PHASE_1 = 0x00;
@@ -576,16 +577,21 @@ this.COMPREHENSIONTLV_TAG_BATTERY_STATE 
 this.COMPREHENSIONTLV_TAG_NETWORK_SEARCH_MODE = 0x65;
 this.COMPREHENSIONTLV_TAG_MEID = 0x6d;
 this.COMPREHENSIONTLV_TAG_BROADCAST_NETWORK_INFO = 0x7a;
 
 // Tags for Service Provider Display Information TLV
 this.SPDI_TAG_SPDI = 0xa3;
 this.SPDI_TAG_PLMN_LIST = 0x80;
 
+// MM INFORMATION message content IEIs
+// See 3GPP TS 24.008 table 9.2.18
+this.PNN_IEI_FULL_NETWORK_NAME = 0x43;
+this.PNN_IEI_SHORT_NETWORK_NAME = 0x45;
+
 // Device identifiers, see TS 11.14, clause 12.7
 this.STK_DEVICE_ID_KEYPAD = 0x01;
 this.STK_DEVICE_ID_DISPLAY = 0x02;
 this.STK_DEVICE_ID_EARPIECE = 0x03;
 this.STK_DEVICE_ID_SIM = 0x81;
 this.STK_DEVICE_ID_ME = 0x82;
 this.STK_DEVICE_ID_NETWORK = 0x83;
 
@@ -983,26 +989,30 @@ this.GECKO_ICC_SERVICES = {
     FDN: 3,
     PLMNSEL: 7,
     CBMI: 14,
     SPN: 17,
     SDN: 18,
     DATA_DOWNLOAD_SMS_PP: 26,
     CBMIR: 30,
     BDN: 31,
+    PNN: 51,
+    OPL: 52,
     SPDI: 56
   },
   usim: {
     FDN: 2,
     SDN: 4,
     BDN: 6,
     CBMI: 15,
     CBMIR: 16,
     SPN: 19,
     DATA_DOWNLOAD_SMS_PP: 28,
+    PNN: 45,
+    OPL: 46,
     SPDI: 51
   }
 };
 
 /**
  * Cell Broadcast constants
  */
 
--- a/dom/system/gonk/ril_worker.js
+++ b/dom/system/gonk/ril_worker.js
@@ -1667,16 +1667,229 @@ let RIL = {
     }
 
     return (serviceTable &&
            (index < serviceTable.length) &&
            (serviceTable[index] & bitmask)) != 0;
   },
 
   /**
+   * Choose network names using EF_OPL and EF_PNN
+   * See 3GPP TS 31.102 sec. 4.2.58 and sec. 4.2.59 for USIM,
+   *     3GPP TS 51.011 sec. 10.3.41 and sec. 10.3.42 for SIM.
+   */
+  updateNetworkName: function updateNetworkName() {
+    let iccInfoPriv = this.iccInfoPrivate;
+    let iccInfo = this.iccInfo;
+
+    // We won't update network name if voice registration isn't ready
+    // or PNN file haven't been retrieved.
+    if (!iccInfoPriv.PNN ||
+        !this.voiceRegistrationState.cell ||
+        this.voiceRegistrationState.cell.gsmLocationAreaCode == -1) {
+      return null;
+    }
+
+    let pnnEntry;
+    let lac = this.voiceRegistrationState.cell.gsmLocationAreaCode;
+    let mcc = this.operator.mcc;
+    let mnc = this.operator.mnc;
+
+    // According to 3GPP TS 31.102 Sec. 4.2.59 and 3GPP TS 51.011 Sec. 10.3.42,
+    // the ME shall use this EF_OPL in association with the EF_PNN in place
+    // of any network name stored within the ME's internal list and any network
+    // name received when registered to the PLMN.
+    if (iccInfoPriv.OPL) {
+      for (let i in iccInfoPriv.OPL) {
+        let opl = iccInfoPriv.OPL[i];
+        // Try to match the MCC/MNC.
+        if (mcc != opl.mcc || mnc != opl.mnc) {
+          continue;
+        }
+        // Try to match the location area code. If current local area code is
+        // covered by lac range that specified in the OPL entry, use the PNN
+        // that specified in the OPL entry.
+        if ((opl.lacTacStart == 0x0 && opl.lacTacEnd == 0xFFFE) ||
+            (opl.lacTacStart <= lac && opl.lacTacEnd >= lac)) {
+          if (opl.pnnRecordId == 0) {
+            // See 3GPP TS 31.102 Sec. 4.2.59 and 3GPP TS 51.011 Sec. 10.3.42,
+            // A value of '00' indicates that the name is to be taken from other
+            // sources.
+            return null;
+          }
+          pnnEntry = iccInfoPriv.PNN[opl.pnnRecordId - 1]
+          break;
+        }
+      }
+    }
+
+    // According to 3GPP TS 31.102 Sec. 4.2.58 and 3GPP TS 51.011 Sec. 10.3.41,
+    // the first record in this EF is used for the default network name when
+    // registered to the HPLMN.
+    // If we haven't get pnnEntry assigned, we should try to assign default
+    // value to it.
+    if (!pnnEntry && mcc == iccInfo.mcc && mnc == iccInfo.mnc) {
+      pnnEntry = iccInfoPriv.PNN[0]
+    }
+
+    if (DEBUG) {
+      if (pnnEntry) {
+        debug("updateNetworkName: Network names will be overriden: longName = " +
+              pnnEntry.fullName + ", shortName = " + pnnEntry.shortName);
+      } else {
+        debug("updateNetworkName: Network names will not be overriden");
+      }
+    }
+
+    if (pnnEntry) {
+      return [pnnEntry.fullName, pnnEntry.shortName];
+    }
+    return null;
+  },
+
+  /**
+   * Read OPL (Operator PLMN List) from USIM.
+   *
+   * See 3GPP TS 31.102 Sec. 4.2.59 for USIM
+   *     3GPP TS 51.011 Sec. 10.3.42 for SIM.
+   */
+  getOPL: function getOPL() {
+    let opl = [];
+    function callback(options) {
+      let len = Buf.readUint32();
+      // The first 7 bytes are LAI (for UMTS) and the format of LAI is defined
+      // in 3GPP TS 23.003, Sec 4.1
+      //    +-------------+---------+
+      //    | Octet 1 - 3 | MCC/MNC |
+      //    +-------------+---------+
+      //    | Octet 4 - 7 |   LAC   |
+      //    +-------------+---------+
+      let mccMnc = [GsmPDUHelper.readHexOctet(),
+                    GsmPDUHelper.readHexOctet(),
+                    GsmPDUHelper.readHexOctet()];
+      if (mccMnc[0] != 0xFF || mccMnc[1] != 0xFF || mccMnc[2] != 0xFF) {
+        let oplElement = {};
+        let semiOctets = [];
+        for (let i = 0; i < mccMnc.length; i++) {
+          semiOctets.push((mccMnc[i] & 0xf0) >> 4);
+          semiOctets.push(mccMnc[i] & 0x0f);
+        }
+        let reformat = [semiOctets[1], semiOctets[0], semiOctets[3],
+                        semiOctets[5], semiOctets[4], semiOctets[2]];
+        let buf = "";
+        for (let i = 0; i < reformat.length; i++) {
+          if (reformat[i] != 0xF) {
+            buf += GsmPDUHelper.semiOctetToBcdChar(reformat[i]);
+          }
+          if (i === 2) {
+            // 0-2: MCC
+            oplElement.mcc = parseInt(buf);
+            buf = "";
+          } else if (i === 5) {
+            // 3-5: MNC
+            oplElement.mnc = parseInt(buf);
+          }
+        }
+        // LAC/TAC
+        oplElement.lacTacStart =
+          (GsmPDUHelper.readHexOctet() << 8) | GsmPDUHelper.readHexOctet();
+        oplElement.lacTacEnd =
+          (GsmPDUHelper.readHexOctet() << 8) | GsmPDUHelper.readHexOctet();
+        // PLMN Network Name Record Identifier
+        oplElement.pnnRecordId = GsmPDUHelper.readHexOctet();
+        if (DEBUG) {
+          debug("OPL: [" + (opl.length + 1) + "]: " + JSON.stringify(oplElement));
+        }
+        opl.push(oplElement);
+      }
+      Buf.readStringDelimiter(len);
+      if (options.p1 < options.totalRecords) {
+        options.p1++;
+        this.iccIO(options);
+      } else {
+        this.iccInfoPrivate.OPL = opl;
+      }
+    }
+
+    this.iccIO({
+      command:   ICC_COMMAND_GET_RESPONSE,
+      fileId:    ICC_EF_OPL,
+      pathId:    this._getPathIdForICCRecord(ICC_EF_OPL),
+      p1:        0, // For GET_RESPONSE, p1 = 0
+      p2:        0, // For GET_RESPONSE, p2 = 0
+      p3:        GET_RESPONSE_EF_SIZE_BYTES,
+      data:      null,
+      pin2:      null,
+      type:      EF_TYPE_LINEAR_FIXED,
+      callback:  callback,
+    });
+  },
+
+  /**
+   * Read PNN (PLMN Network Name) from USIM.
+   *
+   * See 3GPP TS 31.102 Sec. 4.2.58 for USIM
+   *     3GPP TS 51.011 Sec. 10.3.41 for SIM.
+   */
+  getPNN: function getPNN() {
+    let pnn = [];
+    function callback(options) {
+      let pnnElement = this.iccInfoPrivate.PNN = {};
+      let len = Buf.readUint32();
+      let readLen = 0;
+      while (len > readLen) {
+        let tlvTag = GsmPDUHelper.readHexOctet();
+        readLen = readLen + 2; // 1 Hex octet
+        if (tlvTag == 0xFF) {
+          // Unused byte
+          continue;
+        }
+        let tlvLen = GsmPDUHelper.readHexOctet();
+        let name;
+        switch (tlvTag) {
+        case PNN_IEI_FULL_NETWORK_NAME:
+          pnnElement.fullName = GsmPDUHelper.readNetworkName(tlvLen);
+          break;
+        case PNN_IEI_SHORT_NETWORK_NAME:
+          pnnElement.shortName = GsmPDUHelper.readNetworkName(tlvLen);
+          break;
+        default:
+          Buf.seekIncoming(PDU_HEX_OCTET_SIZE * tlvLen);
+        }
+        readLen += (tlvLen * 2 + 2);
+      }
+      if (DEBUG) {
+        debug("PNN: [" + (pnn.length + 1) + "]: " + JSON.stringify(pnnElement));
+      }
+      Buf.readStringDelimiter(len);
+      pnn.push(pnnElement);
+
+      if (options.p1 < options.totalRecords) {
+        options.p1++;
+        this.iccIO(options);
+      } else {
+        this.iccInfoPrivate.PNN = pnn;
+      }
+    }
+
+    this.iccIO({
+      command:   ICC_COMMAND_GET_RESPONSE,
+      fileId:    ICC_EF_PNN,
+      pathId:    this._getPathIdForICCRecord(ICC_EF_PNN),
+      p1:        0, // For GET_RESPONSE, p1 = 0
+      p2:        0, // For GET_RESPONSE, p2 = 0
+      p3:        GET_RESPONSE_EF_SIZE_BYTES,
+      data:      null,
+      pin2:      null,
+      type:      EF_TYPE_LINEAR_FIXED,
+      callback:  callback,
+    });
+  },
+
+  /**
    * Read the (U)SIM Service Table from the ICC.
    */
   getSST: function getSST() {
     function callback() {
       let length = Buf.readUint32();
       // Each octet is encoded into two chars.
       let len = length / 2;
       this.iccInfo.sst = GsmPDUHelper.readHexOctetArray(len);
@@ -1700,16 +1913,30 @@ let RIL = {
 
       if (this.isICCServiceAvailable("SPDI")) {
         if (DEBUG) debug("SPDI: SPDI available.");
         this.getSPDI();
       } else {
         if (DEBUG) debug("SPDI: SPDI service is not available");
       }
 
+      if (this.isICCServiceAvailable("PNN")) {
+        if (DEBUG) debug("PNN: PNN is available");
+        this.getPNN();
+      } else {
+        if (DEBUG) debug("PNN: PNN is not available");
+      }
+
+      if (this.isICCServiceAvailable("OPL")) {
+        if (DEBUG) debug("OPL: OPL is available");
+        this.getOPL();
+      } else {
+        if (DEBUG) debug("OPL: OPL is not available");
+      }
+
       if (this.isICCServiceAvailable("CBMI")) {
         this.getCBMI();
       } else {
         this.cellBroadcastConfigs.CBMI = null;
       }
       if (this.isICCServiceAvailable("CBMIR")) {
         this.getCBMIR();
       } else {
@@ -2538,17 +2765,18 @@ let RIL = {
    * @param body
    *        String containing the message text.
    * @param requestId
    *        String identifying the sms request used by the SmsRequestManager.
    * @param processId
    *        String containing the processId for the SmsRequestManager.
    */
   sendSMS: function sendSMS(options) {
-    //TODO: verify values on 'options'
+    options.langIndex = options.langIndex || PDU_NL_IDENTIFIER_DEFAULT;
+    options.langShiftIndex = options.langShiftIndex || PDU_NL_IDENTIFIER_DEFAULT;
 
     if (!options.retryCount) {
       options.retryCount = 0;
     }
 
     if (options.segmentMaxSeq > 1) {
       if (!options.segmentSeq) {
         // Fist segment to send
@@ -3638,16 +3866,18 @@ let RIL = {
           case ICC_EF_FDN:
           case ICC_EF_MBDN:
           case ICC_EF_UST:
           case ICC_EF_MSISDN:
           case ICC_EF_SPN:
           case ICC_EF_SPDI:
           case ICC_EF_CBMI:
           case ICC_EF_CBMIR:
+          case ICC_EF_OPL:
+          case ICC_EF_PNN:
             return EF_PATH_MF_SIM + EF_PATH_ADF_USIM;
 
           default:
             // The file ids in USIM phone book entries are decided by the
 	    // card manufacturer. So if we don't match any of the cases
 	    // above and if its a USIM return the phone book path.
             return EF_PATH_MF_SIM + EF_PATH_DF_TELECOM + EF_PATH_DF_PHONEBOOK;
         }
@@ -3963,18 +4193,25 @@ let RIL = {
 
     let [longName, shortName, networkTuple] = operatorData;
     let thisTuple = "" + this.operator.mcc + this.operator.mnc;
 
     if (this.operator.longName !== longName ||
         this.operator.shortName !== shortName ||
         thisTuple !== networkTuple) {
 
-      this.operator.longName = longName;
-      this.operator.shortName = shortName;
+      let networkName = this.updateNetworkName();
+      if (networkName) {
+        this.operator.longName = networkName[0];
+        this.operator.shortName = networkName[1];
+      } else {
+        this.operator.longName = longName;
+        this.operator.shortName = shortName;
+      }
+
       this.operator.mcc = 0;
       this.operator.mnc = 0;
 
       // According to ril.h, the operator fields will be NULL when the operator
       // is not currently registered. We can avoid trying to parse the numeric
       // tuple in that case.
       if (DEBUG && !longName) {
         debug("Operator is currently unregistered");
@@ -5965,17 +6202,17 @@ RIL[UNSOLICITED_NITZ_TIME_RECEIVED] = fu
 
   // Always print the NITZ info so we can collection what different providers
   // send down the pipe (see bug XXX).
   // TODO once data is collected, add in |if (DEBUG)|
   
   debug("DateTimeZone string " + dateString);
 
   let now = Date.now();
-	
+
   let year = parseInt(dateString.substr(0, 2), 10);
   let month = parseInt(dateString.substr(3, 2), 10);
   let day = parseInt(dateString.substr(6, 2), 10);
   let hours = parseInt(dateString.substr(9, 2), 10);
   let minutes = parseInt(dateString.substr(12, 2), 10);
   let seconds = parseInt(dateString.substr(15, 2), 10);
   // Note that |tz| is in 15-min units.
   let tz = parseInt(dateString.substr(17, 3), 10);
@@ -6816,26 +7053,28 @@ let GsmPDUHelper = {
         this.writeHexOctet(PDU_IEI_CONCATENATED_SHORT_MESSAGES_8BIT);
         this.writeHexOctet(3);
       }
       this.writeHexOctet(options.segmentRef & 0xFF);
       this.writeHexOctet(options.segmentMaxSeq & 0xFF);
       this.writeHexOctet(options.segmentSeq & 0xFF);
     }
 
-    if (options.langIndex != PDU_NL_IDENTIFIER_DEFAULT) {
-      this.writeHexOctet(PDU_IEI_NATIONAL_LANGUAGE_LOCKING_SHIFT);
-      this.writeHexOctet(1);
-      this.writeHexOctet(options.langIndex);
-    }
-
-    if (options.langShiftIndex != PDU_NL_IDENTIFIER_DEFAULT) {
-      this.writeHexOctet(PDU_IEI_NATIONAL_LANGUAGE_SINGLE_SHIFT);
-      this.writeHexOctet(1);
-      this.writeHexOctet(options.langShiftIndex);
+    if (options.dcs == PDU_DCS_MSG_CODING_7BITS_ALPHABET) {
+      if (options.langIndex != PDU_NL_IDENTIFIER_DEFAULT) {
+        this.writeHexOctet(PDU_IEI_NATIONAL_LANGUAGE_LOCKING_SHIFT);
+        this.writeHexOctet(1);
+        this.writeHexOctet(options.langIndex);
+      }
+
+      if (options.langShiftIndex != PDU_NL_IDENTIFIER_DEFAULT) {
+        this.writeHexOctet(PDU_IEI_NATIONAL_LANGUAGE_SINGLE_SHIFT);
+        this.writeHexOctet(1);
+        this.writeHexOctet(options.langShiftIndex);
+      }
     }
   },
 
   /**
    * Read SM-TL Address.
    *
    * @param len
    *        Length of useful semi-octets within the Address-Value field. For
@@ -7843,16 +8082,70 @@ let GsmPDUHelper = {
     this.readCbWarningType(msg);
 
     // Octet 7..56 is Warning Security Information. However, according to
     // section 9.4.1.3.6, `The UE shall ignore this parameter.` So we just skip
     // processing it here.
 
     return msg;
   },
+
+  /**
+   * Read network name.
+   *
+   * @param len Length of the information element.
+   * @return
+   *   {
+   *     networkName: network name.
+   *     shouldIncludeCi: Should Country's initials included in text string.
+   *   }
+   * @see TS 24.008 clause 10.5.3.5a.
+   */
+  readNetworkName: function readNetworkName(len) {
+    // According to TS 24.008 Sec. 10.5.3.5a, the first octet is:
+    // bit 8: must be 1.
+    // bit 5-7: Text encoding.
+    //          000 - GSM default alphabet.
+    //          001 - UCS2 (16 bit).
+    //          else - reserved.
+    // bit 4: MS should add the letters for Country's Initials and a space
+    //        to the text string if this bit is true.
+    // bit 1-3: number of spare bits in last octet.
+
+    let codingInfo = GsmPDUHelper.readHexOctet();
+    if (!(codingInfo & 0x80)) {
+      return null;
+    }
+
+    let textEncoding = (codingInfo & 0x70) >> 4,
+        shouldIncludeCountryInitials = !!(codingInfo & 0x08),
+        spareBits = codingInfo & 0x07;
+    let resultString;
+
+    switch (textEncoding) {
+    case 0:
+      // GSM Default alphabet.
+      resultString = GsmPDUHelper.readSeptetsToString(
+        ((len - 1) * 8 - spareBits) / 7, 0,
+        PDU_NL_IDENTIFIER_DEFAULT,
+        PDU_NL_IDENTIFIER_DEFAULT);
+      break;
+    case 1:
+      // UCS2 encoded.
+      resultString = this.readUCS2String(len - 1);
+      break;
+    default:
+      // Not an available text coding.
+      return null;
+    }
+
+    // TODO - Bug 820286: According to shouldIncludeCountryInitials, add
+    // country initials to the resulting string.
+    return resultString;
+  }
 };
 
 let StkCommandParamsFactory = {
   createParam: function createParam(cmdDetails, ctlvs) {
     let param;
     switch (cmdDetails.typeOfCommand) {
       case STK_CMD_REFRESH:
         param = this.processRefresh(cmdDetails, ctlvs);
--- a/dom/system/gonk/tests/test_ril_worker_icc.js
+++ b/dom/system/gonk/tests/test_ril_worker_icc.js
@@ -618,16 +618,17 @@ add_test(function test_spn_display_condi
 
   testDisplayConditions(testDisplayCondition, [
     [1, 123, 456, 123, 456, true, true],
     [0, 123, 456, 123, 456, false, true],
     [2, 123, 456, 123, 457, false, false],
     [0, 123, 456, 123, 457, false, true],
   ], run_next_test);
 });
+
 /**
  * Verify Proactive Command : More Time
  */
 add_test(function test_stk_proactive_command_more_time() {
   let worker = newUint8Worker();
   let pduHelper = worker.GsmPDUHelper;
   let berHelper = worker.BerTlvHelper;
   let stkHelper = worker.StkProactiveCmdHelper;
@@ -647,16 +648,153 @@ add_test(function test_stk_proactive_com
   let tlv = stkHelper.searchForTag(COMPREHENSIONTLV_TAG_COMMAND_DETAILS, ctlvs);
   do_check_eq(tlv.value.commandNumber, 0x01);
   do_check_eq(tlv.value.typeOfCommand, STK_CMD_MORE_TIME);
   do_check_eq(tlv.value.commandQualifier, 0x00);
 
   run_next_test();
 });
 
+add_test(function read_network_name() {
+  let worker = newUint8Worker();
+  let helper = worker.GsmPDUHelper;
+  let buf = worker.Buf;
+
+  // Returning length of byte.
+  function writeNetworkName(isUCS2, requireCi, name) {
+    let codingOctet = 0x80;
+    let len;
+    if (requireCi) {
+      codingOctet |= 0x08;
+    }
+
+    if (isUCS2) {
+      codingOctet |= 0x10;
+      len = name.length * 2;
+    } else {
+      let spare = (8 - (name.length * 7) % 8) % 8;
+      codingOctet |= spare;
+      len = Math.ceil(name.length * 7 / 8);
+    }
+    helper.writeHexOctet(codingOctet);
+
+    if (isUCS2) {
+      helper.writeUCS2String(name);
+    } else {
+      helper.writeStringAsSeptets(name, 0, 0, 0);
+    }
+
+    return len + 1; // codingOctet.
+  }
+
+  function testNetworkName(isUCS2, requireCi, name) {
+    let len = writeNetworkName(isUCS2, requireCi, name);
+    do_check_eq(helper.readNetworkName(len), name);
+  }
+
+  testNetworkName( true,  true, "Test Network Name1");
+  testNetworkName( true, false, "Test Network Name2");
+  testNetworkName(false,  true, "Test Network Name3");
+  testNetworkName(false, false, "Test Network Name4");
+
+  run_next_test();
+});
+
+add_test(function test_update_network_name() {
+  let RIL = newWorker({
+    postRILMessage: function fakePostRILMessage(data) {
+      // Do nothing
+    },
+    postMessage: function fakePostMessage(message) {
+      // Do nothing
+    }
+  }).RIL;
+
+  function testNetworkNameIsNull(operatorMcc, operatorMnc) {
+    RIL.operator.mcc = operatorMcc;
+    RIL.operator.mnc = operatorMnc;
+    do_check_eq(RIL.updateNetworkName(), null);
+  }
+
+  function testNetworkName(operatorMcc, operatorMnc,
+                            expectedLongName, expectedShortName) {
+    RIL.operator.mcc = operatorMcc;
+    RIL.operator.mnc = operatorMnc;
+    let result = RIL.updateNetworkName();
+
+    do_check_eq(result[0], expectedLongName);
+    do_check_eq(result[1], expectedShortName);
+  }
+
+  // Before EF_OPL and EF_PNN have been loaded.
+  do_check_eq(RIL.updateNetworkName(), null);
+
+  // Set HPLMN
+  RIL.iccInfo.mcc = 123;
+  RIL.iccInfo.mnc = 456;
+
+  RIL.voiceRegistrationState = {
+    cell: {
+      gsmLocationAreaCode: 0x1000
+    }
+  };
+  RIL.operator = {};
+
+  // Set EF_PNN
+  RIL.iccInfoPrivate = {
+    PNN: [
+      {"fullName": "PNN1Long", "shortName": "PNN1Short"},
+      {"fullName": "PNN2Long", "shortName": "PNN2Short"},
+      {"fullName": "PNN3Long", "shortName": "PNN3Short"},
+      {"fullName": "PNN4Long", "shortName": "PNN4Short"}
+    ]
+  };
+
+  // EF_OPL isn't available and current isn't in HPLMN,
+  testNetworkNameIsNull(123, 457);
+
+  // EF_OPL isn't available and current is in HPLMN,
+  // the first record of PNN should be returned.
+  testNetworkName(123, 456, "PNN1Long", "PNN1Short");
+
+  // Set EF_OPL
+  RIL.iccInfoPrivate.OPL = [
+    {
+      "mcc": 123,
+      "mnc": 456,
+      "lacTacStart": 0,
+      "lacTacEnd": 0xFFFE,
+      "pnnRecordId": 4
+    },
+    {
+      "mcc": 123,
+      "mnc": 457,
+      "lacTacStart": 0,
+      "lacTacEnd": 0x0010,
+      "pnnRecordId": 3
+    },
+    {
+      "mcc": 123,
+      "mnc": 457,
+      "lacTacStart": 0,
+      "lacTacEnd": 0x1010,
+      "pnnRecordId": 2
+    }
+  ];
+
+  // Both EF_PNN and EF_OPL are presented, and current PLMN is HPLMN,
+  testNetworkName(123, 456, "PNN4Long", "PNN4Short");
+
+  // Current PLMN is not HPLMN, and according to LAC, we should get
+  // the second PNN record.
+  testNetworkName(123, 457, "PNN2Long", "PNN2Short");
+
+  run_next_test();
+});
+
 /**
  * Verify Proactive Command : Provide Local Information
  */
 add_test(function test_stk_proactive_command_provide_local_information() {
   let worker = newUint8Worker();
   let pduHelper = worker.GsmPDUHelper;
   let berHelper = worker.BerTlvHelper;
   let stkHelper = worker.StkProactiveCmdHelper;
--- a/dom/system/gonk/tests/test_ril_worker_sms.js
+++ b/dom/system/gonk/tests/test_ril_worker_sms.js
@@ -709,16 +709,62 @@ for (let lst = 0; lst < PDU_NL_LOCKING_S
 
     if (lst == 0) {
       ucs2str += PDU_NL_SINGLE_SHIFT_TABLES[sst];
     }
   }
 }
 test_receiving_ucs2_alphabets(ucs2str);
 
+// Bug 820220: B2G SMS: wrong order and truncated content in multi-part messages
+add_test(function test_sendSMS_UCS2_without_langIndex_langShiftIndex_defined() {
+  let worker = newWriteHexOctetAsUint8Worker();
+
+  worker.Buf.sendParcel = function () {
+    // Each sendParcel() call represents one outgoing segment of a multipart
+    // SMS message. Here, we have the first segment send, so it's "Hello "
+    // only.
+    //
+    // 4(parcel size) + 4(request type) + 4(token)
+    // + 4(two messages) + 4(null SMSC) + 4(message string length)
+    // + 1(first octet) + 1(message reference)
+    // + 2(DA len, TOA) + 4(addr)
+    // + 1(pid) + 1(dcs)
+    // + 1(UDL) + 6(UDHL, type, len, ref, max, seq)
+    // + 12(2 * strlen("Hello "))
+    // + 4(two delimitors) = 57
+    //
+    // If we have additional 6(type, len, langIndex, type len, langShiftIndex)
+    // octets here, then bug 809553 is not fixed.
+    do_check_eq(this.outgoingIndex, 57);
+
+    run_next_test();
+  };
+
+  worker.RIL.sendSMS({
+    number: "1",
+    segmentMaxSeq: 2,
+    fullBody: "Hello World!",
+    dcs: PDU_DCS_MSG_CODING_16BITS_ALPHABET,
+    segmentRef16Bit: false,
+    userDataHeaderLength: 5,
+    strict7BitEncoding: false,
+    requestStatusReport: true,
+    segments: [
+      {
+        body: "Hello ",
+        encodedBodyLength: 12,
+      }, {
+        body: "World!",
+        encodedBodyLength: 12,
+      }
+    ],
+  });
+});
+
 /**
  * Verify GsmPDUHelper#readAddress
  */
 add_test(function test_GsmPDUHelper_readAddress() {
   let worker = newWorker({
     postRILMessage: function fakePostRILMessage(data) {
       // Do nothing
     },
--- a/dom/time/TimeChangeObserver.cpp
+++ b/dom/time/TimeChangeObserver.cpp
@@ -1,15 +1,16 @@
 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this file,
  * You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "TimeChangeObserver.h"
 #include "mozilla/ClearOnShutdown.h"
+#include "mozilla/Services.h"
 #include "mozilla/StaticPtr.h"
 #include "nsPIDOMWindow.h"
 #include "nsDOMEvent.h"
 #include "nsContentUtils.h"
 #include "nsIObserverService.h"
 
 using namespace mozilla;
 using namespace mozilla::hal;
new file mode 100644
--- /dev/null
+++ b/dom/webidl/File.webidl
@@ -0,0 +1,9 @@
+/* -*- 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 FilePropertyBag : BlobPropertyBag {
+  DOMString name = "";
+};
new file mode 100644
--- /dev/null
+++ b/dom/webidl/FormData.webidl
@@ -0,0 +1,18 @@
+/* -*- 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/.
+ *
+ * The origin of this IDL file is
+ * http://xhr.spec.whatwg.org
+ */
+
+interface HTMLFormElement;
+
+[Constructor(optional HTMLFormElement form)]
+interface FormData {
+  // Not supported (bug 739174)
+  // void append(DOMString name, Blob value, optional DOMString filename);
+  void append(DOMString name, Blob value);
+  void append(DOMString name, DOMString value);
+};
--- a/dom/webidl/WebIDL.mk
+++ b/dom/webidl/WebIDL.mk
@@ -28,19 +28,21 @@ webidl_files = \
   DOMSettableTokenList.webidl \
   DOMStringMap.webidl \
   DOMTokenList.webidl \
   DynamicsCompressorNode.webidl \
   Element.webidl \
   EventHandler.webidl \
   EventListener.webidl \
   EventTarget.webidl \
+  File.webidl \
   FileHandle.webidl \
   FileList.webidl \
   FileReaderSync.webidl \
+  FormData.webidl \
   Function.webidl \
   GainNode.webidl \
   HTMLCollection.webidl \
   HTMLElement.webidl \
   HTMLOptionsCollection.webidl \
   HTMLPropertiesCollection.webidl \
   ImageData.webidl \
   Node.webidl \
--- a/dom/webidl/XMLHttpRequest.webidl
+++ b/dom/webidl/XMLHttpRequest.webidl
@@ -7,17 +7,16 @@
  * www.w3.org/TR/2012/WD-XMLHttpRequest-20120117/
  *
  * Copyright © 2012 W3C® (MIT, ERCIM, Keio), All Rights Reserved. W3C
  * liability, trademark and document use rules apply.
  */
 
 interface Document;
 interface Blob;
-interface FormData;
 interface InputStream;
 interface MozChannel;
 interface IID;
 
 enum XMLHttpRequestResponseType {
   "",
   "arraybuffer",
   "blob",
--- a/dom/workers/File.cpp
+++ b/dom/workers/File.cpp
@@ -83,18 +83,17 @@ private:
   {
     return GetPrivate(aObj);
   }
 
   static JSBool
   Construct(JSContext* aCx, unsigned aArgc, jsval* aVp)
   {
     nsRefPtr<nsDOMMultipartFile> file = new nsDOMMultipartFile();
-    nsresult rv = file->InitInternal(aCx, aArgc, JS_ARGV(aCx, aVp),
-                                     Unwrap);
+    nsresult rv = file->InitBlob(aCx, aArgc, JS_ARGV(aCx, aVp), Unwrap);
     if (NS_FAILED(rv)) {
       ThrowDOMExceptionForNSResult(aCx, rv);
       return false;
     }
 
     JSObject* obj = file::CreateBlob(aCx, file);
     if (!obj) {
       return false;
--- a/dom/workers/XMLHttpRequest.h
+++ b/dom/workers/XMLHttpRequest.h
@@ -174,16 +174,22 @@ public:
 
   void
   Send(const nsAString& aBody, ErrorResult& aRv);
 
   void
   Send(JSObject* aBody, ErrorResult& aRv);
 
   void
+  Send(JSObject& aBody, ErrorResult& aRv)
+  {
+    Send(&aBody, aRv);
+  }
+
+  void
   Send(ArrayBuffer& aBody, ErrorResult& aRv) {
     return Send(aBody.Obj(), aRv);
   }
 
   void
   SendAsBinary(const nsAString& aBody, ErrorResult& aRv);
 
   void
--- a/gfx/angle/Makefile.in
+++ b/gfx/angle/Makefile.in
@@ -71,16 +71,17 @@ CPPSRCS = \
         ForLoopUnroll.cpp \
         MapLongVariableNames.cpp \
         spooky.cpp \
         BuiltInFunctionEmulator.cpp \
         Input.cpp \
         Lexer.cpp \
         Preprocessor.cpp \
         Token.cpp \
+        VariablePacker.cpp \
         $(NULL)
 
 # flex/yacc generated files
 CPPSRCS += \
         glslang_lex.cpp \
         glslang_tab.cpp \
         $(NULL)
 
new file mode 100644
--- /dev/null
+++ b/gfx/angle/angle-1317.patch
@@ -0,0 +1,732 @@
+# HG changeset patch
+# Parent ef5d80327785b28df0bd778acc86f4987ba5a678
+
+diff --git a/gfx/angle/Makefile.in b/gfx/angle/Makefile.in
+--- a/gfx/angle/Makefile.in
++++ b/gfx/angle/Makefile.in
+@@ -71,16 +71,17 @@ CPPSRCS = \
+         ForLoopUnroll.cpp \
+         MapLongVariableNames.cpp \
+         spooky.cpp \
+         BuiltInFunctionEmulator.cpp \
+         Input.cpp \
+         Lexer.cpp \
+         Preprocessor.cpp \
+         Token.cpp \
++        VariablePacker.cpp \
+         $(NULL)
+ 
+ # flex/yacc generated files
+ CPPSRCS += \
+         glslang_lex.cpp \
+         glslang_tab.cpp \
+         $(NULL)
+ 
+diff --git a/gfx/angle/include/GLSLANG/ShaderLang.h b/gfx/angle/include/GLSLANG/ShaderLang.h
+--- a/gfx/angle/include/GLSLANG/ShaderLang.h
++++ b/gfx/angle/include/GLSLANG/ShaderLang.h
+@@ -137,17 +137,20 @@ typedef enum {
+   SH_TIMING_RESTRICTIONS = 0x0200,
+     
+   // This flag prints the dependency graph that is used to enforce timing
+   // restrictions on fragment shaders.
+   // This flag only has an effect if all of the following are true:
+   // - The shader spec is SH_WEBGL_SPEC.
+   // - The compile options contain the SH_TIMING_RESTRICTIONS flag.
+   // - The shader type is SH_FRAGMENT_SHADER.
+-  SH_DEPENDENCY_GRAPH = 0x0400
++  SH_DEPENDENCY_GRAPH = 0x0400,
++
++  // Enforce the GLSL 1.017 Appendix A section 7 packing restrictions.
++  SH_ENFORCE_PACKING_RESTRICTIONS = 0x0800,
+ } ShCompileOptions;
+ 
+ //
+ // Driver must call this first, once, before doing any other
+ // compiler operations.
+ // If the function succeeds, the return value is nonzero, else zero.
+ //
+ COMPILER_EXPORT int ShInitialize();
+diff --git a/gfx/angle/src/compiler/Compiler.cpp b/gfx/angle/src/compiler/Compiler.cpp
+--- a/gfx/angle/src/compiler/Compiler.cpp
++++ b/gfx/angle/src/compiler/Compiler.cpp
+@@ -9,16 +9,17 @@
+ #include "compiler/ForLoopUnroll.h"
+ #include "compiler/Initialize.h"
+ #include "compiler/InitializeParseContext.h"
+ #include "compiler/MapLongVariableNames.h"
+ #include "compiler/ParseHelper.h"
+ #include "compiler/RenameFunction.h"
+ #include "compiler/ShHandle.h"
+ #include "compiler/ValidateLimitations.h"
++#include "compiler/VariablePacker.h"
+ #include "compiler/depgraph/DependencyGraph.h"
+ #include "compiler/depgraph/DependencyGraphOutput.h"
+ #include "compiler/timing/RestrictFragmentShaderTiming.h"
+ #include "compiler/timing/RestrictVertexShaderTiming.h"
+ 
+ bool isWebGLBasedSpec(ShShaderSpec spec)
+ {
+      return spec == SH_WEBGL_SPEC || spec == SH_CSS_SHADERS_SPEC;
+@@ -108,16 +109,19 @@ TCompiler::TCompiler(ShShaderType type, 
+ TCompiler::~TCompiler()
+ {
+     ASSERT(longNameMap);
+     longNameMap->Release();
+ }
+ 
+ bool TCompiler::Init(const ShBuiltInResources& resources)
+ {
++    maxUniformVectors = (shaderType == SH_VERTEX_SHADER) ?
++        resources.MaxVertexUniformVectors :
++        resources.MaxFragmentUniformVectors;
+     TScopedPoolAllocator scopedAlloc(&allocator, false);
+ 
+     // Generate built-in symbol table.
+     if (!InitBuiltInSymbolTable(resources))
+         return false;
+     InitExtensionBehavior(resources, extensionBehavior);
+ 
+     return true;
+@@ -187,18 +191,25 @@ bool TCompiler::compile(const char* cons
+             builtInFunctionEmulator.MarkBuiltInFunctionsForEmulation(root);
+ 
+         // Call mapLongVariableNames() before collectAttribsUniforms() so in
+         // collectAttribsUniforms() we already have the mapped symbol names and
+         // we could composite mapped and original variable names.
+         if (success && (compileOptions & SH_MAP_LONG_VARIABLE_NAMES))
+             mapLongVariableNames(root);
+ 
+-        if (success && (compileOptions & SH_ATTRIBUTES_UNIFORMS))
++        if (success && (compileOptions & SH_ATTRIBUTES_UNIFORMS)) {
+             collectAttribsUniforms(root);
++            if (compileOptions & SH_ENFORCE_PACKING_RESTRICTIONS) {
++                success = enforcePackingRestrictions();
++                if (!success) {
++                    infoSink.info.message(EPrefixError, "too many uniforms");
++                }
++            }
++        }
+ 
+         if (success && (compileOptions & SH_INTERMEDIATE_TREE))
+             intermediate.outputTree(root);
+ 
+         if (success && (compileOptions & SH_OBJECT_CODE))
+             translate(root);
+     }
+ 
+@@ -305,16 +316,22 @@ bool TCompiler::enforceVertexShaderTimin
+ }
+ 
+ void TCompiler::collectAttribsUniforms(TIntermNode* root)
+ {
+     CollectAttribsUniforms collect(attribs, uniforms);
+     root->traverse(&collect);
+ }
+ 
++bool TCompiler::enforcePackingRestrictions()
++{
++    VariablePacker packer;
++    return packer.CheckVariablesWithinPackingLimits(maxUniformVectors, uniforms);
++}
++
+ void TCompiler::mapLongVariableNames(TIntermNode* root)
+ {
+     ASSERT(longNameMap);
+     MapLongVariableNames map(longNameMap);
+     root->traverse(&map);
+ }
+ 
+ int TCompiler::getMappedNameMaxLength() const
+diff --git a/gfx/angle/src/compiler/ShHandle.h b/gfx/angle/src/compiler/ShHandle.h
+--- a/gfx/angle/src/compiler/ShHandle.h
++++ b/gfx/angle/src/compiler/ShHandle.h
+@@ -83,32 +83,37 @@ protected:
+     // functionality mandated in GLSL 1.0 spec Appendix A.
+     bool validateLimitations(TIntermNode* root);
+     // Collect info for all attribs and uniforms.
+     void collectAttribsUniforms(TIntermNode* root);
+     // Map long variable names into shorter ones.
+     void mapLongVariableNames(TIntermNode* root);
+     // Translate to object code.
+     virtual void translate(TIntermNode* root) = 0;
++    // Returns true if, after applying the packing rules in the GLSL 1.017 spec
++    // Appendix A, section 7, the shader does not use too many uniforms.
++    bool enforcePackingRestrictions();
+     // Returns true if the shader passes the restrictions that aim to prevent timing attacks.
+     bool enforceTimingRestrictions(TIntermNode* root, bool outputGraph);
+     // Returns true if the shader does not use samplers.
+     bool enforceVertexShaderTimingRestrictions(TIntermNode* root);
+     // Returns true if the shader does not use sampler dependent values to affect control 
+     // flow or in operations whose time can depend on the input values.
+     bool enforceFragmentShaderTimingRestrictions(const TDependencyGraph& graph);
+     // Get built-in extensions with default behavior.
+     const TExtensionBehavior& getExtensionBehavior() const;
+ 
+     const BuiltInFunctionEmulator& getBuiltInFunctionEmulator() const;
+ 
+ private:
+     ShShaderType shaderType;
+     ShShaderSpec shaderSpec;
+ 
++    int maxUniformVectors;
++
+     // Built-in symbol table for the given language, spec, and resources.
+     // It is preserved from compile-to-compile.
+     TSymbolTable symbolTable;
+     // Built-in extensions with default behavior.
+     TExtensionBehavior extensionBehavior;
+ 
+     BuiltInFunctionEmulator builtInFunctionEmulator;
+ 
+diff --git a/gfx/angle/src/compiler/VariableInfo.cpp b/gfx/angle/src/compiler/VariableInfo.cpp
+--- a/gfx/angle/src/compiler/VariableInfo.cpp
++++ b/gfx/angle/src/compiler/VariableInfo.cpp
+@@ -133,16 +133,26 @@ void getUserDefinedVariableInfo(const TT
+         const TType* fieldType = (*structure)[i].type;
+         getVariableInfo(*fieldType,
+                         name + "." + fieldType->getFieldName(),
+                         mappedName + "." + fieldType->getFieldName(),
+                         infoList);
+     }
+ }
+ 
++TVariableInfo::TVariableInfo()
++{
++}
++
++TVariableInfo::TVariableInfo(ShDataType type, int size)
++    : type(type),
++      size(size)
++{
++}
++
+ CollectAttribsUniforms::CollectAttribsUniforms(TVariableInfoList& attribs,
+                                                TVariableInfoList& uniforms)
+     : mAttribs(attribs),
+       mUniforms(uniforms)
+ {
+ }
+ 
+ // We are only interested in attribute and uniform variable declaration.
+diff --git a/gfx/angle/src/compiler/VariableInfo.h b/gfx/angle/src/compiler/VariableInfo.h
+--- a/gfx/angle/src/compiler/VariableInfo.h
++++ b/gfx/angle/src/compiler/VariableInfo.h
+@@ -8,16 +8,19 @@
+ #define COMPILER_VARIABLE_INFO_H_
+ 
+ #include "GLSLANG/ShaderLang.h"
+ #include "compiler/intermediate.h"
+ 
+ // Provides information about a variable.
+ // It is currently being used to store info about active attribs and uniforms.
+ struct TVariableInfo {
++    TVariableInfo(ShDataType type, int size);
++    TVariableInfo();
++
+     TPersistString name;
+     TPersistString mappedName;
+     ShDataType type;
+     int size;
+ };
+ typedef std::vector<TVariableInfo> TVariableInfoList;
+ 
+ // Traverses intermediate tree to collect all attributes and uniforms.
+diff --git a/gfx/angle/src/compiler/VariablePacker.cpp b/gfx/angle/src/compiler/VariablePacker.cpp
+new file mode 100644
+--- /dev/null
++++ b/gfx/angle/src/compiler/VariablePacker.cpp
+@@ -0,0 +1,297 @@
++//
++// Copyright (c) 2002-2012 The ANGLE Project Authors. All rights reserved.
++// Use of this source code is governed by a BSD-style license that can be
++// found in the LICENSE file.
++//
++#include "compiler/VariablePacker.h"
++
++#include <algorithm>
++#include "compiler/ShHandle.h"
++
++namespace {
++int GetSortOrder(ShDataType type)
++{
++    switch (type) {
++        case SH_FLOAT_MAT4:
++            return 0;
++        case SH_FLOAT_MAT2:
++            return 1;
++        case SH_FLOAT_VEC4:
++        case SH_INT_VEC4:
++        case SH_BOOL_VEC4:
++            return 2;
++        case SH_FLOAT_MAT3:
++            return 3;
++        case SH_FLOAT_VEC3:
++        case SH_INT_VEC3:
++        case SH_BOOL_VEC3:
++            return 4;
++        case SH_FLOAT_VEC2:
++        case SH_INT_VEC2:
++        case SH_BOOL_VEC2:
++            return 5;
++        case SH_FLOAT:
++        case SH_INT:
++        case SH_BOOL:
++        case SH_SAMPLER_2D:
++        case SH_SAMPLER_CUBE:
++        case SH_SAMPLER_EXTERNAL_OES:
++        case SH_SAMPLER_2D_RECT_ARB:
++            return 6;
++        default:
++            ASSERT(false);
++            return 7;
++    }
++}
++}    // namespace
++
++int VariablePacker::GetNumComponentsPerRow(ShDataType type)
++{
++    switch (type) {
++        case SH_FLOAT_MAT4:
++        case SH_FLOAT_MAT2:
++        case SH_FLOAT_VEC4:
++        case SH_INT_VEC4:
++        case SH_BOOL_VEC4:
++            return 4;
++        case SH_FLOAT_MAT3:
++        case SH_FLOAT_VEC3:
++        case SH_INT_VEC3:
++        case SH_BOOL_VEC3:
++            return 3;
++        case SH_FLOAT_VEC2:
++        case SH_INT_VEC2:
++        case SH_BOOL_VEC2:
++            return 2;
++        case SH_FLOAT:
++        case SH_INT:
++        case SH_BOOL:
++        case SH_SAMPLER_2D:
++        case SH_SAMPLER_CUBE:
++        case SH_SAMPLER_EXTERNAL_OES:
++        case SH_SAMPLER_2D_RECT_ARB:
++            return 1;
++        default:
++            ASSERT(false);
++            return 5;
++    }
++}
++
++int VariablePacker::GetNumRows(ShDataType type)
++{
++    switch (type) {
++        case SH_FLOAT_MAT4:
++            return 4;
++        case SH_FLOAT_MAT3:
++            return 3;
++        case SH_FLOAT_MAT2:
++            return 1;
++        case SH_FLOAT_VEC4:
++        case SH_INT_VEC4:
++        case SH_BOOL_VEC4:
++        case SH_FLOAT_VEC3:
++        case SH_INT_VEC3:
++        case SH_BOOL_VEC3:
++        case SH_FLOAT_VEC2:
++        case SH_INT_VEC2:
++        case SH_BOOL_VEC2:
++        case SH_FLOAT:
++        case SH_INT:
++        case SH_BOOL:
++        case SH_SAMPLER_2D:
++        case SH_SAMPLER_CUBE:
++        case SH_SAMPLER_EXTERNAL_OES:
++        case SH_SAMPLER_2D_RECT_ARB:
++            return 1;
++        default:
++            ASSERT(false);
++            return 100000;
++    }
++}
++
++struct TVariableInfoComparer {
++    bool operator()(const TVariableInfo& lhs, const TVariableInfo& rhs) const
++    {
++        int lhsSortOrder = GetSortOrder(lhs.type);
++        int rhsSortOrder = GetSortOrder(rhs.type);
++        if (lhsSortOrder != rhsSortOrder) {
++            return lhsSortOrder < rhsSortOrder;
++        }
++        // Sort by largest first.
++        return lhs.size > rhs.size;
++    }
++};
++
++unsigned VariablePacker::makeColumnFlags(int column, int numComponentsPerRow)
++{
++    return ((kColumnMask << (kNumColumns - numComponentsPerRow)) &
++                    kColumnMask) >> column;
++}
++
++void VariablePacker::fillColumns(int topRow, int numRows, int column, int numComponentsPerRow)
++{
++    unsigned columnFlags = makeColumnFlags(column, numComponentsPerRow);
++    for (int r = 0; r < numRows; ++r) {
++        int row = topRow + r;
++        ASSERT((rows_[row] & columnFlags) == 0);
++        rows_[row] |= columnFlags;
++    }
++}
++
++bool VariablePacker::searchColumn(int column, int numRows, int* destRow, int* destSize)
++{
++    ASSERT(destRow);
++
++    for (; topNonFullRow_ < maxRows_ && rows_[topNonFullRow_] == kColumnMask;
++         ++topNonFullRow_) {
++    }
++
++    for (; bottomNonFullRow_ >= 0 && rows_[bottomNonFullRow_] == kColumnMask;
++         --bottomNonFullRow_) {
++    }
++
++    if (bottomNonFullRow_ - topNonFullRow_ + 1 < numRows) {
++        return false;
++    }
++
++    unsigned columnFlags = makeColumnFlags(column, 1);
++    int topGoodRow = 0;
++    int smallestGoodTop = -1;
++    int smallestGoodSize = maxRows_ + 1;
++    int bottomRow = bottomNonFullRow_ + 1;
++    bool found = false;
++    for (int row = topNonFullRow_; row <= bottomRow; ++row) {
++        bool rowEmpty = row < bottomRow ? ((rows_[row] & columnFlags) == 0) : false;
++        if (rowEmpty) {
++            if (!found) {
++                topGoodRow = row;
++                found = true;
++            }
++        } else {
++            if (found) {
++                int size = row - topGoodRow;
++                if (size >= numRows && size < smallestGoodSize) {
++                    smallestGoodSize = size;
++                    smallestGoodTop = topGoodRow;
++                }
++            }
++            found = false;
++        }
++    }
++    if (smallestGoodTop < 0) {
++        return false;
++    }
++
++    *destRow = smallestGoodTop;
++    if (destSize) {
++        *destSize = smallestGoodSize;
++    }
++    return true;
++}
++
++bool VariablePacker::CheckVariablesWithinPackingLimits(int maxVectors, const TVariableInfoList& in_variables)
++{
++    ASSERT(maxVectors > 0);
++    maxRows_ = maxVectors;
++    topNonFullRow_ = 0;
++    bottomNonFullRow_ = maxRows_ - 1;
++    TVariableInfoList variables(in_variables);
++
++    // As per GLSL 1.017 Appendix A, Section 7 variables are packed in specific
++    // order by type, then by size of array, largest first.
++    std::sort(variables.begin(), variables.end(), TVariableInfoComparer());
++    rows_.clear();
++    rows_.resize(maxVectors, 0);
++
++    // Packs the 4 column variables.
++    size_t ii = 0;
++    for (; ii < variables.size(); ++ii) {
++        const TVariableInfo& variable = variables[ii];
++        if (GetNumComponentsPerRow(variable.type) != 4) {
++            break;
++        }
++        topNonFullRow_ += GetNumRows(variable.type) * variable.size;
++    }
++
++    if (topNonFullRow_ > maxRows_) {
++        return false;
++    }
++
++    // Packs the 3 column variables.
++    int num3ColumnRows = 0;
++    for (; ii < variables.size(); ++ii) {
++        const TVariableInfo& variable = variables[ii];
++        if (GetNumComponentsPerRow(variable.type) != 3) {
++            break;
++        }
++        num3ColumnRows += GetNumRows(variable.type) * variable.size;
++    }
++
++    if (topNonFullRow_ + num3ColumnRows > maxRows_) {
++        return false;
++    }
++
++    fillColumns(topNonFullRow_, num3ColumnRows, 0, 3);
++
++    // Packs the 2 column variables.
++    int top2ColumnRow = topNonFullRow_ + num3ColumnRows;
++    int twoColumnRowsAvailable = maxRows_ - top2ColumnRow;
++    int rowsAvailableInColumns01 = twoColumnRowsAvailable;
++    int rowsAvailableInColumns23 = twoColumnRowsAvailable;
++    for (; ii < variables.size(); ++ii) {
++        const TVariableInfo& variable = variables[ii];
++        if (GetNumComponentsPerRow(variable.type) != 2) {
++            break;
++        }
++        int numRows = GetNumRows(variable.type) * variable.size;
++        if (numRows <= rowsAvailableInColumns01) {
++            rowsAvailableInColumns01 -= numRows;
++        } else if (numRows <= rowsAvailableInColumns23) {
++            rowsAvailableInColumns23 -= numRows;
++        } else {
++            return false;
++        }
++    }
++
++    int numRowsUsedInColumns01 =
++        twoColumnRowsAvailable - rowsAvailableInColumns01;
++    int numRowsUsedInColumns23 =
++        twoColumnRowsAvailable - rowsAvailableInColumns23;
++    fillColumns(top2ColumnRow, numRowsUsedInColumns01, 0, 2);
++    fillColumns(maxRows_ - numRowsUsedInColumns23, numRowsUsedInColumns23,
++                2, 2);
++
++    // Packs the 1 column variables.
++    for (; ii < variables.size(); ++ii) {
++        const TVariableInfo& variable = variables[ii];
++        ASSERT(1 == GetNumComponentsPerRow(variable.type));
++        int numRows = GetNumRows(variable.type) * variable.size;
++        int smallestColumn = -1;
++        int smallestSize = maxRows_ + 1;
++        int topRow = -1;
++        for (int column = 0; column < kNumColumns; ++column) {
++            int row = 0;
++            int size = 0;
++            if (searchColumn(column, numRows, &row, &size)) {
++                if (size < smallestSize) {
++                    smallestSize = size;
++                    smallestColumn = column;
++                    topRow = row;
++                }
++            }
++        }
++
++        if (smallestColumn < 0) {
++            return false;
++        }
++
++        fillColumns(topRow, numRows, smallestColumn, 1);
++    }
++
++    ASSERT(variables.size() == ii);
++
++    return true;
++}
++
++
++
+diff --git a/gfx/angle/src/compiler/VariablePacker.h b/gfx/angle/src/compiler/VariablePacker.h
+new file mode 100644
+--- /dev/null
++++ b/gfx/angle/src/compiler/VariablePacker.h
+@@ -0,0 +1,41 @@
++//
++// Copyright (c) 2002-2012 The ANGLE Project Authors. All rights reserved.
++// Use of this source code is governed by a BSD-style license that can be
++// found in the LICENSE file.
++//
++
++#ifndef _VARIABLEPACKER_INCLUDED_
++#define _VARIABLEPACKER_INCLUDED_
++
++#include <vector>
++#include "compiler/ShHandle.h"
++
++class VariablePacker {
++ public:
++    // Returns true if the passed in variables pack in maxVectors following
++    // the packing rules from the GLSL 1.017 spec, Appendix A, section 7.
++    bool CheckVariablesWithinPackingLimits(
++        int maxVectors,
++        const TVariableInfoList& in_variables);
++
++    // Gets how many components in a row a data type takes.
++    static int GetNumComponentsPerRow(ShDataType type);
++
++    // Gets how many rows a data type takes.
++    static int GetNumRows(ShDataType type);
++
++ private:
++    static const int kNumColumns = 4;
++    static const unsigned kColumnMask = (1 << kNumColumns) - 1;
++
++    unsigned makeColumnFlags(int column, int numComponentsPerRow);
++    void fillColumns(int topRow, int numRows, int column, int numComponentsPerRow);
++    bool searchColumn(int column, int numRows, int* destRow, int* destSize);
++
++    int topNonFullRow_;
++    int bottomNonFullRow_;
++    int maxRows_;
++    std::vector<unsigned> rows_;
++};
++
++#endif // _VARIABLEPACKER_INCLUDED_
+diff --git a/gfx/angle/src/libGLESv2/Makefile.in b/gfx/angle/src/libGLESv2/Makefile.in
+--- a/gfx/angle/src/libGLESv2/Makefile.in
++++ b/gfx/angle/src/libGLESv2/Makefile.in
+@@ -84,16 +84,17 @@ CPPSRCS = \
+         ForLoopUnroll.cpp \
+         MapLongVariableNames.cpp \
+         spooky.cpp \
+         BuiltInFunctionEmulator.cpp \
+         Input.cpp \
+         Lexer.cpp \
+         Preprocessor.cpp \
+         Token.cpp \
++        VariablePacker.cpp \
+         $(NULL)
+ 
+ # flex/yacc generated files
+ CPPSRCS += \
+         glslang_lex.cpp \
+         glslang_tab.cpp \
+         $(NULL)
+ 
+diff --git a/gfx/angle/tests/build_tests.gyp b/gfx/angle/tests/build_tests.gyp
+--- a/gfx/angle/tests/build_tests.gyp
++++ b/gfx/angle/tests/build_tests.gyp
+@@ -58,16 +58,35 @@
+         'preprocessor_tests/pragma_test.cpp',
+         'preprocessor_tests/PreprocessorTest.cpp',
+         'preprocessor_tests/PreprocessorTest.h',
+         'preprocessor_tests/space_test.cpp',
+         'preprocessor_tests/token_test.cpp',
+         'preprocessor_tests/version_test.cpp',
+       ],
+     },
++    {
++      'target_name': 'compiler_tests',
++      'type': 'executable',
++      'dependencies': [
++        '../src/build_angle.gyp:translator_common',
++        'gtest',
++        'gmock',
++      ],
++      'include_dirs': [
++        '../include',
++        '../src',
++        '../third_party/googletest/include',
++        '../third_party/googlemock/include',
++      ],
++      'sources': [
++        '../third_party/googlemock/src/gmock_main.cc',
++        'compiler_tests/VariablePacker_test.cpp',
++      ],
++    },
+   ],
+ }
+ 
+ # Local Variables:
+ # tab-width:2
+ # indent-tabs-mode:nil
+ # End:
+ # vim: set expandtab tabstop=2 shiftwidth=2:
+diff --git a/gfx/angle/tests/compiler_tests/VariablePacker_test.cpp b/gfx/angle/tests/compiler_tests/VariablePacker_test.cpp
+new file mode 100644
+--- /dev/null
++++ b/gfx/angle/tests/compiler_tests/VariablePacker_test.cpp
+@@ -0,0 +1,85 @@
++//
++// Copyright (c) 2002-2012 The ANGLE Project Authors. All rights reserved.
++// Use of this source code is governed by a BSD-style license that can be
++// found in the LICENSE file.
++//
++#include "compiler/VariablePacker.h"
++#include "gtest/gtest.h"
++
++TEST(VariablePacking, Pack) {
++  VariablePacker packer;
++  TVariableInfoList vars;
++  const int kMaxRows = 16;
++  // test no vars.
++  EXPECT_TRUE(packer.CheckVariablesWithinPackingLimits(kMaxRows, vars));
++
++  ShDataType types[] = {
++    SH_FLOAT_MAT4,            // 0
++    SH_FLOAT_MAT2,            // 1
++    SH_FLOAT_VEC4,            // 2
++    SH_INT_VEC4,              // 3
++    SH_BOOL_VEC4,             // 4
++    SH_FLOAT_MAT3,            // 5
++    SH_FLOAT_VEC3,            // 6
++    SH_INT_VEC3,              // 7
++    SH_BOOL_VEC3,             // 8
++    SH_FLOAT_VEC2,            // 9
++    SH_INT_VEC2,              // 10
++    SH_BOOL_VEC2,             // 11
++    SH_FLOAT,                 // 12
++    SH_INT,                   // 13
++    SH_BOOL,                  // 14
++    SH_SAMPLER_2D,            // 15
++    SH_SAMPLER_CUBE,          // 16
++    SH_SAMPLER_EXTERNAL_OES,  // 17
++    SH_SAMPLER_2D_RECT_ARB,   // 18
++  };
++
++  for (size_t tt = 0; tt < sizeof(types) / sizeof(types[0]); ++tt) {
++    ShDataType type = types[tt];
++    int num_rows = VariablePacker::GetNumRows(type);
++    int num_components_per_row = VariablePacker::GetNumComponentsPerRow(type);
++    // Check 1 of the type.
++    vars.clear();
++    vars.push_back(TVariableInfo(type, 1));
++    EXPECT_TRUE(packer.CheckVariablesWithinPackingLimits(kMaxRows, vars));
++
++    // Check exactly the right amount of 1 type as an array.
++    int num_vars = kMaxRows / num_rows;
++    vars.clear();
++    vars.push_back(TVariableInfo(type, num_vars));
++    EXPECT_TRUE(packer.CheckVariablesWithinPackingLimits(kMaxRows, vars));
++
++    // test too many
++    vars.clear();
++    vars.push_back(TVariableInfo(type, num_vars + 1));
++    EXPECT_FALSE(packer.CheckVariablesWithinPackingLimits(kMaxRows, vars));
++
++    // Check exactly the right amount of 1 type as individual vars.
++    num_vars = kMaxRows / num_rows *
++        ((num_components_per_row > 2) ? 1 : (4 / num_components_per_row));
++    vars.clear();
++    for (int ii = 0; ii < num_vars; ++ii) {
++      vars.push_back(TVariableInfo(type, 1));
++    }
++    EXPECT_TRUE(packer.CheckVariablesWithinPackingLimits(kMaxRows, vars));
++
++    // Check 1 too many.
++    vars.push_back(TVariableInfo( type, 1));
++    EXPECT_FALSE(packer.CheckVariablesWithinPackingLimits(kMaxRows, vars));
++  }
++
++  // Test example from GLSL ES 3.0 spec chapter 11.
++  vars.clear();
++  vars.push_back(TVariableInfo(SH_FLOAT_VEC4, 1));
++  vars.push_back(TVariableInfo(SH_FLOAT_MAT3, 1));
++  vars.push_back(TVariableInfo(SH_FLOAT_MAT3, 1));
++  vars.push_back(TVariableInfo(SH_FLOAT_VEC2, 6));
++  vars.push_back(TVariableInfo(SH_FLOAT_VEC2, 4));
++  vars.push_back(TVariableInfo(SH_FLOAT_VEC2, 1));
++  vars.push_back(TVariableInfo(SH_FLOAT, 3));
++  vars.push_back(TVariableInfo(SH_FLOAT, 2));
++  vars.push_back(TVariableInfo(SH_FLOAT, 1));
++  EXPECT_TRUE(packer.CheckVariablesWithinPackingLimits(kMaxRows, vars));
++}
++
--- a/gfx/angle/include/GLSLANG/ShaderLang.h
+++ b/gfx/angle/include/GLSLANG/ShaderLang.h
@@ -137,17 +137,20 @@ typedef enum {
   SH_TIMING_RESTRICTIONS = 0x0200,
     
   // This flag prints the dependency graph that is used to enforce timing
   // restrictions on fragment shaders.
   // This flag only has an effect if all of the following are true:
   // - The shader spec is SH_WEBGL_SPEC.
   // - The compile options contain the SH_TIMING_RESTRICTIONS flag.
   // - The shader type is SH_FRAGMENT_SHADER.
-  SH_DEPENDENCY_GRAPH = 0x0400
+  SH_DEPENDENCY_GRAPH = 0x0400,
+
+  // Enforce the GLSL 1.017 Appendix A section 7 packing restrictions.
+  SH_ENFORCE_PACKING_RESTRICTIONS = 0x0800,
 } ShCompileOptions;
 
 //
 // Driver must call this first, once, before doing any other
 // compiler operations.
 // If the function succeeds, the return value is nonzero, else zero.
 //
 COMPILER_EXPORT int ShInitialize();
--- a/gfx/angle/src/compiler/Compiler.cpp
+++ b/gfx/angle/src/compiler/Compiler.cpp
@@ -9,16 +9,17 @@
 #include "compiler/ForLoopUnroll.h"
 #include "compiler/Initialize.h"
 #include "compiler/InitializeParseContext.h"
 #include "compiler/MapLongVariableNames.h"
 #include "compiler/ParseHelper.h"
 #include "compiler/RenameFunction.h"
 #include "compiler/ShHandle.h"
 #include "compiler/ValidateLimitations.h"
+#include "compiler/VariablePacker.h"
 #include "compiler/depgraph/DependencyGraph.h"
 #include "compiler/depgraph/DependencyGraphOutput.h"
 #include "compiler/timing/RestrictFragmentShaderTiming.h"
 #include "compiler/timing/RestrictVertexShaderTiming.h"
 
 bool isWebGLBasedSpec(ShShaderSpec spec)
 {
      return spec == SH_WEBGL_SPEC || spec == SH_CSS_SHADERS_SPEC;
@@ -108,16 +109,19 @@ TCompiler::TCompiler(ShShaderType type, 
 TCompiler::~TCompiler()
 {
     ASSERT(longNameMap);
     longNameMap->Release();
 }
 
 bool TCompiler::Init(const ShBuiltInResources& resources)
 {
+    maxUniformVectors = (shaderType == SH_VERTEX_SHADER) ?
+        resources.MaxVertexUniformVectors :
+        resources.MaxFragmentUniformVectors;
     TScopedPoolAllocator scopedAlloc(&allocator, false);
 
     // Generate built-in symbol table.
     if (!InitBuiltInSymbolTable(resources))
         return false;
     InitExtensionBehavior(resources, extensionBehavior);
 
     return true;
@@ -187,18 +191,25 @@ bool TCompiler::compile(const char* cons
             builtInFunctionEmulator.MarkBuiltInFunctionsForEmulation(root);
 
         // Call mapLongVariableNames() before collectAttribsUniforms() so in
         // collectAttribsUniforms() we already have the mapped symbol names and
         // we could composite mapped and original variable names.
         if (success && (compileOptions & SH_MAP_LONG_VARIABLE_NAMES))
             mapLongVariableNames(root);
 
-        if (success && (compileOptions & SH_ATTRIBUTES_UNIFORMS))
+        if (success && (compileOptions & SH_ATTRIBUTES_UNIFORMS)) {
             collectAttribsUniforms(root);
+            if (compileOptions & SH_ENFORCE_PACKING_RESTRICTIONS) {
+                success = enforcePackingRestrictions();
+                if (!success) {
+                    infoSink.info.message(EPrefixError, "too many uniforms");
+                }
+            }
+        }
 
         if (success && (compileOptions & SH_INTERMEDIATE_TREE))
             intermediate.outputTree(root);
 
         if (success && (compileOptions & SH_OBJECT_CODE))
             translate(root);
     }
 
@@ -305,16 +316,22 @@ bool TCompiler::enforceVertexShaderTimin
 }
 
 void TCompiler::collectAttribsUniforms(TIntermNode* root)
 {
     CollectAttribsUniforms collect(attribs, uniforms);
     root->traverse(&collect);
 }
 
+bool TCompiler::enforcePackingRestrictions()
+{
+    VariablePacker packer;
+    return packer.CheckVariablesWithinPackingLimits(maxUniformVectors, uniforms);
+}
+
 void TCompiler::mapLongVariableNames(TIntermNode* root)
 {
     ASSERT(longNameMap);
     MapLongVariableNames map(longNameMap);
     root->traverse(&map);
 }
 
 int TCompiler::getMappedNameMaxLength() const
--- a/gfx/angle/src/compiler/ShHandle.h
+++ b/gfx/angle/src/compiler/ShHandle.h
@@ -83,32 +83,37 @@ protected:
     // functionality mandated in GLSL 1.0 spec Appendix A.
     bool validateLimitations(TIntermNode* root);
     // Collect info for all attribs and uniforms.
     void collectAttribsUniforms(TIntermNode* root);
     // Map long variable names into shorter ones.
     void mapLongVariableNames(TIntermNode* root);
     // Translate to object code.
     virtual void translate(TIntermNode* root) = 0;
+    // Returns true if, after applying the packing rules in the GLSL 1.017 spec
+    // Appendix A, section 7, the shader does not use too many uniforms.
+    bool enforcePackingRestrictions();
     // Returns true if the shader passes the restrictions that aim to prevent timing attacks.
     bool enforceTimingRestrictions(TIntermNode* root, bool outputGraph);
     // Returns true if the shader does not use samplers.
     bool enforceVertexShaderTimingRestrictions(TIntermNode* root);
     // Returns true if the shader does not use sampler dependent values to affect control 
     // flow or in operations whose time can depend on the input values.
     bool enforceFragmentShaderTimingRestrictions(const TDependencyGraph& graph);
     // Get built-in extensions with default behavior.
     const TExtensionBehavior& getExtensionBehavior() const;
 
     const BuiltInFunctionEmulator& getBuiltInFunctionEmulator() const;
 
 private:
     ShShaderType shaderType;
     ShShaderSpec shaderSpec;
 
+    int maxUniformVectors;
+
     // Built-in symbol table for the given language, spec, and resources.
     // It is preserved from compile-to-compile.
     TSymbolTable symbolTable;
     // Built-in extensions with default behavior.
     TExtensionBehavior extensionBehavior;
 
     BuiltInFunctionEmulator builtInFunctionEmulator;
 
--- a/gfx/angle/src/compiler/VariableInfo.cpp
+++ b/gfx/angle/src/compiler/VariableInfo.cpp
@@ -133,16 +133,26 @@ void getUserDefinedVariableInfo(const TT
         const TType* fieldType = (*structure)[i].type;
         getVariableInfo(*fieldType,
                         name + "." + fieldType->getFieldName(),
                         mappedName + "." + fieldType->getFieldName(),
                         infoList);
     }
 }
 
+TVariableInfo::TVariableInfo()
+{
+}
+
+TVariableInfo::TVariableInfo(ShDataType type, int size)
+    : type(type),
+      size(size)
+{
+}
+
 CollectAttribsUniforms::CollectAttribsUniforms(TVariableInfoList& attribs,
                                                TVariableInfoList& uniforms)
     : mAttribs(attribs),
       mUniforms(uniforms)
 {
 }
 
 // We are only interested in attribute and uniform variable declaration.
--- a/gfx/angle/src/compiler/VariableInfo.h
+++ b/gfx/angle/src/compiler/VariableInfo.h
@@ -8,16 +8,19 @@
 #define COMPILER_VARIABLE_INFO_H_
 
 #include "GLSLANG/ShaderLang.h"
 #include "compiler/intermediate.h"
 
 // Provides information about a variable.
 // It is currently being used to store info about active attribs and uniforms.
 struct TVariableInfo {
+    TVariableInfo(ShDataType type, int size);
+    TVariableInfo();
+
     TPersistString name;
     TPersistString mappedName;
     ShDataType type;
     int size;
 };
 typedef std::vector<TVariableInfo> TVariableInfoList;
 
 // Traverses intermediate tree to collect all attributes and uniforms.
new file mode 100644
--- /dev/null
+++ b/gfx/angle/src/compiler/VariablePacker.cpp
@@ -0,0 +1,297 @@
+//
+// Copyright (c) 2002-2012 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+#include "compiler/VariablePacker.h"
+
+#include <algorithm>
+#include "compiler/ShHandle.h"
+
+namespace {
+int GetSortOrder(ShDataType type)
+{
+    switch (type) {
+        case SH_FLOAT_MAT4:
+            return 0;
+        case SH_FLOAT_MAT2:
+            return 1;
+        case SH_FLOAT_VEC4:
+        case SH_INT_VEC4:
+        case SH_BOOL_VEC4:
+            return 2;
+        case SH_FLOAT_MAT3:
+            return 3;
+        case SH_FLOAT_VEC3:
+        case SH_INT_VEC3:
+        case SH_BOOL_VEC3:
+            return 4;
+        case SH_FLOAT_VEC2:
+        case SH_INT_VEC2:
+        case SH_BOOL_VEC2:
+            return 5;
+        case SH_FLOAT:
+        case SH_INT:
+        case SH_BOOL:
+        case SH_SAMPLER_2D:
+        case SH_SAMPLER_CUBE:
+        case SH_SAMPLER_EXTERNAL_OES:
+        case SH_SAMPLER_2D_RECT_ARB:
+            return 6;
+        default:
+            ASSERT(false);
+            return 7;
+    }
+}
+}    // namespace
+
+int VariablePacker::GetNumComponentsPerRow(ShDataType type)
+{
+    switch (type) {
+        case SH_FLOAT_MAT4:
+        case SH_FLOAT_MAT2:
+        case SH_FLOAT_VEC4:
+        case SH_INT_VEC4:
+        case SH_BOOL_VEC4:
+            return 4;
+        case SH_FLOAT_MAT3:
+        case SH_FLOAT_VEC3:
+        case SH_INT_VEC3:
+        case SH_BOOL_VEC3:
+            return 3;
+        case SH_FLOAT_VEC2:
+        case SH_INT_VEC2:
+        case SH_BOOL_VEC2:
+            return 2;
+        case SH_FLOAT:
+        case SH_INT:
+        case SH_BOOL:
+        case SH_SAMPLER_2D:
+        case SH_SAMPLER_CUBE:
+        case SH_SAMPLER_EXTERNAL_OES:
+        case SH_SAMPLER_2D_RECT_ARB:
+            return 1;
+        default:
+            ASSERT(false);
+            return 5;
+    }
+}
+
+int VariablePacker::GetNumRows(ShDataType type)
+{
+    switch (type) {
+        case SH_FLOAT_MAT4:
+            return 4;
+        case SH_FLOAT_MAT3:
+            return 3;
+        case SH_FLOAT_MAT2:
+            return 1;
+        case SH_FLOAT_VEC4:
+        case SH_INT_VEC4:
+        case SH_BOOL_VEC4:
+        case SH_FLOAT_VEC3:
+        case SH_INT_VEC3:
+        case SH_BOOL_VEC3:
+        case SH_FLOAT_VEC2:
+        case SH_INT_VEC2:
+        case SH_BOOL_VEC2:
+        case SH_FLOAT:
+        case SH_INT:
+        case SH_BOOL:
+        case SH_SAMPLER_2D:
+        case SH_SAMPLER_CUBE:
+        case SH_SAMPLER_EXTERNAL_OES:
+        case SH_SAMPLER_2D_RECT_ARB:
+            return 1;
+        default:
+            ASSERT(false);
+            return 100000;
+    }
+}
+
+struct TVariableInfoComparer {
+    bool operator()(const TVariableInfo& lhs, const TVariableInfo& rhs) const
+    {
+        int lhsSortOrder = GetSortOrder(lhs.type);
+        int rhsSortOrder = GetSortOrder(rhs.type);
+        if (lhsSortOrder != rhsSortOrder) {
+            return lhsSortOrder < rhsSortOrder;
+        }
+        // Sort by largest first.
+        return lhs.size > rhs.size;
+    }
+};
+
+unsigned VariablePacker::makeColumnFlags(int column, int numComponentsPerRow)
+{
+    return ((kColumnMask << (kNumColumns - numComponentsPerRow)) &
+                    kColumnMask) >> column;
+}
+
+void VariablePacker::fillColumns(int topRow, int numRows, int column, int numComponentsPerRow)
+{
+    unsigned columnFlags = makeColumnFlags(column, numComponentsPerRow);
+    for (int r = 0; r < numRows; ++r) {
+        int row = topRow + r;
+        ASSERT((rows_[row] & columnFlags) == 0);
+        rows_[row] |= columnFlags;
+    }
+}
+
+bool VariablePacker::searchColumn(int column, int numRows, int* destRow, int* destSize)
+{
+    ASSERT(destRow);
+
+    for (; topNonFullRow_ < maxRows_ && rows_[topNonFullRow_] == kColumnMask;
+         ++topNonFullRow_) {
+    }
+
+    for (; bottomNonFullRow_ >= 0 && rows_[bottomNonFullRow_] == kColumnMask;
+         --bottomNonFullRow_) {
+    }
+
+    if (bottomNonFullRow_ - topNonFullRow_ + 1 < numRows) {
+        return false;
+    }
+
+    unsigned columnFlags = makeColumnFlags(column, 1);
+    int topGoodRow = 0;
+    int smallestGoodTop = -1;
+    int smallestGoodSize = maxRows_ + 1;
+    int bottomRow = bottomNonFullRow_ + 1;
+    bool found = false;
+    for (int row = topNonFullRow_; row <= bottomRow; ++row) {
+        bool rowEmpty = row < bottomRow ? ((rows_[row] & columnFlags) == 0) : false;
+        if (rowEmpty) {
+            if (!found) {
+                topGoodRow = row;
+                found = true;
+            }
+        } else {
+            if (found) {
+                int size = row - topGoodRow;
+                if (size >= numRows && size < smallestGoodSize) {
+                    smallestGoodSize = size;
+                    smallestGoodTop = topGoodRow;
+                }
+            }
+            found = false;
+        }
+    }
+    if (smallestGoodTop < 0) {
+        return false;
+    }
+
+    *destRow = smallestGoodTop;
+    if (destSize) {
+        *destSize = smallestGoodSize;
+    }
+    return true;
+}
+
+bool VariablePacker::CheckVariablesWithinPackingLimits(int maxVectors, const TVariableInfoList& in_variables)
+{
+    ASSERT(maxVectors > 0);
+    maxRows_ = maxVectors;
+    topNonFullRow_ = 0;
+    bottomNonFullRow_ = maxRows_ - 1;
+    TVariableInfoList variables(in_variables);
+
+    // As per GLSL 1.017 Appendix A, Section 7 variables are packed in specific
+    // order by type, then by size of array, largest first.
+    std::sort(variables.begin(), variables.end(), TVariableInfoComparer());
+    rows_.clear();
+    rows_.resize(maxVectors, 0);
+
+    // Packs the 4 column variables.
+    size_t ii = 0;
+    for (; ii < variables.size(); ++ii) {
+        const TVariableInfo& variable = variables[ii];
+        if (GetNumComponentsPerRow(variable.type) != 4) {
+            break;
+        }
+        topNonFullRow_ += GetNumRows(variable.type) * variable.size;
+    }
+
+    if (topNonFullRow_ > maxRows_) {
+        return false;
+    }
+
+    // Packs the 3 column variables.
+    int num3ColumnRows = 0;
+    for (; ii < variables.size(); ++ii) {
+        const TVariableInfo& variable = variables[ii];
+        if (GetNumComponentsPerRow(variable.type) != 3) {
+            break;
+        }
+        num3ColumnRows += GetNumRows(variable.type) * variable.size;
+    }
+
+    if (topNonFullRow_ + num3ColumnRows > maxRows_) {
+        return false;
+    }
+
+    fillColumns(topNonFullRow_, num3ColumnRows, 0, 3);
+
+    // Packs the 2 column variables.
+    int top2ColumnRow = topNonFullRow_ + num3ColumnRows;
+    int twoColumnRowsAvailable = maxRows_ - top2ColumnRow;
+    int rowsAvailableInColumns01 = twoColumnRowsAvailable;
+    int rowsAvailableInColumns23 = twoColumnRowsAvailable;
+    for (; ii < variables.size(); ++ii) {
+        const TVariableInfo& variable = variables[ii];
+        if (GetNumComponentsPerRow(variable.type) != 2) {
+            break;
+        }
+        int numRows = GetNumRows(variable.type) * variable.size;
+        if (numRows <= rowsAvailableInColumns01) {
+            rowsAvailableInColumns01 -= numRows;
+        } else if (numRows <= rowsAvailableInColumns23) {
+            rowsAvailableInColumns23 -= numRows;
+        } else {
+            return false;
+        }
+    }
+
+    int numRowsUsedInColumns01 =
+        twoColumnRowsAvailable - rowsAvailableInColumns01;
+    int numRowsUsedInColumns23 =
+        twoColumnRowsAvailable - rowsAvailableInColumns23;
+    fillColumns(top2ColumnRow, numRowsUsedInColumns01, 0, 2);
+    fillColumns(maxRows_ - numRowsUsedInColumns23, numRowsUsedInColumns23,
+                2, 2);
+
+    // Packs the 1 column variables.
+    for (; ii < variables.size(); ++ii) {
+        const TVariableInfo& variable = variables[ii];
+        ASSERT(1 == GetNumComponentsPerRow(variable.type));
+        int numRows = GetNumRows(variable.type) * variable.size;
+        int smallestColumn = -1;
+        int smallestSize = maxRows_ + 1;
+        int topRow = -1;
+        for (int column = 0; column < kNumColumns; ++column) {
+            int row = 0;
+            int size = 0;
+            if (searchColumn(column, numRows, &row, &size)) {
+                if (size < smallestSize) {
+                    smallestSize = size;
+                    smallestColumn = column;
+                    topRow = row;
+                }
+            }
+        }
+
+        if (smallestColumn < 0) {
+            return false;
+        }
+
+        fillColumns(topRow, numRows, smallestColumn, 1);
+    }
+
+    ASSERT(variables.size() == ii);
+
+    return true;
+}
+
+
+
new file mode 100644
--- /dev/null
+++ b/gfx/angle/src/compiler/VariablePacker.h
@@ -0,0 +1,41 @@
+//
+// Copyright (c) 2002-2012 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+#ifndef _VARIABLEPACKER_INCLUDED_
+#define _VARIABLEPACKER_INCLUDED_
+
+#include <vector>
+#include "compiler/ShHandle.h"
+
+class VariablePacker {
+ public:
+    // Returns true if the passed in variables pack in maxVectors following
+    // the packing rules from the GLSL 1.017 spec, Appendix A, section 7.
+    bool CheckVariablesWithinPackingLimits(
+        int maxVectors,
+        const TVariableInfoList& in_variables);
+
+    // Gets how many components in a row a data type takes.
+    static int GetNumComponentsPerRow(ShDataType type);
+
+    // Gets how many rows a data type takes.
+    static int GetNumRows(ShDataType type);
+
+ private:
+    static const int kNumColumns = 4;
+    static const unsigned kColumnMask = (1 << kNumColumns) - 1;
+
+    unsigned makeColumnFlags(int column, int numComponentsPerRow);
+    void fillColumns(int topRow, int numRows, int column, int numComponentsPerRow);
+    bool searchColumn(int column, int numRows, int* destRow, int* destSize);
+
+    int topNonFullRow_;
+    int bottomNonFullRow_;
+    int maxRows_;
+    std::vector<unsigned> rows_;
+};
+
+#endif // _VARIABLEPACKER_INCLUDED_
--- a/gfx/angle/src/libGLESv2/Makefile.in
+++ b/gfx/angle/src/libGLESv2/Makefile.in
@@ -84,16 +84,17 @@ CPPSRCS = \
         ForLoopUnroll.cpp \
         MapLongVariableNames.cpp \
         spooky.cpp \
         BuiltInFunctionEmulator.cpp \
         Input.cpp \
         Lexer.cpp \
         Preprocessor.cpp \
         Token.cpp \
+        VariablePacker.cpp \
         $(NULL)
 
 # flex/yacc generated files
 CPPSRCS += \
         glslang_lex.cpp \
         glslang_tab.cpp \
         $(NULL)
 
--- a/gfx/angle/tests/build_tests.gyp
+++ b/gfx/angle/tests/build_tests.gyp
@@ -58,16 +58,35 @@
         'preprocessor_tests/pragma_test.cpp',
         'preprocessor_tests/PreprocessorTest.cpp',
         'preprocessor_tests/PreprocessorTest.h',
         'preprocessor_tests/space_test.cpp',
         'preprocessor_tests/token_test.cpp',
         'preprocessor_tests/version_test.cpp',
       ],
     },
+    {
+      'target_name': 'compiler_tests',
+      'type': 'executable',
+      'dependencies': [
+        '../src/build_angle.gyp:translator_common',
+        'gtest',
+        'gmock',
+      ],
+      'include_dirs': [
+        '../include',
+        '../src',
+        '../third_party/googletest/include',
+        '../third_party/googlemock/include',
+      ],
+      'sources': [
+        '../third_party/googlemock/src/gmock_main.cc',
+        'compiler_tests/VariablePacker_test.cpp',
+      ],
+    },
   ],
 }
 
 # Local Variables:
 # tab-width:2
 # indent-tabs-mode:nil
 # End:
 # vim: set expandtab tabstop=2 shiftwidth=2:
new file mode 100644
--- /dev/null
+++ b/gfx/angle/tests/compiler_tests/VariablePacker_test.cpp
@@ -0,0 +1,85 @@
+//
+// Copyright (c) 2002-2012 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+#include "compiler/VariablePacker.h"
+#include "gtest/gtest.h"
+
+TEST(VariablePacking, Pack) {
+  VariablePacker packer;
+  TVariableInfoList vars;
+  const int kMaxRows = 16;
+  // test no vars.
+  EXPECT_TRUE(packer.CheckVariablesWithinPackingLimits(kMaxRows, vars));
+
+  ShDataType types[] = {
+    SH_FLOAT_MAT4,            // 0
+    SH_FLOAT_MAT2,            // 1
+    SH_FLOAT_VEC4,            // 2
+    SH_INT_VEC4,              // 3
+    SH_BOOL_VEC4,             // 4
+    SH_FLOAT_MAT3,            // 5
+    SH_FLOAT_VEC3,            // 6
+    SH_INT_VEC3,              // 7
+    SH_BOOL_VEC3,             // 8
+    SH_FLOAT_VEC2,            // 9
+    SH_INT_VEC2,              // 10
+    SH_BOOL_VEC2,             // 11
+    SH_FLOAT,                 // 12
+    SH_INT,                   // 13
+    SH_BOOL,                  // 14
+    SH_SAMPLER_2D,            // 15
+    SH_SAMPLER_CUBE,          // 16
+    SH_SAMPLER_EXTERNAL_OES,  // 17
+    SH_SAMPLER_2D_RECT_ARB,   // 18
+  };
+
+  for (size_t tt = 0; tt < sizeof(types) / sizeof(types[0]); ++tt) {
+    ShDataType type = types[tt];
+    int num_rows = VariablePacker::GetNumRows(type);
+    int num_components_per_row = VariablePacker::GetNumComponentsPerRow(type);
+    // Check 1 of the type.
+    vars.clear();
+    vars.push_back(TVariableInfo(type, 1));
+    EXPECT_TRUE(packer.CheckVariablesWithinPackingLimits(kMaxRows, vars));
+
+    // Check exactly the right amount of 1 type as an array.
+    int num_vars = kMaxRows / num_rows;
+    vars.clear();
+    vars.push_back(TVariableInfo(type, num_vars));
+    EXPECT_TRUE(packer.CheckVariablesWithinPackingLimits(kMaxRows, vars));
+
+    // test too many
+    vars.clear();
+    vars.push_back(TVariableInfo(type, num_vars + 1));
+    EXPECT_FALSE(packer.CheckVariablesWithinPackingLimits(kMaxRows, vars));
+
+    // Check exactly the right amount of 1 type as individual vars.
+    num_vars = kMaxRows / num_rows *
+        ((num_components_per_row > 2) ? 1 : (4 / num_components_per_row));
+    vars.clear();
+    for (int ii = 0; ii < num_vars; ++ii) {
+      vars.push_back(TVariableInfo(type, 1));
+    }
+    EXPECT_TRUE(packer.CheckVariablesWithinPackingLimits(kMaxRows, vars));
+
+    // Check 1 too many.
+    vars.push_back(TVariableInfo( type, 1));
+    EXPECT_FALSE(packer.CheckVariablesWithinPackingLimits(kMaxRows, vars));
+  }
+
+  // Test example from GLSL ES 3.0 spec chapter 11.
+  vars.clear();
+  vars.push_back(TVariableInfo(SH_FLOAT_VEC4, 1));
+  vars.push_back(TVariableInfo(SH_FLOAT_MAT3, 1));
+  vars.push_back(TVariableInfo(SH_FLOAT_MAT3, 1));
+  vars.push_back(TVariableInfo(SH_FLOAT_VEC2, 6));
+  vars.push_back(TVariableInfo(SH_FLOAT_VEC2, 4));
+  vars.push_back(TVariableInfo(SH_FLOAT_VEC2, 1));
+  vars.push_back(TVariableInfo(SH_FLOAT, 3));
+  vars.push_back(TVariableInfo(SH_FLOAT, 2));
+  vars.push_back(TVariableInfo(SH_FLOAT, 1));
+  EXPECT_TRUE(packer.CheckVariablesWithinPackingLimits(kMaxRows, vars));
+}
+
--- a/gfx/gl/GLContext.cpp
+++ b/gfx/gl/GLContext.cpp
@@ -290,17 +290,18 @@ GLContext::InitWithPrefix(const char *pr
         // The order of these strings must match up with the order of the enum
         // defined in GLContext.h for vendor IDs
         glVendorString = (const char *)fGetString(LOCAL_GL_VENDOR);
         const char *vendorMatchStrings[VendorOther] = {
                 "Intel",
                 "NVIDIA",
                 "ATI",
                 "Qualcomm",
-                "Imagination"
+                "Imagination",
+                "nouveau"
         };
         mVendor = VendorOther;
         for (int i = 0; i < VendorOther; ++i) {
             if (DoesStringMatch(glVendorString, vendorMatchStrings[i])) {
                 mVendor = i;
                 break;
             }
         }
@@ -509,21 +510,30 @@ GLContext::InitWithPrefix(const char *pr
 
         raw_fGetIntegerv(LOCAL_GL_MAX_TEXTURE_SIZE, &mMaxTextureSize);
         raw_fGetIntegerv(LOCAL_GL_MAX_CUBE_MAP_TEXTURE_SIZE, &mMaxCubeMapTextureSize);
         raw_fGetIntegerv(LOCAL_GL_MAX_RENDERBUFFER_SIZE, &mMaxRenderbufferSize);
 
 #ifdef XP_MACOSX
         if (mWorkAroundDriverBugs &&
             mVendor == VendorIntel) {
-            // see bug 737182 for 2D textures, bug 684822 for cube map textures.
+            // see bug 737182 for 2D textures, bug 684882 for cube map textures.
             mMaxTextureSize        = NS_MIN(mMaxTextureSize,        4096);
             mMaxCubeMapTextureSize = NS_MIN(mMaxCubeMapTextureSize, 512);
             // for good measure, we align renderbuffers on what we do for 2D textures
             mMaxRenderbufferSize   = NS_MIN(mMaxRenderbufferSize,   4096);
+            mNeedsTextureSizeChecks = true;
+        }
+#endif
+#ifdef MOZ_X11
+        if (mWorkAroundDriverBugs &&
+            mVendor == VendorNouveau) {
+            // see bug 814716. Clamp MaxCubeMapTextureSize at 2K for Nouveau.
+            mMaxCubeMapTextureSize = NS_MIN(mMaxCubeMapTextureSize, 2048);
+            mNeedsTextureSizeChecks = true;
         }
 #endif
 
         mMaxTextureImageSize = mMaxTextureSize;
 
         UpdateActualFormat();
     }
 
--- a/gfx/gl/GLContext.h
+++ b/gfx/gl/GLContext.h
@@ -160,16 +160,17 @@ public:
         mOffscreenReadFBO(0),
         mOffscreenColorRB(0),
         mOffscreenDepthRB(0),
         mOffscreenStencilRB(0),
         mMaxTextureSize(0),
         mMaxCubeMapTextureSize(0),
         mMaxTextureImageSize(0),
         mMaxRenderbufferSize(0),
+        mNeedsTextureSizeChecks(false),
         mWorkAroundDriverBugs(true)
 #ifdef DEBUG
         , mGLError(LOCAL_GL_NO_ERROR)
 #endif
     {
         mUserData.Init();
         mOwningThread = NS_GetCurrentThread();
 
@@ -336,16 +337,17 @@ public:
     virtual bool SupportsRobustness() = 0;
 
     enum {
         VendorIntel,
         VendorNVIDIA,
         VendorATI,
         VendorQualcomm,
         VendorImagination,
+        VendorNouveau,
         VendorOther
     };
 
     enum {
         RendererAdreno200,
         RendererAdreno205,
         RendererSGX530,
         RendererSGX540,
@@ -1325,17 +1327,16 @@ public:
     void MarkExtensionUnsupported(GLExtensions aKnownExtension) {
         mAvailableExtensions[aKnownExtension] = 0;
     }
 
     // Shared code for GL extensions and GLX extensions.
     static bool ListHasExtension(const GLubyte *extensions,
                                  const char *extension);
 
-    GLint GetMaxTextureSize() { return mMaxTextureSize; }
     GLint GetMaxTextureImageSize() { return mMaxTextureImageSize; }
     void SetFlipped(bool aFlipped) { mFlipped = aFlipped; }
 
     // this should just be a std::bitset, but that ended up breaking
     // MacOS X builds; see bug 584919.  We can replace this with one
     // later on.  This is handy to use in WebGL contexts as well,
     // so making it public.
     template<size_t Size>
@@ -1576,34 +1577,34 @@ protected:
 
     nsTArray<nsIntRect> mViewportStack;
     nsTArray<nsIntRect> mScissorStack;
 
     GLint mMaxTextureSize;
     GLint mMaxCubeMapTextureSize;
     GLint mMaxTextureImageSize;
     GLint mMaxRenderbufferSize;
+    bool mNeedsTextureSizeChecks;
     bool mWorkAroundDriverBugs;
 
     bool IsTextureSizeSafeToPassToDriver(GLenum target, GLsizei width, GLsizei height) const {
-#ifdef XP_MACOSX
-        if (mWorkAroundDriverBugs &&
-            mVendor == VendorIntel) {
-            // see bug 737182 for 2D textures, bug 684822 for cube map textures.
-            // some drivers handle incorrectly some large texture sizes that are below the
+        if (mNeedsTextureSizeChecks) {
+            // some drivers incorrectly handle some large texture sizes that are below the
             // max texture size that they report. So we check ourselves against our own values
             // (mMax[CubeMap]TextureSize).
+            // see bug 737182 for Mac Intel 2D textures
+            // see bug 684882 for Mac Intel cube map textures
+            // see bug 814716 for Mesa Nouveau
             GLsizei maxSize = target == LOCAL_GL_TEXTURE_CUBE_MAP ||
                                 (target >= LOCAL_GL_TEXTURE_CUBE_MAP_POSITIVE_X &&
                                 target <= LOCAL_GL_TEXTURE_CUBE_MAP_NEGATIVE_Z)
                               ? mMaxCubeMapTextureSize
                               : mMaxTextureSize;
             return width <= maxSize && height <= maxSize;
         }
-#endif
         return true;
     }
 
 public:
  
     /** \returns the first GL error, and guarantees that all GL error flags are cleared,
       * i.e. that a subsequent GetError call will return NO_ERROR
       */
--- a/gfx/gl/GLTextureImage.cpp
+++ b/gfx/gl/GLTextureImage.cpp
@@ -195,18 +195,21 @@ TiledTextureImage::TiledTextureImage(GLC
     , mCurrentImage(0)
     , mIterationCallback(nullptr)
     , mInUpdate(false)
     , mRows(0)
     , mColumns(0)
     , mGL(aGL)
     , mTextureState(Created)
 {
-    mTileSize = (!(aFlags & TextureImage::ForceSingleTile) && mGL->WantsSmallTiles())
-        ? 256 : mGL->GetMaxTextureSize();
+    if (!(aFlags & TextureImage::ForceSingleTile) && mGL->WantsSmallTiles()) {
+      mTileSize = 256;
+    } else {
+      mGL->fGetIntegerv(LOCAL_GL_MAX_TEXTURE_SIZE, (GLint*) &mTileSize);
+    }
     if (aSize.width != 0 && aSize.height != 0) {
         Resize(aSize);
     }
 }
 
 TiledTextureImage::~TiledTextureImage()
 {
 }
--- a/gfx/layers/Layers.cpp
+++ b/gfx/layers/Layers.cpp
@@ -284,17 +284,18 @@ Layer::Layer(LayerManager* aManager, voi
   mMaskLayer(nullptr),
   mPostXScale(1.0f),
   mPostYScale(1.0f),
   mOpacity(1.0),
   mContentFlags(0),
   mUseClipRect(false),
   mUseTileSourceRect(false),
   mIsFixedPosition(false),
-  mDebugColorIndex(0)
+  mDebugColorIndex(0),
+  mAnimationGeneration(0)
 {}
 
 Layer::~Layer()
 {}
 
 Animation*
 Layer::AddAnimation(TimeStamp aStart, TimeDuration aDuration, float aIterations,
                     int aDirection, nsCSSProperty aProperty, const AnimationData& aData)
--- a/gfx/layers/Layers.h
+++ b/gfx/layers/Layers.h
@@ -799,16 +799,19 @@ public:
   float GetPostYScale() { return mPostYScale; }
   bool GetIsFixedPosition() { return mIsFixedPosition; }
   gfxPoint GetFixedPositionAnchor() { return mAnchor; }
   Layer* GetMaskLayer() { return mMaskLayer; }
 
   AnimationArray& GetAnimations() { return mAnimations; }
   InfallibleTArray<AnimData>& GetAnimationData() { return mAnimationData; }
 
+  uint64_t GetAnimationGeneration() { return mAnimationGeneration; }
+  void SetAnimationGeneration(uint64_t aCount) { mAnimationGeneration = aCount; }
+
   /**
    * DRAWING PHASE ONLY
    *
    * Apply pending changes to layers before drawing them, if those
    * pending changes haven't been overridden by later changes.
    */
   void ApplyPendingUpdatesToSubtree();
 
@@ -1103,16 +1106,19 @@ protected:
   nsIntRect mTileSourceRect;
   nsIntRegion mInvalidRegion;
   uint32_t mContentFlags;
   bool mUseClipRect;
   bool mUseTileSourceRect;
   bool mIsFixedPosition;
   gfxPoint mAnchor;
   DebugOnly<uint32_t> mDebugColorIndex;
+  // If this layer is used for OMTA, then this counter is used to ensure we
+  // stay in sync with the animation manager
+  uint64_t mAnimationGeneration;
 };
 
 /**
  * A Layer which we can draw into using Thebes. It is a conceptually
  * infinite surface, but each ThebesLayer has an associated "valid region"
  * of contents that it is currently storing, which is finite. ThebesLayer
  * implementations can store content between paints.
  * 
--- a/gfx/layers/ipc/CompositorParent.cpp
+++ b/gfx/layers/ipc/CompositorParent.cpp
@@ -813,17 +813,17 @@ CompositorParent::TransformShadowTree(Ti
   bool wantNextFrame = false;
   Layer* layer = mLayerManager->GetPrimaryScrollableLayer();
   ShadowLayer* shadow = layer->AsShadowLayer();
   ContainerLayer* container = layer->AsContainerLayer();
   Layer* root = mLayerManager->GetRoot();
 
   // NB: we must sample animations *before* sampling pan/zoom
   // transforms.
-  wantNextFrame |= SampleAnimations(root, mLastCompose);
+  wantNextFrame |= SampleAnimations(root, aCurrentFrame);
 
   const FrameMetrics& metrics = container->GetFrameMetrics();
   // We must apply the resolution scale before a pan/zoom transform, so we call
   // GetTransform here.
   const gfx3DMatrix& rootTransform = root->GetTransform();
   const gfx3DMatrix& currentTransform = layer->GetTransform();
 
   // FIXME/bug 775437: unify this interface with the ~native-fennec
--- a/gfx/layers/opengl/CanvasLayerOGL.cpp
+++ b/gfx/layers/opengl/CanvasLayerOGL.cpp
@@ -157,17 +157,18 @@ CanvasLayerOGL::Initialize(const Data& a
     NS_WARNING("CanvasLayerOGL::Initialize called without surface or GL context!");
     return;
   }
 
   mBounds.SetRect(0, 0, aData.mSize.width, aData.mSize.height);
       
   // Check the maximum texture size supported by GL. glTexImage2D supports
   // images of up to 2 + GL_MAX_TEXTURE_SIZE
-  GLint texSize = gl()->GetMaxTextureSize();
+  GLint texSize;
+  gl()->fGetIntegerv(LOCAL_GL_MAX_TEXTURE_SIZE, &texSize);
   if (mBounds.width > (2 + texSize) || mBounds.height > (2 + texSize)) {
     mDelayedUpdates = true;
     MakeTextureIfNeeded(gl(), mTexture);
     // This should only ever occur with 2d canvas, WebGL can't already have a texture
     // of this size can it?
     NS_ABORT_IF_FALSE(mCanvasSurface || mDrawTarget, 
                       "Invalid texture size when WebGL surface already exists at that size?");
   }
--- a/gfx/layers/opengl/LayerManagerOGL.cpp
+++ b/gfx/layers/opengl/LayerManagerOGL.cpp
@@ -57,17 +57,19 @@ bool
 LayerManagerOGL::Initialize(bool force)
 {
   return Initialize(CreateContext(), force);
 }
 
 int32_t
 LayerManagerOGL::GetMaxTextureSize() const
 {
-  return mGLContext->GetMaxTextureSize();
+  int32_t maxSize;
+  mGLContext->fGetIntegerv(LOCAL_GL_MAX_TEXTURE_SIZE, &maxSize);
+  return maxSize;
 }
 
 void
 LayerManagerOGL::MakeCurrent(bool aForce)
 {
   if (mDestroyed) {
     NS_WARNING("Call on destroyed layer manager");
     return;
--- a/gfx/thebes/gfxSVGGlyphs.cpp
+++ b/gfx/thebes/gfxSVGGlyphs.cpp
@@ -38,34 +38,33 @@
 
 #include "nscore.h"
 #include "nsError.h"
 #include "nsAutoPtr.h"
 #include "nsIParser.h"
 #include "nsIDOMNodeList.h"
 #include "nsString.h"
 #include "nsIDocument.h"
-#include "nsPrintfCString.h"
 #include "nsICategoryManager.h"
 #include "nsIDocumentLoaderFactory.h"
 #include "nsIContentViewer.h"
 #include "nsIStreamListener.h"
 #include "nsServiceManagerUtils.h"
 #include "nsIPresShell.h"
 #include "nsIFrame.h"
 #include "nsQueryFrame.h"
 #include "nsIContentSink.h"
 #include "nsXMLContentSink.h"
 #include "nsNetUtil.h"
 #include "nsIInputStream.h"
-#include "nsContentUtils.h"
 #include "nsStringStream.h"
 #include "nsStreamUtils.h"
 #include "nsIPrincipal.h"
 #include "Element.h"
+#include "nsSVGUtils.h"
 
 #define SVG_CONTENT_TYPE NS_LITERAL_CSTRING("image/svg+xml")
 #define UTF8_CHARSET NS_LITERAL_CSTRING("utf-8")
 
 typedef mozilla::dom::Element Element;
 
 mozilla::gfx::UserDataKey gfxTextObjectPaint::sUserDataKey;
 
@@ -225,27 +224,27 @@ gfxSVGGlyphs::RenderGlyph(gfxContext *aC
         return false;
     }
 
     gfxContextAutoSaveRestore aContextRestorer(aContext);
 
     Element *glyph = mGlyphIdMap.Get(aGlyphId);
     NS_ASSERTION(glyph, "No glyph element. Should check with HasSVGGlyph() first!");
 
-    return nsContentUtils::PaintSVGGlyph(glyph, aContext, aDrawMode, aObjectPaint);
+    return nsSVGUtils::PaintSVGGlyph(glyph, aContext, aDrawMode, aObjectPaint);
 }
 
 bool
 gfxSVGGlyphs::GetGlyphExtents(uint32_t aGlyphId, const gfxMatrix& aSVGToAppSpace,
                               gfxRect *aResult)
 {
     Element *glyph = mGlyphIdMap.Get(aGlyphId);
     NS_ASSERTION(glyph, "No glyph element. Should check with HasSVGGlyph() first!");
 
-    return nsContentUtils::GetSVGGlyphExtents(glyph, aSVGToAppSpace, aResult);
+    return nsSVGUtils::GetSVGGlyphExtents(glyph, aSVGToAppSpace, aResult);
 }
 
 Element *
 gfxSVGGlyphs::GetGlyphElement(uint32_t aGlyphId)
 {
     Element *elem;
 
     if (!mGlyphIdMap.Get(aGlyphId, &elem)) {
--- a/js/src/config/config.mk
+++ b/js/src/config/config.mk
@@ -71,19 +71,19 @@ RM = rm -f
 
 # LIBXUL_DIST is not defined under js/src, thus we make it mean DIST there.
 LIBXUL_DIST ?= $(DIST)
 
 # FINAL_TARGET specifies the location into which we copy end-user-shipped
 # build products (typelibs, components, chrome).
 #
 # If XPI_NAME is set, the files will be shipped to $(DIST)/xpi-stage/$(XPI_NAME)
-# If DIST_SUBDIR is set, the files will be shipped to $(DIST)/$(DIST_SUBDIR)
-# Otherwise, the default $(DIST)/bin will be used.
-FINAL_TARGET = $(if $(XPI_NAME),$(DIST)/xpi-stage/$(XPI_NAME),$(if $(DIST_SUBDIR),$(DIST)/bin/$(DIST_SUBDIR),$(DIST)/bin))
+# instead of $(DIST)/bin. In both cases, if DIST_SUBDIR is set, the files will be
+# shipped to a $(DIST_SUBDIR) subdirectory.
+FINAL_TARGET = $(if $(XPI_NAME),$(DIST)/xpi-stage/$(XPI_NAME),$(DIST)/bin)$(DIST_SUBDIR:%=/%)
 
 ifdef XPI_NAME
 DEFINES += -DXPI_NAME=$(XPI_NAME)
 endif
 
 # The VERSION_NUMBER is suffixed onto the end of the DLLs we ship.
 VERSION_NUMBER		= 50
 
--- a/js/src/config/makefiles/autotargets.mk
+++ b/js/src/config/makefiles/autotargets.mk
@@ -51,28 +51,28 @@ mkdir_stem =$(foreach val,$(getargv),$(s
 ## Generate timestamp file for threadsafe directory creation
 mkdir_deps =$(foreach dir,$(getargv),$(call slash_strip,$(dir)/.mkdir.done))
 
 #######################
 ##---]  TARGETS  [---##
 #######################
 
 %/.mkdir.done: # mkdir -p -p => mkdir -p
-	$(subst $(space)-p,$(null),$(MKDIR)) -p $(dir $@)
+	$(subst $(space)-p,$(null),$(MKDIR)) -p "$(dir $@)"
 # Make the timestamp old enough for not being a problem with symbolic links
 # targets depending on it. Use Jan 3, 1980 to accomodate any timezone where
 # 198001010000 would translate to something older than FAT epoch.
-	@touch -t 198001030000 $@
+	@$(TOUCH) -t 198001030000 "$@"
 
 # A handful of makefiles are attempting "mkdir dot".  Likely not intended
 # or stale logic so add a stub target to handle the request and warn for now.
 .mkdir.done:
 ifndef NOWARN_AUTOTARGETS # {
 	@echo "WARNING: $(MKDIR) -dot- requested by $(MAKE) -C $(CURDIR) $(MAKECMDGOALS)"
-	@touch -t 198001030000 $@
+	@$(TOUCH) -t 198001030000 $@
 endif #}
 
 INCLUDED_AUTOTARGETS_MK = 1
 endif #}
 
 
 ## Accumulate deps and cleanup
 ifneq (,$(GENERATED_DIRS))
--- a/js/src/config/rules.mk
+++ b/js/src/config/rules.mk
@@ -1539,17 +1539,17 @@ define install_cmd_override
 $(1): install_cmd = $$(if $$(nsinstall_is_usable),$$(INSTALL),$$(NSINSTALL_PY)) $$(1)
 endef
 endif
 
 define install_file_template
 $(or $(3),libs):: $(2)/$(notdir $(1))
 $(call install_cmd_override,$(2)/$(notdir $(1)))
 $(2)/$(notdir $(1)): $(1) $$(call mkdir_deps,$(2))
-	$$(call install_cmd,$(4) $$< $${@D})
+	$$(call install_cmd,$(4) "$$<" "$${@D}")
 endef
 $(foreach category,$(INSTALL_TARGETS),\
   $(if $($(category)_DEST),,$(error Missing $(category)_DEST))\
   $(foreach file,$($(category)_FILES),\
     $(eval $(call install_file_template,$(file),$($(category)_DEST),$($(category)_TARGET),$(IFLAGS1)))\
   )\
   $(foreach file,$($(category)_EXECUTABLES),\
     $(eval $(call install_file_template,$(file),$($(category)_DEST),$($(category)_TARGET),$(IFLAGS2)))\
@@ -1586,18 +1586,18 @@ endef
 #   files. Setting this variable is optional; if unset, we preprocess the
 #   files for the 'libs' target.
 
 # preprocess_file_template defines preprocessing rules.
 # $(call preprocess_file_template, source_file, output_file,
 #                                  makefile_target, extra_flags)
 define preprocess_file_template
 $(2): $(1) $$(call mkdir_deps,$(dir $(2))) $$(GLOBAL_DEPS)
-	$$(RM) $$@
-	$$(PYTHON) $$(topsrcdir)/config/Preprocessor.py $(4) $$(DEFINES) $$(ACDEFINES) $$(XULPPFLAGS) $$< > $$@
+	$$(RM) "$$@"
+	$$(PYTHON) $$(topsrcdir)/config/Preprocessor.py $(4) $$(DEFINES) $$(ACDEFINES) $$(XULPPFLAGS) "$$<" > "$$@"
 $(3):: $(2)
 endef
 
 $(foreach category,$(PP_TARGETS),						\
   $(foreach file,$($(category)),						\
     $(eval $(call preprocess_file_template,					\
                   $(file),							\
                   $(or $($(category)_PATH),$(CURDIR))/$(notdir $(file:.in=)),	\
--- a/js/src/ion/CodeGenerator.cpp
+++ b/js/src/ion/CodeGenerator.cpp
@@ -828,18 +828,16 @@ CodeGenerator::visitCallGeneric(LCallGen
     Register calleereg = ToRegister(call->getFunction());
     Register objreg    = ToRegister(call->getTempObject());
     Register nargsreg  = ToRegister(call->getNargsReg());
     uint32_t unusedStack = StackOffsetOfPassedArg(call->argslot());
     Label invoke, thunk, makeCall, end;
 
     // Known-target case is handled by LCallKnown.
     JS_ASSERT(!call->hasSingleTarget());
-    // Unknown constructor case is handled by LCallConstructor.
-    JS_ASSERT(!call->mir()->isConstructing());
 
     // Generate an ArgumentsRectifier.
     IonCompartment *ion = gen->ionCompartment();
     IonCode *argumentsRectifier = ion->getArgumentsRectifier();
 
     masm.checkStackAlignment();
 
     // Guard that calleereg is actually a function object.
@@ -900,16 +898,26 @@ CodeGenerator::visitCallGeneric(LCallGen
     masm.jump(&end);
 
     // Handle uncompiled or native functions.
     masm.bind(&invoke);
     if (!emitCallInvokeFunction(call, calleereg, call->numActualArgs(), unusedStack))
         return false;
 
     masm.bind(&end);
+
+    // If the return value of the constructing function is Primitive,
+    // replace the return value with the Object from CreateThis.
+    if (call->mir()->isConstructing()) {
+        Label notPrimitive;
+        masm.branchTestPrimitive(Assembler::NotEqual, JSReturnOperand, &notPrimitive);
+        masm.loadValue(Address(StackPointer, unusedStack), JSReturnOperand);
+        masm.bind(&notPrimitive);
+    }
+
     dropArguments(call->numStackArgs() + 1);
     return true;
 }
 
 bool
 CodeGenerator::visitCallKnown(LCallKnown *call)
 {
     JSContext *cx = GetIonContext()->cx;
@@ -921,16 +929,20 @@ CodeGenerator::visitCallKnown(LCallKnown
 
     // Native single targets are handled by LCallNative.
     JS_ASSERT(!target->isNative());
     // Missing arguments must have been explicitly appended by the IonBuilder.
     JS_ASSERT(target->nargs <= call->numStackArgs());
 
     masm.checkStackAlignment();
 
+    // Make sure the function has a JSScript
+    if (target->isInterpretedLazy() && !target->getOrCreateScript(cx))
+        return false;
+
     // If the function is known to be uncompilable, only emit the call to InvokeFunction.
     ExecutionMode executionMode = gen->info().executionMode();
     RootedScript targetScript(cx, target->nonLazyScript());
     if (GetIonScript(targetScript, executionMode) == ION_DISABLED_SCRIPT) {
         if (!emitCallInvokeFunction(call, calleereg, call->numActualArgs(), unusedStack))
             return false;
 
         if (call->mir()->isConstructing()) {
@@ -990,49 +1002,16 @@ CodeGenerator::visitCallKnown(LCallKnown
         masm.loadValue(Address(StackPointer, unusedStack), JSReturnOperand);
         masm.bind(&notPrimitive);
     }
 
     dropArguments(call->numStackArgs() + 1);
     return true;
 }
 
-typedef bool (*InvokeConstructorFn)(JSContext *, JSObject *, uint32_t, Value *, Value *);
-static const VMFunction InvokeConstructorInfo =
-    FunctionInfo<InvokeConstructorFn>(ion::InvokeConstructor);
-
-bool
-CodeGenerator::visitCallConstructor(LCallConstructor *call)
-{
-    JS_ASSERT(call->mir()->isConstructing());
-
-    // Holds the function object.
-    const LAllocation *callee = call->getFunction();
-    Register calleereg = ToRegister(callee);
-
-    uint32_t callargslot = call->argslot();
-    uint32_t unusedStack = StackOffsetOfPassedArg(callargslot);
-
-    // Nestle %esp up to the argument vector.
-    masm.freeStack(unusedStack);
-
-    pushArg(StackPointer);                  // argv.
-    pushArg(Imm32(call->numActualArgs()));  // argc.
-    pushArg(calleereg);                     // JSFunction *.
-
-    if (!callVM(InvokeConstructorInfo, call))
-        return false;
-
-    // Un-nestle %esp from the argument vector. No prefix was pushed.
-    masm.reserveStack(unusedStack);
-
-    dropArguments(call->numStackArgs() + 1);
-    return true;
-}
-
 bool
 CodeGenerator::emitCallInvokeFunction(LApplyArgsGeneric *apply, Register extraStackSize)
 {
     Register objreg = ToRegister(apply->getTempObject());
     JS_ASSERT(objreg != extraStackSize);
 
     // Push the space used by the arguments.
     masm.movePtr(StackPointer, objreg);
@@ -1837,20 +1816,18 @@ CodeGenerator::visitInitProp(LInitProp *
     return callVM(InitPropInfo, lir);
 }
 
 typedef JSObject *(*NewGCThingFn)(JSContext *cx, gc::AllocKind allocKind, size_t thingSize);
 static const VMFunction NewGCThingInfo =
     FunctionInfo<NewGCThingFn>(js::ion::NewGCThing);
 
 bool
-CodeGenerator::visitCreateThis(LCreateThis *lir)
+CodeGenerator::visitCreateThisWithTemplate(LCreateThisWithTemplate *lir)
 {
-    JS_ASSERT(lir->mir()->hasTemplateObject());
-
     JSObject *templateObject = lir->mir()->getTemplateObject();
     gc::AllocKind allocKind = templateObject->getAllocKind();
     int thingSize = (int)gc::Arena::thingSize(allocKind);
     Register objReg = ToRegister(lir->output());
 
     OutOfLineCode *ool = oolCallVM(NewGCThingInfo, lir,
                                    (ArgList(), Imm32(allocKind), Imm32(thingSize)),
                                    StoreRegisterTo(objReg));
@@ -1867,38 +1844,65 @@ CodeGenerator::visitCreateThis(LCreateTh
     return true;
 }
 
 typedef JSObject *(*CreateThisFn)(JSContext *cx, HandleObject callee, JSObject *proto);
 static const VMFunction CreateThisInfo =
     FunctionInfo<CreateThisFn>(js_CreateThisForFunctionWithProto);
 
 bool
-CodeGenerator::visitCreateThisVM(LCreateThisVM *lir)
+CodeGenerator::emitCreateThisVM(LInstruction *lir,
+                                const LAllocation *proto,
+                                const LAllocation *callee)
 {
-    const LAllocation *proto = lir->getPrototype();
-    const LAllocation *callee = lir->getCallee();
-
-    // Push arguments.
     if (proto->isConstant())
         pushArg(ImmGCPtr(&proto->toConstant()->toObject()));
     else
         pushArg(ToRegister(proto));
 
     if (callee->isConstant())
         pushArg(ImmGCPtr(&callee->toConstant()->toObject()));
     else
         pushArg(ToRegister(callee));
 
-    if (!callVM(CreateThisInfo, lir))
+    return callVM(CreateThisInfo, lir);
+}
+
+bool
+CodeGenerator::visitCreateThisV(LCreateThisV *lir)
+{
+    Label done, vm;
+
+    const LAllocation *proto = lir->getPrototype();
+    const LAllocation *callee = lir->getCallee();
+
+    // When callee could be a native, put MagicValue in return operand.
+    // Use the VMCall when callee turns out to not be a native.
+    masm.branchIfInterpreted(ToRegister(callee), &vm);
+    masm.moveValue(MagicValue(JS_IS_CONSTRUCTING), GetValueOutput(lir));
+    masm.jump(&done);
+
+    masm.bind(&vm);
+    if (!emitCreateThisVM(lir, proto, callee))
         return false;
+
+    masm.tagValue(JSVAL_TYPE_OBJECT, ReturnReg, GetValueOutput(lir));
+
+    masm.bind(&done);
+
     return true;
 }
 
 bool
+CodeGenerator::visitCreateThisO(LCreateThisO *lir)
+{
+    return emitCreateThisVM(lir, lir->getPrototype(), lir->getCallee());
+}
+
+bool
 CodeGenerator::visitReturnFromCtor(LReturnFromCtor *lir)
 {
     ValueOperand value = ToValue(lir, LReturnFromCtor::ValueIndex);
     Register obj = ToRegister(lir->getObject());
     Register output = ToRegister(lir->output());
 
     Label valueIsObject, end;
 
--- a/js/src/ion/CodeGenerator.h
+++ b/js/src/ion/CodeGenerator.h
@@ -74,35 +74,36 @@ class CodeGenerator : public CodeGenerat
     bool visitElements(LElements *lir);
     bool visitTypeBarrier(LTypeBarrier *lir);
     bool visitMonitorTypes(LMonitorTypes *lir);
     bool visitCallNative(LCallNative *call);
     bool emitCallInvokeFunction(LInstruction *call, Register callereg,
                                 uint32_t argc, uint32_t unusedStack);
     bool visitCallGeneric(LCallGeneric *call);
     bool visitCallKnown(LCallKnown *call);
-    bool visitCallConstructor(LCallConstructor *call);
     bool emitCallInvokeFunction(LApplyArgsGeneric *apply, Register extraStackSize);
     void emitPushArguments(LApplyArgsGeneric *apply, Register extraStackSpace);
     void emitPopArguments(LApplyArgsGeneric *apply, Register extraStackSize);
     bool visitApplyArgsGeneric(LApplyArgsGeneric *apply);
     bool visitDoubleToInt32(LDoubleToInt32 *lir);
     bool visitNewSlots(LNewSlots *lir);
     bool visitNewArrayCallVM(LNewArray *lir);
     bool visitNewArray(LNewArray *lir);
     bool visitOutOfLineNewArray(OutOfLineNewArray *ool);
     bool visitNewObjectVMCall(LNewObject *lir);
     bool visitNewObject(LNewObject *lir);
     bool visitOutOfLineNewObject(OutOfLineNewObject *ool);
     bool visitNewDeclEnvObject(LNewDeclEnvObject *lir);
     bool visitNewCallObject(LNewCallObject *lir);
     bool visitNewStringObject(LNewStringObject *lir);
     bool visitInitProp(LInitProp *lir);
-    bool visitCreateThis(LCreateThis *lir);
-    bool visitCreateThisVM(LCreateThisVM *lir);
+    bool emitCreateThisVM(LInstruction *lir, const LAllocation *proto, const LAllocation *callee);
+    bool visitCreateThisV(LCreateThisV *lir);
+    bool visitCreateThisO(LCreateThisO *lir);
+    bool visitCreateThisWithTemplate(LCreateThisWithTemplate *lir);
     bool visitReturnFromCtor(LReturnFromCtor *lir);
     bool visitArrayLength(LArrayLength *lir);
     bool visitTypedArrayLength(LTypedArrayLength *lir);
     bool visitTypedArrayElements(LTypedArrayElements *lir);
     bool visitStringLength(LStringLength *lir);
     bool visitInitializedLength(LInitializedLength *lir);
     bool visitSetInitializedLength(LSetInitializedLength *lir);
     bool visitNotV(LNotV *ins);
--- a/js/src/ion/IonBuilder.cpp
+++ b/js/src/ion/IonBuilder.cpp
@@ -57,27 +57,27 @@ bool
 IonBuilder::abort(const char *message, ...)
 {
     // Don't call PCToLineNumber in release builds.
 #ifdef DEBUG
     va_list ap;
     va_start(ap, message);
     abortFmt(message, ap);
     va_end(ap);
-    IonSpew(IonSpew_Abort, "aborted @ %s:%d", script_->filename, PCToLineNumber(script_, pc));
+    IonSpew(IonSpew_Abort, "aborted @ %s:%d", script()->filename, PCToLineNumber(script(), pc));
 #endif
     return false;
 }
 
 void
 IonBuilder::spew(const char *message)
 {
     // Don't call PCToLineNumber in release builds.
 #ifdef DEBUG
-    IonSpew(IonSpew_MIR, "%s @ %s:%d", message, script_->filename, PCToLineNumber(script_, pc));
+    IonSpew(IonSpew_MIR, "%s @ %s:%d", message, script()->filename, PCToLineNumber(script(), pc));
 #endif
 }
 
 static inline int32_t
 GetJumpOffset(jsbytecode *pc)
 {
     JS_ASSERT(js_CodeSpec[JSOp(*pc)].type() == JOF_JUMP);
     return GET_JUMP_OFFSET(pc);
@@ -163,17 +163,17 @@ IonBuilder::getSingleCallTarget(uint32_t
 
     return obj->toFunction();
 }
 
 uint32_t
 IonBuilder::getPolyCallTargets(uint32_t argc, jsbytecode *pc,
                                AutoObjectVector &targets, uint32_t maxTargets)
 {
-    types::TypeSet *calleeTypes = oracle->getCallTarget(script_, argc, pc);
+    types::TypeSet *calleeTypes = oracle->getCallTarget(script(), argc, pc);
     if (!calleeTypes)
         return 0;
 
     if (calleeTypes->baseFlags() != 0)
         return 0;
 
     unsigned objCount = calleeTypes->getObjectCount();
 
@@ -195,17 +195,17 @@ IonBuilder::canInlineTarget(JSFunction *
 {
     AssertCanGC();
 
     if (!target->isInterpreted()) {
         IonSpew(IonSpew_Inlining, "Cannot inline due to non-interpreted");
         return false;
     }
 
-    if (target->getParent() != &script_->global()) {
+    if (target->getParent() != &script()->global()) {
         IonSpew(IonSpew_Inlining, "Cannot inline due to scope mismatch");
         return false;
     }
 
     RootedScript inlineScript(cx, target->nonLazyScript());
     ExecutionMode executionMode = info().executionMode();
     if (!CanIonCompile(inlineScript, executionMode)) {
         IonSpew(IonSpew_Inlining, "Cannot inline due to disable Ion compilation");
@@ -220,17 +220,17 @@ IonBuilder::canInlineTarget(JSFunction *
             return false;
         }
         builder = builder->callerBuilder_;
     }
 
     bool canInline = oracle->canEnterInlinedFunction(target);
 
     if (!canInline) {
-        IonSpew(IonSpew_Inlining, "Cannot inline due to oracle veto %d", script_->lineno);
+        IonSpew(IonSpew_Inlining, "Cannot inline due to oracle veto %d", script()->lineno);
         return false;
     }
 
     IonSpew(IonSpew_Inlining, "Inlining good to go!");
     return true;
 }
 
 void
@@ -269,20 +269,20 @@ IonBuilder::pushLoop(CFGState::State ini
 bool
 IonBuilder::build()
 {
     current = newBlock(pc);
     if (!current)
         return false;
 
     IonSpew(IonSpew_Scripts, "Analyzing script %s:%d (%p) (usecount=%d) (maxloopcount=%d)",
-            script_->filename, script_->lineno, (void *)script_, (int)script_->getUseCount(),
-            (int)script_->getMaxLoopCount());
-
-    if (!graph().addScript(script_))
+            script()->filename, script()->lineno, (void *)script(), (int)script()->getUseCount(),
+            (int)script()->getMaxLoopCount());
+
+    if (!graph().addScript(script()))
         return false;
 
     if (!initParameters())
         return false;
 
     // Initialize local variables.
     for (uint32_t i = 0; i < info().nlocals(); i++) {
         MConstant *undef = MConstant::New(UndefinedValue());
@@ -298,17 +298,17 @@ IonBuilder::build()
         MInstruction *scope = MConstant::New(UndefinedValue());
         current->add(scope);
         current->initSlot(info().scopeChainSlot(), scope);
     }
 
     // Emit the start instruction, so we can begin real instructions.
     current->makeStart(MStart::New(MStart::StartType_Default));
     if (instrumentedProfiling())
-        current->add(MFunctionBoundary::New(script_, MFunctionBoundary::Enter));
+        current->add(MFunctionBoundary::New(script(), MFunctionBoundary::Enter));
 
     // Parameters have been checked to correspond to the typeset, now we unbox
     // what we can in an infallible manner.
     rewriteParameters();
 
     // It's safe to start emitting actual IR, so now build the scope chain.
     if (!initScopeChain())
         return false;
@@ -341,17 +341,17 @@ IonBuilder::build()
         MInstruction *ins = current->getEntrySlot(i)->toInstruction();
         if (ins->type() == MIRType_Value)
             ins->setResumePoint(current->entryResumePoint());
     }
 
     // Recompile to inline calls if this function is hot.
     insertRecompileCheck();
 
-    if (script_->argumentsHasVarBinding()) {
+    if (script()->argumentsHasVarBinding()) {
         lazyArguments_ = MConstant::New(MagicValue(JS_OPTIMIZED_ARGUMENTS));
         current->add(lazyArguments_);
     }
 
     if (!traverseBytecode())
         return false;
 
     if (!processIterators())
@@ -395,19 +395,19 @@ IonBuilder::processIterators()
     return true;
 }
 
 bool
 IonBuilder::buildInline(IonBuilder *callerBuilder, MResumePoint *callerResumePoint,
                         MDefinition *thisDefn, MDefinitionVector &argv)
 {
     IonSpew(IonSpew_Scripts, "Inlining script %s:%d (%p)",
-            script_->filename, script_->lineno, (void *)script_);
-
-    if (!graph().addScript(script_))
+            script()->filename, script()->lineno, (void *)script());
+
+    if (!graph().addScript(script()))
         return false;
 
     callerBuilder_ = callerBuilder;
     callerResumePoint_ = callerResumePoint;
 
     if (callerBuilder->failedBoundsCheck_)
         failedBoundsCheck_ = true;
 
@@ -425,17 +425,17 @@ IonBuilder::buildInline(IonBuilder *call
     MBasicBlock *predecessor = callerBuilder->current;
     JS_ASSERT(predecessor == callerResumePoint->block());
 
     // All further instructions generated in from this scope should be
     // considered as part of the function that we're inlining. We also need to
     // keep track of the inlining depth because all scripts inlined on the same
     // level contiguously have only one Inline_Exit node.
     if (instrumentedProfiling())
-        predecessor->add(MFunctionBoundary::New(script_,
+        predecessor->add(MFunctionBoundary::New(script(),
                                                 MFunctionBoundary::Inline_Enter,
                                                 inliningDepth));
 
     predecessor->end(MGoto::New(current));
     if (!current->addPredecessorWithoutPhis(predecessor))
         return false;
 
     // Explicitly pass Undefined for missing arguments.
@@ -449,17 +449,17 @@ IonBuilder::buildInline(IonBuilder *call
             MConstant *undef = MConstant::New(UndefinedValue());
             current->add(undef);
             if (!argv.append(undef))
                 return false;
         }
     }
 
     // The Oracle ensures that the inlined script does not use the scope chain.
-    JS_ASSERT(!script_->analysis()->usesScopeChain());
+    JS_ASSERT(!script()->analysis()->usesScopeChain());
     MInstruction *scope = MConstant::New(UndefinedValue());
     current->add(scope);
     current->initSlot(info().scopeChainSlot(), scope);
 
     current->initSlot(info().thisSlot(), thisDefn);
 
     IonSpew(IonSpew_Inlining, "Initializing %u arg slots", nargs);
 
@@ -501,19 +501,19 @@ IonBuilder::rewriteParameters()
 
     for (uint32_t i = START_SLOT; i < CountArgSlots(info().fun()); i++) {
         MParameter *param = current->getSlot(i)->toParameter();
 
         // Find the original (not cloned) type set for the MParameter, as we
         // will be adding constraints to it.
         types::StackTypeSet *types;
         if (param->index() == MParameter::THIS_SLOT)
-            types = oracle->thisTypeSet(script_);
+            types = oracle->thisTypeSet(script());
         else
-            types = oracle->parameterTypeSet(script_, param->index());
+            types = oracle->parameterTypeSet(script(), param->index());
         if (!types)
             continue;
 
         JSValueType definiteType = types->getKnownTypeTag();
         if (definiteType == JSVAL_TYPE_UNKNOWN)
             continue;
 
         MInstruction *actual = NULL;
@@ -549,44 +549,44 @@ IonBuilder::rewriteParameters()
 
 bool
 IonBuilder::initParameters()
 {
     if (!info().fun())
         return true;
 
     MParameter *param = MParameter::New(MParameter::THIS_SLOT,
-                                        cloneTypeSet(oracle->thisTypeSet(script_)));
+                                        cloneTypeSet(oracle->thisTypeSet(script())));
     current->add(param);
     current->initSlot(info().thisSlot(), param);
 
     for (uint32_t i = 0; i < info().nargs(); i++) {
-        param = MParameter::New(i, cloneTypeSet(oracle->parameterTypeSet(script_, i)));
+        param = MParameter::New(i, cloneTypeSet(oracle->parameterTypeSet(script(), i)));
         current->add(param);
         current->initSlot(info().argSlot(i), param);
     }
 
     return true;
 }
 
 bool
 IonBuilder::initScopeChain()
 {
     MInstruction *scope = NULL;
 
     // If the script doesn't use the scopechain, then it's already initialized
     // from earlier.
-    if (!script_->analysis()->usesScopeChain())
+    if (!script()->analysis()->usesScopeChain())
         return true;
 
     // The scope chain is only tracked in scripts that have NAME opcodes which
     // will try to access the scope. For other scripts, the scope instructions
     // will be held live by resume points and code will still be generated for
     // them, so just use a constant undefined value.
-    if (!script_->compileAndGo)
+    if (!script()->compileAndGo)
         return abort("non-CNG global scripts are not supported");
 
     if (JSFunction *fun = info().fun()) {
         MCallee *callee = MCallee::New();
         current->add(callee);
 
         scope = MFunctionEnvironment::New(callee);
         current->add(scope);
@@ -599,17 +599,17 @@ IonBuilder::initScopeChain()
                     return false;
             }
 
             scope = createCallObject(callee, scope);
             if (!scope)
                 return false;
         }
     } else {
-        scope = MConstant::New(ObjectValue(script_->global()));
+        scope = MConstant::New(ObjectValue(script()->global()));
         current->add(scope);
     }
 
     current->setScopeChain(scope);
     return true;
 }
 
 // We try to build a control-flow graph in the order that it would be built as
@@ -952,17 +952,17 @@ IonBuilder::inspectOpcode(JSOp op)
       case JSOP_GETGNAME:
       case JSOP_CALLGNAME:
       {
         RootedPropertyName name(cx, info().getAtom(pc)->asPropertyName());
         return jsop_getgname(name);
       }
 
       case JSOP_BINDGNAME:
-        return pushConstant(ObjectValue(script_->global()));
+        return pushConstant(ObjectValue(script()->global()));
 
       case JSOP_SETGNAME:
       {
         RootedPropertyName name(cx, info().getAtom(pc)->asPropertyName());
         return jsop_setgname(name);
       }
 
       case JSOP_NAME:
@@ -2296,17 +2296,17 @@ IonBuilder::lookupSwitch(JSOp op, jssrcn
     bool defaultShared = false;
 
     MBasicBlock *prevCond = NULL;
     MCompare *prevCmpIns = NULL;
     MBasicBlock *prevBody = NULL;
     bool prevShared = false;
     jsbytecode *prevpc = NULL;
     for (unsigned int i = 0; i < ncases; i++) {
-        Value rval = script_->getConst(GET_UINT32_INDEX(pc2));
+        Value rval = script()->getConst(GET_UINT32_INDEX(pc2));
         pc2 += UINT32_INDEX_LEN;
         jsbytecode *casepc = pc + GET_JUMP_OFFSET(pc2);
         pc2 += JUMP_OFFSET_LEN;
         JS_ASSERT(casepc > pc && casepc <= exitpc);
         JS_ASSERT_IF(i > 0, prevpc <= casepc);
 
         // Create case block
         MBasicBlock *cond = newBlock(((i == 0) ? current : prevCond), casepc);
@@ -2862,17 +2862,17 @@ IonBuilder::processReturn(JSOp op)
 
       default:
         def = NULL;
         JS_NOT_REACHED("unknown return op");
         break;
     }
 
     if (instrumentedProfiling())
-        current->add(MFunctionBoundary::New(script_, MFunctionBoundary::Exit));
+        current->add(MFunctionBoundary::New(script(), MFunctionBoundary::Exit));
     MReturn *ret = MReturn::New(def);
     current->end(ret);
 
     if (!graph().addExit(current))
         return ControlStatus_Error;
 
     // Make sure no one tries to use this block now.
     current = NULL;
@@ -2906,17 +2906,17 @@ IonBuilder::pushConstant(const Value &v)
 
 bool
 IonBuilder::jsop_bitnot()
 {
     MDefinition *input = current->pop();
     MBitNot *ins = MBitNot::New(input);
 
     current->add(ins);
-    ins->infer(oracle->unaryTypes(script_, pc));
+    ins->infer(oracle->unaryTypes(script(), pc));
 
     current->push(ins);
     if (ins->isEffectful() && !resumeAfter(ins))
         return false;
     return true;
 }
 bool
 IonBuilder::jsop_bitop(JSOp op)
@@ -2952,29 +2952,29 @@ IonBuilder::jsop_bitop(JSOp op)
         break;
 
       default:
         JS_NOT_REACHED("unexpected bitop");
         return false;
     }
 
     current->add(ins);
-    ins->infer(oracle->binaryTypes(script_, pc));
+    ins->infer(oracle->binaryTypes(script(), pc));
 
     current->push(ins);
     if (ins->isEffectful() && !resumeAfter(ins))
         return false;
 
     return true;
 }
 
 bool
 IonBuilder::jsop_binary(JSOp op, MDefinition *left, MDefinition *right)
 {
-    TypeOracle::Binary b = oracle->binaryOp(script_, pc);
+    TypeOracle::Binary b = oracle->binaryOp(script(), pc);
 
     if (op == JSOP_ADD && b.rval == MIRType_String &&
         (b.lhs == MIRType_String || b.lhs == MIRType_Int32) &&
         (b.rhs == MIRType_String || b.rhs == MIRType_Int32))
     {
         MConcat *ins = MConcat::New(left, right);
         current->add(ins);
         current->push(ins);
@@ -3003,17 +3003,17 @@ IonBuilder::jsop_binary(JSOp op, MDefini
         ins = MMod::New(left, right);
         break;
 
       default:
         JS_NOT_REACHED("unexpected binary opcode");
         return false;
     }
 
-    TypeOracle::BinaryTypes types = oracle->binaryTypes(script_, pc);
+    TypeOracle::BinaryTypes types = oracle->binaryTypes(script(), pc);
     current->add(ins);
     ins->infer(cx, types);
     current->push(ins);
 
     if (ins->isEffectful())
         return resumeAfter(ins);
     return maybeInsertResume();
 }
@@ -3025,17 +3025,17 @@ IonBuilder::jsop_binary(JSOp op)
     MDefinition *left = current->pop();
 
     return jsop_binary(op, left, right);
 }
 
 bool
 IonBuilder::jsop_pos()
 {
-    TypeOracle::Unary types = oracle->unaryOp(script_, pc);
+    TypeOracle::Unary types = oracle->unaryOp(script(), pc);
     if (IsNumberType(types.ival)) {
         // Already int32 or double.
         JS_ASSERT(IsNumberType(types.rval));
         return true;
     }
 
     // Compile +x as x * 1.
     MDefinition *value = current->pop();
@@ -3199,57 +3199,58 @@ IonBuilder::makeInliningDecision(AutoObj
     //     higher proportion of the runtime of the function than for larger
     //     functions.
     //  2. The cost of inlining (in terms of size expansion of the SSA graph),
     //     and size expansion of the ultimately generated code, will be
     //     less significant.
     //  3. Do not inline functions which are not called as frequently as their
     //     callers.
 
-    uint32_t callerUses = script_->getUseCount();
+    uint32_t callerUses = script()->getUseCount();
 
     uint32_t totalSize = 0;
     uint32_t checkUses = js_IonOptions.usesBeforeInlining;
     bool allFunctionsAreSmall = true;
     RootedFunction target(cx);
-    RootedScript script(cx);
+    RootedScript targetScript(cx);
     for (size_t i = 0; i < targets.length(); i++) {
         target = targets[i]->toFunction();
         if (!target->isInterpreted())
             return false;
 
-        script = target->nonLazyScript();
-        uint32_t calleeUses = script->getUseCount();
+        targetScript = target->nonLazyScript();
+        uint32_t calleeUses = targetScript->getUseCount();
 
         if (target->nargs < argc) {
             IonSpew(IonSpew_Inlining, "Not inlining, overflow of arguments.");
             return false;
         }
 
-        totalSize += script->length;
+        totalSize += targetScript->length;
         if (totalSize > js_IonOptions.inlineMaxTotalBytecodeLength)
             return false;
 
-        if (script->length > js_IonOptions.smallFunctionMaxBytecodeLength)
+        if (targetScript->length > js_IonOptions.smallFunctionMaxBytecodeLength)
             allFunctionsAreSmall = false;
 
         if (calleeUses * js_IonOptions.inlineUseCountRatio < callerUses) {
             IonSpew(IonSpew_Inlining, "Not inlining, callee is not hot");
             return false;
         }
     }
     if (allFunctionsAreSmall)
         checkUses = js_IonOptions.smallFunctionUsesBeforeInlining;
 
-    if (script_->getUseCount() < checkUses) {
+    if (script()->getUseCount() < checkUses) {
         IonSpew(IonSpew_Inlining, "Not inlining, caller is not hot");
         return false;
     }
 
-    if (!oracle->canInlineCall(script_, pc)) {
+    RootedScript scriptRoot(cx, script());
+    if (!oracle->canInlineCall(scriptRoot, pc)) {
         IonSpew(IonSpew_Inlining, "Cannot inline due to uninlineable call site");
         return false;
     }
 
     for (size_t i = 0; i < targets.length(); i++) {
         if (!canInlineTarget(targets[i]->toFunction())) {
             IonSpew(IonSpew_Inlining, "Decided not to inline");
             return false;
@@ -3773,17 +3774,18 @@ IonBuilder::createDeclEnvObject(MDefinit
 }
 
 MInstruction *
 IonBuilder::createCallObject(MDefinition *callee, MDefinition *scope)
 {
     // Create a template CallObject that we'll use to generate inline object
     // creation.
 
-    RootedObject templateObj(cx, CallObject::createTemplateObject(cx, script_));
+    RootedScript scriptRoot(cx, script());
+    RootedObject templateObj(cx, CallObject::createTemplateObject(cx, scriptRoot));
     if (!templateObj)
         return NULL;
 
     // If the CallObject needs dynamic slots, allocate those now.
     MInstruction *slots;
     if (templateObj->hasDynamicSlots()) {
         size_t nslots = JSObject::dynamicSlotsCount(templateObj->numFixedSlots(),
                                                     templateObj->slotSpan());
@@ -3799,17 +3801,17 @@ IonBuilder::createCallObject(MDefinition
     MInstruction *callObj = MNewCallObject::New(templateObj, slots);
     current->add(callObj);
 
     // Initialize the object's reserved slots.
     current->add(MStoreFixedSlot::New(callObj, CallObject::enclosingScopeSlot(), scope));
     current->add(MStoreFixedSlot::New(callObj, CallObject::calleeSlot(), callee));
 
     // Initialize argument slots.
-    for (AliasedFormalIter i(script_); i; i++) {
+    for (AliasedFormalIter i(script()); i; i++) {
         unsigned slot = i.scopeSlot();
         unsigned formal = i.frameIndex();
         MDefinition *param = current->getSlot(info().argSlot(formal));
         if (slot >= templateObj->numFixedSlots())
             current->add(MStoreSlot::New(slots, slot - templateObj->numFixedSlots(), param));
         else
             current->add(MStoreFixedSlot::New(callObj, slot, param));
     }
@@ -3848,17 +3850,17 @@ IonBuilder::createThisScripted(MDefiniti
     } else {
         MCallGetProperty *callGetProp = MCallGetProperty::New(callee, cx->names().classPrototype);
         callGetProp->setIdempotent();
         getProto = callGetProp;
     }
     current->add(getProto);
 
     // Create this from prototype
-    MCreateThis *createThis = MCreateThis::New(callee, getProto, NULL);
+    MCreateThis *createThis = MCreateThis::New(callee, getProto);
     current->add(createThis);
 
     return createThis;
 }
 
 JSObject *
 IonBuilder::getSingletonPrototype(JSFunction *target)
 {
@@ -3889,44 +3891,54 @@ IonBuilder::createThisScriptedSingleton(
     RootedObject templateObject(cx, js_CreateThisForFunctionWithProto(cx, target, proto));
     if (!templateObject)
         return NULL;
 
     // Trigger recompilation if the templateObject changes.
     if (templateObject->type()->newScript)
         types::HeapTypeSet::WatchObjectStateChange(cx, templateObject->type());
 
-    MConstant *protoDef = MConstant::New(ObjectValue(*proto));
-    current->add(protoDef);
-
-    MCreateThis *createThis = MCreateThis::New(callee, protoDef, templateObject);
+    MCreateThisWithTemplate *createThis = MCreateThisWithTemplate::New(templateObject);
     current->add(createThis);
 
     return createThis;
 }
 
 MDefinition *
 IonBuilder::createThis(HandleFunction target, MDefinition *callee)
 {
+    // Create this for unknown target
+    if (!target)
+        return createThisScripted(callee);
+
+    // Create this for native function
     if (target->isNative()) {
         if (!target->isNativeConstructor())
             return NULL;
         return createThisNative();
     }
 
-    MDefinition *createThis = NULL;
+    // Create this with known prototype.
     RootedObject proto(cx, getSingletonPrototype(target));
 
     // Try baking in the prototype.
-    if (proto)
-        createThis = createThisScriptedSingleton(target, proto, callee);
-
-    // If the prototype could not be hardcoded, emit a GETPROP.
+    if (proto) {
+        MDefinition *createThis = createThisScriptedSingleton(target, proto, callee);
+        if (createThis)
+            return createThis;
+    }
+
+    MDefinition *createThis = createThisScripted(callee);
     if (!createThis)
-        createThis = createThisScripted(callee);
+        return NULL;
+
+    // The native function case is already handled upfront.
+    // Here we can safely remove the native check for MCreateThis.
+    JS_ASSERT(createThis->isCreateThis());
+    createThis->toCreateThis()->removeNativeCheck();
 
     return createThis;
 }
 
 bool
 IonBuilder::jsop_funcall(uint32_t argc)
 {
     // Stack for JSOP_FUNCALL:
@@ -3937,17 +3949,17 @@ IonBuilder::jsop_funcall(uint32_t argc)
     // argc+2: The native 'call' function.
 
     // If |Function.prototype.call| may be overridden, don't optimize callsite.
     RootedFunction native(cx, getSingleCallTarget(argc, pc));
     if (!native || !native->isNative() || native->native() != &js_fun_call)
         return makeCall(native, argc, false);
 
     // Extract call target.
-    types::StackTypeSet *funTypes = oracle->getCallArg(script_, argc, 0, pc);
+    types::StackTypeSet *funTypes = oracle->getCallArg(script(), argc, 0, pc);
     RootedObject funobj(cx, (funTypes) ? funTypes->getSingleton() : NULL);
     RootedFunction target(cx, (funobj && funobj->isFunction()) ? funobj->toFunction() : NULL);
 
     // Unwrap the (JSFunction *) parameter.
     int funcDepth = -((int)argc + 1);
     MPassArg *passFunc = current->peek(funcDepth)->toPassArg();
     current->rewriteAtDepth(funcDepth, passFunc->getArgument());
 
@@ -3979,17 +3991,17 @@ bool
 IonBuilder::jsop_funapply(uint32_t argc)
 {
     RootedFunction native(cx, getSingleCallTarget(argc, pc));
     if (argc != 2)
         return makeCall(native, argc, false);
 
     // Disable compilation if the second argument to |apply| cannot be guaranteed
     // to be either definitely |arguments| or definitely not |arguments|.
-    types::StackTypeSet *argObjTypes = oracle->getCallArg(script_, argc, 2, pc);
+    types::StackTypeSet *argObjTypes = oracle->getCallArg(script(), argc, 2, pc);
     LazyArgumentsType isArgObj = oracle->isArgumentObject(argObjTypes);
     if (isArgObj == MaybeArguments)
         return abort("fun.apply with MaybeArguments");
 
     // Fallback to regular call if arg 2 is not definitely |arguments|.
     if (isArgObj != DefinitelyArguments)
         return makeCall(native, argc, false);
 
@@ -4002,17 +4014,17 @@ IonBuilder::jsop_funapply(uint32_t argc)
 
     // Stack for JSOP_FUNAPPLY:
     // 1:      MPassArg(Vp)
     // 2:      MPassArg(This)
     // argc+1: MPassArg(JSFunction *), the 'f' in |f.call()|, in |this| position.
     // argc+2: The native 'apply' function.
 
     // Extract call target.
-    types::StackTypeSet *funTypes = oracle->getCallArg(script_, argc, 0, pc);
+    types::StackTypeSet *funTypes = oracle->getCallArg(script(), argc, 0, pc);
     RootedObject funobj(cx, (funTypes) ? funTypes->getSingleton() : NULL);
     RootedFunction target(cx, (funobj && funobj->isFunction()) ? funobj->toFunction() : NULL);
 
     // Vp
     MPassArg *passVp = current->pop()->toPassArg();
     passVp->replaceAllUsesWith(passVp->getArgument());
     passVp->block()->discard(passVp);
 
@@ -4036,30 +4048,30 @@ IonBuilder::jsop_funapply(uint32_t argc)
 
     MApplyArgs *apply = MApplyArgs::New(target, argFunc, numArgs, argThis);
     current->add(apply);
     current->push(apply);
     if (!resumeAfter(apply))
         return false;
 
     types::StackTypeSet *barrier;
-    types::StackTypeSet *types = oracle->returnTypeSet(script_, pc, &barrier);
+    types::StackTypeSet *types = oracle->returnTypeSet(script(), pc, &barrier);
     return pushTypeBarrier(apply, types, barrier);
 }
 
 bool
 IonBuilder::jsop_call(uint32_t argc, bool constructing)
 {
     AssertCanGC();
 
     // Acquire known call target if existent.
     AutoObjectVector targets(cx);
     uint32_t numTargets = getPolyCallTargets(argc, pc, targets, 4);
     types::StackTypeSet *barrier;
-    types::StackTypeSet *types = oracle->returnTypeSet(script_, pc, &barrier);
+    types::StackTypeSet *types = oracle->returnTypeSet(script(), pc, &barrier);
 
     // Attempt to inline native and scripted functions.
     if (inliningEnabled()) {
         // Inline a single native call if possible.
         if (numTargets == 1 && targets[0]->toFunction()->isNative()) {
             RootedFunction target(cx, targets[0]->toFunction());
             switch (inlineNativeCall(target->native(), argc, constructing)) {
               case InliningStatus_Inlined:
@@ -4119,18 +4131,18 @@ IonBuilder::makeCallHelper(HandleFunctio
     // potentially perform rearrangement.
     MPrepareCall *start = new MPrepareCall;
     MPassArg *firstArg = current->peek(-1)->toPassArg();
     firstArg->block()->insertBefore(firstArg, start);
     call->initPrepareCall(start);
 
     MPassArg *thisArg = current->pop()->toPassArg();
 
-    // If the target is known, inline the constructor on the caller-side.
-    if (constructing && target) {
+    // Inline the constructor on the caller-side.
+    if (constructing) {
         MDefinition *callee = current->peek(-1);
         MDefinition *create = createThis(target, callee);
         if (!create) {
             abort("Failure inlining constructor for call.");
             return NULL;
         }
 
         MPassArg *newThis = MPassArg::New(create);
@@ -4168,62 +4180,63 @@ IonBuilder::makeCallBarrier(HandleFuncti
 
     return pushTypeBarrier(call, types, barrier);
 }
 
 bool
 IonBuilder::makeCall(HandleFunction target, uint32_t argc, bool constructing)
 {
     types::StackTypeSet *barrier;
-    types::StackTypeSet *types = oracle->returnTypeSet(script_, pc, &barrier);
+    types::StackTypeSet *types = oracle->returnTypeSet(script(), pc, &barrier);
     return makeCallBarrier(target, argc, constructing, types, barrier);
 }
 
 bool
 IonBuilder::jsop_compare(JSOp op)
 {
     MDefinition *right = current->pop();
     MDefinition *left = current->pop();
 
     MCompare *ins = MCompare::New(left, right, op);
     current->add(ins);
     current->push(ins);
 
-    ins->infer(cx, oracle->binaryTypes(script_, pc));
+    TypeOracle::BinaryTypes b = oracle->binaryTypes(script(), pc);
+    ins->infer(cx, b);
 
     if (ins->isEffectful() && !resumeAfter(ins))
         return false;
     return true;
 }
 
 JSObject *
 IonBuilder::getNewArrayTemplateObject(uint32_t count)
 {
     RootedObject templateObject(cx, NewDenseUnallocatedArray(cx, count));
     if (!templateObject)
         return NULL;
 
-    RootedScript script(cx, script_);
-    if (types::UseNewTypeForInitializer(cx, script, pc, JSProto_Array)) {
+    RootedScript scriptRoot(cx, script());
+    if (types::UseNewTypeForInitializer(cx, scriptRoot, pc, JSProto_Array)) {
         if (!JSObject::setSingletonType(cx, templateObject))
             return NULL;
     } else {
-        types::TypeObject *type = types::TypeScript::InitObject(cx, script, pc, JSProto_Array);
+        types::TypeObject *type = types::TypeScript::InitObject(cx, scriptRoot, pc, JSProto_Array);
         if (!type)
             return NULL;
         templateObject->setType(type);
     }
 
     return templateObject;
 }
 
 bool
 IonBuilder::jsop_newarray(uint32_t count)
 {
-    JS_ASSERT(script_->compileAndGo);
+    JS_ASSERT(script()->compileAndGo);
 
     JSObject *templateObject = getNewArrayTemplateObject(count);
     if (!templateObject)
         return false;
 
     MNewArray *ins = new MNewArray(count, templateObject, MNewArray::NewArray_Allocating);
 
     current->add(ins);
@@ -4231,54 +4244,54 @@ IonBuilder::jsop_newarray(uint32_t count
 
     return true;
 }
 
 bool
 IonBuilder::jsop_newobject(HandleObject baseObj)
 {
     // Don't bake in the TypeObject for non-CNG scripts.
-    JS_ASSERT(script_->compileAndGo);
+    JS_ASSERT(script()->compileAndGo);
 
     RootedObject templateObject(cx);
 
     if (baseObj) {
         templateObject = CopyInitializerObject(cx, baseObj);
     } else {
         gc::AllocKind kind = GuessObjectGCKind(0);
         templateObject = NewBuiltinClassInstance(cx, &ObjectClass, kind);
     }
 
     if (!templateObject)
         return false;
 
-    RootedScript script(cx, script_);
-    if (types::UseNewTypeForInitializer(cx, script, pc, JSProto_Object)) {
+    RootedScript scriptRoot(cx, script());
+    if (types::UseNewTypeForInitializer(cx, scriptRoot, pc, JSProto_Object)) {
         if (!JSObject::setSingletonType(cx, templateObject))
             return false;
     } else {
-        types::TypeObject *type = types::TypeScript::InitObject(cx, script, pc, JSProto_Object);
+        types::TypeObject *type = types::TypeScript::InitObject(cx, scriptRoot, pc, JSProto_Object);
         if (!type)
             return false;
         templateObject->setType(type);
     }
 
     MNewObject *ins = MNewObject::New(templateObject);
 
     current->add(ins);
     current->push(ins);
 
     return resumeAfter(ins);
 }
 
 bool
 IonBuilder::jsop_initelem()
 {
-    if (oracle->propertyWriteCanSpecialize(script_, pc)) {
-        if (oracle->elementWriteIsDenseArray(script_, pc))
+    if (oracle->propertyWriteCanSpecialize(script(), pc)) {
+        if (oracle->elementWriteIsDenseArray(script(), pc))
             return jsop_initelem_dense();
     }
 
     return abort("NYI: JSOP_INITELEM supports for non dense objects/arrays.");
 }
 
 bool
 IonBuilder::jsop_initelem_dense()
@@ -4321,17 +4334,17 @@ CanEffectlesslyCallLookupGenericOnObject
 bool
 IonBuilder::jsop_initprop(HandlePropertyName name)
 {
     MDefinition *value = current->pop();
     MDefinition *obj = current->peek(-1);
 
     RootedObject templateObject(cx, obj->toNewObject()->templateObject());
 
-    if (!oracle->propertyWriteCanSpecialize(script_, pc)) {
+    if (!oracle->propertyWriteCanSpecialize(script(), pc)) {
         // This should only happen for a few names like __proto__.
         return abort("INITPROP Monitored initprop");
     }
 
     if (!CanEffectlesslyCallLookupGenericOnObject(templateObject))
         return abort("INITPROP template object is special");
 
     RootedObject holder(cx);
@@ -4345,17 +4358,17 @@ IonBuilder::jsop_initprop(HandleProperty
     if (!shape || holder != templateObject) {
         // JSOP_NEWINIT becomes an MNewObject without preconfigured properties.
         MInitProp *init = MInitProp::New(obj, name, value);
         current->add(init);
         return resumeAfter(init);
     }
 
     bool needsBarrier = true;
-    TypeOracle::BinaryTypes b = oracle->binaryTypes(script_, pc);
+    TypeOracle::BinaryTypes b = oracle->binaryTypes(script(), pc);
     if (b.lhsTypes &&
         ((jsid)id == types::MakeTypeId(cx, id)) &&
         !b.lhsTypes->propertyNeedsBarrier(cx, id))
     {
         needsBarrier = false;
     }
 
     if (templateObject->isFixedSlot(shape->slot())) {
@@ -4669,25 +4682,25 @@ IonBuilder::insertRecompileCheck()
 {
     if (!inliningEnabled())
         return;
 
     if (inliningDepth > 0)
         return;
 
     // Don't recompile if we are already inlining.
-    if (script_->getUseCount() >= js_IonOptions.usesBeforeInlining)
+    if (script()->getUseCount() >= js_IonOptions.usesBeforeInlining)
         return;
 
     // Don't recompile if the oracle cannot provide inlining information
     // or if the script has no calls.
     if (!oracle->canInlineCalls())
         return;
 
-    uint32_t minUses = UsesBeforeIonRecompile(script_, pc);
+    uint32_t minUses = UsesBeforeIonRecompile(script(), pc);
     MRecompileCheck *check = MRecompileCheck::New(minUses);
     current->add(check);
 }
 
 static inline bool
 TestSingletonProperty(JSContext *cx, HandleObject obj, HandleId id, bool *isKnownConstant)
 {
     // We would like to completely no-op property/global accesses which can
@@ -4945,39 +4958,40 @@ IonBuilder::jsop_getgname(HandleProperty
     // Optimize undefined, NaN, and Infinity.
     if (name == cx->names().undefined)
         return pushConstant(UndefinedValue());
     if (name == cx->names().NaN)
         return pushConstant(cx->runtime->NaNValue);
     if (name == cx->names().Infinity)
         return pushConstant(cx->runtime->positiveInfinityValue);
 
-    RootedObject globalObj(cx, &script_->global());
+    RootedObject globalObj(cx, &script()->global());
     JS_ASSERT(globalObj->isNative());
 
     RootedId id(cx, NameToId(name));
 
     // For the fastest path, the property must be found, and it must be found
     // as a normal data property on exactly the global object.
     const js::Shape *shape = globalObj->nativeLookup(cx, id);
     if (!shape || !shape->hasDefaultGetter() || !shape->hasSlot())
         return jsop_getname(name);
 
-    types::HeapTypeSet *propertyTypes = oracle->globalPropertyTypeSet(script_, pc, id);
+    types::HeapTypeSet *propertyTypes = oracle->globalPropertyTypeSet(script(), pc, id);
     if (propertyTypes && propertyTypes->isOwnProperty(cx, globalObj->getType(cx), true)) {
         // The property has been reconfigured as non-configurable, non-enumerable
         // or non-writable.
         return jsop_getname(name);
     }
 
     // If the property is permanent, a shape guard isn't necessary.
     JSValueType knownType = JSVAL_TYPE_UNKNOWN;
 
-    types::StackTypeSet *barrier = oracle->propertyReadBarrier(script_, pc);
-    types::StackTypeSet *types = oracle->propertyRead(script_, pc);
+    RootedScript scriptRoot(cx, script());
+    types::StackTypeSet *barrier = oracle->propertyReadBarrier(scriptRoot, pc);
+    types::StackTypeSet *types = oracle->propertyRead(script(), pc);
     if (types) {
         JSObject *singleton = types->getSingleton();
 
         knownType = types->getKnownTypeTag();
         if (!barrier) {
             if (singleton) {
                 // Try to inline a known constant value.
                 bool isKnownConstant;
@@ -5014,23 +5028,23 @@ IonBuilder::jsop_getgname(HandleProperty
 
     current->push(load);
     return pushTypeBarrier(load, types, barrier);
 }
 
 bool
 IonBuilder::jsop_setgname(HandlePropertyName name)
 {
-    RootedObject globalObj(cx, &script_->global());
+    RootedObject globalObj(cx, &script()->global());
     RootedId id(cx, NameToId(name));
 
     JS_ASSERT(globalObj->isNative());
 
     bool canSpecialize;
-    types::HeapTypeSet *propertyTypes = oracle->globalPropertyWrite(script_, pc, id, &canSpecialize);
+    types::HeapTypeSet *propertyTypes = oracle->globalPropertyWrite(script(), pc, id, &canSpecialize);
 
     // This should only happen for a few names like __proto__.
     if (!canSpecialize || globalObj->watched())
         return jsop_setprop(name);
 
     // For the fastest path, the property must be found, and it must be found
     // as a normal data property on exactly the global object.
     const js::Shape *shape = globalObj->nativeLookup(cx, id);
@@ -5085,17 +5099,17 @@ IonBuilder::jsop_setgname(HandleProperty
     return resumeAfter(store);
 }
 
 bool
 IonBuilder::jsop_getname(HandlePropertyName name)
 {
     MDefinition *object;
     if (js_CodeSpec[*pc].format & JOF_GNAME) {
-        MInstruction *global = MConstant::New(ObjectValue(script_->global()));
+        MInstruction *global = MConstant::New(ObjectValue(script()->global()));
         current->add(global);
         object = global;
     } else {
         current->push(current->scopeChain());
         object = current->pop();
     }
 
     MGetNameCache *ins;
@@ -5105,41 +5119,43 @@ IonBuilder::jsop_getname(HandlePropertyN
         ins = MGetNameCache::New(object, name, MGetNameCache::NAME);
 
     current->add(ins);
     current->push(ins);
 
     if (!resumeAfter(ins))
         return false;
 
-    types::StackTypeSet *barrier = oracle->propertyReadBarrier(script_, pc);
-    types::StackTypeSet *types = oracle->propertyRead(script_, pc);
+    RootedScript scriptRoot(cx, script());
+    types::StackTypeSet *barrier = oracle->propertyReadBarrier(scriptRoot, pc);
+    types::StackTypeSet *types = oracle->propertyRead(script(), pc);
 
     monitorResult(ins, barrier, types);
     return pushTypeBarrier(ins, types, barrier);
 }
 
 bool
 IonBuilder::jsop_intrinsicname(HandlePropertyName name)
 {
-    types::StackTypeSet *types = oracle->propertyRead(script_, pc);
+    types::StackTypeSet *types = oracle->propertyRead(script(), pc);
     JSValueType type = types->getKnownTypeTag();
 
     // If we haven't executed this opcode yet, we need to get the intrinsic
     // value and monitor the result.
     if (type == JSVAL_TYPE_UNKNOWN) {
         MCallGetIntrinsicValue *ins = MCallGetIntrinsicValue::New(name);
 
         current->add(ins);
         current->push(ins);
 
         if (!resumeAfter(ins))
             return false;
 
-        types::StackTypeSet *barrier = oracle->propertyReadBarrier(script_, pc);
+        RootedScript scriptRoot(cx, script());
+        types::StackTypeSet *barrier = oracle->propertyReadBarrier(scriptRoot, pc);
         monitorResult(ins, barrier, types);
         return pushTypeBarrier(ins, types, barrier);
     }
 
     // Bake in the intrinsic. Make sure that TI agrees with us on the type.
     RootedValue vp(cx, UndefinedValue());
     if (!cx->global()->getIntrinsicValue(cx, name, &vp))
         return false;
@@ -5151,41 +5167,41 @@ IonBuilder::jsop_intrinsicname(HandlePro
     current->push(ins);
 
     return true;
 }
 
 bool
 IonBuilder::jsop_bindname(PropertyName *name)
 {
-    JS_ASSERT(script_->analysis()->usesScopeChain());
+    JS_ASSERT(script()->analysis()->usesScopeChain());
 
     MDefinition *scopeChain = current->scopeChain();
-    MBindNameCache *ins = MBindNameCache::New(scopeChain, name, script_, pc);
+    MBindNameCache *ins = MBindNameCache::New(scopeChain, name, script(), pc);
 
     current->add(ins);
     current->push(ins);
 
     return resumeAfter(ins);
 }
 
 bool
 IonBuilder::jsop_getelem()
 {
-    if (oracle->elementReadIsDenseArray(script_, pc))
+    if (oracle->elementReadIsDenseArray(script(), pc))
         return jsop_getelem_dense();
 
     int arrayType = TypedArray::TYPE_MAX;
-    if (oracle->elementReadIsTypedArray(script_, pc, &arrayType))
+    if (oracle->elementReadIsTypedArray(script(), pc, &arrayType))
         return jsop_getelem_typed(arrayType);
 
-    if (oracle->elementReadIsString(script_, pc))
+    if (oracle->elementReadIsString(script(), pc))
         return jsop_getelem_string();
 
-    LazyArgumentsType isArguments = oracle->elementReadMagicArguments(script_, pc);
+    LazyArgumentsType isArguments = oracle->elementReadMagicArguments(script(), pc);
     if (isArguments == MaybeArguments)
         return abort("Type is not definitely lazy arguments.");
     if (isArguments == DefinitelyArguments)
         return jsop_arguments_getelem();
 
     MDefinition *rhs = current->pop();
     MDefinition *lhs = current->pop();
 
@@ -5193,46 +5209,48 @@ IonBuilder::jsop_getelem()
 
     // TI does not account for GETELEM with string indexes, so we have to monitor
     // the result of MGetElementCache if it's expected to access string properties.
     // If the result of MGetElementCache is not monitored, we won't generate any
     // getprop stubs.
     bool mustMonitorResult = false;
     bool cacheable = false;
 
-    oracle->elementReadGeneric(script_, pc, &cacheable, &mustMonitorResult);
+    oracle->elementReadGeneric(script(), pc, &cacheable, &mustMonitorResult);
 
     if (cacheable)
         ins = MGetElementCache::New(lhs, rhs, mustMonitorResult);
     else
         ins = MCallGetElement::New(lhs, rhs);
 
     current->add(ins);
     current->push(ins);
 
     if (!resumeAfter(ins))
         return false;
 
-    types::StackTypeSet *barrier = oracle->propertyReadBarrier(script_, pc);
-    types::StackTypeSet *types = oracle->propertyRead(script_, pc);
+    RootedScript scriptRoot(cx, script());
+    types::StackTypeSet *barrier = oracle->propertyReadBarrier(scriptRoot, pc);
+    types::StackTypeSet *types = oracle->propertyRead(script(), pc);
 
     if (mustMonitorResult)
         monitorResult(ins, barrier, types);
     return pushTypeBarrier(ins, types, barrier);
 }
 
 bool
 IonBuilder::jsop_getelem_dense()
 {
     if (oracle->arrayPrototypeHasIndexedProperty())
         return abort("GETELEM Array proto has indexed properties");
 
-    types::StackTypeSet *barrier = oracle->propertyReadBarrier(script_, pc);
-    types::StackTypeSet *types = oracle->propertyRead(script_, pc);
-    bool needsHoleCheck = !oracle->elementReadIsPacked(script_, pc);
+    RootedScript scriptRoot(cx, script());
+    types::StackTypeSet *barrier = oracle->propertyReadBarrier(scriptRoot, pc);
+    types::StackTypeSet *types = oracle->propertyRead(script(), pc);
+    bool needsHoleCheck = !oracle->elementReadIsPacked(script(), pc);
     bool maybeUndefined = types->hasType(types::Type::UndefinedType());
 
     MDefinition *id = current->pop();
     MDefinition *obj = current->pop();
 
     JSValueType knownType = JSVAL_TYPE_UNKNOWN;
     if (!barrier) {
         knownType = types->getKnownTypeTag();
@@ -5316,18 +5334,19 @@ GetTypedArrayElements(MDefinition *obj)
         return MConstantElements::New(data);
     }
     return MTypedArrayElements::New(obj);
 }
 
 bool
 IonBuilder::jsop_getelem_typed(int arrayType)
 {
-    types::StackTypeSet *barrier = oracle->propertyReadBarrier(script_, pc);
-    types::StackTypeSet *types = oracle->propertyRead(script_, pc);
+    RootedScript scriptRoot(cx, script());
+    types::StackTypeSet *barrier = oracle->propertyReadBarrier(scriptRoot, pc);
+    types::StackTypeSet *types = oracle->propertyRead(script(), pc);
 
     MDefinition *id = current->pop();
     MDefinition *obj = current->pop();
 
     bool maybeUndefined = types->hasType(types::Type::UndefinedType());
 
     // Reading from an Uint32Array will result in a double for values
     // that don't fit in an int32. We have to bailout if this happens
@@ -5414,41 +5433,41 @@ IonBuilder::jsop_getelem_string()
     current->add(idInt32);
     id = idInt32;
 
     MStringLength *length = MStringLength::New(str);
     current->add(length);
 
     // This will cause an invalidation of this script once the 'undefined' type
     // is monitored by the interpreter.
-    JS_ASSERT(oracle->propertyRead(script_, pc)->getKnownTypeTag() == JSVAL_TYPE_STRING);
+    JS_ASSERT(oracle->propertyRead(script(), pc)->getKnownTypeTag() == JSVAL_TYPE_STRING);
     id = addBoundsCheck(id, length);
 
     MCharCodeAt *charCode = MCharCodeAt::New(str, id);
     current->add(charCode);
 
     MFromCharCode *result = MFromCharCode::New(charCode);
     current->add(result);
     current->push(result);
     return true;
 }
 
 bool
 IonBuilder::jsop_setelem()
 {
-    if (oracle->propertyWriteCanSpecialize(script_, pc)) {
-        if (oracle->elementWriteIsDenseArray(script_, pc))
+    if (oracle->propertyWriteCanSpecialize(script(), pc)) {
+        if (oracle->elementWriteIsDenseArray(script(), pc))
             return jsop_setelem_dense();
 
         int arrayType = TypedArray::TYPE_MAX;
-        if (oracle->elementWriteIsTypedArray(script_, pc, &arrayType))
+        if (oracle->elementWriteIsTypedArray(script(), pc, &arrayType))
             return jsop_setelem_typed(arrayType);
     }
 
-    LazyArgumentsType isArguments = oracle->elementWriteMagicArguments(script_, pc);
+    LazyArgumentsType isArguments = oracle->elementWriteMagicArguments(script(), pc);
     if (isArguments == MaybeArguments)
         return abort("Type is not definitely lazy arguments.");
     if (isArguments == DefinitelyArguments)
         return jsop_arguments_setelem();
 
     MDefinition *value = current->pop();
     MDefinition *index = current->pop();
     MDefinition *object = current->pop();
@@ -5461,18 +5480,18 @@ IonBuilder::jsop_setelem()
 }
 
 bool
 IonBuilder::jsop_setelem_dense()
 {
     if (oracle->arrayPrototypeHasIndexedProperty())
         return abort("SETELEM Array proto has indexed properties");
 
-    MIRType elementType = oracle->elementWrite(script_, pc);
-    bool packed = oracle->elementWriteIsPacked(script_, pc);
+    MIRType elementType = oracle->elementWrite(script(), pc);
+    bool packed = oracle->elementWriteIsPacked(script(), pc);
 
     MDefinition *value = current->pop();
     MDefinition *id = current->pop();
     MDefinition *obj = current->pop();
 
     // Ensure id is an integer.
     MInstruction *idInt32 = MToInt32::New(id);
     current->add(idInt32);
@@ -5481,17 +5500,17 @@ IonBuilder::jsop_setelem_dense()
     // Get the elements vector.
     MElements *elements = MElements::New(obj);
     current->add(elements);
 
     // Use MStoreElementHole if this SETELEM has written to out-of-bounds
     // indexes in the past. Otherwise, use MStoreElement so that we can hoist
     // the initialized length and bounds check.
     MStoreElementCommon *store;
-    if (oracle->setElementHasWrittenHoles(script_, pc)) {
+    if (oracle->setElementHasWrittenHoles(script(), pc)) {
         MStoreElementHole *ins = MStoreElementHole::New(obj, elements, id, value);
         store = ins;
 
         current->add(ins);
         current->push(value);
 
         if (!resumeAfter(ins))
             return false;
@@ -5507,17 +5526,17 @@ IonBuilder::jsop_setelem_dense()
         current->add(ins);
         current->push(value);
 
         if (!resumeAfter(ins))
             return false;
     }
 
     // Determine whether a write barrier is required.
-    if (oracle->elementWriteNeedsBarrier(script_, pc))
+    if (oracle->elementWriteNeedsBarrier(script(), pc))
         store->setNeedsBarrier();
 
     if (elementType != MIRType_None && packed)
         store->setElementType(elementType);
 
     return true;
 }
 
@@ -5567,17 +5586,17 @@ IonBuilder::jsop_length()
 
     RootedPropertyName name(cx, info().getAtom(pc)->asPropertyName());
     return jsop_getprop(name);
 }
 
 bool
 IonBuilder::jsop_length_fastPath()
 {
-    TypeOracle::UnaryTypes sig = oracle->unaryTypes(script_, pc);
+    TypeOracle::UnaryTypes sig = oracle->unaryTypes(script(), pc);
     if (!sig.inTypes || !sig.outTypes)
         return false;
 
     if (sig.outTypes->getKnownTypeTag() != JSVAL_TYPE_INT32)
         return false;
 
     switch (sig.inTypes->getKnownTypeTag()) {
       case JSVAL_TYPE_STRING: {
@@ -5638,18 +5657,19 @@ IonBuilder::jsop_arguments_length()
     current->add(ins);
     current->push(ins);
     return true;
 }
 
 bool
 IonBuilder::jsop_arguments_getelem()
 {
-    types::StackTypeSet *barrier = oracle->propertyReadBarrier(script_, pc);
-    types::StackTypeSet *types = oracle->propertyRead(script_, pc);
+    RootedScript scriptRoot(cx, script());
+    types::StackTypeSet *barrier = oracle->propertyReadBarrier(scriptRoot, pc);
+    types::StackTypeSet *types = oracle->propertyRead(script(), pc);
 
     MDefinition *idx = current->pop();
 
     // Type Inference has guaranteed this is an optimized arguments object.
     MDefinition *args = current->pop();
     args->setFoldedUnchecked();
 
     // To ensure that we are not looking above the number of actual arguments.
@@ -6124,18 +6144,19 @@ IonBuilder::invalidatedIdempotentCache()
 }
 
 bool
 IonBuilder::loadSlot(MDefinition *obj, Shape *shape, MIRType rvalType)
 {
     JS_ASSERT(shape->hasDefaultGetter());
     JS_ASSERT(shape->hasSlot());
 
-    types::StackTypeSet *barrier = oracle->propertyReadBarrier(script_, pc);
-    types::StackTypeSet *types = oracle->propertyRead(script_, pc);
+    RootedScript scriptRoot(cx, script());
+    types::StackTypeSet *barrier = oracle->propertyReadBarrier(scriptRoot, pc);
+    types::StackTypeSet *types = oracle->propertyRead(script(), pc);
 
     if (shape->slot() < shape->numFixedSlots()) {
         MLoadFixedSlot *load = MLoadFixedSlot::New(obj, shape->slot());
         current->add(load);
         current->push(load);
 
         load->setResultType(rvalType);
         return pushTypeBarrier(load, types, barrier);
@@ -6179,20 +6200,21 @@ IonBuilder::storeSlot(MDefinition *obj, 
     return resumeAfter(store);
 }
 
 bool
 IonBuilder::jsop_getprop(HandlePropertyName name)
 {
     RootedId id(cx, NameToId(name));
 
-    types::StackTypeSet *barrier = oracle->propertyReadBarrier(script_, pc);
-    types::StackTypeSet *types = oracle->propertyRead(script_, pc);
-    TypeOracle::Unary unary = oracle->unaryOp(script_, pc);
-    TypeOracle::UnaryTypes uTypes = oracle->unaryTypes(script_, pc);
+    RootedScript scriptRoot(cx, script());
+    types::StackTypeSet *barrier = oracle->propertyReadBarrier(scriptRoot, pc);
+    types::StackTypeSet *types = oracle->propertyRead(script(), pc);
+    TypeOracle::Unary unary = oracle->unaryOp(script(), pc);
+    TypeOracle::UnaryTypes uTypes = oracle->unaryTypes(script(), pc);
 
     bool emitted = false;
 
     // Try to optimize arguments.length.
     if (!getPropTryArgumentsLength(&emitted) || emitted)
         return emitted;
 
     // Try to hardcode known constants.
@@ -6226,17 +6248,17 @@ IonBuilder::jsop_getprop(HandlePropertyN
     monitorResult(call, barrier, types);
     return pushTypeBarrier(call, types, barrier);
 }
 
 bool
 IonBuilder::getPropTryArgumentsLength(bool *emitted)
 {
     JS_ASSERT(*emitted == false);
-    LazyArgumentsType isArguments = oracle->propertyReadMagicArguments(script_, pc);
+    LazyArgumentsType isArguments = oracle->propertyReadMagicArguments(script(), pc);
 
     if (isArguments == MaybeArguments)
         return abort("Type is not definitely lazy arguments.");
     if (isArguments != DefinitelyArguments)
         return true;
     if (JSOp(*pc) != JSOP_LENGTH)
         return true;
 
@@ -6248,17 +6270,17 @@ bool
 IonBuilder::getPropTryConstant(bool *emitted, HandleId id, types::StackTypeSet *barrier,
                                types::StackTypeSet *types, TypeOracle::UnaryTypes unaryTypes)
 {
     JS_ASSERT(*emitted == false);
     JSObject *singleton = types ? types->getSingleton() : NULL;
     if (!singleton || barrier)
         return true;
 
-    RootedObject global(cx, &script_->global());
+    RootedObject global(cx, &script()->global());
 
     bool isConstant, testObject, testString;
     if (!TestSingletonPropertyTypes(cx, unaryTypes.inTypes, global, id,
                                     &isConstant, &testObject, &testString))
         return false;
 
     if (!isConstant)
         return true;
@@ -6373,22 +6395,22 @@ IonBuilder::getPropTryCommonGetter(bool 
     return true;
 }
 
 bool
 IonBuilder::getPropTryMonomorphic(bool *emitted, HandleId id, types::StackTypeSet *barrier,
                                   TypeOracle::Unary unary, TypeOracle::UnaryTypes unaryTypes)
 {
     JS_ASSERT(*emitted == false);
-    bool accessGetter = oracle->propertyReadAccessGetter(script_, pc);
+    bool accessGetter = oracle->propertyReadAccessGetter(script(), pc);
 
     if (unary.ival != MIRType_Object)
         return true;
 
-    Shape *objShape = mjit::GetPICSingleShape(cx, script_, pc, info().constructing());
+    Shape *objShape = mjit::GetPICSingleShape(cx, script(), pc, info().constructing());
     if (!objShape || objShape->inDictionary()) {
         spew("GETPROP not monomorphic");
         return true;
     }
 
     MDefinition *obj = current->pop();
 
     // The JM IC was monomorphic, so we inline the property access as long as
@@ -6413,17 +6435,17 @@ IonBuilder::getPropTryMonomorphic(bool *
 }
 
 bool
 IonBuilder::getPropTryPolymorphic(bool *emitted, HandlePropertyName name, HandleId id,
                                   types::StackTypeSet *barrier, types::StackTypeSet *types,
                                   TypeOracle::Unary unary, TypeOracle::UnaryTypes unaryTypes)
 {
     JS_ASSERT(*emitted == false);
-    bool accessGetter = oracle->propertyReadAccessGetter(script_, pc);
+    bool accessGetter = oracle->propertyReadAccessGetter(script(), pc);
 
     // The input value must either be an object, or we should have strong suspicions
     // that it can be safely unboxed to an object.
     if (unary.ival != MIRType_Object && !unaryTypes.inTypes->objectOrSentinel())
         return true;
 
     MIRType rvalType = unary.rval;
     if (barrier || IsNullOrUndefined(unary.rval) || accessGetter)
@@ -6435,17 +6457,18 @@ IonBuilder::getPropTryPolymorphic(bool *
 
     // Try to mark the cache as idempotent. We only do this if JM is enabled
     // (its ICs are used to mark property reads as likely non-idempotent) or
     // if we are compiling eagerly (to improve test coverage).
     if (unary.ival == MIRType_Object &&
         (cx->methodJitEnabled || js_IonOptions.eagerCompilation) &&
         !invalidatedIdempotentCache())
     {
-        if (oracle->propertyReadIdempotent(script_, pc, id))
+        RootedScript scriptRoot(cx, script());
+        if (oracle->propertyReadIdempotent(scriptRoot, pc, id))
             load->setIdempotent();
     }
 
     if (JSOp(*pc) == JSOP_CALLPROP) {
         if (!annotateGetPropertyCache(cx, obj, load, unaryTypes.inTypes, types))
             return false;
     }
 
@@ -6470,19 +6493,19 @@ IonBuilder::getPropTryPolymorphic(bool *
 }
 
 bool
 IonBuilder::jsop_setprop(HandlePropertyName name)
 {
     MDefinition *value = current->pop();
     MDefinition *obj = current->pop();
 
-    bool monitored = !oracle->propertyWriteCanSpecialize(script_, pc);
-
-    TypeOracle::BinaryTypes binaryTypes = oracle->binaryTypes(script_, pc);
+    bool monitored = !oracle->propertyWriteCanSpecialize(script(), pc);
+
+    TypeOracle::BinaryTypes binaryTypes = oracle->binaryTypes(script(), pc);
 
     if (!monitored) {
         if (types::HeapTypeSet *propTypes = GetDefiniteSlot(cx, binaryTypes.lhsTypes, name)) {
             MStoreFixedSlot *fixed = MStoreFixedSlot::New(obj, propTypes->definiteSlot(), value);
             current->add(fixed);
             current->push(value);
             if (propTypes->needsBarrier(cx))
                 fixed->setNeedsBarrier();
@@ -6526,46 +6549,46 @@ IonBuilder::jsop_setprop(HandlePropertyN
         MCall *call = makeCallHelper(setter, 1, false);
         if (!call)
             return false;
 
         current->push(value);
         return resumeAfter(call);
     }
 
-    oracle->binaryOp(script_, pc);
+    oracle->binaryOp(script(), pc);
 
     MSetPropertyInstruction *ins;
     if (monitored) {
-        ins = MCallSetProperty::New(obj, value, name, script_->strictModeCode);
+        ins = MCallSetProperty::New(obj, value, name, script()->strictModeCode);
     } else {
         Shape *objShape;
-        if ((objShape = mjit::GetPICSingleShape(cx, script_, pc, info().constructing())) &&
+        if ((objShape = mjit::GetPICSingleShape(cx, script(), pc, info().constructing())) &&
             !objShape->inDictionary())
         {
             // The JM IC was monomorphic, so we inline the property access as
             // long as the shape is not in dictionary mode. We cannot be sure
             // that the shape is still a lastProperty, and calling Shape::search
             // on dictionary mode shapes that aren't lastProperty is invalid.
             obj = addShapeGuard(obj, objShape, Bailout_CachedShapeGuard);
 
             Shape *shape = objShape->search(cx, NameToId(name));
             JS_ASSERT(shape);
 
             spew("Inlining monomorphic SETPROP");
 
             jsid typeId = types::MakeTypeId(cx, id);
-            bool needsBarrier = oracle->propertyWriteNeedsBarrier(script_, pc, typeId);
+            bool needsBarrier = oracle->propertyWriteNeedsBarrier(script(), pc, typeId);
 
             return storeSlot(obj, shape, value, needsBarrier);
         }
 
         spew("SETPROP not monomorphic");
 
-        ins = MSetPropertyCache::New(obj, value, name, script_->strictModeCode);
+        ins = MSetPropertyCache::New(obj, value, name, script()->strictModeCode);
 
         if (!binaryTypes.lhsTypes || binaryTypes.lhsTypes->propertyNeedsBarrier(cx, id))
             ins->setNeedsBarrier();
     }
 
     current->add(ins);
     current->push(value);
 
@@ -6583,17 +6606,17 @@ IonBuilder::jsop_delprop(HandlePropertyN
     current->push(ins);
 
     return resumeAfter(ins);
 }
 
 bool
 IonBuilder::jsop_regexp(RegExpObject *reobj)
 {
-    JSObject *prototype = script_->global().getOrCreateRegExpPrototype(cx);
+    JSObject *prototype = script()->global().getOrCreateRegExpPrototype(cx);
     if (!prototype)
         return false;
 
     MRegExp *ins = MRegExp::New(reobj, prototype, MRegExp::MustClone);
     current->add(ins);
     current->push(ins);
 
     return true;
@@ -6607,105 +6630,105 @@ IonBuilder::jsop_object(JSObject *obj)
     current->push(ins);
 
     return true;
 }
 
 bool
 IonBuilder::jsop_lambda(JSFunction *fun)
 {
-    JS_ASSERT(script_->analysis()->usesScopeChain());
+    JS_ASSERT(script()->analysis()->usesScopeChain());
     MLambda *ins = MLambda::New(current->scopeChain(), fun);
     current->add(ins);
     current->push(ins);
 
     return resumeAfter(ins);
 }
 
 bool
 IonBuilder::jsop_deflocalfun(uint32_t local, JSFunction *fun)
 {
-    JS_ASSERT(script_->analysis()->usesScopeChain());
+    JS_ASSERT(script()->analysis()->usesScopeChain());
 
     MLambda *ins = MLambda::New(current->scopeChain(), fun);
     current->add(ins);
     current->push(ins);
 
     current->setLocal(local);
     current->pop();
 
     return resumeAfter(ins);
 }
 
 bool
 IonBuilder::jsop_defvar(uint32_t index)
 {
     JS_ASSERT(JSOp(*pc) == JSOP_DEFVAR || JSOp(*pc) == JSOP_DEFCONST);
 
-    PropertyName *name = script_->getName(index);
+    PropertyName *name = script()->getName(index);
 
     // Bake in attrs.
     unsigned attrs = JSPROP_ENUMERATE | JSPROP_PERMANENT;
     if (JSOp(*pc) == JSOP_DEFCONST)
         attrs |= JSPROP_READONLY;
 
     // Pass the ScopeChain.
-    JS_ASSERT(script_->analysis()->usesScopeChain());
+    JS_ASSERT(script()->analysis()->usesScopeChain());
 
     // Bake the name pointer into the MDefVar.
     MDefVar *defvar = MDefVar::New(name, attrs, current->scopeChain());
     current->add(defvar);
 
     return resumeAfter(defvar);
 }
 
 bool
 IonBuilder::jsop_this()
 {
     if (!info().fun())
         return abort("JSOP_THIS outside of a JSFunction.");
 
-    if (script_->strictModeCode) {
+    if (script()->strictModeCode) {
         current->pushSlot(info().thisSlot());
         return true;
     }
 
-    types::StackTypeSet *types = oracle->thisTypeSet(script_);
+    types::StackTypeSet *types = oracle->thisTypeSet(script());
     if (types && types->getKnownTypeTag() == JSVAL_TYPE_OBJECT) {
         // This is safe, because if the entry type of |this| is an object, it
         // will necessarily be an object throughout the entire function. OSR
         // can introduce a phi, but this phi will be specialized.
         current->pushSlot(info().thisSlot());
         return true;
     }
 
     return abort("JSOP_THIS hard case not yet handled");
 }
 
 bool
 IonBuilder::jsop_typeof()
 {
-    TypeOracle::Unary unary = oracle->unaryOp(script_, pc);
+    TypeOracle::Unary unary = oracle->unaryOp(script(), pc);
 
     MDefinition *input = current->pop();
     MTypeOf *ins = MTypeOf::New(input, unary.ival);
 
     current->add(ins);
     current->push(ins);
 
     if (ins->isEffectful() && !resumeAfter(ins))
         return false;
     return true;
 }
 
 bool
 IonBuilder::jsop_toid()
 {
     // No-op if the index is an integer.
-    TypeOracle::Unary unary = oracle->unaryOp(script_, pc);
+    TypeOracle::Unary unary = oracle->unaryOp(script(), pc);
     if (unary.ival == MIRType_Int32)
         return true;
 
     MDefinition *index = current->pop();
     MToId *ins = MToId::New(current->peek(-1), index);
 
     current->add(ins);
     current->push(ins);
@@ -6776,21 +6799,21 @@ IonBuilder::walkScopeChain(unsigned hops
 
     return scope;
 }
 
 bool
 IonBuilder::jsop_getaliasedvar(ScopeCoordinate sc)
 {
     types::StackTypeSet *barrier;
-    types::StackTypeSet *actual = oracle->aliasedVarBarrier(script_, pc, &barrier);
+    types::StackTypeSet *actual = oracle->aliasedVarBarrier(script(), pc, &barrier);
 
     MDefinition *obj = walkScopeChain(sc.hops);
 
-    RootedShape shape(cx, ScopeCoordinateToStaticScope(script_, pc).scopeShape());
+    RootedShape shape(cx, ScopeCoordinateToStaticScope(script(), pc).scopeShape());
 
     MInstruction *load;
     if (shape->numFixedSlots() <= sc.slot) {
         MInstruction *slots = MSlots::New(obj);
         current->add(slots);
 
         load = MLoadSlot::New(slots, sc.slot - shape->numFixedSlots());
     } else {
@@ -6814,17 +6837,17 @@ IonBuilder::jsop_getaliasedvar(ScopeCoor
 }
 
 bool
 IonBuilder::jsop_setaliasedvar(ScopeCoordinate sc)
 {
     MDefinition *rval = current->peek(-1);
     MDefinition *obj = walkScopeChain(sc.hops);
 
-    RootedShape shape(cx, ScopeCoordinateToStaticScope(script_, pc).scopeShape());
+    RootedShape shape(cx, ScopeCoordinateToStaticScope(script(), pc).scopeShape());
 
     MInstruction *store;
     if (shape->numFixedSlots() <= sc.slot) {
         MInstruction *slots = MSlots::New(obj);
         current->add(slots);
 
         store = MStoreSlot::NewBarriered(slots, sc.slot - shape->numFixedSlots(), rval);
     } else {
@@ -6833,17 +6856,17 @@ IonBuilder::jsop_setaliasedvar(ScopeCoor
 
     current->add(store);
     return resumeAfter(store);
 }
 
 bool
 IonBuilder::jsop_in()
 {
-    if (oracle->inObjectIsDenseArray(script_, pc))
+    if (oracle->inObjectIsDenseArray(script(), pc))
         return jsop_in_dense();
 
     MDefinition *obj = current->pop();
     MDefinition *id = current->pop();
     MIn *ins = new MIn(id, obj);
 
     current->add(ins);
     current->push(ins);
@@ -6852,17 +6875,17 @@ IonBuilder::jsop_in()
 }
 
 bool
 IonBuilder::jsop_in_dense()
 {
     if (oracle->arrayPrototypeHasIndexedProperty())
         return abort("JSOP_IN Array proto has indexed properties");
 
-    bool needsHoleCheck = !oracle->inArrayIsPacked(script_, pc);
+    bool needsHoleCheck = !oracle->inArrayIsPacked(script(), pc);
 
     MDefinition *obj = current->pop();
     MDefinition *id = current->pop();
 
     // Ensure id is an integer.
     MInstruction *idInt32 = MToInt32::New(id);
     current->add(idInt32);
     id = idInt32;
@@ -6884,17 +6907,17 @@ IonBuilder::jsop_in_dense()
 }
 
 bool
 IonBuilder::jsop_instanceof()
 {
     MDefinition *rhs = current->pop();
     MDefinition *obj = current->pop();
 
-    TypeOracle::BinaryTypes types = oracle->binaryTypes(script_, pc);
+    TypeOracle::BinaryTypes types = oracle->binaryTypes(script(), pc);
 
     // If this is an 'x instanceof function' operation and we can determine the
     // exact function and prototype object being tested for, use a typed path.
     do {
         RawObject rhsObject = types.rhsTypes ? types.rhsTypes->getSingleton() : NULL;
         if (!rhsObject || !rhsObject->isFunction() || rhsObject->isBoundFunction())
             break;
 
--- a/js/src/ion/IonMacroAssembler.h
+++ b/js/src/ion/IonMacroAssembler.h
@@ -279,16 +279,26 @@ class MacroAssembler : public MacroAssem
         // perform an aligned 32-bit load and adjust the bitmask accordingly.
         JS_STATIC_ASSERT(offsetof(JSFunction, nargs) % sizeof(uint32_t) == 0);
         JS_STATIC_ASSERT(offsetof(JSFunction, flags) == offsetof(JSFunction, nargs) + 2);
         JS_STATIC_ASSERT(IS_LITTLE_ENDIAN);
         Address address(fun, offsetof(JSFunction, nargs));
         uint32_t bit = JSFunction::INTERPRETED << 16;
         branchTest32(Assembler::Zero, address, Imm32(bit), label);
     }
+    void branchIfInterpreted(Register fun, Label *label) {
+        // 16-bit loads are slow and unaligned 32-bit loads may be too so
+        // perform an aligned 32-bit load and adjust the bitmask accordingly.
+        JS_STATIC_ASSERT(offsetof(JSFunction, nargs) % sizeof(uint32_t) == 0);
+        JS_STATIC_ASSERT(offsetof(JSFunction, flags) == offsetof(JSFunction, nargs) + 2);
+        JS_STATIC_ASSERT(IS_LITTLE_ENDIAN);
+        Address address(fun, offsetof(JSFunction, nargs));
+        uint32_t bit = JSFunction::INTERPRETED << 16;
+        branchTest32(Assembler::NonZero, address, Imm32(bit), label);
+    }
 
     using MacroAssemblerSpecific::Push;
 
     void Push(jsid id, Register scratchReg) {
         if (JSID_IS_GCTHING(id)) {
             // If we're pushing a gcthing, then we can't just push the tagged jsid
             // value since the GC won't have any idea that the push instruction
             // carries a reference to a gcthing.  Need to unpack the pointer,
--- a/js/src/ion/LIR-Common.h
+++ b/js/src/ion/LIR-Common.h
@@ -415,36 +415,60 @@ class LToIdV : public LCallInstructionHe
 
     MToId *mir() const {
         return mir_->toToId();
     }
 };
 
 // Allocate an object for |new| on the caller-side.
 // Always performs object initialization with a fast path.
-class LCreateThis : public LInstructionHelper<1, 0, 0>
+class LCreateThisWithTemplate : public LInstructionHelper<1, 0, 0>
 {
   public:
-    LIR_HEADER(CreateThis)
-
-    LCreateThis()
+    LIR_HEADER(CreateThisWithTemplate)
+
+    LCreateThisWithTemplate()
     { }
 
+    MCreateThisWithTemplate *mir() const {
+        return mir_->toCreateThisWithTemplate();
+    }
+};
+
+// Allocate an object for |new| on the caller-side, when there is no templateObject.
+class LCreateThisV : public LCallInstructionHelper<BOX_PIECES, 2, 0>
+{
+  public:
+    LIR_HEADER(CreateThisV)
+
+    LCreateThisV(const LAllocation &callee, const LAllocation &prototype)
+    {
+        setOperand(0, callee);
+        setOperand(1, prototype);
+    }
+
+    const LAllocation *getCallee() {
+        return getOperand(0);
+    }
+    const LAllocation *getPrototype() {
+        return getOperand(1);
+    }
+
     MCreateThis *mir() const {
         return mir_->toCreateThis();
     }
 };
 
 // Allocate an object for |new| on the caller-side, when there is no templateObject.
-class LCreateThisVM : public LCallInstructionHelper<1, 2, 0>
+class LCreateThisO : public LCallInstructionHelper<1, 2, 0>
 {
   public:
-    LIR_HEADER(CreateThisVM)
-
-    LCreateThisVM(const LAllocation &callee, const LAllocation &prototype)
+    LIR_HEADER(CreateThisO)
+
+    LCreateThisO(const LAllocation &callee, const LAllocation &prototype)
     {
         setOperand(0, callee);
         setOperand(1, prototype);
     }
 
     const LAllocation *getCallee() {
         return getOperand(0);
     }
@@ -676,34 +700,16 @@ class LCallDOMNative : public LJSCallIns
     const LAllocation *getArgArgc() {
         return getTemp(3)->output();
     }
     const LAllocation *getArgVp() {
         return getTemp(4)->output();
     }
 };
 
-// Generates a polymorphic callsite for |new|, where |this| has not been
-// pre-allocated by the caller.
-class LCallConstructor : public LJSCallInstructionHelper<BOX_PIECES, 1, 0>
-{
-  public:
-    LIR_HEADER(CallConstructor)
-
-    LCallConstructor(const LAllocation &func, uint32_t argslot)
-      : JSCallHelper(argslot)
-    {
-        setOperand(0, func);
-    }
-
-    const LAllocation *getFunction() {
-        return getOperand(0);
-    }
-};
-
 template <size_t defs, size_t ops>
 class LDOMPropertyInstructionHelper : public LCallInstructionHelper<defs, 1 + ops, 3>
 {
   protected:
     LDOMPropertyInstructionHelper(const LDefinition &JSContextReg, const LAllocation &ObjectReg,
                                   const LDefinition &PrivReg, const LDefinition &ValueReg)
     {
         this->setOperand(0, ObjectReg);
--- a/js/src/ion/LOpcodes.h
+++ b/js/src/ion/LOpcodes.h
@@ -30,22 +30,22 @@
     _(NewStringObject)              \
     _(InitProp)                     \
     _(CheckOverRecursed)            \
     _(RecompileCheck)               \
     _(DefVar)                       \
     _(CallKnown)                    \
     _(CallGeneric)                  \
     _(CallNative)                   \
-    _(CallConstructor)              \
     _(ApplyArgsGeneric)             \
     _(StackArgT)                    \
     _(StackArgV)                    \
-    _(CreateThis)                   \
-    _(CreateThisVM)                 \
+    _(CreateThisV)                  \
+    _(CreateThisO)                  \
+    _(CreateThisWithTemplate)       \
     _(ReturnFromCtor)               \
     _(BitNotI)                      \
     _(BitNotV)                      \
     _(BitOpI)                       \
     _(BitOpV)                       \
     _(ShiftI)                       \
     _(UrshD)                        \
     _(Return)                       \
--- a/js/src/ion/Lowering.cpp
+++ b/js/src/ion/Lowering.cpp
@@ -231,27 +231,34 @@ LIRGenerator::visitPassArg(MPassArg *arg
 
     // Known types can move constant types and/or payloads.
     LStackArgT *stack = new LStackArgT(argslot, useRegisterOrConstant(opd));
     stack->setMir(arg);
     return add(stack);
 }
 
 bool
+LIRGenerator::visitCreateThisWithTemplate(MCreateThisWithTemplate *ins)
+{
+    LCreateThisWithTemplate *lir = new LCreateThisWithTemplate();
+    return define(lir, ins) && assignSafepoint(lir, ins);
+}
+
+bool
 LIRGenerator::visitCreateThis(MCreateThis *ins)
 {
-    // Template objects permit fast initialization.
-    if (ins->hasTemplateObject()) {
-        LCreateThis *lir = new LCreateThis();
-        return define(lir, ins) && assignSafepoint(lir, ins);
+    if (ins->needNativeCheck()) {
+        JS_ASSERT(ins->type() == MIRType_Value);
+        LCreateThisV *lir = new LCreateThisV(useRegisterAtStart(ins->getCallee()),
+                                             useRegisterOrConstantAtStart(ins->getPrototype()));
+        return defineReturn(lir, ins) && assignSafepoint(lir, ins);
     }
 
-    LCreateThisVM *lir = new LCreateThisVM(useRegisterOrConstantAtStart(ins->getCallee()),
-                                           useRegisterOrConstantAtStart(ins->getPrototype()));
-
+    LCreateThisO *lir = new LCreateThisO(useRegisterOrConstantAtStart(ins->getCallee()),
+                                         useRegisterOrConstantAtStart(ins->getPrototype()));
     return defineReturn(lir, ins) && assignSafepoint(lir, ins);
 }
 
 bool
 LIRGenerator::visitReturnFromCtor(MReturnFromCtor *ins)
 {
     LReturnFromCtor *lir = new LReturnFromCtor(useRegister(ins->getObject()));
     if (!useBox(lir, LReturnFromCtor::ValueIndex, ins->getValue()))
@@ -292,23 +299,16 @@ LIRGenerator::visitCall(MCall *call)
             return (defineReturn(lir, call) && assignSafepoint(lir, call));
         }
 
         LCallKnown *lir = new LCallKnown(useFixed(call->getFunction(), CallTempReg0),
                                          argslot, tempFixed(CallTempReg2));
         return (defineReturn(lir, call) && assignSafepoint(lir, call));
     }
 
-    // Call unknown constructors.
-    if (call->isConstructing()) {
-        LCallConstructor *lir = new LCallConstructor(useFixed(call->getFunction(),
-                                                     CallTempReg0), argslot);
-        return (defineReturn(lir, call) && assignSafepoint(lir, call));
-    }
-
     // Call anything, using the most generic code.
     LCallGeneric *lir = new LCallGeneric(useFixed(call->getFunction(), CallTempReg0),
         argslot, tempFixed(ArgumentsRectifierReg), tempFixed(CallTempReg2));
     return (assignSnapshot(lir) && defineReturn(lir, call) && assignSafepoint(lir, call));
 }
 
 bool
 LIRGenerator::visitApplyArgs(MApplyArgs *apply)
@@ -734,17 +734,17 @@ LIRGenerator::visitMinMax(MMinMax *ins)
 bool
 LIRGenerator::visitAbs(MAbs *ins)
 {
     MDefinition *num = ins->num();
 
     if (num->type() == MIRType_Int32) {
         LAbsI *lir = new LAbsI(useRegisterAtStart(num));
         // needed to handle abs(INT32_MIN)
-        if (!ins->range()->isFinite() && !assignSnapshot(lir))
+        if (ins->fallible() && !assignSnapshot(lir))
             return false;
         return defineReuseInput(lir, ins, 0);
     }
 
     JS_ASSERT(num->type() == MIRType_Double);
     LAbsD *lir = new LAbsD(useRegisterAtStart(num));
     return defineReuseInput(lir, ins, 0);
 }
--- a/js/src/ion/Lowering.h
+++ b/js/src/ion/Lowering.h
@@ -84,16 +84,17 @@ class LIRGenerator : public LIRGenerator
     bool visitNewDeclEnvObject(MNewDeclEnvObject *ins);
     bool visitNewCallObject(MNewCallObject *ins);
     bool visitNewStringObject(MNewStringObject *ins);
     bool visitInitProp(MInitProp *ins);
     bool visitCheckOverRecursed(MCheckOverRecursed *ins);
     bool visitDefVar(MDefVar *ins);
     bool visitPrepareCall(MPrepareCall *ins);
     bool visitPassArg(MPassArg *arg);
+    bool visitCreateThisWithTemplate(MCreateThisWithTemplate *ins);
     bool visitCreateThis(MCreateThis *ins);
     bool visitReturnFromCtor(MReturnFromCtor *ins);
     bool visitCall(MCall *call);
     bool visitApplyArgs(MApplyArgs *apply);
     bool visitTest(MTest *test);
     bool visitPolyInlineDispatch(MPolyInlineDispatch *ins);
     bool visitCompare(MCompare *comp);
     bool visitTypeOf(MTypeOf *ins);
--- a/js/src/ion/MCallOptimize.cpp
+++ b/js/src/ion/MCallOptimize.cpp
@@ -108,33 +108,33 @@ IonBuilder::discardCall(uint32_t argc, M
     bb->pop();
     return true;
 }
 
 types::StackTypeSet *
 IonBuilder::getInlineReturnTypeSet()
 {
     types::StackTypeSet *barrier;
-    types::StackTypeSet *returnTypes = oracle->returnTypeSet(script_, pc, &barrier);
+    types::StackTypeSet *returnTypes = oracle->returnTypeSet(script(), pc, &barrier);
 
     JS_ASSERT(returnTypes);
     return returnTypes;
 }
 
 MIRType
 IonBuilder::getInlineReturnType()
 {
     types::StackTypeSet *returnTypes = getInlineReturnTypeSet();
     return MIRTypeFromValueType(returnTypes->getKnownTypeTag());
 }
 
 types::StackTypeSet *
 IonBuilder::getInlineArgTypeSet(uint32_t argc, uint32_t arg)
 {
-    types::StackTypeSet *argTypes = oracle->getCallArg(script_, argc, arg, pc);
+    types::StackTypeSet *argTypes = oracle->getCallArg(script(), argc, arg, pc);
     JS_ASSERT(argTypes);
     return argTypes;
 }
 
 MIRType
 IonBuilder::getInlineArgType(uint32_t argc, uint32_t arg)
 {
     types::StackTypeSet *argTypes = getInlineArgTypeSet(argc, arg);
--- a/js/src/ion/MIR.cpp
+++ b/js/src/ion/MIR.cpp
@@ -713,16 +713,22 @@ MBinaryArithInstruction::foldsTo(bool us
         return this;
 
     if (IsConstant(lhs, getIdentity()))
         return rhs; // x op id => x
 
     return this;
 }
 
+bool
+MAbs::fallible() const
+{
+    return !range() || !range()->isFinite();
+}
+
 MDefinition *
 MDiv::foldsTo(bool useValueNumbers)
 {
     if (specialization_ == MIRType_None)
         return this;
 
     if (MDefinition *folded = EvaluateConstantOperands(this))
         return folded;
--- a/js/src/ion/MIR.h
+++ b/js/src/ion/MIR.h
@@ -1566,52 +1566,84 @@ class MGuardString
         return this;
     }
     AliasSet getAliasSet() const {
         return AliasSet::None();
     }
 };
 
 // Caller-side allocation of |this| for |new|:
+// Given a templateobject, construct |this| for JSOP_NEW
+class MCreateThisWithTemplate
+  : public MNullaryInstruction
+{
+    // Template for |this|, provided by TI
+    CompilerRootObject templateObject_;
+
+    MCreateThisWithTemplate(JSObject *templateObject)
+      : templateObject_(templateObject)
+    {
+        setResultType(MIRType_Object);
+    }
+
+  public:
+    INSTRUCTION_HEADER(CreateThisWithTemplate);
+    static MCreateThisWithTemplate *New(JSObject *templateObject)
+    {
+        return new MCreateThisWithTemplate(templateObject);
+    }
+    JSObject *getTemplateObject() const {
+        return templateObject_;
+    }
+
+    // Although creation of |this| modifies global state, it is safely repeatable.
+    AliasSet getAliasSet() const {
+        return AliasSet::None();
+    }
+};
+
+// Caller-side allocation of |this| for |new|:
 // Given a prototype operand, construct |this| for JSOP_NEW.
 // For native constructors, returns MagicValue(JS_IS_CONSTRUCTING).
 class MCreateThis
   : public MAryInstruction<2>,
     public MixPolicy<ObjectPolicy<0>, ObjectPolicy<1> >
 {
-    // Template for |this|, provided by TI, or NULL.
-    CompilerRootObject templateObject_;
-
-    MCreateThis(MDefinition *callee, MDefinition *prototype, JSObject *templateObject)
-      : templateObject_(templateObject)
+    bool needNativeCheck_;
+
+    MCreateThis(MDefinition *callee, MDefinition *prototype)
+      : needNativeCheck_(true)
     {
         initOperand(0, callee);
         initOperand(1, prototype);
-        setResultType(MIRType_Object);
+
+        // Type is mostly object, except for native constructors
+        // therefore the need of Value type.
+        setResultType(MIRType_Value);
     }
 
   public:
     INSTRUCTION_HEADER(CreateThis)
-    static MCreateThis *New(MDefinition *callee, MDefinition *prototype, JSObject *templateObject)
+    static MCreateThis *New(MDefinition *callee, MDefinition *prototype)
     {
-        return new MCreateThis(callee, prototype, templateObject);
+        return new MCreateThis(callee, prototype);
     }
 
     MDefinition *getCallee() const {
         return getOperand(0);
     }
     MDefinition *getPrototype() const {
         return getOperand(1);
     }
-    bool hasTemplateObject() const {
-        return !!templateObject_;
-    }
-    JSObject *getTemplateObject() const {
-        JS_ASSERT(hasTemplateObject());
-        return templateObject_;
+    void removeNativeCheck() {
+        needNativeCheck_ = false;
+        setResultType(MIRType_Object);
+    }
+    bool needNativeCheck() const {
+        return needNativeCheck_;
     }
 
     // Although creation of |this| modifies global state, it is safely repeatable.
     AliasSet getAliasSet() const {
         return AliasSet::None();
     }
     TypePolicy *typePolicy() {
         return this;
@@ -2238,16 +2270,17 @@ class MAbs
         return getOperand(0);
     }
     TypePolicy *typePolicy() {
         return this;
     }
     bool congruentTo(MDefinition *const &ins) const {
         return congruentIfOperandsEqual(ins);
     }
+    bool fallible() const;
 
     AliasSet getAliasSet() const {
         return AliasSet::None();
     }
     void computeRange();
 };
 
 // Inline implementation of Math.sqrt().
--- a/js/src/ion/MOpcodes.h
+++ b/js/src/ion/MOpcodes.h
@@ -25,16 +25,17 @@ namespace ion {
     _(Beta)                                                                 \
     _(OsrValue)                                                             \
     _(OsrScopeChain)                                                        \
     _(ReturnFromCtor)                                                       \
     _(CheckOverRecursed)                                                    \
     _(RecompileCheck)                                                       \
     _(DefVar)                                                               \
     _(CreateThis)                                                           \
+    _(CreateThisWithTemplate)                                               \
     _(PrepareCall)                                                          \
     _(PassArg)                                                              \
     _(Call)                                                                 \
     _(ApplyArgs)                                                            \
     _(BitNot)                                                               \
     _(TypeOf)                                                               \
     _(ToId)                                                                 \
     _(BitAnd)                                                               \
--- a/js/src/ion/TypeOracle.cpp
+++ b/js/src/ion/TypeOracle.cpp
@@ -61,28 +61,28 @@ MIRType
 TypeInferenceOracle::getMIRType(HeapTypeSet *types)
 {
     return GetMIRType(types->getKnownTypeTag(cx));
 }
 
 TypeOracle::UnaryTypes
 TypeInferenceOracle::unaryTypes(JSScript *script, jsbytecode *pc)
 {
-    JS_ASSERT(script == this->script_);
+    JS_ASSERT(script == this->script());
 
     UnaryTypes res;
     res.inTypes = script->analysis()->poppedTypes(pc, 0);
     res.outTypes = script->analysis()->pushedTypes(pc, 0);
     return res;
 }
 
 TypeOracle::BinaryTypes
 TypeInferenceOracle::binaryTypes(JSScript *script, jsbytecode *pc)
 {
-    JS_ASSERT(script == this->script_);
+    JS_ASSERT(script == this->script());
 
     JSOp op = (JSOp)*pc;
 
     BinaryTypes res;
     if (op == JSOP_NEG || op == JSOP_POS) {
         res.lhsTypes = script->analysis()->poppedTypes(pc, 0);
         res.rhsTypes = NULL;
         res.outTypes = script->analysis()->pushedTypes(pc, 0);
@@ -92,28 +92,28 @@ TypeInferenceOracle::binaryTypes(JSScrip
         res.outTypes = script->analysis()->pushedTypes(pc, 0);
     }
     return res;
 }
 
 TypeOracle::Unary
 TypeInferenceOracle::unaryOp(JSScript *script, jsbytecode *pc)
 {
-    JS_ASSERT(script == this->script_);
+    JS_ASSERT(script == this->script());
 
     Unary res;
     res.ival = getMIRType(script->analysis()->poppedTypes(pc, 0));
     res.rval = getMIRType(script->analysis()->pushedTypes(pc, 0));
     return res;
 }
 
 TypeOracle::Binary
 TypeInferenceOracle::binaryOp(JSScript *script, jsbytecode *pc)
 {
-    JS_ASSERT(script == this->script_);
+    JS_ASSERT(script == this->script());
 
     JSOp op = (JSOp)*pc;
 
     Binary res;
     if (op == JSOP_NEG || op == JSOP_POS) {
         res.lhs = getMIRType(script->analysis()->poppedTypes(pc, 0));
         res.rhs = MIRType_Int32;
         res.rval = getMIRType(script->analysis()->pushedTypes(pc, 0));
@@ -123,55 +123,55 @@ TypeInferenceOracle::binaryOp(JSScript *
         res.rval = getMIRType(script->analysis()->pushedTypes(pc, 0));
     }
     return res;
 }
 
 StackTypeSet *
 TypeInferenceOracle::thisTypeSet(JSScript *script)
 {
-    JS_ASSERT(script == this->script_);
+    JS_ASSERT(script == this->script());
     return TypeScript::ThisTypes(script);
 }
 
 bool
 TypeInferenceOracle::getOsrTypes(jsbytecode *osrPc, Vector<MIRType> &slotTypes)
 {
     JS_ASSERT(JSOp(*osrPc) == JSOP_LOOPENTRY);
-    JS_ASSERT(script_->code < osrPc);
-    JS_ASSERT(osrPc < script_->code + script_->length);
+    JS_ASSERT(script()->code < osrPc);
+    JS_ASSERT(osrPc < script()->code + script()->length);
 
     Vector<types::StackTypeSet *> slotTypeSets(cx);
-    if (!slotTypeSets.resize(TotalSlots(script_)))
+    if (!slotTypeSets.resize(TotalSlots(script())))
         return false;
 
-    for (uint32_t slot = ThisSlot(); slot < TotalSlots(script_); slot++)
-        slotTypeSets[slot] = TypeScript::SlotTypes(script_, slot);
+    for (uint32_t slot = ThisSlot(); slot < TotalSlots(script()); slot++)
+        slotTypeSets[slot] = TypeScript::SlotTypes(script(), slot);
 
-    jsbytecode *pc = script_->code;
-    ScriptAnalysis *analysis = script_->analysis();
+    jsbytecode *pc = script()->code;
+    ScriptAnalysis *analysis = script()->analysis();
 
     // To determine the slot types at the OSR pc, we have to do a forward walk
     // over the bytecode to reconstruct the types.
     for (;;) {
         Bytecode *opinfo = analysis->maybeCode(pc);
         if (opinfo) {
             if (opinfo->jumpTarget) {
                 // Update variable types for all new values at this bytecode.
                 if (const SlotValue *newv = analysis->newValues(pc)) {
                     while (newv->slot) {
-                        if (newv->slot < TotalSlots(script_))
+                        if (newv->slot < TotalSlots(script()))
                             slotTypeSets[newv->slot] = analysis->getValueTypes(newv->value);
                         newv++;
                     }
                 }
             }
 
             if (BytecodeUpdatesSlot(JSOp(*pc))) {
-                uint32_t slot = GetBytecodeSlot(script_, pc);
+                uint32_t slot = GetBytecodeSlot(script(), pc);
                 if (analysis->trackSlot(slot))
                     slotTypeSets[slot] = analysis->pushedTypes(pc, 0);
             }
         }
 
         if (pc == osrPc)
             break;
 
@@ -184,35 +184,35 @@ TypeInferenceOracle::getOsrTypes(jsbytec
     // scripts. This means we have to subtract 1 for global/eval scripts.
     JS_ASSERT(ThisSlot() == 1);
     JS_ASSERT(ArgSlot(0) == 2);
 
 #ifdef DEBUG
     uint32_t stackDepth = analysis->getCode(osrPc).stackDepth;
 #endif
 
-    if (script_->function()) {
-        JS_ASSERT(slotTypes.length() == TotalSlots(script_) + stackDepth);
+    if (script()->function()) {
+        JS_ASSERT(slotTypes.length() == TotalSlots(script()) + stackDepth);
 
-        for (size_t i = ThisSlot(); i < TotalSlots(script_); i++)
+        for (size_t i = ThisSlot(); i < TotalSlots(script()); i++)
             slotTypes[i] = getMIRType(slotTypeSets[i]);
     } else {
-        JS_ASSERT(slotTypes.length() == TotalSlots(script_) + stackDepth - 1);
+        JS_ASSERT(slotTypes.length() == TotalSlots(script()) + stackDepth - 1);
 
-        for (size_t i = ArgSlot(0); i < TotalSlots(script_); i++)
+        for (size_t i = ArgSlot(0); i < TotalSlots(script()); i++)
             slotTypes[i - 1] = getMIRType(slotTypeSets[i]);
     }
 
     return true;
 }
 
 StackTypeSet *
 TypeInferenceOracle::parameterTypeSet(JSScript *script, size_t index)
 {
-    JS_ASSERT(script == this->script_);
+    JS_ASSERT(script == this->script());
     return TypeScript::ArgTypes(script, index);
 }
 
 StackTypeSet *
 TypeInferenceOracle::propertyRead(JSScript *script, jsbytecode *pc)
 {
     return script->analysis()->pushedTypes(pc, 0);
 }
@@ -479,24 +479,24 @@ TypeInferenceOracle::elementWrite(JSScri
     }
 
     return elementType;
 }
 
 bool
 TypeInferenceOracle::arrayPrototypeHasIndexedProperty()
 {
-    RootedScript script(cx, script_);
-    return ArrayPrototypeHasIndexedProperty(cx, script);
+    RootedScript scriptRoot(cx, script());
+    return ArrayPrototypeHasIndexedProperty(cx, scriptRoot);
 }
 
 bool
 TypeInferenceOracle::canInlineCalls()
 {
-    return script_->analysis()->hasFunctionCalls();
+    return script()->analysis()->hasFunctionCalls();
 }
 
 bool
 TypeInferenceOracle::propertyWriteCanSpecialize(JSScript *script, jsbytecode *pc)
 {
     return !script->analysis()->getCode(pc).monitoredTypes;
 }
 
@@ -514,20 +514,20 @@ TypeInferenceOracle::elementWriteNeedsBa
     // a property. The object is the third value popped by SETELEM.
     StackTypeSet *types = script->analysis()->poppedTypes(pc, 2);
     return types->propertyNeedsBarrier(cx, JSID_VOID);
 }
 
 StackTypeSet *
 TypeInferenceOracle::getCallTarget(JSScript *caller, uint32_t argc, jsbytecode *pc)
 {
-    JS_ASSERT(caller == this->script_);
+    JS_ASSERT(caller == this->script());
     JS_ASSERT(js_CodeSpec[*pc].format & JOF_INVOKE && JSOp(*pc) != JSOP_EVAL);
 
-    ScriptAnalysis *analysis = script_->analysis();
+    ScriptAnalysis *analysis = script()->analysis();
     return analysis->poppedTypes(pc, argc + 1);
 }
 
 StackTypeSet *
 TypeInferenceOracle::getCallArg(JSScript *script, uint32_t argc, uint32_t arg, jsbytecode *pc)
 {
     JS_ASSERT(argc >= arg);
     // Bytecode order: Function, This, Arg0, Arg1, ..., ArgN, Call.
--- a/js/src/ion/TypeOracle.h
+++ b/js/src/ion/TypeOracle.h
@@ -203,16 +203,18 @@ class TypeInferenceOracle : public TypeO
     MIRType getMIRType(types::StackTypeSet *types);
     MIRType getMIRType(types::HeapTypeSet *types);
 
   public:
     TypeInferenceOracle() : cx(NULL), script_(NULL) {}
 
     bool init(JSContext *cx, JSScript *script);
 
+    UnrootedScript script() { return script_.get(); }
+
     UnaryTypes unaryTypes(JSScript *script, jsbytecode *pc);
     BinaryTypes binaryTypes(JSScript *script, jsbytecode *pc);
     Unary unaryOp(JSScript *script, jsbytecode *pc);
     Binary binaryOp(JSScript *script, jsbytecode *pc);
     types::StackTypeSet *thisTypeSet(JSScript *script);
     bool getOsrTypes(jsbytecode *osrPc, Vector<MIRType> &slotTypes);
     types::StackTypeSet *parameterTypeSet(JSScript *script, size_t index);
     types::HeapTypeSet *globalPropertyTypeSet(JSScript *script, jsbytecode *pc, jsid id);
--- a/js/src/ion/VMFunctions.cpp
+++ b/js/src/ion/VMFunctions.cpp
@@ -88,45 +88,16 @@ InvokeFunction(JSContext *cx, JSFunction
     // Run the function in the interpreter.
     bool ok = Invoke(cx, thisv, fval, argc, argvWithoutThis, rval);
     if (ok && needsMonitor)
         types::TypeScript::Monitor(cx, *rval);
 
     return ok;
 }
 
-bool
-InvokeConstructor(JSContext *cx, JSObject *obj, uint32_t argc, Value *argv, Value *rval)
-{
-    Value fval = ObjectValue(*obj);
-
-    // See the comment in InvokeFunction.
-    bool needsMonitor;
-
-    if (obj->isFunction()) {
-        if (obj->toFunction()->isInterpretedLazy() &&
-            !obj->toFunction()->getOrCreateScript(cx))
-        {
-            return false;
-        }
-        needsMonitor = ShouldMonitorReturnType(obj->toFunction());
-    } else {
-        needsMonitor = true;
-    }
-
-    // Data in the argument vector is arranged for a JIT -> JIT call.
-    Value *argvWithoutThis = argv + 1;
-
-    bool ok = js::InvokeConstructor(cx, fval, argc, argvWithoutThis, rval);
-    if (ok && needsMonitor)
-        types::TypeScript::Monitor(cx, *rval);
-
-    return ok;
-}
-
 JSObject *
 NewGCThing(JSContext *cx, gc::AllocKind allocKind, size_t thingSize)
 {
     return gc::NewGCThing<JSObject>(cx, allocKind, thingSize);
 }
 
 bool
 CheckOverRecursed(JSContext *cx)
--- a/js/src/ion/VMFunctions.h
+++ b/js/src/ion/VMFunctions.h
@@ -406,17 +406,16 @@ class AutoDetectInvalidation
 
     ~AutoDetectInvalidation() {
         if (!disabled_ && ionScript_->invalidated())
             cx_->runtime->setIonReturnOverride(*rval_);
     }
 };
 
 bool InvokeFunction(JSContext *cx, JSFunction *fun, uint32_t argc, Value *argv, Value *rval);
-bool InvokeConstructor(JSContext *cx, JSObject *obj, uint32_t argc, Value *argv, Value *rval);
 JSObject *NewGCThing(JSContext *cx, gc::AllocKind allocKind, size_t thingSize);
 
 bool CheckOverRecursed(JSContext *cx);
 
 bool DefVarOrConst(JSContext *cx, HandlePropertyName dn, unsigned attrs, HandleObject scopeChain);
 bool InitProp(JSContext *cx, HandleObject obj, HandlePropertyName name, HandleValue value);
 
 template<bool Equal>
new file mode 100644
--- /dev/null
+++ b/js/src/jit-test/tests/ion/bug816492.js
@@ -0,0 +1,8 @@
+function TestCase(n, d, e, a) {}
+function reportCompare () {
+      var testcase = new TestCase();
+}
+reportCompare();
+schedulegc(10);
+this.TestCase=Number;
+reportCompare(4294967295.5);
new file mode 100644
--- /dev/null
+++ b/js/src/jit-test/tests/ion/bug819794.js
@@ -0,0 +1,7 @@
+x = [];
+x[2] = 1;
+x.unshift(0);
+x.unshift(0);
+x.sort(function() {
+        return Math.abs(4)
+})
--- a/js/src/jsgcinlines.h
+++ b/js/src/jsgcinlines.h
@@ -523,17 +523,17 @@ NewGCThing(JSContext *cx, js::gc::AllocK
     return static_cast<T *>(t);
 }
 
 /* Alternate form which allocates a GC thing if doing so cannot trigger a GC. */
 template <typename T>
 inline T *
 TryNewGCThing(JSContext *cx, js::gc::AllocKind kind, size_t thingSize)
 {
-    AssertCanGC();
+    AutoAssertNoGC nogc;
     JS_ASSERT(thingSize == js::gc::Arena::thingSize(kind));
     JS_ASSERT_IF(cx->compartment == cx->runtime->atomsCompartment,
                  kind == js::gc::FINALIZE_STRING || kind == js::gc::FINALIZE_SHORT_STRING);
     JS_ASSERT(!cx->runtime->isHeapBusy());
     JS_ASSERT(!cx->runtime->noGCOrAllocationCheck);
 
 #ifdef JS_GC_ZEAL
     if (cx->runtime->needZealousGC())
--- a/js/src/jsscript.h
+++ b/js/src/jsscript.h
@@ -5,24 +5,25 @@
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #ifndef jsscript_h___
 #define jsscript_h___
 /*
  * JS script descriptor.
  */
-#include "jsprvtd.h"
 #include "jsdbgapi.h"
-#include "jsclist.h"
 #include "jsinfer.h"
 #include "jsopcode.h"
 #include "jsscope.h"
 
 #include "gc/Barrier.h"
+#include "gc/Root.h"
+
+ForwardDeclareJS(Script);
 
 namespace js {
 
 namespace ion {
     struct IonScript;
     struct IonScriptCounts;
 }
 
--- a/js/src/jsstr.cpp
+++ b/js/src/jsstr.cpp
@@ -12,16 +12,17 @@
  * native methods store strings (possibly newborn) converted from their 'this'
  * parameter and arguments on the stack: 'this' conversions at argv[-1], arg
  * conversions at their index (argv[0], argv[1]).  This is a legitimate method
  * of rooting things that might lose their newborn root due to subsequent GC
  * allocations in the same native method.
  */
 
 #include "mozilla/Attributes.h"
+#include "mozilla/CheckedInt.h"
 #include "mozilla/FloatingPoint.h"
 
 #include <stdlib.h>
 #include <string.h>
 #include "jstypes.h"
 #include "jsutil.h"
 #include "jsprf.h"
 #include "jsapi.h"
@@ -58,16 +59,18 @@
 #include "vm/StringObject-inl.h"
 #include "vm/String-inl.h"
 
 using namespace js;
 using namespace js::gc;
 using namespace js::types;
 using namespace js::unicode;
 
+using mozilla::CheckedInt;
+
 static JSLinearString *
 ArgToRootedString(JSContext *cx, CallArgs &args, unsigned argno)
 {
     if (argno >= args.length())
         return cx->names().undefined;
 
     Value &arg = args[argno];
     JSString *str = ToString(cx, arg);
@@ -2020,29 +2023,38 @@ FindReplaceLength(JSContext *cx, RegExpS
         rdata.repstr = repstr->ensureLinear(cx);
         if (!rdata.repstr)
             return false;
         *sizep = rdata.repstr->length();
         return true;
     }
 
     JSString *repstr = rdata.repstr;
-    size_t replen = repstr->length();
+    CheckedInt<uint32_t> replen = repstr->length();
     for (const jschar *dp = rdata.dollar, *ep = rdata.dollarEnd; dp;
          dp = js_strchr_limit(dp, '$', ep)) {
         JSSubString sub;
         size_t skip;
         if (InterpretDollar(res, dp, ep, rdata, &sub, &skip)) {
-            replen += sub.length - skip;
+            if (sub.length > skip)
+                replen += sub.length - skip;
+            else
+                replen -= skip - sub.length;
             dp += skip;
         } else {
             dp++;
         }
     }
-    *sizep = replen;
+
+    if (!replen.isValid()) {
+        js_ReportAllocationOverflow(cx);
+        return false;
+    }
+
+    *sizep = replen.value();
     return true;
 }
 
 /*
  * Precondition: |rdata.sb| already has necessary growth space reserved (as
  * derived from FindReplaceLength).
  */
 static void
@@ -2083,18 +2095,24 @@ ReplaceRegExpCallback(JSContext *cx, Reg
     size_t leftoff = rdata.leftIndex;
     size_t leftlen = res->matchStart() - leftoff;
     rdata.leftIndex = res->matchLimit();
 
     size_t replen = 0;  /* silence 'unused' warning */
     if (!FindReplaceLength(cx, res, rdata, &replen))
         return false;
 
-    size_t growth = leftlen + replen;
-    if (!rdata.sb.reserve(rdata.sb.length() + growth))
+    CheckedInt<uint32_t> newlen(rdata.sb.length());
+    newlen += leftlen;
+    newlen += replen;
+    if (!newlen.isValid()) {
+        js_ReportAllocationOverflow(cx);
+        return false;
+    }
+    if (!rdata.sb.reserve(newlen.value()))
         return false;
 
     JSLinearString &str = rdata.str->asLinear();  /* flattened for regexp */
     const jschar *left = str.chars() + leftoff;
 
     rdata.sb.infallibleAppend(left, leftlen); /* skipped-over portion of the search value */
     DoReplace(res, rdata);
     return true;
--- a/js/xpconnect/loader/Makefile.in
+++ b/js/xpconnect/loader/Makefile.in
@@ -8,18 +8,21 @@ srcdir		= @srcdir@
 VPATH		= @srcdir@
 
 include $(DEPTH)/config/autoconf.mk
 
 MODULE		= jsloader
 LIBRARY_NAME	= jsloader_s
 FORCE_STATIC_LIB = 1
 LIBXUL_LIBRARY = 1
-LOCAL_INCLUDES += -I$(srcdir)/../src \
-                  -I$(srcdir)/../wrappers
+LOCAL_INCLUDES += \
+  -I$(srcdir)/../src \
+  -I$(srcdir)/../wrappers \
+  -I$(topsrcdir)/content/base/src \
+  $(NULL)
 
 CPPSRCS		= mozJSComponentLoader.cpp mozJSSubScriptLoader.cpp mozJSLoaderUtils.cpp
 
 EXTRA_JS_MODULES = XPCOMUtils.jsm ISO8601DateUtils.jsm
 
 include $(topsrcdir)/config/rules.mk
 
 DEFINES += \
--- a/js/xpconnect/loader/mozJSComponentLoader.cpp
+++ b/js/xpconnect/loader/mozJSComponentLoader.cpp
@@ -38,17 +38,17 @@
 #include "nsIObserverService.h"
 #include "nsIXPCScriptable.h"
 #include "nsString.h"
 #include "nsIScriptSecurityManager.h"
 #include "nsIURI.h"
 #include "nsIFileURL.h"
 #include "nsIJARURI.h"
 #include "nsNetUtil.h"
-#include "nsDOMFile.h"
+#include "nsDOMBlobBuilder.h"
 #include "jsprf.h"
 #include "nsJSPrincipals.h"
 // For reporting errors with the console service
 #include "nsIScriptError.h"
 #include "nsIConsoleService.h"
 #include "nsIStorageStream.h"
 #include "nsIStringStream.h"
 #if defined(XP_WIN)
@@ -240,17 +240,17 @@ File(JSContext *cx, unsigned argc, jsval
     nsresult rv;
 
     if (!argc) {
         XPCThrower::Throw(NS_ERROR_UNEXPECTED, cx);
         return false;
     }
 
     nsCOMPtr<nsISupports> native;
-    rv = nsDOMFileFile::NewFile(getter_AddRefs(native));
+    rv = nsDOMMultipartFile::NewFile(getter_AddRefs(native));
     if (NS_FAILED(rv)) {
         XPCThrower::Throw(rv, cx);
         return false;
     }
 
     nsCOMPtr<nsIJSNativeInitializer> initializer = do_QueryInterface(native);
     NS_ASSERTION(initializer, "what?");
 
--- a/js/xpconnect/src/nsDOMQS.h
+++ b/js/xpconnect/src/nsDOMQS.h
@@ -4,16 +4,17 @@
 
 #ifndef nsDOMQS_h__
 #define nsDOMQS_h__
 
 #include "nsDOMClassInfoID.h"
 #include "nsGenericHTMLElement.h"
 #include "nsHTMLCanvasElement.h"
 #include "nsHTMLDivElement.h"
+#include "nsHTMLFormElement.h"
 #include "nsHTMLImageElement.h"
 #include "nsHTMLOptionElement.h"
 #include "nsHTMLOptGroupElement.h"
 #include "nsHTMLVideoElement.h"
 #include "nsHTMLDocument.h"
 #include "nsICSSDeclaration.h"
 #include "nsSVGStylableElement.h"
 
@@ -151,16 +152,17 @@ xpc_qsUnwrapArg<_clazz>(JSContext *cx, j
     nsISupports* argRef = static_cast<nsIContent*>(*ppArgRef);                \
     nsresult rv = xpc_qsUnwrapArg<_clazz>(cx, v, ppArg, &argRef, vp);         \
     *ppArgRef = static_cast<_clazz*>(static_cast<nsIContent*>(argRef));       \
     return rv;                                                                \
 }
 
 DEFINE_UNWRAP_CAST_HTML(canvas, nsHTMLCanvasElement)
 DEFINE_UNWRAP_CAST_HTML(div, nsHTMLDivElement)
+DEFINE_UNWRAP_CAST_HTML(form, nsHTMLFormElement)
 DEFINE_UNWRAP_CAST_HTML(img, nsHTMLImageElement)
 DEFINE_UNWRAP_CAST_HTML(optgroup, nsHTMLOptGroupElement)
 DEFINE_UNWRAP_CAST_HTML(option, nsHTMLOptionElement)
 DEFINE_UNWRAP_CAST_HTML(video, nsHTMLVideoElement)
 
 inline nsISupports*
 ToSupports(nsContentList *p)
 {
--- a/js/xpconnect/tests/unit/component-file.js
+++ b/js/xpconnect/tests/unit/component-file.js
@@ -30,41 +30,32 @@ FileComponent.prototype =
 
     // should be able to construct a file
     var f1 = File(file.path);
     // with either constructor syntax
     var f2 = new File(file.path);
     // and with nsIFiles
     var f3 = File(file);
     var f4 = new File(file);
-    // and extra args are ignored
-    var f5 = File(file.path, "foopy");
-    var f6 = new File(file, Date(123123154));
 
     // do some tests
     do_check_true(f1 instanceof Ci.nsIDOMFile, "Should be a DOM File");
     do_check_true(f2 instanceof Ci.nsIDOMFile, "Should be a DOM File");
     do_check_true(f3 instanceof Ci.nsIDOMFile, "Should be a DOM File");
     do_check_true(f4 instanceof Ci.nsIDOMFile, "Should be a DOM File");
-    do_check_true(f5 instanceof Ci.nsIDOMFile, "Should be a DOM File");
-    do_check_true(f6 instanceof Ci.nsIDOMFile, "Should be a DOM File");
 
     do_check_true(f1.name == "xpcshell.ini", "Should be the right file");
     do_check_true(f2.name == "xpcshell.ini", "Should be the right file");
     do_check_true(f3.name == "xpcshell.ini", "Should be the right file");
     do_check_true(f4.name == "xpcshell.ini", "Should be the right file");
-    do_check_true(f5.name == "xpcshell.ini", "Should be the right file");
-    do_check_true(f6.name == "xpcshell.ini", "Should be the right file");
 
     do_check_true(f1.type = "text/plain", "Should be the right type");
     do_check_true(f2.type = "text/plain", "Should be the right type");
     do_check_true(f3.type = "text/plain", "Should be the right type");
     do_check_true(f4.type = "text/plain", "Should be the right type");
-    do_check_true(f5.type = "text/plain", "Should be the right type");
-    do_check_true(f6.type = "text/plain", "Should be the right type");
 
     var threw = false;
     try {
       // Needs a ctor argument
       var f7 = File();
     } catch (e) {
       threw = true;
     }
--- a/layout/base/FrameLayerBuilder.cpp
+++ b/layout/base/FrameLayerBuilder.cpp
@@ -270,17 +270,18 @@ public:
   /**
    * This is the method that actually walks a display list and builds
    * the child layers. We invoke it recursively to process clipped sublists.
    * @param aClipRect the clip rect to apply to the list items, or null
    * if no clipping is required
    */
   void ProcessDisplayItems(const nsDisplayList& aList,
                            FrameLayerBuilder::Clip& aClip,
-                           uint32_t aFlags);
+                           uint32_t aFlags,
+                           const nsIFrame* aForceActiveScrolledRoot = nullptr);
   /**
    * This finalizes all the open ThebesLayers by popping every element off
    * mThebesLayerDataStack, then sets the children of the container layer
    * to be all the layers in mNewChildLayers in that order and removes any
    * layers as children of the container that aren't in mNewChildLayers.
    * @param aTextContentFlags if any child layer has CONTENT_COMPONENT_ALPHA,
    * set *aTextContentFlags to CONTENT_COMPONENT_ALPHA
    */
@@ -556,16 +557,19 @@ protected:
    * aLayer is the layer to be clipped.
    * aRoundedRectClipCount is used when building mask layers for ThebesLayers,
    * SetupMaskLayer will build a mask layer for only the first
    * aRoundedRectClipCount rounded rects in aClip
    */
   void SetupMaskLayer(Layer *aLayer, const FrameLayerBuilder::Clip& aClip,
                       uint32_t aRoundedRectClipCount = UINT32_MAX);
 
+  bool ChooseActiveScrolledRoot(const nsDisplayList& aList,
+                                const nsIFrame **aActiveScrolledRoot);
+
   nsDisplayListBuilder*            mBuilder;
   LayerManager*                    mManager;
   FrameLayerBuilder*               mLayerBuilder;
   nsIFrame*                        mContainerFrame;
   const nsIFrame*                  mContainerReferenceFrame;
   ContainerLayer*                  mContainerLayer;
   FrameLayerBuilder::ContainerParameters mParameters;
   /**
@@ -2019,65 +2023,49 @@ PaintInactiveLayer(nsDisplayListBuilder*
     aContext->Rectangle(itemVisibleRect);
     aContext->Fill();
     aItem->SetPainted();
   }
 #endif
 }
 
 /**
- * Checks if aAncestor is an ancestor of aFrame
- */
-static bool IsFrameAncestorOf(const nsIFrame *aAncestor, const nsIFrame *aFrame)
-{
-  if (!aFrame) {
-    return false;
-  }
-  for (const nsIFrame* f = aFrame; f; f = nsLayoutUtils::GetCrossDocParentFrame(f)) {
-    if (f == aAncestor) {
-      return true;
-    }
-  }
-  return false;
-}
-
-/**
  * Chooses a single active scrolled root for the entire display list, used
  * when we are flattening layers.
  */
-static bool ChooseActiveScrolledRoot(nsDisplayListBuilder *aBuilder,
-                                     const nsDisplayList& aList,
-                                     const nsIFrame **aActiveScrolledRoot)
+bool
+ContainerState::ChooseActiveScrolledRoot(const nsDisplayList& aList,
+                                         const nsIFrame **aActiveScrolledRoot)
 {
   for (nsDisplayItem* item = aList.GetBottom(); item; item = item->GetAbove()) {
     nsDisplayItem::Type type = item->GetType();
     if (type == nsDisplayItem::TYPE_CLIP ||
         type == nsDisplayItem::TYPE_CLIP_ROUNDED_RECT) {
-      if (!ChooseActiveScrolledRoot(aBuilder,
-                                    *item->GetSameCoordinateSystemChildren(),
-                                    aActiveScrolledRoot)) {
-        return false;
+      if (ChooseActiveScrolledRoot(*item->GetSameCoordinateSystemChildren(),
+                                   aActiveScrolledRoot)) {
+        return true;
       }
       continue;
     }
 
-    if (!*aActiveScrolledRoot) {
-      // Try using the actual active scrolled root of the backmost item, as that
-      // should result in the least invalidation when scrolling.
-      aBuilder->IsFixedItem(item, aActiveScrolledRoot);
-    } else if (!IsFrameAncestorOf(*aActiveScrolledRoot, item->GetUnderlyingFrame())) {
-      // If there are items that aren't descendants of the background's active scrolled
-      // root, then give up and just use the container's reference frame instead.
-      return false;
+    LayerState layerState = item->GetLayerState(mBuilder, mManager, mParameters);
+    // Don't use an item that won't be part of any ThebesLayers to pick the
+    // active scrolled root.
+    if (layerState == LAYER_ACTIVE_FORCE) {
+      continue;
+    }
+
+    // Try using the actual active scrolled root of the backmost item, as that
+    // should result in the least invalidation when scrolling.
+    mBuilder->IsFixedItem(item, aActiveScrolledRoot);
+    if (*aActiveScrolledRoot) {
+      return true;
     }
   }
-  if (!*aActiveScrolledRoot) {
-    return false;
-  }
-  return true;
+  return false;
 }
 
 /*
  * Iterate through the non-clip items in aList and its descendants.
  * For each item we compute the effective clip rect. Each item is assigned
  * to a layer. We invalidate the areas in ThebesLayers where an item
  * has moved from one ThebesLayer to another. Also,
  * aState->mInvalidThebesContent is invalidated in every ThebesLayer.
@@ -2087,40 +2075,43 @@ static bool ChooseActiveScrolledRoot(nsD
  * individually when we draw them.)
  * We set the visible rect for all layers, although the actual setting
  * of visible rects for some ThebesLayers is deferred until the calling
  * of ContainerState::Finish.
  */
 void
 ContainerState::ProcessDisplayItems(const nsDisplayList& aList,
                                     FrameLayerBuilder::Clip& aClip,
-                                    uint32_t aFlags)
+                                    uint32_t aFlags,
+                                    const nsIFrame* aForceActiveScrolledRoot)
 {
   SAMPLE_LABEL("ContainerState", "ProcessDisplayItems");
 
   const nsIFrame* lastActiveScrolledRoot = nullptr;
   nsPoint topLeft;
 
   // When NO_COMPONENT_ALPHA is set, items will be flattened into a single
   // layer, so we need to choose which active scrolled root to use for all
   // items.
   if (aFlags & NO_COMPONENT_ALPHA) {
-    if (!ChooseActiveScrolledRoot(mBuilder, aList, &lastActiveScrolledRoot)) {
+    if (aForceActiveScrolledRoot) {
+      lastActiveScrolledRoot = aForceActiveScrolledRoot;
+    } else if (!ChooseActiveScrolledRoot(aList, &lastActiveScrolledRoot)) {
       lastActiveScrolledRoot = mContainerReferenceFrame;
     }
 
     topLeft = lastActiveScrolledRoot->GetOffsetToCrossDoc(mContainerReferenceFrame);
   }
 
   for (nsDisplayItem* item = aList.GetBottom(); item; item = item-